Go Down

Topic: Artificial Horizon display using a gyro (Read 9142 times) previous topic - next topic

i3dm

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.



i3dm

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.



i3dm

Thank you for the link - is that your own code?

CrossRoads

"Published on Dec 3, 2015"
Too bad you can't get that code.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

bodmer

#5
Aug 11, 2016, 10:18 pm Last Edit: Aug 11, 2016, 10:22 pm by bodmer
...

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 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.
Formerly Rowboteer (now a broken user profile!)

i3dm

i already did the trig, just looking for a fast way to fill the screen up to the line.

i3dm

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 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?

bodmer

#8
Aug 12, 2016, 01:50 am Last Edit: Aug 12, 2016, 02:23 am by bodmer
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.
Formerly Rowboteer (now a broken user profile!)

bodmer

#9
Aug 12, 2016, 01:52 am Last Edit: Aug 12, 2016, 02:14 am by bodmer
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)
Formerly Rowboteer (now a broken user profile!)

i3dm

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() ?

i3dm

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.


david_prentice

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.

i3dm

#13
Aug 12, 2016, 11:39 am Last Edit: Aug 12, 2016, 11:45 am by i3dm
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


bodmer

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
Formerly Rowboteer (now a broken user profile!)

Go Up