TFT_HX8357.h - graph from 0.96" oled on 3.2"

Hi there.

I just bought an LCD that works perfect with the TFT_HX8357.h library, i really love the many examples provided. I have a sketch that worked on the cheap OLEDs with the Adafruit library. I tried to convert the code so it works on my larger display and have succeeded quite far. There is however one issue that I have trouble converting as I am more of a recycler (learning by copy and pasting other peoples work and try to analyze it and change things to get it the way I want (I'm not an advanced coder).

The problem I have is that the graph that plots in a continuous motion on the little OLED plots different on the 3.2", it stops after reaching the the 128th pixel and then kind of levels out the already plotted data where as on the OLED it just continues to plot. I hope my explanation makes some sense?

I am trying to understand what it is that causes this and what I should change in my code to have the graph plotting continuously but I'm kind of stuck...

I scaled my project down as to only contain the relevant data to have the graph working so it might be easier for someone to examine and point me in the right direction as I have no clue what to do...

Any help is much appreciated (I implemented a random() as to simulate A0 data).
Information about my setup:
Arduino Mega 2560
3.2" TFT display
IDE 1.6.7

//*********************************************************************
#include <Wire.h>
#include <TFT_HX8357.h> // Hardware-specific library
TFT_HX8357 tft = TFT_HX8357();       // Invoke custom library

int sensorValue = 0;        // variable to store the value coming from the sensor
long randomNumber;  // This just holds a random number to simulate A0 between 55 and 60

const int MAX = 60;         // Defines were to start drawing the data graph (60 is starting from left, 0 is starting from the right)
int sensorArray[ MAX ];
int autoScale = 2;          // Set the scale for the graph at standard 2 = range 1-128

uint32_t storeDataTimer = millis();
uint32_t refreshTimer = millis();
uint32_t printTimer = millis();
//********************************************************************

//  Do the calculations for the sensor to get the desired value

void sensorCalc()
{                                             

  randomNumber = random(55,60); // Random number to simulate A0
  sensorValue = randomNumber; // Sensor value
} // sensorCalc

//********************************************************************
void setup()   
{ 
  randomSeed(42); // Makes the random number more random (for testing purpose only)
  Wire.begin();              // Start the wire protocoll

  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK); 
  
  for ( int i = 0; i < MAX; i++ )
  {                               
    sensorArray[ i ] = 0;         // Start clean graph
  } 
} // setup
//********************************************************************

void loop() 
{                                                                                                                                                     
  drawSensorGraph();       // Call the graph inside this section

  if ( storeDataTimer > millis() )  
    storeDataTimer = millis();
  if ( refreshTimer > millis() )  
    refreshTimer = millis();
  if ( printTimer > millis() )  
    printTimer = millis();  

  
  if ( millis() - storeDataTimer > 500 ) // Original value 1m (60000ms) x 60 = 60m
  { 
    storeDataTimer = millis();
    storeData();
  }
  
} // loop
//********************************************************************
//                    This section controls the data storage
void storeData(){
static int i = 0;
    
  if ( isnan( ( int ) sensorValue ) )
    if ( i < MAX )
    {
      sensorArray[ i ] = 0;
      i++;
    }
    else
    {
      for ( int j = 0; j < MAX - 1; j++ )
      {
        sensorArray[ j ] = sensorArray[ j + 1 ];
        sensorArray[ MAX - 1 ] = 0; 
      }
    }
  else
  {
    if ( i < MAX )
    {
      sensorArray[ i ] = sensorValue;
      i++;  // This draws the graph data      
    }
    else
    {
      for ( int j = 0; j < MAX - 1; j++ )
      {
        sensorArray[ j ] = sensorArray[ j + 1 ];
        sensorArray[ MAX - 1 ] = sensorValue; 
      }
    }
  }
} // storeData
//********************************************************************
//                    This section draws the line ans shows the sensor in the graph
void drawSensorGraph()
{
  sensorCalc(); // Call the sensor calculations inside this loop  
  drawGraph();  // Call the graph inside this loop
  
   for (int i = 0; i < MAX; i++ )
   tft.drawFastHLine( 128 - MAX * 2 + i * 2, 64 - sensorArray[ i ] / autoScale, 2, TFT_WHITE ); // 128 is the maximum value before the data is no longer visible on the screen
}
//********************************************************************
//                    This section draws the graphics used in the data trend
void drawGraph()
{
  tft.drawPixel( 6, 13, TFT_WHITE ); 
  tft.drawPixel( 6, 23, TFT_WHITE ); 
  tft.drawPixel( 6, 33, TFT_WHITE ); 
  tft.drawPixel( 6, 43, TFT_WHITE ); 
  tft.drawPixel( 6, 53, TFT_WHITE ); 
  tft.drawPixel( 27, 62, TFT_WHITE ); 
  tft.drawPixel( 47, 62, TFT_WHITE ); 
  tft.drawPixel( 67, 62, TFT_WHITE ); 
  tft.drawPixel( 87, 62, TFT_WHITE ); 
  tft.drawPixel( 107, 62, TFT_WHITE ); 
  tft.drawFastVLine( 7, 0, 100, TFT_WHITE );
  tft.drawFastHLine( 7, 63, 120, TFT_WHITE );
}
//********************************************************************

A link to the original OLED project in case this is of any use

Hi, I'll have a look later this evening and report back.

OK, there are a few problems with your code. I have corrected the plotting of the sensor readings for you.

The main difference between the small OLED screens and TFTs is that with the OLED ones the whole screen is re-plotted and renewed on each update whereas the with a TFT the screen retains the old plotted positions so it has to be erased. I have therefore added code to erase the old plots when the screen needs to scroll. I have also simplified the sensor data storage function.

You also had an error where [j+1] exceeded the array size which has been corrected. I have also changed the code to prevent the empty array values from being plotted.

There are some other improvements that could be made, but I have resisted making any more changes!

Good luck with your project.

Here is the corrected code:

//*********************************************************************
#include <Wire.h>
#include <TFT_HX8357.h> // Hardware-specific library
TFT_HX8357 tft = TFT_HX8357();       // Invoke custom library

int sensorValue = 0;        // variable to store the value coming from the sensor
long randomNumber;  // This just holds a random number to simulate A0 between 55 and 60

const int MAX = 60;         // Defines were to start drawing the data graph (60 is starting from left, 0 is starting from the right)
int sensorArray[ MAX ];
int autoScale = 2;          // Set the scale for the graph at standard 2 = range 1-128
int pointer = 0;            // Pointer to current array storage location

uint32_t storeDataTimer = millis();
uint32_t refreshTimer = millis();
uint32_t printTimer = millis();
//********************************************************************

//  Do the calculations for the sensor to get the desired value

void sensorCalc()
{

  randomNumber = random(25, 60); // Random number to simulate A0
  sensorValue = randomNumber; // Sensor value
} // sensorCalc

//********************************************************************
void setup()
{
  Serial.begin(9600);
  randomSeed(42); // Makes the random number more random (for testing purpose only)
  Wire.begin();              // Start the wire protocoll

  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);

  for ( int i = 0; i < MAX; i++ )
  {
    sensorArray[ i ] = 0;         // Start clean graph
  }
} // setup
//********************************************************************

