Teensy4.0 ST7735 Freezing when using frame buffer.

Status
Not open for further replies.
Hi all,

I'm trying to make an aircraft attitude indicator with the classic 1.8 inch tft and a mpu6050. I had a break from the project after getting some really promesing results. Recently I carried on with the project but the code im sure was working before now freezes at around 27 degrees angle of bank and the led turns off. between these time so got a new pc so re doenloaded arduino and teensyduino. If i turn framebuffer off it works okay but is flickery as hell as expected. Any ideas what could be happening? I ran a previous version of my code that is more basic and this works okay. Its just the roll that breaks it, if i keep the roll centered i can pitch all day long.

Code:
//#define TFT_MISO  12
#define TFT_MOSI  11  //a12
#define TFT_SCK   13  //a13
#define TFT_DC   9 
#define TFT_CS   10  
#define TFT_RST  8

#define ST7735_BROWN 0x9A60

#define PlaneSquareL 61
#define PlaneSquareR 67
#define PlaneSquareT 77
#define PlaneSquareB 83

#define PlaneWingLeft 16
#define PlaneWingRight 112
#define PlaneWingWidth 30

#define TenWidth 40
#define FiveWidth 15
#define TwoPFiveWidth 8

#define HWF 102

int16_t Colour1, Colour2;

#include <ST7735_t3.h>
#include <SPI.h>
#include <Wire.h>

ST7735_t3 tft = ST7735_t3(TFT_CS, TFT_DC, TFT_RST);

float Pitch, Roll, Yaw;

int centerY, centerX;
int TestX1, TestY1, TestX2, TestY2;
double gradient;
int intercept, xintercept;
int RightIntercept, RightIntercept2;

void setup() {
  Wire.begin(); // initate connection to the MPU
  Wire.setClock(400000);
  tft.initR(INITR_BLACKTAB);
  SetupIMU();
  tft.useFrameBuffer(true); //use the frame buffer to prevent flickeing
  tft.fillScreen(ST7735_BLACK);
}

