Arduino Forum

Using Arduino => Displays => Topic started by: i3dm on Aug 11, 2016, 08:09 pm

Title: Artificial Horizon display using a gyro
Post by: i3dm on Aug 11, 2016, 08:09 pm
Hello guys,

i would lik to build a mini artificial Horizon display for a model airplane.
the code should take roll + pitch angles from an MPU6050 and display an articial horizon "ball" similar to that of an aircraft.
im using the SPI 1.8" display, and managed to build a static display of pitch = 0 roll = 0, similar to the attached picture.
so far im trying to run the diaply with variable angles, without the gyro, just for making sure i have the display running well.

im using the Adafruit ST7735 library, and i can fill parts of the screen with   tft.fillRoundRect function, but i can not get how to fill "angled" parts of the screen.
i managed to get a code running just the Artifical horizon line using DrawLine:
Code: [Select]
  for (int16_t y=0; y < 10; y++)
{

  for (int16_t x=40; x < 120; x++)
  {
   tft.drawLine(0, x, 130, 160-x, color);   // startx, start y, stop x, stop y
      tft.drawLine(0, x, 130, 160-x, ST7735_BLACK);   // startx, start y, stop x, stop y
  }

    for (int16_t x=120; x >40; x--)
  {
   tft.drawLine(0, x, 130, 160-x, color);   // startx, start y, stop x, stop y
      tft.drawLine(0, x, 130, 160-x, ST7735_BLACK);   // startx, start y, stop x, stop y
  }
 
   //     tft.drawLine(0, 70, 130, 90, color);   // startx, start y, stop x, stop y
}
}


but how do i fill the screen in color above and below that line?
under that line should be brown, and above it blue.

also, in order to get just one line on the screen at all times, i have to "delete" the line by drawing a black line over it, this wont work with full color background.

basically what im trying to get is a code like the piece of code i added, but above the line all blue, under the line all brown.

any ideas?
thanks.


Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 11, 2016, 08:16 pm
i did try a for loop with a single pixel print, from 0,0 all the way up to the angled line, but it is very slow.
takes about 2 seconds to fill a whole screen - and i need to refresh it at least 1-2 times a second.

