128x96 oled refresh

I am turning on a display page using an RFID module.

When the RFID sees a card a powerState toggles to HIGH and the display is on.

At the moment when on (RFID HIGH), the page rewrites every second to display a new time.

I want to make it appear that the display is just on when the RFID is set HIGH and the display will appear to rewrite instantly but I cant see how to do this??

/**

Also does anyone have a link to the document listing all the functions and what they do?

---------------------------------------------------------------------------------------
* Pin layout:
SOFT_SPI_MISO_PIN = 50 ----- can be changed in the RFID.cpp file
SOFT_SPI_MOSI_PIN = 63 ----- can be changed in the RFID.cpp file
SOFT_SPI_SCK_PIN  = 64 ----- can be changed in the RFID.cpp file
SOFT_SPI_SS_PIN: Pin 67 ----- can be changed in the code below
SOFT_SPI_RST_PIN: Pin 5 ----- can be changed in the code below
*/

#include "RFID.h"
#include <DigitalIO.h> // our software SPI library

#define SS_PIN 67
#define RST_PIN 5
 
RFID rfid(SS_PIN, RST_PIN); //create an instance rfid for the class RFID


String cardNum;
unsigned long RFID;
int powerPin = 3;
int powerpinRead;
int prevpowerpinRead = LOW;
int powerpinState = LOW;
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers


// These are OLED hardware spi
#define sclk 52
#define mosi 51
#define dc   15 
#define cs   53//OCS on  big display
#define rst  2

// Color definitions
#define	BLACK           0x0000
#define	BLUE            0x001F
#define	RED             0xF800
#define	GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
//#include <SPI.h> //Don't seem to need this to make OLED work?


Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, mosi, sclk, rst);  

float p = 3.1415926;

void fillpixelbypixel(uint16_t color) {
  for (uint8_t x=0; x < tft.width(); x++) {
    for (uint8_t y=0; y < tft.height(); y++) {
      tft.drawPixel(x, y, color);
    }
  }
  delay(100);
}

void setup(void) {
  Serial.begin(9600);
  Serial.println("initilizing RFID...");
  rfid.init(); // initilize the RFID module
  Serial.println("start ");
  
  Serial.println("Initialise RFID!");
  tft.begin();
  Serial.println("start");
 
 uint16_t time = millis();
  tft.fillRect(0, 0, 128, 128, BLACK);
  time = millis() - time;
  
 // Serial.println(time, DEC);
  //delay(500);

  pinMode(powerPin, OUTPUT); 

 }