void loop() {
  UpdateIMU(); // get the pitch, roll and yaw values

  //fill background colour (brown when upright)
  tft.fillScreen(Colour1);

  //pitch sensitivity
  Pitch = Pitch * 4;

  //calculate the center point of the horizon line
  centerY = Pitch * cos(Roll * 0.0174533) + 80;
  centerX = 65 - (Pitch * sin(Roll * 0.0174533));

  //calculate the left and right points
  TestX1 = centerX - (HWF * cos(Roll * 0.0174533));
  TestY1 = centerY  - (HWF * sin(Roll * 0.0174533));
  TestX2 = centerX + (HWF * cos(Roll * 0.0174533));
  TestY2 = centerY  + (HWF * sin(Roll * 0.0174533));

  //if we are upside down switch the colours
  if(Roll < -90 || Roll > 90){Colour1 = ST7735_BLUE; Colour2 = ST7735_BROWN;}
  else{Colour2 = ST7735_BLUE; Colour1 = ST7735_BROWN;}

  //calculate the gradient of the horizon
  gradient = (double)(TestY2 - TestY1)/(double)(TestX2 - TestX1);

  //calculate the left hand intercept of the horizon
  intercept = TestY1 - (gradient * TestX1);
  xintercept = -intercept / gradient;
  if(xintercept < 0 || xintercept > 128){xintercept = 0;}

  //cqalculate the right intercept of teh horizon
  RightIntercept = gradient * 128 + intercept;  

  //fill the background colour
  if(RightIntercept > 0){tft.fillTriangle(xintercept,0,128,0,128,RightIntercept,Colour2);}
  if(xintercept == 0){xintercept = 128;}
  if(RightIntercept < 0){RightIntercept2 = 0;}
  else{RightIntercept2 = RightIntercept;}
  if(intercept > 0){tft.fillTriangle(0,intercept,0,0,xintercept,RightIntercept2,Colour2);}

  //draw the horizon
  tft.drawLine(0,intercept,128,RightIntercept,ST7735_WHITE); // Draw The horizon

  //draw the 2.5 degree lines
  for(int i = 10; i < 100; i += 10)
  {
    if(i % 20 != 0)
    {
      int center2P5X = centerX - (i * sin(Roll * 0.0174533));
      int center2P5Y = centerY + (i * cos(Roll * 0.0174533));
      tft.drawLine(center2P5X - (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  + (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),center2P5X + (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  - (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
      center2P5X = centerX + (i * sin(Roll * 0.0174533));
      center2P5Y = centerY - (i * cos(Roll * 0.0174533));
      tft.drawLine(center2P5X - (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  + (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),center2P5X + (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  - (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
    }
  }

  
  //draw the 5 degree lines
  for(int i = 20; i < 160; i += 20)
  {
    if(i % 40 != 0)
    {
      int center5X = centerX - (i * sin(Roll * 0.0174533));
      int center5Y = centerY + (i * cos(Roll * 0.0174533));
      tft.drawLine(center5X - (20 * sin((Roll + 90) * 0.0174533)),center5Y  + (20 * cos((Roll + 90) * 0.0174533)),center5X + (20 * sin((Roll + 90) * 0.0174533)),center5Y  - (20 * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
      center5X = centerX + (i * sin(Roll * 0.0174533));
      center5Y = centerY - (i * cos(Roll * 0.0174533));
      tft.drawLine(center5X - (20 * sin((Roll + 90) * 0.0174533)),center5Y  + (20 * cos((Roll + 90) * 0.0174533)),center5X + (20 * sin((Roll + 90) * 0.0174533)),center5Y  - (20 * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
    }
  }
  
  //draw the 10 degree lines
  for(int i = 40; i < 280; i += 40)
  {
    int center10X = centerX - (i * sin(Roll * 0.0174533));
    int center10Y = centerY + (i * cos(Roll * 0.0174533));
    tft.drawLine(center10X - (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  + (TenWidth * cos((Roll + 90) * 0.0174533)),center10X + (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  - (TenWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
    center10X = centerX + (i * sin(Roll * 0.0174533));
    center10Y = centerY - (i * cos(Roll * 0.0174533));
    tft.drawLine(center10X - (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  + (TenWidth * cos((Roll + 90) * 0.0174533)),center10X + (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  - (TenWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
  }

  DrawPlaneCursor();  
 
  tft.updateScreen();

}

void DrawPlaneCursor(){
  int PlaneWingRightOffset = PlaneWingLeft + PlaneWingWidth;
  int IndicatorThickness = PlaneSquareB - PlaneSquareT;
  int PlaneSquareWidth = PlaneSquareR - PlaneSquareL;
  
  //draw the center square
  tft.drawFastHLine(PlaneSquareL, PlaneSquareT, PlaneSquareWidth, ST7735_WHITE);
  tft.drawFastHLine(PlaneSquareL, PlaneSquareB - 1, PlaneSquareWidth, ST7735_WHITE);
  tft.drawFastVLine(PlaneSquareL, PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.drawFastVLine(PlaneSquareR - 1, PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.fillRect(PlaneSquareL +1,PlaneSquareT + 1, PlaneSquareWidth -2,IndicatorThickness -2,ST7735_BLACK);

  //draw the left wing    
  tft.fillRect(PlaneWingLeft + 1,PlaneSquareT + 1,PlaneWingWidth,IndicatorThickness - 2,ST7735_BLACK);
  tft.fillRect(PlaneWingRightOffset - PlaneSquareWidth + 3,PlaneSquareB - 1,IndicatorThickness - 2,IndicatorThickness - 2,ST7735_BLACK);
  tft.drawFastHLine(PlaneWingLeft,PlaneSquareT,PlaneWingWidth + 1,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingLeft,PlaneSquareT + 1,IndicatorThickness -1,ST7735_WHITE);
  tft.drawFastHLine(PlaneWingLeft,PlaneSquareT + IndicatorThickness - 1,PlaneWingWidth - PlaneSquareWidth + 2,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingLeft + PlaneWingWidth,PlaneSquareT,2*(IndicatorThickness) - 3,ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRightOffset - PlaneSquareWidth + 2,PlaneSquareB + IndicatorThickness - 4,PlaneSquareR-PlaneSquareL - 2,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRightOffset - PlaneSquareWidth + 1,PlaneSquareB - 1, IndicatorThickness - 2, ST7735_WHITE);

  //draw the right wing
  tft.fillRect(PlaneWingRight - PlaneWingWidth + 1,PlaneSquareT  + 1, PlaneWingWidth - 1,IndicatorThickness - 2, ST7735_BLACK);
  tft.fillRect(PlaneWingRight - PlaneWingWidth + 1,PlaneSquareB - 1,IndicatorThickness - 2,IndicatorThickness - 2,ST7735_BLACK);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth,PlaneSquareT,PlaneWingWidth,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - 1,PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth + PlaneSquareWidth - 1,PlaneSquareT + IndicatorThickness - 1,PlaneWingWidth - PlaneSquareWidth + 1, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - PlaneWingWidth + PlaneSquareWidth - 1,PlaneSquareT + IndicatorThickness,IndicatorThickness - 3,ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth,PlaneSquareT + 2*IndicatorThickness - 3,PlaneSquareWidth,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - PlaneWingWidth, PlaneSquareT + 1, IndicatorThickness*2 - 4,ST7735_WHITE);

}
 
Sorry, I have not had much of a chance to look through this code.

I did try to compile it and it fails as it is missing probably some header files or the like that define: setupIMU() and UpdateIMU();

I am guessing maybe other file(s), where these are defined?
 
Sorry, I have not had much of a chance to look through this code.

I did try to compile it and it fails as it is missing probably some header files or the like that define: setupIMU() and UpdateIMU();

I am guessing maybe other file(s), where these are defined?

Thanks for the comment Kurt! You are correct, there is the GyroCompute file. Im using the i2c dev mpu6050 lib. Code given below!

Code:
#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"


MPU6050 mpu;

#define OUTPUT_READABLE_YAWPITCHROLL


#define INTERRUPT_PIN 7  // use pin 2 on Arduino Uno & most boards

bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector


// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}

void SetupIMU()
{
    mpu.initialize();
    pinMode(INTERRUPT_PIN, INPUT);

    // verify connection
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

    // wait for ready
    Serial.println(F("\nSend any character to begin DMP programming and demo: "));
    //while (Serial.available() && Serial.read()); // empty buffer
    //while (!Serial.available());                 // wait for data
    //while (Serial.available() && Serial.read()); // empty buffer again

    // load and configure the DMP
    //Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

    // supply your own gyro offsets here, scaled for min sensitivity
    mpu.setXGyroOffset(-24);
    mpu.setYGyroOffset(79);
    mpu.setZGyroOffset(6);
    mpu.setXAccelOffset(66);
    mpu.setYAccelOffset(1159);
    mpu.setZAccelOffset(1742); // 1688 factory default for my test chip

    // make sure it worked (returns 0 if so)
    if (devStatus == 0) {
        // Calibration Time: generate offsets and calibrate our MPU6050
        //mpu.CalibrateAccel(6);
        //mpu.CalibrateGyro(6);
        //mpu.PrintActiveOffsets();
        //delay(10000);
        // turn on the DMP, now that it's ready
        //Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

        // enable Arduino interrupt detection
        //Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
        //Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
        //Serial.println(F(")..."));
        attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();

        // set our DMP Ready flag so the main loop() function knows it's okay to use it
        //Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;

        // get expected DMP packet size for later comparison
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        // ERROR!
        // 1 = initial memory load failed
        // 2 = DMP configuration updates failed
        // (if it's going to break, usually the code will be 1)
        //Serial.print(F("DMP Initialization failed (code "));
        //Serial.print(devStatus);
        //Serial.println(F(")"));
    }

    
}
void UpdateIMU()
{
  if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet 

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

            Roll = (ypr[1] * 180/M_PI);
            Pitch = ypr[2] * 180/M_PI;


            if(Pitch > 90){Pitch = 180 - Pitch;}
            else if(Pitch < -90){Pitch = -180 - Pitch;}
            
            //Serial.print("\t");
            //Serial.println(Yaw);
        #endif

    }
}
 
Thanks,

I am not sure if I have that IMU here or not. I have few but not sure about that one. Also that new code is depending on two more external files... So again harder to setup and test it.

So still hard to know yet where the hang/crash/freeze? For example I can not tell from your comments if the code totally hangs or just the display is not updating or ?

The hard part about debugging some things like this, is turning on the frame buffer might indicate that it is the screen code. But it could be that maybe timing differences which causes IMU to have an issue. Or maybe there is some code that is overflowing an array or the like and when it runs one way that overflow does not cause as much of an issue...

So wondering if you might be able to boil it down some more and help localize it.
Things like maybe add a bunch of Serial.print type statements in the code, that maybe through each pass of the code it prints out all of the IMU values that the main code uses. If it turns out that they are constant for many iterations, maybe the printing code could check to see if all values are the same and only print if something changed...

Then if if get a hang/crash/... See if you can strip out the IMU code and see if simpler test case with out IMU maybe has a few iterations hard coded in with maybe code to wait for Serial Input in between and then see if we can step it into the one that stop working.

Again might also add serial.prints or the like at different locations in the code, to see if you can localize where things stop.

Note: if it were me, I would be using something like a Logic Analyzer to help localize. that is I would add things like digitalWriteFast or digitalToggleFast of different unused IO pins at strategic places in the code and then watch what is happening and see if things stop, detect where by state of these IO pins.

Also there is a recent thread with @Frank B and @defragster about using one of Frank's libraries to add code in to show information about a crash. Things like trying to access through null pointer or divide by 0 or ...
I think it is this one: https://github.com/FrankBoesing/T4_PowerButton
That you might try adding and see if that shows some crash.
 
Hi Kurt, thanks again for the reply. Ill look intoi that powerbutton thing. Fornow ive removed the gyro code. if you set Roll to say 25 it updates fine(LED ON). if i set it to say 30 it does not update. I tried the writelines reviously but couldnt find anything conclusive. Please see code excluding gyro below. Set Pitch and roll in setup to test :)

Code:
//#define TFT_MISO  12
#define TFT_MOSI  11  //a12
#define TFT_SCK   13  //a13
#define TFT_DC   9 
#define TFT_CS   10  
#define TFT_RST  8

#define ST7735_BROWN 0x9A60

#define PlaneSquareL 61
#define PlaneSquareR 67
#define PlaneSquareT 77
#define PlaneSquareB 83

#define PlaneWingLeft 16
#define PlaneWingRight 112
#define PlaneWingWidth 30

#define TenWidth 40
#define FiveWidth 15
#define TwoPFiveWidth 8

#define HWF 102

int16_t Colour1, Colour2;

#include <ST7735_t3.h>
#include <SPI.h>
#include <Wire.h>

ST7735_t3 tft = ST7735_t3(TFT_CS, TFT_DC, TFT_RST);

float Pitch, Roll, Yaw;

int centerY, centerX;
int TestX1, TestY1, TestX2, TestY2;
double gradient;
int intercept, xintercept;
int RightIntercept, RightIntercept2;

void setup() {
  tft.initR(INITR_BLACKTAB);
  tft.useFrameBuffer(true); //use the frame buffer to prevent flickeing
  tft.fillScreen(ST7735_BLACK);

  Roll = 25;
  Pitch = 0;
}

void loop() {
  //fill background colour (brown when upright)
  tft.fillScreen(Colour1);

  //pitch sensitivity
  Pitch = Pitch * 4;

  //calculate the center point of the horizon line
  centerY = Pitch * cos(Roll * 0.0174533) + 80;
  centerX = 65 - (Pitch * sin(Roll * 0.0174533));

  //calculate the left and right points
  TestX1 = centerX - (HWF * cos(Roll * 0.0174533));
  TestY1 = centerY  - (HWF * sin(Roll * 0.0174533));
  TestX2 = centerX + (HWF * cos(Roll * 0.0174533));
  TestY2 = centerY  + (HWF * sin(Roll * 0.0174533));

  //if we are upside down switch the colours
  if(Roll < -90 || Roll > 90){Colour1 = ST7735_BLUE; Colour2 = ST7735_BROWN;}
  else{Colour2 = ST7735_BLUE; Colour1 = ST7735_BROWN;}

  //calculate the gradient of the horizon
  gradient = (double)(TestY2 - TestY1)/(double)(TestX2 - TestX1);

  //calculate the left hand intercept of the horizon
  intercept = TestY1 - (gradient * TestX1);
  xintercept = -intercept / gradient;
  if(xintercept < 0 || xintercept > 128){xintercept = 0;}

  //cqalculate the right intercept of teh horizon
  RightIntercept = gradient * 128 + intercept;  

  //fill the background colour
  if(RightIntercept > 0){tft.fillTriangle(xintercept,0,128,0,128,RightIntercept,Colour2);}
  if(xintercept == 0){xintercept = 128;}
  if(RightIntercept < 0){RightIntercept2 = 0;}
  else{RightIntercept2 = RightIntercept;}
  if(intercept > 0){tft.fillTriangle(0,intercept,0,0,xintercept,RightIntercept2,Colour2);}

  //draw the horizon
  tft.drawLine(0,intercept,128,RightIntercept,ST7735_WHITE); // Draw The horizon

  //draw the 2.5 degree lines
  for(int i = 10; i < 100; i += 10)
  {
    if(i % 20 != 0)
    {
      int center2P5X = centerX - (i * sin(Roll * 0.0174533));
      int center2P5Y = centerY + (i * cos(Roll * 0.0174533));
      tft.drawLine(center2P5X - (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  + (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),center2P5X + (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  - (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
      center2P5X = centerX + (i * sin(Roll * 0.0174533));
      center2P5Y = centerY - (i * cos(Roll * 0.0174533));
      tft.drawLine(center2P5X - (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  + (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),center2P5X + (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)),center2P5Y  - (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
    }
  }

  
  //draw the 5 degree lines
  for(int i = 20; i < 160; i += 20)
  {
    if(i % 40 != 0)
    {
      int center5X = centerX - (i * sin(Roll * 0.0174533));
      int center5Y = centerY + (i * cos(Roll * 0.0174533));
      tft.drawLine(center5X - (20 * sin((Roll + 90) * 0.0174533)),center5Y  + (20 * cos((Roll + 90) * 0.0174533)),center5X + (20 * sin((Roll + 90) * 0.0174533)),center5Y  - (20 * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
      center5X = centerX + (i * sin(Roll * 0.0174533));
      center5Y = centerY - (i * cos(Roll * 0.0174533));
      tft.drawLine(center5X - (20 * sin((Roll + 90) * 0.0174533)),center5Y  + (20 * cos((Roll + 90) * 0.0174533)),center5X + (20 * sin((Roll + 90) * 0.0174533)),center5Y  - (20 * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
    }
  }
  
  //draw the 10 degree lines
  for(int i = 40; i < 280; i += 40)
  {
    int center10X = centerX - (i * sin(Roll * 0.0174533));
    int center10Y = centerY + (i * cos(Roll * 0.0174533));
    tft.drawLine(center10X - (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  + (TenWidth * cos((Roll + 90) * 0.0174533)),center10X + (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  - (TenWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
    center10X = centerX + (i * sin(Roll * 0.0174533));
    center10Y = centerY - (i * cos(Roll * 0.0174533));
    tft.drawLine(center10X - (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  + (TenWidth * cos((Roll + 90) * 0.0174533)),center10X + (TenWidth * sin((Roll + 90) * 0.0174533)),center10Y  - (TenWidth * cos((Roll + 90) * 0.0174533)),ST7735_WHITE);
  }

  DrawPlaneCursor();  
 
  tft.updateScreen();

}

void DrawPlaneCursor(){
  int PlaneWingRightOffset = PlaneWingLeft + PlaneWingWidth;
  int IndicatorThickness = PlaneSquareB - PlaneSquareT;
  int PlaneSquareWidth = PlaneSquareR - PlaneSquareL;
  
  //draw the center square
  tft.drawFastHLine(PlaneSquareL, PlaneSquareT, PlaneSquareWidth, ST7735_WHITE);
  tft.drawFastHLine(PlaneSquareL, PlaneSquareB - 1, PlaneSquareWidth, ST7735_WHITE);
  tft.drawFastVLine(PlaneSquareL, PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.drawFastVLine(PlaneSquareR - 1, PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.fillRect(PlaneSquareL +1,PlaneSquareT + 1, PlaneSquareWidth -2,IndicatorThickness -2,ST7735_BLACK);

  //draw the left wing    
  tft.fillRect(PlaneWingLeft + 1,PlaneSquareT + 1,PlaneWingWidth,IndicatorThickness - 2,ST7735_BLACK);
  tft.fillRect(PlaneWingRightOffset - PlaneSquareWidth + 3,PlaneSquareB - 1,IndicatorThickness - 2,IndicatorThickness - 2,ST7735_BLACK);
  tft.drawFastHLine(PlaneWingLeft,PlaneSquareT,PlaneWingWidth + 1,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingLeft,PlaneSquareT + 1,IndicatorThickness -1,ST7735_WHITE);
  tft.drawFastHLine(PlaneWingLeft,PlaneSquareT + IndicatorThickness - 1,PlaneWingWidth - PlaneSquareWidth + 2,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingLeft + PlaneWingWidth,PlaneSquareT,2*(IndicatorThickness) - 3,ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRightOffset - PlaneSquareWidth + 2,PlaneSquareB + IndicatorThickness - 4,PlaneSquareR-PlaneSquareL - 2,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRightOffset - PlaneSquareWidth + 1,PlaneSquareB - 1, IndicatorThickness - 2, ST7735_WHITE);

  //draw the right wing
  tft.fillRect(PlaneWingRight - PlaneWingWidth + 1,PlaneSquareT  + 1, PlaneWingWidth - 1,IndicatorThickness - 2, ST7735_BLACK);
  tft.fillRect(PlaneWingRight - PlaneWingWidth + 1,PlaneSquareB - 1,IndicatorThickness - 2,IndicatorThickness - 2,ST7735_BLACK);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth,PlaneSquareT,PlaneWingWidth,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - 1,PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth + PlaneSquareWidth - 1,PlaneSquareT + IndicatorThickness - 1,PlaneWingWidth - PlaneSquareWidth + 1, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - PlaneWingWidth + PlaneSquareWidth - 1,PlaneSquareT + IndicatorThickness,IndicatorThickness - 3,ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth,PlaneSquareT + 2*IndicatorThickness - 3,PlaneSquareWidth,ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - PlaneWingWidth, PlaneSquareT + 1, IndicatorThickness*2 - 4,ST7735_WHITE);

}
 
It appears to be blowing up in the 5 degree drawing...
Probably on the 2nd draw line where maybe we are not detecting the negative number in some spot:
Here is my current instrumented version of your code:

Code:
//#define TFT_MISO  12
#define TFT_MOSI  11  //a12
#define TFT_SCK   13  //a13
#define TFT_DC   9
#define TFT_CS   10
#define TFT_RST  8

#define ST7735_BROWN 0x9A60

#define PlaneSquareL 61
#define PlaneSquareR 67
#define PlaneSquareT 77
#define PlaneSquareB 83

#define PlaneWingLeft 16
#define PlaneWingRight 112
#define PlaneWingWidth 30

#define TenWidth 40
#define FiveWidth 15
#define TwoPFiveWidth 8

#define HWF 102

int16_t Colour1, Colour2;

#include <ST7735_t3.h>
#include <SPI.h>
#include <Wire.h>

ST7735_t3 tft = ST7735_t3(TFT_CS, TFT_DC, TFT_RST);

float Pitch, Roll, Yaw;

int centerY, centerX;
int TestX1, TestY1, TestX2, TestY2;
double gradient;
int intercept, xintercept;
int RightIntercept, RightIntercept2;

void setup() {
  tft.initR(INITR_BLACKTAB);
  tft.useFrameBuffer(true); //use the frame buffer to prevent flickeing
  tft.fillScreen(ST7735_BLACK);

  Roll = 30;
  Pitch = 0;
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);
}
uint32_t loop_count = 0;
void loop() {
  //fill background colour (brown when upright)
  Serial.printf("Loop Count %u\n", ++loop_count); Serial.flush();
  tft.fillScreen(Colour1);

  //pitch sensitivity
  Pitch = Pitch * 4;

  //calculate the center point of the horizon line
  centerY = Pitch * cos(Roll * 0.0174533) + 80;
  centerX = 65 - (Pitch * sin(Roll * 0.0174533));

  //calculate the left and right points
  TestX1 = centerX - (HWF * cos(Roll * 0.0174533));
  TestY1 = centerY  - (HWF * sin(Roll * 0.0174533));
  TestX2 = centerX + (HWF * cos(Roll * 0.0174533));
  TestY2 = centerY  + (HWF * sin(Roll * 0.0174533));

  //if we are upside down switch the colours
  if (Roll < -90 || Roll > 90) {
    Colour1 = ST7735_BLUE;
    Colour2 = ST7735_BROWN;
  }
  else {
    Colour2 = ST7735_BLUE;
    Colour1 = ST7735_BROWN;
  }

  //calculate the gradient of the horizon
  gradient = (double)(TestY2 - TestY1) / (double)(TestX2 - TestX1);

  //calculate the left hand intercept of the horizon
  intercept = TestY1 - (gradient * TestX1);
  xintercept = -intercept / gradient;
  if (xintercept < 0 || xintercept > 128) {
    xintercept = 0;
  }

  //cqalculate the right intercept of teh horizon
  RightIntercept = gradient * 128 + intercept;

  //fill the background colour
  if (RightIntercept > 0) {
    tft.fillTriangle(xintercept, 0, 128, 0, 128, RightIntercept, Colour2);
  }
  if (xintercept == 0) {
    xintercept = 128;
  }
  if (RightIntercept < 0) {
    RightIntercept2 = 0;
  }
  else {
    RightIntercept2 = RightIntercept;
  }
  if (intercept > 0) {
    tft.fillTriangle(0, intercept, 0, 0, xintercept, RightIntercept2, Colour2);
  }

  //draw the horizon
  Serial.println("Before horizon"); Serial.flush();
  tft.drawLine(0, intercept, 128, RightIntercept, ST7735_WHITE); // Draw The horizon
  //draw the 2.5 degree lines
  for (int i = 10; i < 100; i += 10)
  {
    if (i % 20 != 0)
    {
      int center2P5X = centerX - (i * sin(Roll * 0.0174533));
      int center2P5Y = centerY + (i * cos(Roll * 0.0174533));
      tft.drawLine(center2P5X - (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)), center2P5Y  + (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)), center2P5X + (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)), center2P5Y  - (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)), ST7735_WHITE);
      center2P5X = centerX + (i * sin(Roll * 0.0174533));
      center2P5Y = centerY - (i * cos(Roll * 0.0174533));
      tft.drawLine(center2P5X - (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)), center2P5Y  + (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)), center2P5X + (TwoPFiveWidth * sin((Roll + 90) * 0.0174533)), center2P5Y  - (TwoPFiveWidth * cos((Roll + 90) * 0.0174533)), ST7735_WHITE);
    }
  }


  //draw the 5 degree lines
  Serial.println("Before 5 degree"); Serial.flush();
  for (int i = 20; i < 160; i += 20)
  {
    if (i % 40 != 0)
    {
      int center5X = centerX - (i * sin(Roll * 0.0174533));
      int center5Y = centerY + (i * cos(Roll * 0.0174533));
      Serial.printf("  %i %i:%i ", i, center5X, center5Y); Serial.flush();
      tft.drawLine(center5X - (20 * sin((Roll + 90) * 0.0174533)), center5Y  + (20 * cos((Roll + 90) * 0.0174533)), center5X + (20 * sin((Roll + 90) * 0.0174533)), center5Y  - (20 * cos((Roll + 90) * 0.0174533)), ST7735_WHITE);
      center5X = centerX + (i * sin(Roll * 0.0174533));
      center5Y = centerY - (i * cos(Roll * 0.0174533));
      Serial.printf(" $ %i:%i\n", center5X, center5Y); Serial.flush();
      tft.drawLine(center5X - (20 * sin((Roll + 90) * 0.0174533)), center5Y  + (20 * cos((Roll + 90) * 0.0174533)), center5X + (20 * sin((Roll + 90) * 0.0174533)), center5Y  - (20 * cos((Roll + 90) * 0.0174533)), ST7735_WHITE);
    }
  }

  //draw the 10 degree lines
  Serial.println("Before 10 degree"); Serial.flush();
  for (int i = 40; i < 280; i += 40)
  {
    int center10X = centerX - (i * sin(Roll * 0.0174533));
    int center10Y = centerY + (i * cos(Roll * 0.0174533));
    tft.drawLine(center10X - (TenWidth * sin((Roll + 90) * 0.0174533)), center10Y  + (TenWidth * cos((Roll + 90) * 0.0174533)), center10X + (TenWidth * sin((Roll + 90) * 0.0174533)), center10Y  - (TenWidth * cos((Roll + 90) * 0.0174533)), ST7735_WHITE);
    center10X = centerX + (i * sin(Roll * 0.0174533));
    center10Y = centerY - (i * cos(Roll * 0.0174533));
    tft.drawLine(center10X - (TenWidth * sin((Roll + 90) * 0.0174533)), center10Y  + (TenWidth * cos((Roll + 90) * 0.0174533)), center10X + (TenWidth * sin((Roll + 90) * 0.0174533)), center10Y  - (TenWidth * cos((Roll + 90) * 0.0174533)), ST7735_WHITE);
  }

  Serial.println("Before cursor"); Serial.flush();
  DrawPlaneCursor();

  Serial.println("Before updateScreen"); Serial.flush();
  tft.updateScreen();

}

void DrawPlaneCursor() {
  int PlaneWingRightOffset = PlaneWingLeft + PlaneWingWidth;
  int IndicatorThickness = PlaneSquareB - PlaneSquareT;
  int PlaneSquareWidth = PlaneSquareR - PlaneSquareL;

  //draw the center square
  tft.drawFastHLine(PlaneSquareL, PlaneSquareT, PlaneSquareWidth, ST7735_WHITE);
  tft.drawFastHLine(PlaneSquareL, PlaneSquareB - 1, PlaneSquareWidth, ST7735_WHITE);
  tft.drawFastVLine(PlaneSquareL, PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.drawFastVLine(PlaneSquareR - 1, PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.fillRect(PlaneSquareL + 1, PlaneSquareT + 1, PlaneSquareWidth - 2, IndicatorThickness - 2, ST7735_BLACK);

  //draw the left wing
  tft.fillRect(PlaneWingLeft + 1, PlaneSquareT + 1, PlaneWingWidth, IndicatorThickness - 2, ST7735_BLACK);
  tft.fillRect(PlaneWingRightOffset - PlaneSquareWidth + 3, PlaneSquareB - 1, IndicatorThickness - 2, IndicatorThickness - 2, ST7735_BLACK);
  tft.drawFastHLine(PlaneWingLeft, PlaneSquareT, PlaneWingWidth + 1, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingLeft, PlaneSquareT + 1, IndicatorThickness - 1, ST7735_WHITE);
  tft.drawFastHLine(PlaneWingLeft, PlaneSquareT + IndicatorThickness - 1, PlaneWingWidth - PlaneSquareWidth + 2, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingLeft + PlaneWingWidth, PlaneSquareT, 2 * (IndicatorThickness) - 3, ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRightOffset - PlaneSquareWidth + 2, PlaneSquareB + IndicatorThickness - 4, PlaneSquareR - PlaneSquareL - 2, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRightOffset - PlaneSquareWidth + 1, PlaneSquareB - 1, IndicatorThickness - 2, ST7735_WHITE);

  //draw the right wing
  tft.fillRect(PlaneWingRight - PlaneWingWidth + 1, PlaneSquareT  + 1, PlaneWingWidth - 1, IndicatorThickness - 2, ST7735_BLACK);
  tft.fillRect(PlaneWingRight - PlaneWingWidth + 1, PlaneSquareB - 1, IndicatorThickness - 2, IndicatorThickness - 2, ST7735_BLACK);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth, PlaneSquareT, PlaneWingWidth, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - 1, PlaneSquareT + 1, IndicatorThickness - 2, ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth + PlaneSquareWidth - 1, PlaneSquareT + IndicatorThickness - 1, PlaneWingWidth - PlaneSquareWidth + 1, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - PlaneWingWidth + PlaneSquareWidth - 1, PlaneSquareT + IndicatorThickness, IndicatorThickness - 3, ST7735_WHITE);
  tft.drawFastHLine(PlaneWingRight - PlaneWingWidth, PlaneSquareT + 2 * IndicatorThickness - 3, PlaneSquareWidth, ST7735_WHITE);
  tft.drawFastVLine(PlaneWingRight - PlaneWingWidth, PlaneSquareT + 1, IndicatorThickness * 2 - 4, ST7735_WHITE);

}

And the debug output:
Code:
Loop Count 1
Before horizon
Before 5 degree
  20 54:97  $ 75:62
  60 34:131  $ 95:28
  100 14:166  $ 115:-6
  140 -5:201  $ 135:-41

Note: I am running this on an Adafruit 128x128 St7735 display.
Now to see what gets passed into the ST7735_t3 library and why maybe it is not being truncated properly...

Update: I did quick and dirty code to see what values were computed to pass to drawline:
Changed in the above:
Code:
      int x1 = center5X - (20 * sin((Roll + 90) * 0.0174533));
      int y1 = center5Y  + (20 * cos((Roll + 90) * 0.0174533));
      int x2 = center5X + (20 * sin((Roll + 90) * 0.0174533));
      int y2 = center5Y  - (20 * cos((Roll + 90) * 0.0174533));
      Serial.printf(" $ %i:%i => (%d, %d)(%d, %d)\n", center5X, center5Y, x1, y1, x2, y2); Serial.flush();
Output is now:
Code:
Loop Count 1
Before horizon
Before 5 degree
  20 54:97  $ 75:62 => (57, 51)(92, 72)
  60 34:131  $ 95:28 => (77, 17)(112, 38)
  100 14:166  $ 115:-6 => (97, -16)(132, 4)
  140 -5:201  $ 135:-41 => (117, -51)(152, -30)
So the Y value stays negative, the code should just return... Will now see what is going on in the library.
 
Thanks for looking into this. I knew that the lines were often being drawn 'off the screen' but im sure before they were just 'dealt with' and not rendered. I know know what has changed in the recent version. I could potentially try to mod the lib to ensure negative pixels are not rendered.

Running up a previous version it only seems to be when the line value becomes nagatoive beoyond a certain point, then it breaks. In that version you hav eit seems to be between 26.7 and 26.8 degrees aob. I guessthis is when the negative number breaks it.
 
SOLUTION FOUND!!

After digging into the library i found that line 752 of ST7735_t3.h was commented out.

Code:
if((x < _displayclipx1) ||(x >= _displayclipx2) || (y < _displayclipy1) || (y >= _displayclipy2)) return;

this is in the Pixel function and means that if the pixel is outside the bound s of the display, dont draw it. I dont know why it was commented out. It wasnt before, hence why it worked before and not now, Anyway i un-commented it and it now works as before.

Big thanks kurt, without your help this would have taken me forever to figure out. Sometimes you just need a nudge in the right direction. 90% of solving a problem is knowing what the problem is. I thought you might want to see it working, so see attached video. :)


Some details about the project.

I hope to make a flight instrument for use in my cessna 172 aircraft. It should fi in a 3 1/4 instrument slot and prtovide attitude information as well as other auxilary functions (flight timer and potentially heading / altitude sensor depending). im at the stage when im milling copper for a first full instrument prototype. The hardest part has been the vector AH code. It been on and off for about 6 months. This is the 5 hardware change and 12th software version. Started off using nano then stm32 blue pill but too slow (5 fps on stm). with 600mhz to play with its now buttery smooth!
 
Fixed: for some reason we had the checking for bounds in the Pixel function commented out.
We called this with a negative value that in the case of frame buffer just overwrote random memory.

Fix is simple: look the st7735_t3.h file and look for the pixel method.
There is a bounds check that was commented out. remove the // from that line.

I pushed up a change and issued a PR https://github.com/PaulStoffregen/ST7735_t3/pull/24
 
Fixed: for some reason we had the checking for bounds in the Pixel function commented out.
We called this with a negative value that in the case of frame buffer just overwrote random memory.

Fix is simple: look the st7735_t3.h file and look for the pixel method.
There is a bounds check that was commented out. remove the // from that line.

I pushed up a change and issued a PR https://github.com/PaulStoffregen/ST7735_t3/pull/24

HaHa, beat you to it! Only Joking, thank you so much for the help, glad we have fixed it. makes you wonder why it was commented out though...
 
Status
Not open for further replies.
Back
Top