void loop()
{
  drawSensorGraph();       // Call the graph inside this section

  if ( storeDataTimer > millis() )
    storeDataTimer = millis();
  if ( refreshTimer > millis() )
    refreshTimer = millis();
  if ( printTimer > millis() )
    printTimer = millis();


  if ( millis() - storeDataTimer > 500 ) // Original value 1m (60000ms) x 60 = 60m
  {
    storeDataTimer = millis();
    storeData();
  }

} // loop
//********************************************************************
//                    This section controls the data storage
void storeData() {
  // Check if we need to scroll the plot
  if (pointer > (MAX - 1)) {
    pointer = MAX - 1;
    for ( int i = 0; i < (MAX - 1); i++ )
    {
      tft.drawFastHLine( 128 - MAX * 2 + i * 2, 64 - sensorArray[ i ] / autoScale, 2, TFT_BLACK ); // Erase the old plot
      if (i < (MAX - 1)) sensorArray[ i] = sensorArray[ i + 1 ]; // We add this test otherwise j + 1 is more than the array size
    }
  }
  
  sensorArray[ pointer ] = sensorValue;
  pointer++;
} // storeData
//********************************************************************
//                    This section draws the line ans shows the sensor in the graph
void drawSensorGraph()
{
  sensorCalc(); // Call the sensor calculations inside this loop
  drawGraph();  // Call the graph inside this loop
  if (pointer == 0) return; // Nothing to draw yet
  for (int i = 0; i < (pointer - 1); i++ ) // Only plot valid points
    tft.drawFastHLine( 128 - MAX * 2 + i * 2, 64 - sensorArray[ i ] / autoScale, 2, TFT_GREEN ); // 128 is the maximum value before the data is no longer visible on the screen
}
//********************************************************************
//                    This section draws the graphics used in the data trend
void drawGraph()
{
  tft.drawPixel( 6, 13, TFT_WHITE );
  tft.drawPixel( 6, 23, TFT_WHITE );
  tft.drawPixel( 6, 33, TFT_WHITE );
  tft.drawPixel( 6, 43, TFT_WHITE );
  tft.drawPixel( 6, 53, TFT_WHITE );
  tft.drawPixel( 27, 62, TFT_WHITE );
  tft.drawPixel( 47, 62, TFT_WHITE );
  tft.drawPixel( 67, 62, TFT_WHITE );
  tft.drawPixel( 87, 62, TFT_WHITE );
  tft.drawPixel( 107, 62, TFT_WHITE );
  tft.drawFastVLine( 7, 0, 100, TFT_WHITE );
  tft.drawFastHLine( 7, 63, 120, TFT_WHITE );
}
//********************************************************************

Hello Bodmer

Thank you for taking the time to respond and my apologize for not replying earlier. Somehow I didn't receive an update in my email and read your input just now. I will try your code tonight! I'm very eager to test :slight_smile:

And thanks again for your library, I really love the examples! :slight_smile:

I will test tonight and update this topic.

It works perfectly!!! :slight_smile:
I made some changes since I now have a larger display and used the layout in the example but a smaller (200x150px) and changed to vertical line as looks better for my sensor. It looks so nice, I even kept the green color :slight_smile:

Thanks again! :slight_smile:

Great, good luck with your project.