This project started out watching some YouTube ‘Ux-Radar’ demonstrations that I thought I’d like to move onto. Sure enough (as usual I’ve found) most of the code I tried had ‘issues’ and didn’t work and the code was very poorly documented.
So, as I’m teaching myself, the basis of a Radar screen background is very well provided within the Bodmer examples, 320x240 and Sprite folders. I used Rotated_Sprite_2 as my teach guide. Implementing the addition of a Ux device and servo for rotation should hopefully be easy to complete my project.
The code below is for any ‘Newbie’ getting to grips with Sprites which hopefully I’ve fully documented that you can try out and play around, with the various functions I’ve put together.
BUT, I have an issue that’s fried my brain! At lines 150 to 160 in the code inside this function,
void drawDegsEmptyGraticule(String label, int32_t val)
once the numerical angle value is outside of the defined sprite, it screws itself up by a factor of decimal 10 once the return angle is less than 100 on the first return sweep?
Can any one please offer advice/solution to correct the issue, be critical if you find something blatantly obvious.
TIA
#include <Arduino.h>
// This example plots a rotated Sprite into another Sprite and then the resultant composited
// Sprite is pushed to the TFT screen. This example is for a 240 x 320 screen.
// The motivation for developing this capability is that animated dials can be drawn easily
// and the complex calculations involved are handled by the TFT_eSPI library. To create a dial
// with a moving needle a graphic of a meter needle is plotted at a specified angle into another
// Sprite that contains the dial face. When the needle Sprite is pushed to the dial Sprite the
// plotting ensures two pivot points for each Sprite coincide with pixel level accuracy.
// Two rotation pivot points must be set, one for the first Sprite and one for the second
// Sprite using setPivot(). These pivot points do not need to be within the Sprite boundaries.
// In this example a needle graphic is also be plotted direct to a defined TFT pivot point.
// The rotation angle is in degrees, an angle of 0 means no Sprite rotation.
// The pushRotated() function works with 1, 8 and 16-bit per pixel (bpp) Sprites.
// For 1 bpp Sprites the foreground and background colours are defined with the
// member function setBitmapColor(foregroundColor, backgroundColor).
// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library:
// https://github.com/Bodmer/TFT_eSPI
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
#define Radar_WIDTH 317
#define Radar_HEIGHT 237
#define Radar_BeamWidth 17
#define Radar_BeamHeight 140 //128
#define OuterScreenRadius 140
#define InnerScreenRadius 132
#define PixelCentrePtx 150
#define PixelCentrePty 215
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
//Create a 'background' sprite BODMER version
//TFT_eSprite dial = TFT_eSprite(&tft); // Sprite object for dial
//TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle
//Create a 'background' sprite DEGS version
TFT_eSprite Radarback = TFT_eSprite(&tft); // Sprite object for Radarback
TFT_eSprite RadarbackG = TFT_eSprite(&tft); // Sprite object for Radarback
TFT_eSprite needleBeam = TFT_eSprite(&tft);// Sprite object for needleBeam
TFT_eSprite RadarBeam = TFT_eSprite(&tft); // Sprite object for Wedge type needle
TFT_eSprite RadarBeamG = TFT_eSprite(&tft); // Sprite object for Wedge type needle
const int MAX_RANGE_CM = 50;
uint32_t startMillis;
// =======================================================================================
// =======================================================================================
// Create the Radar graticule, the graticule outer and place scale markers
// ****** Developed from Bodmer Example Rotated_Sprite_2 ******
// =======================================================================================
/*
void createDegsDialScale(int16_t start_angle, int16_t end_angle, int16_t increment)
{
// Create the dial Sprite
Radarback.setColorDepth(8); // Size is odd (i.e. 91) so there is a centre pixel at 45,45
//Radarback.setSwapBytes(true); // We need to swap the colour bytes (endianess)
Radarback.createSprite(91, 91); // 8bpp requires 91 * 91 = 8281 bytes
Radarback.setPivot(45,45); // set pivot in middle of dial Sprite
// Draw dial outline
Radarback.fillSprite(TFT_TRANSPARENT); // Fill with transparent colour
Radarback.fillCircle(45,45,43,TFT_DARKGREY); // Draw dial outer
// Hijack the use of the needleBeam Sprite since that has not been used yet!
needleBeam.createSprite(3, 3); // 3 pixels wide, 3 high
needleBeam.fillSprite(TFT_WHITE); // Fill with white
needleBeam.setPivot(1, 43); // Set pivot point x to the Sprite centre and y to marker radius
for (int16_t angle = start_angle; angle <= end_angle; angle += increment) {
needleBeam.pushRotated(&Radarback, angle); // Sprite is used to make scale markers
yield(); // Avoid a watchdog time-out
}
needleBeam.deleteSprite(); // Delete the hijacked Sprite
}
*/
void createDegsGraticule(int16_t start_angle, int16_t end_angle, int16_t increment){
// Create the dial Sprite
RadarbackG.setColorDepth(8); // Size is odd (i.e. 91) so there is a centre pixel at 45,45
//Radarback.setSwapBytes(true); // We need to swap the colour bytes (endianess)
//RadarbackG.createSprite(301, 301); // 8bpp requires 91 * 91 = 8281 bytes
//RadarbackG.setPivot(150,150); // set pivot in middle of dial Sprite
RadarbackG.createSprite(301, 301); // 8bpp requires 91 * 91 = 8281 bytes
RadarbackG.setPivot(150,150); // set pivot in middle of dial Sprite
// Draw dial outline
RadarbackG.fillSprite(TFT_TRANSPARENT); // Fill with transparent colour
//RadarbackG.fillCircle(150,150,147,TFT_DARKGREY); // Draw dial outer
//RadarbackG.fillCircle(PixelCentrePtx,PixelCentrePty,PixelCentrePtx-3,TFT_DARKGREY); // Draw dial outer
RadarbackG.fillCircle(PixelCentrePtx,150,PixelCentrePtx-3,TFT_DARKGREY); // Draw dial outer
// Hijack the use of the needleBeam Sprite since that has not been used yet!
RadarBeamG.createSprite(3, 12); // 3 pixels wide, 3 high
RadarBeamG.fillSprite(TFT_WHITE); // Fill with white
RadarBeamG.setPivot(1, 147); // Set pivot point x to the Sprite centre and y to marker radius
for (int16_t angle = start_angle; angle <= end_angle; angle += increment) {
RadarBeamG.pushRotated(&RadarbackG, angle); // Sprite is used to make scale markers
yield(); // Avoid a watchdog time-out
}
RadarBeamG.deleteSprite(); // Delete the hijacked Sprite
}
// ===========================================================================//
// Add the empty (Bodmer Dial Face) or Graticule face with a label and value =//
// ===========================================================================//
/*
void drawDegsEmptyDial(String label, int32_t val)
{
// Draw black face
Radarback.fillCircle(45, 45, 40, TFT_BLACK);
Radarback.drawPixel(45, 45, TFT_WHITE); // For demo only, mark pivot point with a white pixel
Radarback.setTextDatum(TC_DATUM); // Draw dial text
Radarback.drawString(label, 45, 15, 2);
Radarback.drawNumber(val, 45, 60, 2);
//tft.drawString(label, 5, 15, 2);
//tft.drawNumber(val, 45, 15, 2);
}
*/
void drawDegsEmptyGraticule(String label, int32_t val)
{
// Draw black face
//RadarbackG.fillCircle(PixelCentrePtx,PixelCentrePty, OuterScreenRadius, TFT_BLACK);
//RadarbackG.drawPixel(PixelCentrePtx,PixelCentrePty, TFT_WHITE); // For demo only, mark pivot point with a white pixel
RadarbackG.fillCircle(PixelCentrePtx,150, OuterScreenRadius, TFT_BLACK);
RadarbackG.drawPixel(PixelCentrePtx,150, TFT_WHITE); // For demo only, mark pivot point with a white pixel
//RadarbackG.setTextDatum(TC_DATUM); // Draw dial text
RadarbackG.drawString(label, 110, 25, 2);
RadarbackG.drawNumber(val, 165, 25, 2);
RadarbackG.drawString(label, 60, 45, 2);
RadarbackG.drawNumber(val, 110, 45, 2);
RadarbackG.drawString("Background Sprite_co-ordinates", 0,0);
RadarbackG.drawString(label, 0, 10, 2);
RadarbackG.drawNumber(val, 50, 10, 2);
////RadarbackG.drawNumber(val/10, 50, 10, 2); //Dividing val/10 'partially' works?
tft.drawString("tft_co-ordinates",2,2);
tft.drawString(label, 0, 15, 2);
tft.drawNumber(val, 50, 15, 2);
////tft.drawNumber(val/10, 50, 15, 2); //Dividing val/10 'partially' works?150
//Draw 12 lines
float sx, sy, x0, yy0, x1, yy1;
for(int i = 0; i<210; i+= 30) {
//sx = cos((i-90)*0.0174532925);
//sy = sin((i-90)*0.0174532925);
sx = cos((i+180)*0.0174532925);
sy = sin((i+180)*0.0174532925);
x0 = sx*(InnerScreenRadius+4)+PixelCentrePtx;
//yy0 = sy*(InnerScreenRadius+4)+PixelCentrePty;
yy0 = sy*(InnerScreenRadius+4)+150;
x1 = sx*10+PixelCentrePtx;
//yy1 = sy*10+PixelCentrePty;
yy1 = sy*10+150;
//virtual void TFT_eSPI::drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color)
RadarbackG.drawLine(x0, yy0, x1, yy1, TFT_GREEN);
RadarbackG.drawCircle(PixelCentrePtx,150,OuterScreenRadius,TFT_GREEN);
RadarbackG.drawCircle(PixelCentrePtx,150,OuterScreenRadius/3,TFT_GREEN);
RadarbackG.drawCircle(PixelCentrePtx,150,OuterScreenRadius*2/3,TFT_GREEN);
Radarback.drawCircle(PixelCentrePtx,150,10,TFT_WHITE);
//void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color)
RadarbackG.drawLine(10, 145, 290, 145, TFT_WHITE);
RadarbackG.drawLine(10, 155, 290, 155, TFT_WHITE);
RadarbackG.drawLine(10, 145, 10, 155, TFT_WHITE);
RadarbackG.drawLine(290, 145, 290, 155, TFT_WHITE);
}
// Draw 12 dots
RadarbackG.fillCircle(PixelCentrePtx,OuterScreenRadius-122, 4, TFT_WHITE);
for(int i = 0; i<=360; i+= 30) {
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*InnerScreenRadius+PixelCentrePtx;
yy0 = sy*InnerScreenRadius+150;
// Draw main quadrant dots. NOTE: Angles are CW rotation
if(i==30 || i==330) RadarbackG.fillCircle(x0, yy0, 2, TFT_WHITE);
if(i==60 || i==300) RadarbackG.fillCircle(x0, yy0, 2, TFT_WHITE);
if(i==90 || i==270) RadarbackG.fillCircle(x0, yy0, 2, TFT_WHITE);
}
// Draw 60 dots Outer Ring
for(int i = 0; i<360; i+= 6) {
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*InnerScreenRadius+PixelCentrePtx;
yy0 = sy*InnerScreenRadius+150;
// Draw 'minute' or '6 degree' markers
RadarbackG.fillCircle(x0, yy0, 1, TFT_WHITE);
}
// Draw 60 dots Middle Ring
for(int i = 0; i<360; i+= 6) {
//int OuterScreenRadius = 140;
//int InnerScreenRadius = 137;
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*(InnerScreenRadius*2/3)+PixelCentrePtx;
yy0 = sy*(InnerScreenRadius*2/3)+150;
// Draw minute markers
RadarbackG.fillCircle(x0, yy0, 1, TFT_WHITE);
}
// Draw 60 dots Inner Ring
for(int i = 0; i<360; i+= 6) {
//int OuterScreenRadius = 140;
//int InnerScreenRadius = 137;
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*(InnerScreenRadius*2/6)+PixelCentrePtx;
yy0 = sy*(InnerScreenRadius*2/6)+150;
// Draw minute markers
RadarbackG.fillCircle(x0, yy0, 1, TFT_WHITE);
}
}
// =============================================================================================
// Update the dial of your choice and plot to screen with needle of your choice at defined angle
// =============================================================================================
/*
void plotDegsDialNeedle(int16_t x, int16_t y, int16_t angle, String label, uint16_t val)
{
// Draw the blank dial in the Sprite, add label and number
drawDegsEmptyDial(label, val);
// Push a rotated needle Sprite to the dial Sprite, with black as transparent colour
needleBeam.pushRotated(&Radarback, angle, TFT_BLACK); // dial is the destination Sprite
//RadarBeam.pushRotated(&Radarback, angle, TFT_BLACK); // dial is the destination Sprite
// Push the resultant dial Sprite to the screen, with transparent colour
Radarback.pushSprite(x, y, TFT_TRANSPARENT);
}
*/
/*
void plotDegsDialRadar(int16_t x, int16_t y, int16_t angle, String label, uint16_t val)
{
// Draw the blank dial in the Sprite, add label and number
drawDegsEmptyDial(label, val);
// Push a rotated needle Sprite to the dial Sprite, with black as transparent colour
//needleBeam.pushRotated(&Radarback, angle, TFT_BLACK); // dial is the destination Sprite
RadarBeam.pushRotated(&Radarback, angle, TFT_BLACK); // dial is the destination Sprite
// Push the resultant dial Sprite to the screen, with transparent colour
Radarback.pushSprite(x, y, TFT_TRANSPARENT);
}
*/
void plotDegsDialRadarGraticule(int16_t x, int16_t y, int16_t angle, String label, uint16_t val)
{
// Draw the blank dial in the Sprite, add label and number
drawDegsEmptyGraticule(label, val);
// Push a rotated needle Sprite to the dial Sprite, with black as transparent colour
//needleBeam.pushRotated(&Radarback, angle, TFT_BLACK); // dial is the destination Sprite
RadarBeamG.pushRotated(&RadarbackG, angle, TFT_BLACK); // dial is the destination Sprite
// Push the resultant dial Sprite to the screen, with transparent colour
RadarbackG.pushSprite(x, y, TFT_TRANSPARENT);
}
// =======================================================================================
// Create the needle Sprite and the image of the needle
// =======================================================================================
void createDegsNeedle(void)
{
needleBeam.setColorDepth(8);
needleBeam.createSprite(11, 49); // create the needle Sprite 11 pixels wide by 49 high
needleBeam.fillSprite(TFT_BLACK); // Fill with black
// Define needle pivot point
uint16_t piv_x = needleBeam.width() / 2; // x pivot of Sprite (middle)
uint16_t piv_y = needleBeam.height() - 10; // y pivot of Sprite (10 pixels from bottom)
needleBeam.setPivot(piv_x, piv_y); // Set pivot point in this Sprite
// Draw the red needle with a yellow tip
// Keep needle tip 1 pixel inside dial circle to avoid leaving stray pixels
needleBeam.fillRect(piv_x - 1, 2, 3, piv_y + 8, TFT_GREEN);
needleBeam.fillRect(piv_x - 1, 2, 3, 5, TFT_YELLOW);
// Draw needle centre boss
needleBeam.fillCircle(piv_x, piv_y, 5, TFT_MAROON);
needleBeam.drawPixel( piv_x, piv_y, TFT_WHITE); // Mark needle pivot point with a white pixel
}
////void createRadarGraticule(int16_t start_angle, int16_t end_angle, int16_t increment){
/*
void createRadarGraticule(){
// Create the dial Sprite of defined size
Radarback.setColorDepth(8); // VERY IMPORTANT
//Create the SIZE of the Sprite
Radarback.createSprite(Radar_WIDTH, Radar_HEIGHT); //(317,237)
Radarback.setPivot(PixelCentrePtx,PixelCentrePty); // set pivot in middle of dial Sprite (160, 225)
//Radarback.setSwapBytes(true); // We need to swap the colour bytes (endianess)
// Draw dial outline
Radarback.fillSprite(TFT_TRANSPARENT); // Fill with transparent colour
Radarback.fillCircle(PixelCentrePtx+2,PixelCentrePty+2,OuterScreenRadius+2,TFT_BLACK); // Draw dial outer
//Draw 12 lines
float sx, sy, x0, yy0, x1, yy1;
for(int i = 0; i<210; i+= 30) {
//sx = cos((i-90)*0.0174532925);
//sy = sin((i-90)*0.0174532925);
sx = cos((i+180)*0.0174532925);
sy = sin((i+180)*0.0174532925);
x0 = sx*(InnerScreenRadius+4)+PixelCentrePtx;
yy0 = sy*(InnerScreenRadius+4)+PixelCentrePty;
x1 = sx*10+PixelCentrePtx;
yy1 = sy*10+PixelCentrePty;
//virtual void TFT_eSPI::drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color)
Radarback.drawLine(x0, yy0, x1, yy1, TFT_GREEN);
Radarback.drawCircle(PixelCentrePtx,PixelCentrePty,OuterScreenRadius,TFT_GREEN);
Radarback.drawCircle(PixelCentrePtx,PixelCentrePty,OuterScreenRadius/3,TFT_GREEN);
Radarback.drawCircle(PixelCentrePtx,PixelCentrePty,OuterScreenRadius*2/3,TFT_GREEN);
Radarback.drawCircle(PixelCentrePtx,PixelCentrePty,10,TFT_WHITE);
//void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color)
Radarback.drawLine(10, 222, 310, 222, TFT_WHITE);
Radarback.drawLine(10, 228, 310, 228, TFT_WHITE);
Radarback.drawLine(10, 222, 10, 228, TFT_WHITE);
Radarback.drawLine(310, 222, 310, 228, TFT_WHITE);
}
// Draw 12 dots
for(int i = 0; i<360; i+= 30) {
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*InnerScreenRadius+PixelCentrePtx;
yy0 = sy*InnerScreenRadius+PixelCentrePty;
// Draw main quadrant dots. NOTE: Angles are CW rotation
if(i==0) Radarback.fillCircle(x0, yy0, 2, TFT_WHITE);
if(i==30 || i==330) Radarback.fillCircle(x0, yy0, 2, TFT_WHITE);
if(i==60 || i==300) Radarback.fillCircle(x0, yy0, 2, TFT_WHITE);
if(i==90 || i==270) Radarback.fillCircle(x0, yy0, 2, TFT_WHITE);
}
// Draw 60 dots Outer Ring
for(int i = 0; i<360; i+= 6) {
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*InnerScreenRadius+PixelCentrePtx;
yy0 = sy*InnerScreenRadius+PixelCentrePty;
// Draw 'minute' or '6 degree' markers
Radarback.fillCircle(x0, yy0, 1, TFT_WHITE);
}
// Draw 60 dots Middle Ring
for(int i = 0; i<360; i+= 6) {
//int OuterScreenRadius = 140;
//int InnerScreenRadius = 137;
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*(InnerScreenRadius*2/3)+PixelCentrePtx;
yy0 = sy*(InnerScreenRadius*2/3)+PixelCentrePty;
// Draw minute markers
Radarback.fillCircle(x0, yy0, 1, TFT_WHITE);
}
// Draw 60 dots Inner Ring
for(int i = 0; i<360; i+= 6) {
//int OuterScreenRadius = 140;
//int InnerScreenRadius = 137;
sx = cos((i-90)*0.0174532925);
sy = sin((i-90)*0.0174532925);
x0 = sx*(InnerScreenRadius*2/6)+PixelCentrePtx;
yy0 = sy*(InnerScreenRadius*2/6)+PixelCentrePty;
// Draw minute markers
Radarback.fillCircle(x0, yy0, 1, TFT_WHITE);
}
}
*/
// =======================================================================================
// Update the Graticule and plot to screen with Radar beam at defined angle
// =======================================================================================
/*
void ScanRadarBeam(int16_t x, int16_t y, int16_t angle, String label, uint16_t val)
{ // Draw the blank dial in the Sprite, add label and number
drawEmptyGraticule(label, val);
// Push a rotated RadarBeam Sprite to the Radarback Sprite, with black as transparent colour
RadarBeam.pushRotated(&Radarback, angle, TFT_BLACK); // dial is the destination Sprite
// Push the resultant dial Sprite to the screen, with transparent colour
Radarback.pushSprite(x, y, TFT_TRANSPARENT);
}
*/
void createRadarBeam()
{
RadarBeam.setColorDepth(8);
//void *TFT_eSprite::createSprite(int16_t width, int16_t height, uint8_t frames = (uint8_t)1U)
RadarBeam.createSprite(21, 89); //(21, 89)
// Create the choice of Sprite 21 pixels wide by 89 high in pixels
// RadarBeam.createSprite(Radar_BeamWidth = 21, Radar_BeamHeight = 89);
RadarBeam.fillSprite(TFT_BLACK); // Fill with black
//======================================================================================================================//
//--- Define the Sprite pivot point (In my case a wedge derivative from Bodmers examples representing a radar beam) ---// */
//======================================================================================================================//
// How to calculate these IMPORTANT values applied to Sprites, specially for a wedge variant?
// The area (WxH) of the Sprite is specified in the defined variables RadarBeam.createSprite(21, 89);
//* It ALWAYS starts at the top left corner co-ordinates (x,y)=(0,0) to (x,y)=(21,89).
//* These are in pixels so in a 320x240 display you have to understand exactly what the orietentation of (x,y)=(0,0) is.
//* The next task is to then calculate where you want your sprite object to be positioned relative to a background.
//* So, for my example uint16_t piv_x (21 / 2) = 10 comes from aligning the (x,y)=(0,0) point on the 320x240 display.
//* NOTE: If like myself you create a background thats of the form:-
//* #define Radar_WIDTH 316
//* #define Radar_HEIGHT 236
//* void TFT_eSPI::setPivot(int16_t x, int16_t y)
//* Radarback.createSprite(Radar_WIDTH, Radar_HEIGHT);
//* Then uint16_t piv_x = (316/2) [background display/2]
//* Then uint16_t piv_y = (236/2)-(The START 'pixel' value where you want the END point of the Sprite to be)
//* Radarback.setPivot(10, 44-1);
//* The next IMPORTANT thing to understand here is where the variables (ax, ay, bx, by) lie on the screen you
//* are using. In my case 320x240 pixels and tft.setRotation(1). Using #defines for naming variables helps to prevent
//* you losing your way around what you are trying to achieve especially when you are trying to produce a visual effect.
uint16_t piv_x = Radarback.width()/2; // x pivot of Sprite (middle pixel) width = 21
uint16_t piv_y = Radarback.height()/2; // y pivot of Sprite (44 pixels from bottom) height.
Radarback.setPivot(piv_x, 45);
//Radarback.setPivot(piv_x, piv_y-1);
//void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, float br, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF)
RadarBeam.drawWedgeLine(10,12,10,45,8,1,TFT_SKYBLUE);
}
void createRadarBeamG()
{
RadarBeamG.setColorDepth(8);
//void *TFT_eSprite::createSprite(int16_t width, int16_t height, uint8_t frames = (uint8_t)1U)
RadarBeamG.createSprite(21, 280);
// Create the choice of Sprite 21 pixels wide by 280 high in pixels
RadarBeamG.fillSprite(TFT_BLACK); // Fill with black
uint16_t piv_x = RadarbackG.width()/2; // x pivot of Sprite (middle pixel) width = 21
uint16_t piv_y = RadarbackG.height()/2; // y pivot of Sprite (140 pixels from bottom) height.
RadarbackG.setPivot(piv_x, piv_y-1); // piv_y BECOMES OuterScreenRadius
//void TFT_eSPI::drawWedgeLine(float ax, float ay, float bx, float by, float ar, float br, uint32_t fg_color, uint32_t bg_color = 0x00FFFFFF)
RadarBeamG.drawWedgeLine(10,12,10,OuterScreenRadius-4,8,1,TFT_VIOLET);
}
void setup(){
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_NAVY);
/************************************************/
/* BODMER EXAMPLE CODE */
/************************************************/
// == Original implementation of Rotated_Sprite_2 == //
/************************************************/
/* MY RADAR EXAMPLE CODE */
/************************************************/
//createDegsDialScale(-120, 120, 15);
//drawDegsEmptyDial("Degs", 54321);
createDegsGraticule(-120,120,30);
////drawDegsEmptyGraticule("Degs", 54321); //This is the black blank screen
// ** Push a copy of the dial to the screen so we can see it **//
//Radarback.pushSprite(210, 140); //Alternative learning version
////RadarbackG.pushSprite(0, 70);
///delay(1000);
// Create the needle Sprite
createDegsNeedle(); // draw the needle graphic
needleBeam.pushSprite(245, 10); // push a copy of the needle to the screen so we can see it
delay(1000);
// Create the Radar beam Sprite
createRadarBeam();
RadarBeam.pushSprite(265, 10); // push a copy of the needle to the screen so we can see it
// Create the Radar beam Sprite
createRadarBeamG();
RadarBeamG.pushSprite(295, 10); // push a copy of the needle to the screen so we can see it
}
void loop(){
// Push the needle sprite to the dial Sprite at different angles and then push the dial to the screen
// Use angle increments in range 1 to 6 for smoother or faster movement.
/*
for (int16_t angle = -120; angle <= 120; angle += 2) {
plotDegsDialNeedle(10,10, angle, "ANGLE", angle + 120);
delay(20); //Decreasing or increasing this delay also speeds up plotting movement.
yield(); // Avoid a watchdog time-out
}
delay(500); // Pause
// Update the dial Sprite with decreasing angle and plot to screen at 0,0, no delay
for (int16_t angle = 120; angle >= -120; angle -= 4) {
plotDegsDialRadar(170,10, angle, "ANGLE", angle + 120);
delay(20);
yield(); // Avoid a watchdog time-out
}
*/
/**************************************************/
/* Derived from BODMER EXAMPLE CODE */
/* Two things to note: */
/* 1. Decreasing or increasing the size of the */
/* sweep angle also adjusts the sweep rotation */
/* speed. */
/* 2. It's important to realise/understand you */
/* create a new composite sprite written over */
/* the previous composite sprite at EXACTLY */
/* the SPECIFIED PIXEL POINTS in your code. */
/**************************************************/
for (int16_t angle = -90; angle <= 90; angle += 1) { // angle = sweep angle
plotDegsDialRadarGraticule(10,70, angle, "ANGLE", angle + 90);
delay(50); //Decreasing or increasing this delay also speeds up plotting movement.
//delay(1000);
yield(); // Avoid a watchdog time-out
}
delay(500); // Pause Pause type RadarBeamG angle sweep
// Update the dial Sprite with decreasing angle and plot to screen at 0,0, no delay
for (int16_t angle = 90; angle >= -90; angle -= 1) {
plotDegsDialRadarGraticule(10,70, angle, "ANGLE", angle + 90);
delay(50);
//delay(1000);
yield(); // Avoid a watchdog time-out
}
delay(500); // Pause Pause type RadarBeamG angle sweep
//*** TRY THIS OUT BELOW TO SHOW HOW THE SPRITES ARE COMBINED ***//
//*** AND DISPLAYED IN A DIFFERENT SCREEN ROTATION DEPENDING ON ***//
//*** EXACTLY the SPECIFIED PIXEL POINTS in your code. ***//
//*** IT TEACHES YOU HOW BODMER OVERLAYES SPRITES TO BUILD ***//
//*** A COMPOSITE DISPLAY WITHOUT FLICKER. ***//
/*/
// Update the dial Sprite with decreasing angle and plot to screen at 0,0, no delay
for (int16_t angle = 110; angle >= -110; angle -= 4) {
plotDegsDialRadarGraticule(170,10, angle, "ANGLE", angle + 110);
delay(20);
yield(); // Avoid a watchdog time-out
}
*/