Title: Re: Artificial Horizon display using a gyro
Post by: TFTLCDCyg on Aug 11, 2016, 08:23 pm
See this video: https://www.youtube.com/watch?v=6viXWUyE6ks
 (https://www.youtube.com/watch?v=6viXWUyE6ks)


Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 11, 2016, 08:28 pm
Thank you for the link - is that your own code?
Title: Re: Artificial Horizon display using a gyro
Post by: CrossRoads on Aug 11, 2016, 08:39 pm
"Published on Dec 3, 2015"
Too bad you can't get that code.
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 11, 2016, 10:18 pm
...

but how do i fill the screen in color above and below that line?

...

If you want to display just "roll" angle, i.e. pitch angle is zero then:

Use trigonometry (Tan) to find the coordinates of the point at the edge of the screen of a line at the angle you want which passes through the middle of the screen. Since the middle of the screen is a known point this is easy.

Then reflect the coordinate to get the point at the opposite edge.  Now you have two points and you can draw two filled triangles and two filled rectangles to set the above and below horizon colours, then draw a line at the horizon.


If you want to add pitch then calculate the coordinate shift on the y axis and the use this as the point that the angled line passes though and to get the intersection coordinates at the edges of the screen. You cannot use coordinate reflection is this case. so you must use trig to get the 2 end points of the horizon line.

If you draw it out on paper you will see what I mean.

When you have debugged your code on the Adafruit library and are using an AVR processor (e.g. UNO, Mega etc)  and do not achieve the refresh rate you want... then try my library here  library here (https://github.com/Bodmer/TFT_ST7735) which is 3 to 10 times faster for graphics operations.  I think you could achieve at least 5 frames per second. For a simpler display with a single line for a horizon you should be able to get at least 50 frames per second.
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 12:05 am
i already did the trig, just looking for a fast way to fill the screen up to the line.
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 12:15 am
If you want to display just "roll" angle, i.e. pitch angle is zero then:

Use trigonometry (Tan) to find the coordinates of the point at the edge of the screen of a line at the angle you want which passes through the middle of the screen. Since the middle of the screen is a known point this is easy.

Then reflect the coordinate to get the point at the opposite edge.  Now you have two points and you can draw two filled triangles and two filled rectangles to set the above and below horizon colours, then draw a line at the horizon.


If you want to add pitch then calculate the coordinate shift on the y axis and the use this as the point that the angled line passes though and to get the intersection coordinates at the edges of the screen. You cannot use coordinate reflection is this case. so you must use trig to get the 2 end points of the horizon line.

If you draw it out on paper you will see what I mean.

When you have debugged your code on the Adafruit library and are using an AVR processor (e.g. UNO, Mega etc)  and do not achieve the refresh rate you want... then try my library here  library here (https://github.com/Bodmer/TFT_ST7735) which is 3 to 10 times faster for graphics operations.  I think you could achieve at least 5 frames per second. For a simpler display with a single line for a horizon you should be able to get at least 50 frames per second.
tried your library, but for some reason your examples dont display anything on the screen?
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 12, 2016, 01:50 am
i already did the trig, just looking for a fast way to fill the screen up to the line.

fillTriangle() and fillRect() as hinted in post #5

Edit: If you want to make your code much smarter and hence quicker then it is quite easy to use the old and new angle coordinates to work out the minimum size of triangles (either 2, or 4 triangles where a corner transition occursl) that needs to be filled, this would boost the frame rate significantly for smaller/slower angle changes.
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 12, 2016, 01:52 am
tried your library, but for some reason your examples dont display anything on the screen?

You will need to edit the User_Setup.h file inside the library as stated in the ReadMe file to suit your pin settings and display variant ("TAB" colour)!

Edit: Forgot to mention the library is only compatible with AVR processors (UNO, Leonardo, Mega etc)
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 10:59 am
Im using Arduino Pro mini with Atmel 328P, is that compatible?
so i understand the only "fast" way to fill the screen is with fillTriangle() and fillRect() ?
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 11:14 am
You will need to edit the User_Setup.h file inside the library as stated in the ReadMe file to suit your pin settings and display variant ("TAB" colour)!

Edit: Forgot to mention the library is only compatible with AVR processors (UNO, Leonardo, Mega etc)
i edited the .h file with my correct pin numbers, and tried all 5 tab options - none of them seems to work. i get a white screen in all of them.

Title: Re: Artificial Horizon display using a gyro
Post by: david_prentice on Aug 12, 2016, 11:27 am
A Pro Mini should work fine.     The 3.3V version does not require any level shifting.

Paste your sketch in a CODE window or attach the file.    Are you just wanting a line that moves or a filled semi-circle that rotates?

You generally get the most responsive display if you just erase the old triangle and draw the new triangle.   Most changes are incremental.   i.e. a thin triangle.

Post a link to your actual display.   There are several 128x160 controllers.    I have a sketch that will diagnose which one you have.

David.
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 11:39 am
Here is my code which builds the backgorund image:
Code: [Select]


#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS     10
#define TFT_RST    9
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);
#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!

void setup(void)
{
  tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
  DrawAHI();
}

void loop()
{
// none
}



void DrawAHI() {
  // play
  tft.fillScreen(ST7735_BLACK);
  tft.fillRoundRect(0, 0, 130, 80, 0, ST7735_BLUE); // start point X, start pint Y, Length X, Length Y, corner radius
  tft.fillRoundRect(0, 83, 130, 80, 0, 0x79E0); // start point X, start pint Y, Length X, Length Y, corner radius
  tft.fillRoundRect(35, 50, 60, 60, 30, ST7735_WHITE);
  tft.fillRoundRect(40, 55, 50, 50, 25, ST7735_BLACK);
  tft.fillRoundRect(40, 80, 50, 3, 0, ST7735_RED);
  tft.fillRoundRect(63, 55, 3, 50, 0, ST7735_RED);
// side vertical lines
  tft.fillRoundRect(15, 30, 5, 100, 0, 0x7BEF);
  tft.fillRoundRect(110, 30, 5, 100, 0, 0x7BEF);

  tft.setCursor(2, 30);
  tft.setTextColor(ST7735_WHITE);
  tft.print("20");
  tft.setCursor(2, 120);
  tft.setTextColor(ST7735_WHITE);
  tft.print("20");
  tft.setCursor(2, 50);
  tft.setTextColor(ST7735_WHITE);
  tft.print("10");
  tft.setCursor(2, 100);
  tft.setTextColor(ST7735_WHITE);
  tft.print("10");
  tft.setCursor(115, 30);
  tft.setTextColor(ST7735_WHITE);
  tft.print("20");
  tft.setCursor(115, 120);
  tft.setTextColor(ST7735_WHITE);
  tft.print("20");
  tft.setCursor(115, 50);
  tft.setTextColor(ST7735_WHITE);
  tft.print("10");
  tft.setCursor(115, 100);
  tft.setTextColor(ST7735_WHITE);
  tft.print("10");

  tft.setCursor(10, 0);
  tft.setTextColor(ST7735_GREEN);
  tft.print("SPD  LNAV WNAV PTH");
 
  tft.setCursor(10, 150);
  tft.setTextColor(ST7735_GREEN);
  tft.print("Lior Z. AHI Display");
 
/*
 code color
 0x0000 Black
 0xFFFF White
 0xBDF7 Light Gray
 0x7BEF Dark Gray
 0xF800 Red
 0xFFE0 Yellow
 0xFBE0 Orange
 0x79E0 Brown
 0x7E0  Green
 0x7FF  Cyan
 0x1F Blue
 0xF81F Pink
 */

}


i would like the middle round to stay stationary, and the blue and brown background to move as AHI moves.

for now i will settle for automated movement, and can integrate actual gyro data later.

Even with my current sketch, if you move DrawAHI() to main loop, in order to refresh it, it is very slow to refresh, probably about 1hz and that looks bad as it blinks and fills the screen top to bottom.
so im looking for faster ways to do it.

see:
https://www.youtube.com/watch?v=EwzJB1GzdwY

Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 12, 2016, 12:29 pm
i edited the .h file with my correct pin numbers, and tried all 5 tab options - none of them seems to work. i get a white screen in all of them.


Just checked the library and it works fine with a Mini Pro. The only other gotcha I can think of (apart from not using hardware SPI pins and an edit error in User_Setup) is that you are using a really old and outdated version of the IDE. You need to use the latest 1.6.x IDE
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 01:02 pm
Just checked the library and it works fine with a Mini Pro. The only other gotcha I can think of (apart from not using hardware SPI pins and an edit error in User_Setup) is that you are using a really old and outdated version of the IDE. You need to use the latest 1.6.x IDE
im using the latest IDE version, perhaps you could run me through the connections? i cant find where the mistake is.
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 01:15 pm
i would like to end up with something similar to this:

https://www.youtube.com/watch?v=ta71EIkgIqo
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 01:28 pm
Just checked the library and it works fine with a Mini Pro. The only other gotcha I can think of (apart from not using hardware SPI pins and an edit error in User_Setup) is that you are using a really old and outdated version of the IDE. You need to use the latest 1.6.x IDE
managed to get library working, now could use a bit of help "translating" my code which uses the Adafruit Library, to yours :)
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 01:56 pm
bodmer, i changed my code to use your library but i still find it being slow.

here's what im trying to do and what happens:

1. fill the background with grpahics.
2. print a AH line on the existing filled screen at a certain angle.

now, in order to refresh (change line angle) i have to do:
3. fill the background with grpahics.
4. print a AH line on the existing filled screen at a certain (different) angle.

i guess the screen filling takes some time, because this causes a lot of flashing and delay in the screen.

any ideas how to do this quickly without the flashing and delays?
i did manage to print just the line, on a black ground, with a good refresh rate. but as soon as i add the background graphics, it all becomes slow.


Title: Re: Artificial Horizon display using a gyro
Post by: david_prentice on Aug 12, 2016, 02:13 pm
Thanks for the video.   A picture is worth a thousand words.
A moving picture is worth even more!

As far as I know,  the ST7735 can not display a separate foreground and background.
Which means that updating the display is going to need some intelligence.

Either by redrawing each object that contains the "new" triangle.
Or by reading the GRAM and replacing the CYAN or GRAY in the new triangles.    Reading GRAM with an AVR is relatively slow.

I can do it both ways but it is fiddly getting the graphics to match.
I will wait until Bodmer comes up with a better method.

David.
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 12, 2016, 02:18 pm
Thank you, this makes me believe im in the right direction.
i wonder how the guy in the  video did it.... perhaps he used a stronger processor.

so for now i can say i can actually do what i wanted, the only problem i have left is the (slow) speed it takes to fill up the screen with graphics.

Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 12, 2016, 09:56 pm
@i3dm

I have you example sketch running from post #13.  This runs at 8 frames per second (fps).

Most of the flicker comes from clearing the screen to black, then drawing the graphics.

It takes 46ms to clear the screen to black so since the TFT screen is internally refreshed at 70Hz you end up seeing it flashing. This time is determined by the 8MHz SPI rate. Because my library is highly optimised the Pro Mini ATMega 328 is actually managing to send bits at 7.12Mhz to clear the screen in that time, and it cannot go any faster without overclocking it.

There is not need to clear the screen to black since the new graphics image covers the whole screen anyway. Taking out the clear to black bring the frame rate to 13 fps (77ms to redraw the whole screen area with graphics) this shows that with some smart plotting code that you should be able to get the performance you want.

I am almost certain the "guy in the video" is using a processor which has more RAM, the image is being drawn to a "virtual" screen, then sent to the TFT in a burst so only the bits that have moved appear to changed. A 16 bit colour virtual screen would need 40Kbytes of RAM for a 160x128 display, so the Due or perhaps a Teensy could do this. The Due/Teensy can also DMA the virtual image to the display so the processor could be fetching the new Gyro values while the screen image is updateed.

Adafruit are moving towards this virtual screen in RAM approach (they call it a "canvas") which is a smart move as this is a method well suited to higher performance processors which will no doubt be adopted within the Arduino environment at some point in the future.

So to get the display flicker free on a humble Arduino like the Pro Mini is possible but you will need to either simplify the graphics you are plotting in the area that changes, or work out how to change just the tiny bits that need to change.

Alternatively you could use a screen that provides a co-processor to handle the graphics but then things get stupidly expensive compared to these nice little $3 displays.

Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 13, 2016, 11:09 pm
@i3dm

It dawned on me that I have an arc drawing function that can be used, this makes things much simpler.

So I have bashed together some demo code based on your sketch and have it running on an UNO with a circular horizon window.

It runs at 40 frames per second for 2 degree angle change increments, and about 50 frames per second for 1 degree angle changes which is not bad for a humble UNO!


Video here (https://youtu.be/d64MK43169s).

Let me know if this might suit your needs and I will tidy up the code.

Edit: Just done some more tests and it conveniently runs at 60 frames per second when the horizon is near to horizontal (this is because triangles are filled with horizontal line segments in the library).
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 14, 2016, 04:25 pm
Yes this could help very much, please post the code for testing, thank you.
PS - you also have an email from me.
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 14, 2016, 10:45 pm
Here's the "proof of concept" code. You will probably have trouble using it to draw arbitrary angles as there will be a tenancy to leaving small segments that are not correctly redrawn. This is due to rounding errors and a directional asymmetry in the arc drawing algorithm.

I will update the code to make it more suitable for your application and email you a copy.

Edit: There is no need to draw the four "20"'s during refresh, so these can be plotted during setup only. This saves a few milliseconds and then with 2 degree angle changes the UNO can update the screen at an impressive 70 frames per second.

Code: [Select]

// Demo code for artifical horizon display
// Written for a 160 x 128 TFT display

#include <SPI.h>

// Use ONE of these three libraries, comment out other two!

// For S6D02A1 based TFT displays
//#include <TFT_S6D02A1.h>         // Bodmer's graphics and font library for S6D02A1 driver chip
//TFT_S6D02A1 tft = TFT_S6D02A1(); // Invoke library, pins defined in User_Setup.h
//                                    https://github.com/Bodmer/TFT_S6D02A1

// For ST7735 based TFT displays
#include <TFT_ST7735.h>          // Bodmer's graphics and font library for ST7735 driver chip
TFT_ST7735 tft = TFT_ST7735();   // Invoke library, pins defined in User_Setup.h
//                                    https://github.com/Bodmer/TFT_ST7735

// For ILI9341 based TFT displays (note sketch is currently setup for a 160 x 128 display)
//#include <TFT_ILI9341.h>         // Bodmer's graphics and font library for ILI9341 driver chip
//TFT_ILI9341 tft = TFT_ILI9341(); // Invoke library, pins defined in User_Setup.h
//                                    https://github.com/Bodmer/TFT_ILI9341

#define REDRAW_DELAY 17 // minimum delay in milliseconds between display updates

#define HOR 63      // Horizon circle outside radius
#define HIR 24      // Horizon circle inside radius
#define HAW HOR-HIR // Horizon arc width (outside - inside radius)

#define BROWN 0x5140 //0x5960
#define SKY_BLUE   0x02B5 //0x0318 //0x039B //0x34BF
#define DARK_RED   0x8000
#define DARK_GREY  0x39C7

#define XC 64 // x coord of centre of horizon
#define YC 80 // y coord of centre of horizon

#define ANGLE_INC 2 // Angle increment for arc segments

#define DEG2RAD 0.0174532925

int roll_angle = 0;
int roll_delta = 90;

int demo_delta = ANGLE_INC;

unsigned long redrawTime = 0;


// #########################################################################
// Setup, runs once on boot up
// #########################################################################

void setup(void) {
  Serial.begin(115200);

  tft.begin();
  tft.setRotation(0);

  tft.fillScreen(TFT_BLACK);

  // Centre graphics
  // Draw the inner white arc (360 degrees = a circle)
  fillArc(XC, YC, 0, 360 / ANGLE_INC, HIR, HIR, 2, DARK_GREY);

  // Draw the red cross-hairs
  tft.fillRect(XC - 21, YC -  1, 42,  3, DARK_RED);
  tft.fillRect(XC -  1, YC - 21,  3, 42, DARK_RED);

  // Draw the two 180 degree arc segments for sky and ground
  fillArc(XC, YC, -90, 180 / ANGLE_INC, HOR, HOR, HAW, SKY_BLUE);
  fillArc(XC, YC,  90, 180 / ANGLE_INC, HOR, HOR, HAW, BROWN);

  // Draw fixed text
  tft.setTextColor(TFT_GREEN);
  tft.setCursor(10, 0);
  tft.print("SPD  LNAV WNAV PTH");
  tft.setCursor(10, 150);
  tft.print("Lior Z. AHI Display");
}

// #########################################################################
// Main loop, keeps looping around
// #########################################################################

void loop() {

  // Refresh the display at regular intervals
  if (millis() > redrawTime) {
    redrawTime = millis() + REDRAW_DELAY;

    unsigned long drawTime = millis(); // Test only

    // Change to ramp down the horizon angle for the demo and swap the colours for the direction change
    if (roll_angle > (360 - ANGLE_INC)) {
      demo_delta = -ANGLE_INC;
      roll_delta = -90;     // roll_delta is -90 for anticlockwise rotation
      //delay(500);
    }

    // Change to ramp up the horizon angle for the demo and swap the colours for the direction change
    if (roll_angle < ANGLE_INC) {
      demo_delta = ANGLE_INC;
      roll_delta = 90;     // roll_delta is +90 for clockwise rotation
      //delay(500);
    }

    // Draw the new parts of the two arc segments 180 degrees apart
    // If roll_angle is zero = horizontal
    fillArc(XC, YC, roll_angle + roll_delta, 1, HOR, HOR, HAW, SKY_BLUE);
    fillArc(XC, YC, roll_angle - roll_delta, 1, HOR, HOR, HAW, BROWN);

 
    drawInfo();

    // This is for the demo to produce an angle that changes
    roll_angle += demo_delta;
 
    //if (roll_angle == 90) delay(1000);

    if (millis() - drawTime > REDRAW_DELAY) Serial.println(millis() - drawTime); // Test only to see how long an update takes

    //delay(500);
  }
}


// #########################################################################
// Draw a circular or elliptical arc with a defined thickness
// #########################################################################

// x,y == coords of centre of arc
// start_angle = 0 - 359
// seg_count = number of 6 degree segments to draw (60 => 360 degree arc)
// rx = x axis outer radius
// ry = y axis outer radius
// w  = width (thickness) of arc in pixels
// colour = 16 bit colour value
// Note if rx and ry are the same then an arc of a circle is drawn

int fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour)
{
  // Fudge factor adjustment for this sketch (so horizon is horizontal when start anngle is 0)
  start_angle--;
 
  byte seg = ANGLE_INC; // Segments are INC degrees wide
  byte inc = ANGLE_INC; // Draw segments every INC degrees, increase for segmented ring

  // Calculate first pair of coordinates for segment start
  float sx = cos((start_angle - 90) * DEG2RAD);
  float sy = sin((start_angle - 90) * DEG2RAD);
  uint16_t x0 = sx * (rx - w) + x;
  uint16_t y0 = sy * (ry - w) + y;
  uint16_t x1 = sx * rx + x;
  uint16_t y1 = sy * ry + y;

  // Draw colour trapezoids every inc degrees
  for (int i = start_angle; i < start_angle + seg * seg_count; i += inc) {

    // Calculate pair of coordinates for segment end
    float sx2 = cos((i + seg - 90) * DEG2RAD);
    float sy2 = sin((i + seg - 90) * DEG2RAD);
    int x2 = sx2 * (rx - w) + x;
    int y2 = sy2 * (ry - w) + y;
    int x3 = sx2 * rx + x;
    int y3 = sy2 * ry + y;

    tft.fillTriangle(x0, y0, x1, y1, x2, y2, colour);
    tft.fillTriangle(x1, y1, x2, y2, x3, y3, colour);

    // Copy segment end to sgement start for next segment
    x0 = x2;
    y0 = y2;
    x1 = x3;
    y1 = y3;
  }
}


// #########################################################################
// Draw the information
// #########################################################################

void drawInfo(void)
{
  // side vertical lines
  tft.fillRect( 15, 30, 5, 100, DARK_GREY);
  tft.fillRect(108, 30, 5, 100, DARK_GREY);

  tft.setTextColor(TFT_WHITE);
  tft.setCursor(2, 30);
  tft.print("20");
  tft.setCursor(2, 122);
  tft.print("20");
  tft.setCursor(2, 50);
  tft.print("10");
  tft.setCursor(2, 102);
  tft.print("10");
  tft.setCursor(115, 30);
  tft.print("20");
  tft.setCursor(115, 122);
  tft.print("20");
  tft.setCursor(115, 50);
  tft.print("10");
  tft.setCursor(115, 102);
  tft.print("10");


}

Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 16, 2016, 12:01 am
New code, new method of drawing. This one gives a full screen display with new graphic design and pitch as well as roll.

Performance is pretty good with a humble UNO and the display is virtually flicker free (video looks worse than it is due to frame rate aliasing with the camera).

Video here. (https://www.youtube.com/watch?v=uzmPFqYQigQ)

Sketch attached.
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 16, 2016, 11:13 pm
New code, new method of drawing. This one gives a full screen display with new graphic design and pitch as well as roll.

Performance is pretty good with a humble UNO and the display is virtually flicker free (video looks worse than it is due to frame rate aliasing with the camera).

Video here. (https://www.youtube.com/watch?v=uzmPFqYQigQ)

Sketch attached.
youre the best bodmer - this works amazing.
i still need to see why my display flickers a bit and i should be good to go :)
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 17, 2016, 02:06 am
@i3dm

The demo in post #25 only works over the roll range  +/-50 degrees, after that some plotting artifacts are left on the screen.

Attached is the latest that handles +/- 180 degree rolls.  Pitch is specified in pixels, the 10 degree marker line is 20 pixels from the centre, so you have to convert pitch angle to pixels.

This is the last version I will be producing in the near future! It works better than I expected so it will be added as an example to my libraries.


The flickering you are getting is due to brightness changes caused by power line fluctuations, not the graphics drawing.  Power the display from 5V, use 1K series resistors and 2K2 to GND resistor dividers on the logic lines to avoid pumping current into the display.

E.g. Arduino digital pin 13 through a 1K resistor to display SCL, add a 2K2 resistor from display SCL to GND.

Do this for RESET, AO, CS and SDA
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 19, 2016, 09:45 am
Thank you for everything Bodmer, you the man!
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 19, 2016, 10:25 am
About the voltage divider, if i want to get 3.3V at the logic lines when arduino is suplying 5V, then the series resistor should be the 2.2k and 1k to ground.
that gices about 3.4v on logic line to LCD.
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 19, 2016, 01:33 pm
About the voltage divider, if i want to get 3.3V at the logic lines when arduino is suplying 5V, then the series resistor should be the 2.2k and 1k to ground.
that gices about 3.4v on logic line to LCD.

No, 1K and 2.2K" to ground.

5*(2.2/(2.2+1))=3.43V which will be fine and is thing the 3.3V +/-0.3V limit for the driver inputs
Title: Re: Artificial Horizon display using a gyro
Post by: i3dm on Aug 19, 2016, 01:59 pm
Meant to do it like this:
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Aug 19, 2016, 07:50 pm
Meant to do it like this:

Yes, that is right  :)
Title: Re: Artificial Horizon display using a gyro
Post by: Leonardoxms on Sep 22, 2016, 11:05 pm
Hello guys. I'm trying to make it work with the  ST7735 controller displays.  But I'm getting lots of unwanted pixels on screen as the roll and pitch does its thing.  Any sugestions?
 
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Sep 23, 2016, 01:09 am
@Leonardoxms

Are you using the sketch attached to post #27?

What changes have you made?

Are you using this graphics library (https://github.com/Bodmer/TFT_ST7735)?

If so, do all the other example sketches work OK?

Which Arduino are you using?

How have you wired the display to your Arduino?
Title: Re: Artificial Horizon display using a gyro
Post by: Leonardoxms on Sep 23, 2016, 02:09 pm
Hello.  I´m using arduino pro mini.  I din´t make any changes to the code.  I´m also using the sketch and LIB you suggeted.

I´ve wired this way:

 sclk -13
 mosi -11 
 cs -  9
 dc - 8
 rst - 7 

The display module that I´m using is this one:

http://forum.arduino.cc/index.php?topic=125034.0

thanks
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Sep 23, 2016, 02:26 pm
Run the sketch here (http://forum.arduino.cc/index.php?topic=406501.msg2923815#msg2923815).

What does it report?

What voltage are you running the pro mini on?

Have you used series resistors in the data/control lines?
Title: Re: Artificial Horizon display using a gyro
Post by: Leonardoxms on Sep 23, 2016, 03:30 pm
Report:

TFT driver register values:
===========================
Register 0x01: 0x00
Register 0x04: 0x7C89F0
Register 0x09: 0x610000
Register 0x0A: 0x08
Register 0x0B: 0x00
Register 0x0C: 0x06
Register 0x0D: 0x00
Register 0x0E: 0x00
Register 0x0F: 0x00
Register 0x2E: 0x281400
Register 0xDA: 0x7C
Register 0xDB: 0x89
Register 0xDC: 0xF0
===========================

Looks like driver chip is: ST7735 (empirical value)

I´m running on 5V and I didn´t use resistors in the data/control lines.

Title: Re: Artificial Horizon display using a gyro
Post by: Leonardoxms on Sep 23, 2016, 04:12 pm
https://drive.google.com/file/d/0BzKrt8UWkNbRZFJqQlVKQ21GTlk/view?usp=sharing


In the link above, you can see the problem I´m having.

Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Sep 24, 2016, 12:32 am
The display driver is not 5V tolerant. Put series resistors in the control and data lines as follows:


pro mini digital pin 7 through a 1K2 resistor to display RST
pro mini digital pin 8 through a 1K2 resistor to display DC
pro mini digital pin 9 through a 1K2 resistor to display CS
pro mini digital pin 11 through a 1K2 resistor to display MOSI
pro mini digital pin 13 through a 1K2 resistor to display SCLK
Title: Re: Artificial Horizon display using a gyro
Post by: Leonardoxms on Sep 24, 2016, 04:22 am
Did all that.  Still presenting the same symptoms.   Any other suggestions?   
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Sep 24, 2016, 11:13 pm
Which version of the Arduino IDE are you using?

Do other example sketches that come with the library work OK?

One problem is that your display shows random pixels on two edges, this is indicative of the wrong setup.  Try different TAB_COLOUR options in User_Setup.h and find which one gets rid of those bad edge pixels. Edit the file, save, recompile and upload the sketch to try each option.
Title: Re: Artificial Horizon display using a gyro
Post by: imolodkin on Oct 22, 2016, 09:41 pm
@Leonardoxms

Are you using the sketch attached to post #27?

What changes have you made?

Are you using this graphics library (https://github.com/Bodmer/TFT_ST7735)?

If so, do all the other example sketches work OK?

Which Arduino are you using?

How have you wired the display to your Arduino?
Hi!

I use your sketch from post #27 on Uno with ILI9341 2.8'' 320x240 and have  a similar problem with unwanted pixels. I have successfully changed resolution and orientation in the code, already tried different settings in User_Setup to get rid of them. Graphics test sketch running fine. Adafruit library render good image without any troubles, but really slow.

I hope you could help me. Thanks in advance!
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Oct 30, 2016, 12:39 pm
@imolodkin

The redraw technique used works best on small displays but if you make the following changes to the post #27 sketch then it should fix your missing pixels.  If it does not then post your sketch so I can run it and see what changes you have made.


Near the start of sketch change the line as follows:

Code: [Select]
#define HOR 400    // Horizon vector line length ### was 172


Then use this adapted drawHorizon() function:

Code: [Select]
// #########################################################################
// Draw the horizon with a new roll (angle in range -180 to +180)
// #########################################################################

void drawHorizon(int roll, int pitch)
{
  // Calculate coordinates for line start
  float sx = cos(roll * DEG2RAD);
  float sy = sin(roll * DEG2RAD);

  int16_t x0 = sx * HOR;
  int16_t y0 = sy * HOR;
  int16_t xd = 0;
  int16_t yd = 1;
  int16_t xdn  = 0;
  int16_t ydn = 0;

  if (roll > 45 && roll <  135) {
    xd = -1;
    yd =  0;
  }
  if (roll >=  135)             {
    xd =  0;
    yd = -1;
  }
  if (roll < -45 && roll > -135) {
    xd =  1;
    yd =  0;
  }
  if (roll <= -135)             {
    xd =  0;
    yd = -1;
  }

  if ((roll != last_roll) || (pitch != last_pitch))
  {
    xdn = 6 * xd;
    ydn = 6 * yd;
    tft.drawLine(XC - x0 - xdn, YC - y0 - ydn - pitch, XC + x0 - xdn, YC + y0 - ydn - pitch, SKY_BLUE);
    tft.drawLine(XC - x0 + xdn, YC - y0 + ydn - pitch, XC + x0 + xdn, YC + y0 + ydn - pitch, BROWN);
    xdn = 5 * xd;
    ydn = 5 * yd;
    tft.drawLine(XC - x0 - xdn, YC - y0 - ydn - pitch, XC + x0 - xdn, YC + y0 - ydn - pitch, SKY_BLUE);
    tft.drawLine(XC - x0 + xdn, YC - y0 + ydn - pitch, XC + x0 + xdn, YC + y0 + ydn - pitch, BROWN);
    xdn = 4 * xd;
    ydn = 4 * yd;
    tft.drawLine(XC - x0 - xdn, YC - y0 - ydn - pitch, XC + x0 - xdn, YC + y0 - ydn - pitch, SKY_BLUE);
    tft.drawLine(XC - x0 + xdn, YC - y0 + ydn - pitch, XC + x0 + xdn, YC + y0 + ydn - pitch, BROWN);
   
    xdn = 3 * xd;
    ydn = 3 * yd;
    tft.drawLine(XC - x0 - xdn, YC - y0 - ydn - pitch, XC + x0 - xdn, YC + y0 - ydn - pitch, SKY_BLUE);
    tft.drawLine(XC - x0 + xdn, YC - y0 + ydn - pitch, XC + x0 + xdn, YC + y0 + ydn - pitch, BROWN);
  }
  xdn = 2 * xd;
  ydn = 2 * yd;
  tft.drawLine(XC - x0 - xdn, YC - y0 - ydn - pitch, XC + x0 - xdn, YC + y0 - ydn - pitch, SKY_BLUE);
  tft.drawLine(XC - x0 + xdn, YC - y0 + ydn - pitch, XC + x0 + xdn, YC + y0 + ydn - pitch, BROWN);

  tft.drawLine(XC - x0 - xd, YC - y0 - yd - pitch, XC + x0 - xd, YC + y0 - yd - pitch, SKY_BLUE);
  tft.drawLine(XC - x0 + xd, YC - y0 + yd - pitch, XC + x0 + xd, YC + y0 + yd - pitch, BROWN);

  tft.drawLine(XC - x0, YC - y0 - pitch,   XC + x0, YC + y0 - pitch,   TFT_WHITE);

  last_roll = roll;
  last_pitch = pitch;

}


Since the larger display has ~ 4x the number of pixels to draw I would expect the code to run 4x slower than for a 160 x 128 display and thus the text/numbers will flicker when it is redrawn.
Title: Re: Artificial Horizon display using a gyro
Post by: imolodkin on Nov 01, 2016, 06:21 pm
Your patch works perfectly, thank you!!!!!! Speed is acceptable, no flickering.
But there are still random artifacts on the left and top sides.  They were before my changes too, but only with this library. Do you have any suggestions?
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Nov 03, 2016, 01:57 pm
@imolodkin

Post a copy of your sketch so I can run it and see what is happening.
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Nov 03, 2016, 04:32 pm
@imolodkin

Missing pixels in lines is a problem encountered with the new 1.6.12 IDE,  I have updated the ILI9341 library on Github (https://github.com/Bodmer/TFT_ILI9341) to correct this.
Title: Re: Artificial Horizon display using a gyro
Post by: imolodkin on Nov 14, 2016, 11:07 am
@bodmer

I'm really sorry for the delay, didn't get any forum notifications.

I've updated the library and now it works great! Thank you so much for your support!
Title: Re: Artificial Horizon display using a gyro
Post by: Ratlos on Dec 14, 2016, 08:52 pm
Hello
i test Demo
Quote
// Demo code for artifical horizon display
// Written by Bodmer for a 160 x 128 TFT display
// 15/8/16   https://github.com/Bodmer/TFT_ST7735

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define TFT_CS     10
#define TFT_RST    9
#define TFT_DC     8
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);
#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!

// #include <SPI.h>
// Use ONE of these three highly optimised libraries, comment out other two!
// For S6D02A1 based TFT displays
// #include <TFT_S6D02A1.h>         // Bodmer's graphics and font library for S6D02A1 driver chip
// TFT_S6D02A1 tft = TFT_S6D02A1(); // Invoke library, pins defined in User_Setup.h
//                                    https://github.com/Bodmer/TFT_S6D02A1
// For ST7735 based TFT displays
// #include <TFT_ST7735.h>          // Bodmer's graphics and font library for ST7735 driver chip
// TFT_ST7735 tft = TFT_ST7735();   // Invoke library, pins defined in User_Setup.h
//                                    https://github.com/Bodmer/TFT_ST7735

// For ILI9341 based TFT displays (note sketch is currently setup for a 160 x 128 display)
//#include <TFT_ILI9341.h>         // Bodmer's graphics and font library for ILI9341 driver chip
//TFT_ILI9341 tft = TFT_ILI9341(); // Invoke library, pins defined in User_Setup.h
//                                    https://github.com/Bodmer/TFT_ILI9341
Arduino Version 1.6.12

by Test

Quote
C:\Users\Heli\Desktop\Demo_artificial_horizon_7\Demo_artificial_horizon_9.ino:10:95: fatal error: TFT_S6D02A1.h: No such file or directory

 #include <TFT_S6D02A1.h>         // Bodmer's graphics and font library for S6D02A1 driver chip

                                                                                               ^

compilation terminated.

exit status 1
Fehler beim Kompilieren für das Board Arduino/Genuino Uno.
I am a beginner
And look for the error.
For many days

Thanks for any help
Title: Re: Artificial Horizon display using a gyro
Post by: ad2049q on Dec 14, 2016, 09:19 pm
Trying to think of things which could slow down a lot of writes to an LCD, I see that you have quite a few pins in use, but ?no? mention of pullup resistors.  Does the screen or adafruit recommend anything ? 
Your code looks as though it is going to presume 30k pullup built in, which might require comms to go slower than their best or be less reliable than ideal, especially if you have more than 6 inches of cabling from microcontroller to display.  Various opinions abound about adding external pullup resistors from a digital pin to arduino Vcc, but I found 10kOhm or 3.3kOhm more likely to work than none at all and necessary when using a few feet of cables.
Title: Re: Artificial Horizon display using a gyro
Post by: Ratlos on Dec 17, 2016, 12:06 am
Hello,
Was a copy error.
There was wrong data in the file.
For whatever reason.
Thanks
Title: Re: Artificial Horizon display using a gyro
Post by: Ratlos on Dec 19, 2016, 12:58 am
Hello,
hm work only with Arduino Duo
i have Arduino Due  ;o(
But it is fine
thx
Ratlos
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Mar 08, 2017, 01:42 am
@olf5

As you are a beginner I would start by creating a simpler sketch! For example just draw a line though the centre of the screen at an angle that is output by the sensor.  You will need to store the end coordinates of the last drawn line so you can erase it by over-writing with background before drawing the new line.
Title: Re: Artificial Horizon display using a gyro
Post by: paddesky on Jul 24, 2017, 07:41 pm
Hi there ...
Does anyone here?
I want to run this code for horizon indicator, any other updates?
Hey guys, is this topic active?
Title: Re: Artificial Horizon display using a gyro
Post by: DrWino on May 16, 2018, 11:53 pm
Hello Bodmer:

I have been using your TFT eSPI library with a M5stack ESP32 320x240. Works quite well ! I was wondering - why not make a artificial horizon indicator using the sprites. The pitch scale and sky+earth image would be replotted as a sprite with the wings symbol static (along with other features). What do you think ?
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on May 17, 2018, 10:02 am
@DrWino

I did try this and it works. I will tidy up the sketch and include it as an example. I also created a simple animated compass with moving needle and dial which I might add.
Title: Re: Artificial Horizon display using a gyro
Post by: DrWino on May 17, 2018, 01:27 pm
Very good. Can you send me the example ? Does not matter if it is not too finished - it will a good exercise to figure out how you did this ! Thanks.
Title: Re: Artificial Horizon display using a gyro
Post by: Javierdc on May 21, 2018, 05:24 am
Hello BOdmer! I am using the ILI9341_due Library and the same solved problem on  post #46 appears again. Can you help me? Som missed pixels in the border of moving Indicator.

Tahnks!
Title: Re: Artificial Horizon display using a gyro
Post by: caiopoit on Jun 05, 2018, 03:03 pm
Would this code be hard to convert to be used on a higher resolution display (in order to show some other values out of the AH) and with a STM32 board?
Title: Re: Artificial Horizon display using a gyro
Post by: DrWino on Jun 14, 2018, 12:52 pm
Hello Bodmer. Any chance of getting the sprite example. Confused about how the sprite programming works. Thanks
Title: Re: Artificial Horizon display using a gyro
Post by: tlankford01 on Oct 15, 2018, 03:45 am
@DrWino

I did try this and it works. I will tidy up the sketch and include it as an example. I also created a simple animated compass with moving needle and dial which I might add.
I am curious if you could provide examples to the hardware and sketch.  Is there a hardware design online to the display and the wiring?  Thank you in advance.
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Oct 15, 2018, 02:19 pm
Ah, I forgot about that post.  I will search out the sketches and upload it within the next 24 hours.
Title: Re: Artificial Horizon display using a gyro
Post by: bodmer on Oct 16, 2018, 02:14 am
Here's the compass demo, draws the compass in a Sprite then plots it to screen. Demo shows compass continuously rotating.  Not sure where I put the artificial horizon demo... but I will find it.

Runs on ESP8266 or ESP32 with TFT_eSPI library.

Title: Re: Artificial Horizon display using a gyro
Post by: BIONICSIX75 on Sep 06, 2019, 05:34 am
Hi bodmer
I am happy to have you.
I want to make on RC SCALE HELI
I did a lot of web search.
Then I found your post
I'm with UNO and ST7735 TFT
Successful upload of demo file.
It's so cool
My videos https://youtu.be/cmZKbdqm7wg
Is there any ST-7789 library?
I want to apply it to ST7768 IPS TFT.
And I do not know how to work with the Gyro MP-6050.
Please let me know if there is a solution.