void tftPrintTest() {
    
    tft.setCursor(0, 5);
  tft.fillScreen(BLACK);
 tft.setTextColor(WHITE);
  tft.setTextSize(0);
 tft.println("Hello World!");
  tft.setTextSize(1);
 tft.setTextColor(GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(WHITE);
  tft.print(" seconds.");
  //delay(500);

}

void loop() {

 readRfid();
 printRfid();
powerpinRead =rfid.isCard();
 Serial.println ( powerpinRead);
 
 if (rfid.isCard())
{
     
}
if (powerpinRead == HIGH && prevpowerpinRead == LOW && millis() - time > debounce) 
{
    if (powerpinState == HIGH)
       powerpinState = LOW;
        else
    powerpinState = HIGH;
    time = millis();    
}
  digitalWrite(powerPin, powerpinState);
    prevpowerpinRead = powerpinRead;
  Serial.println(powerpinState);

if (powerpinState == HIGH)
  {tftPrintTest();
  delay(500);
  }
  else 
  {tft.fillScreen(BLACK);
  }
  
}
void readRfid()
{
  if (rfid.isCard())
  {
    if (rfid.readCardSerial())
    {
      for (int i=0; i<=4; i++)//card value: "xyz xyz xyz xyz xyz" (15 digits maximum; 5 pairs of xyz)hence 0<=i<=4 //
      {
        RFID = rfid.serNum[i];
        cardNum += RFID; // store RFID value into string "cardNum" and concatinate it with each iteration
      }
    }
  }
  rfid.halt();
}

void printRfid()
{
 if (cardNum != '\0')//if string cardNum is not empty, print the value
 {
    Serial.println("Card found");
    Serial.print("Cardnumber: ");
    Serial.println(cardNum);
    cardNum.remove(0);
   //This is an arduino function.
  //remove the stored value after printing. else the new card value that is read
  // will be concatinated with the previous string.
  delay(500); 
 }
}

I had a look, did some cleaning so i could get some overview, one of the things is i am not exactly sure what you want, but i figure you'll have another go at explaining. a few things, for me (others) it is easier if a sketch starts out with all #include statements, then all #define, and then the variables & objects declarations, then any prototype function declarations (if any) then setup() then loop() then the rest..

i'd change

if (powerpinState == HIGH)
       powerpinState = LOW;
        else
    powerpinState = HIGH;

intopowerpinState = !powerpinState;
and then you start to do something with the powerpin reading the card again, mainly what is it that you want to happen in what sequence ?

Thankyou very much. I am very new to this stuff and at 60 its a bit of a challenge!!

Anyway the main point is the RFID is just used to run the display program. The RFID drives the toggled output and when it is high the display program runs.

The timer routine just shows seconds updating on the display. The problem is unless I write the display to black each time it loops then the timer characters get all overwritten and the over write is slow.

What I need is for this display to 'appear' on all the time and for the seconds counter to clearly increment.

The problem is the rewrite takes more than a second so doesn't appear as a 'static' page.

So my question is how do I speed up the display program - tftPrintTest() to make it appear to be on all the time a HIGH RFID is toggled and the seconds clearly increment.

kpg:
Thankyou very much. I am very new to this stuff and at 60 its a bit of a challenge!!

It is always a challenge at 12 at 34 and at 60...
but anywayi do have a tft and i know they are "not too quick" but basically all you really want to do is write to the screen

tft.setTextColor(MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(WHITE);
  tft.print(" seconds.");

this bit, actually just this bit:

tft.setTextColor(MAGENTA);
  tft.print(millis() / 1000);

the rest sort of stays there all the time if the screen is on. Am i correct.
So i don't exactly know where these things get printed, since the cursor got set a few lines back, but either we can find out, or we can set the cursor where we want it to be., then just before we print the new seconds value, we can blot-out a rectangle over the top of the old digits usingtft.fillRect(x1,y1,x2,y2,color); now that will almost for sure take less then a second to do the rectangle and the new digits, we can put it in s separate function so we can call the tftPrintTest(); once and ideally we can even just fire the printing of the seconds if the seconds are different from what they were before, that means we need to keep track of them so create a global variable 'secs' assign millis()/1000 to it and then compare it with that thereafter and update the screen and the value when it is less then the current one. that way it will run on time (well enough i hope)

Thanks.

Yes the main point is I want the rest of the screen to stay on and I only want refresh the numbers. I think I understand what you at saying by creating a rectangle 'mask' to just overwrite the seconds area but wont the loop just make the whole screen refresh anyway or is it just because I start with a fill to black? that appears to turn it off and on again? I can easily test that and I think it is that.

getting there.......

So I cleaned up the code and made only the section of the screen where the seconds counters is be the area that refills black. As it refills faster than 1 second the seconds counter is clear and doesn't jump any seconds now.

BUT.....the refill still appears to make the seconds numbers flash. I know the frame rate of the display is very fast so is there anyway I can speed up the refill to make the seconds just appear to change rather than flash and change?

/**

---------------------------------------------------------------------------------------
* Pin layout:
SOFT_SPI_MISO_PIN = 50 ----- can be changed in the RFID.cpp file
SOFT_SPI_MOSI_PIN = 63 ----- can be changed in the RFID.cpp file
SOFT_SPI_SCK_PIN  = 64 ----- can be changed in the RFID.cpp file
SOFT_SPI_SS_PIN: Pin 67 ----- can be changed in the code below
SOFT_SPI_RST_PIN: Pin 5 ----- can be changed in the code below
*/

#include "RFID.h"
#include <DigitalIO.h> // our software SPI library
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
//#include <SPI.h> //Don't seem to need this to make OLED work?

#define SS_PIN 67//software SPI pins for RFID
#define RST_PIN 5//software SPI pins for RFID

// These are OLED hardware spi
#define sclk 52
#define mosi 51
#define dc   15 
#define cs   53//OCS on  big display
#define rst  2

// Color definitions
#define  BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

 
RFID rfid(SS_PIN, RST_PIN); //create an instance rfid for the class RFID
Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, mosi, sclk, rst);  

String cardNum;
unsigned long RFID;
int powerPin = 3;
int powerpinRead;
int prevpowerpinRead = LOW;
int powerpinState = LOW;
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers
float p = 3.1415926;

void fillpixelbypixel(uint16_t color) {
  for (uint8_t x=0; x < tft.width(); x++) {
    for (uint8_t y=0; y < tft.height(); y++) {
      tft.drawPixel(x, y, color);
    }
  }
  delay(100);
}

void setup(void) {
  Serial.begin(9600);
  Serial.println("initilizing RFID!");
  rfid.init(); // initilize the RFID module
  Serial.println("start ");
  Serial.println("Initialise OLED!");
  tft.begin();
  Serial.println("start");
 
 uint16_t time = millis();
  tft.fillRect(0, 0, 128, 128, BLACK);
  time = millis() - time;
  
 // Serial.println(time, DEC);
  //delay(500);

  pinMode(powerPin, OUTPUT); 

 }

void tftPrintTest() {
    
    tft.setCursor(0, 5);
  //tft.fillScreen(BLACK);
    tft.setTextColor(WHITE);
    tft.setTextSize(1);
 //tft.println("Hello World!");
//  tft.setTextSize(1);
 //tft.setTextColor(GREEN);
 // tft.print(p, 6);
 // tft.println(" Want pi?");
 // tft.println(" ");
 // tft.print(8675309, HEX); // print 8,675,309 out in HEX!
 // tft.println(" Print HEX!");
 // tft.println(" ");
 // tft.setTextColor(WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
   tft.setTextSize(4);
  tft.fillRect(1,20,50,30,BLACK);
  //tft.fillRect(x1,y1,x2,y2,color);
  tft.setTextColor(MAGENTA);
  tft.print(millis() / 1000);
  tft.setCursor(0, 60);
  tft.setTextColor(WHITE);
  tft.setTextSize(1);
  tft.println("seconds.");
  //delay(500);

}

void loop() {

 readRfid();
 printRfid();
 powerpinRead =rfid.isCard();
 Serial.println ( powerpinRead);
  
}
void readRfid()
{
  if (rfid.isCard())
  {
    if (rfid.readCardSerial())
    {
      for (int i=0; i<=4; i++)//card value: "xyz xyz xyz xyz xyz" (15 digits maximum; 5 pairs of xyz)hence 0<=i<=4 //
      {
        RFID = rfid.serNum[i];
        cardNum += RFID; // store RFID value into string "cardNum" and concatinate it with each iteration
      }
    }
  }

  if (powerpinRead == HIGH && prevpowerpinRead == LOW && millis() - time > debounce) 
{
    if (powerpinState == HIGH)
       powerpinState = LOW;
        else
    powerpinState = HIGH;
    time = millis();    
}
  digitalWrite(powerPin, powerpinState);
    prevpowerpinRead = powerpinRead;
  Serial.println(powerpinState);

if (powerpinState == HIGH)
  {tftPrintTest();
  //delay(500);
  }
  else 
  {tft.fillScreen(BLACK);
  }
  rfid.halt();
}

void printRfid()
{
 if (cardNum != '\0')//if string cardNum is not empty, print the value
 {
    Serial.println("Card found");
    Serial.print("Cardnumber: ");
    Serial.println(cardNum);
    cardNum.remove(0);
   //This is an arduino function.
  //remove the stored value after printing. else the new card value that is read
  // will be concatinated with the previous string.
  //delay(500); 
 }
}

Also a slight aside but I borrowed some of the display code ...and in it there is a section that I don't understand what it is doing and if I comment it out it doesn't make any difference??? Any ideas?

void fillpixelbypixel(uint16_t color) {
  for (uint8_t x=0; x < tft.width(); x++) {
    for (uint8_t y=0; y < tft.height(); y++) {
      tft.drawPixel(x, y, color);
    }
  }
  delay(100);
}

I did find this link to a faster refresh but I am not sure it is compatible with the standard Adafruit libraries as my functions start with TFT. and these appear to start with OLED.

Has anyone tried to use this with a MEGA and a 1351 128x96 OLED?

kpg:
Also a slight aside but I borrowed some of the display code ...and in it there is a section that I don't understand what it is doing and if I comment it out it doesn't make any difference??? Any ideas?

void fillpixelbypixel(uint16_t color) {

for (uint8_t x=0; x < tft.width(); x++) {
    for (uint8_t y=0; y < tft.height(); y++) {
      tft.drawPixel(x, y, color);
    }
  }
  delay(100);
}

That code fills the screen pixel by pixel, but since it is never called from anywhere within your code, it doesn't really do anything (does get compiled, but then omitted from the binary file)

kpg:
So I cleaned up the code and made only the section of the screen where the seconds counters is be the area that refills black.

Yes, but maybe you can have a look at the state change example here so you don't have to print any excess info on screen every time around and still set the screen up when the 'HIGH' state starts

kpg:
BUT.....the refill still appears to make the seconds numbers flash. I know the frame rate of the display is very fast so is there anyway I can speed up the refill to make the seconds just appear to change rather than flash and change?

There should be, unfortunately with this library any call to any of the functions automatically displays immediately where as we actually want to blot out the part of the ram, and then write the new info before we display anything. It can be done, but i think we'd have to alter the library to do so, or maybe find another library tht also support your display.

void tftPrintSeconds() {
  tft.setCursor(5,20);
  tft.setTextSize(4);
  tft.setTextColor(MAGENTA);
  uint32_t secs=millis() / 1000;
  tft.fillRect(1,20,50,30,BLACK);
  tft.print(secs);

something like this minimizes the time between the blotting out and the displaying of the digits (cursor position is a guess..)

Thanks guys

I will try a few things and report back.

As I mentioned I did find a modified library with a 'fast fill' but it seems to have a bug.

So is the only real way to get fast graphics/text is to use the SD card?

It seems a fairly basic request to be able to display a changing text without flickering? Someone must have done this?

kpg:
As I mentioned I did find a modified library with a 'fast fill' but it seems to have a bug.

I was more thinking along the lines of one of the other OLED libraries that do depend on adafruit gfx, but not on SPITFT like this one does or we could try and see if we can make the call to display the created data separately from the graphics creation.

It seems a fairly basic request to be able to display a changing text without flickering?

You are continuously updating the display, including setting it to black.
That's not good, although perhaps it shouldn't affect actual update rate. Instead, only touch the display when you actually have changed data. (ie every every time "seconds" is not what it was last (oldseconds?)
You may not need the "clear" operation (it'll depend on whether sending text loads the background as well.)
If not needed, then not doing it should result in a cleaner display.

So is there a way in the library functions to not load the background and only the text?

I've had a look at the library files but I'm a bit new to this and can't find any documentation detailing the functions?

Appreciate the help.

Hi i also had a look, but since i never had an OLED, it took some time before i found Adafruit_SPITFT.h &.ccp (i had to download them as part of AdafruitGFX ) and i don't see a real easy way achieving what you want. What i did think was that you could create a bitmap image first, write the digits to that, and then display that image. That is a feasible option although it is not something i can do in half an hour either.
Also i did find another library which may work for your display. here only it doesn't support your size (128x96) but only 128x128 for your display type and i am not sure if that would help at all.

Or create a 16-bit color bitmaps for digits and display those, that sounds like the least work to me.

Pff it was a bit of a search, but i think i found what you need,keep in mind this should/may only work for the default font. Searching through Adafruit_GFX.cpp i saw that the drawChar, did have a reference to a background color, and in the end i found an overloaded version of setTextColor() here

void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
    textcolor   = c;
    textbgcolor = b;

which means that when you set the textcolor, you can also specify the backgroundcolor

tft.setTextColor(MAGENTA,BLACK);
  uint32_t secs=millis() / 1000;
  //tft.fillRect(1,20,50,30,BLACK);
  tft.print(secs);

and you don't need to draw the rectangle to blot it out first. So no messing with the library, just searching through it. The disturbing thing is i actually knew this already, but when thinking about it it didn't pop into my mind.

You are a star> Thanks!!

I will give that a go and report in.

Cheers and Happy New Year!!

For a while I have been trying to find away to write a simple seconds counter test to a 128x96 OLED without refreshing the whole display or writing a black fill which in both cases made the text appear to flicker.

Thanks to Diva_Rishi who tracked down a function in the library that writes the background and foreground of the text simultaneously, it now works without any flicker!

code is

void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
    textcolor   = c;
    textbgcolor = b;