Hi everybody,
today I would like to solve a strange problem with 7219Matrix displays which I am using on several projects and often get the same problem: The output on the Matrix gets scrambled after a few minutes working well. Actually on my NANO processors they work pretty fine but on any ESP32 processor I get this strange effect which I show on the pictures below: First the working Version on a ATmega 328P NANO:
code for this Version is
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <DS3231.h>
#include <Wire.h>
#include <SSD1306Ascii.h>
#include <SSD1306AsciiAvrI2c.h>
int pinMin = 10;
int pinHour = 9;
int pinLight = 5;
int GetBtn = 6; // left button
int SetBtn = 7; // right button
//Din connects to pin 11
//CLK connects to pin 13
int numberOfHorizontalDisplays = 10;
int numberOfVerticalDisplays = 1;
int HourPosRect5[4] = {41,51,61,71};
int HourPosRect1[4] = {1,11,21,31};
int MinPosBars[11] = {40,43,46,51,54,57,62,65,68,73,76};
int MinPosRect[4] = {1,11,21,31};
int yPos = 0;
int Hori = 2; // 2 for bars 8 for rectangle
int Vert = 8;
int numHour5;
int numHour1;
int numMinBars;
int numMinRect;
int H5rect;
int H1rect;
int Mbar;
int Mrect;
unsigned long currentMillis;
unsigned long startTimer;
bool LightON;
byte Year ;
byte Month ;
byte Date ;
byte DoW ;
byte Hour ;
byte Minute ;
byte Second ;
bool Century=false;
bool h12 ;
bool PM ;
const char *WeekDay[] = { "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado","Domingo" };
//const char *Mon[] = {"XXX", "ENE", "FEB", "MAR", "ABR", "MAY", "JUN", "JUL", "AGO", "SEP", "OCT", "NOV", "DIC"};
bool END;
int Block[7];
int dispPos=0;
int setVal=0;
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 20
#define CLK_PIN 13 // or SCK
#define DATA_PIN 11 // or MOSI
#define pinMin 10 // Minute Matrix
#define pinHour 9 // Hour Matrix
SSD1306AsciiAvrI2c win;
Max72xxPanel matMin = Max72xxPanel(pinMin, numberOfVerticalDisplays, numberOfHorizontalDisplays);
Max72xxPanel matHour = Max72xxPanel(pinHour, numberOfVerticalDisplays, numberOfHorizontalDisplays);
DS3231 Clock;
void setup()
{
pinMode(pinLight, OUTPUT);
pinMode(GetBtn, INPUT);
pinMode(SetBtn, INPUT);
matMin.setIntensity(2);
matMin.setRotation(0);
matHour.setIntensity(2);
matHour.setRotation(0);
matMin.fillScreen(LOW); matMin.write();
matHour.fillScreen(LOW); matHour.write();
Wire.begin();
win.begin(&SH1106_128x64, 0x3c);
win.setFont(System5x7);
win.clear();
Clock.setClockMode(false);
//Clock.setSecond(0);
//Clock.setMinute(54);
//Clock.setHour(18);
Block[0] = Clock.getYear(), DEC;
Block[1] = Clock.getMonth(Century), DEC;
Block[2] = Clock.getDate(), DEC;
Block[3] = Clock.getDoW(), DEC;
Block[4] = Clock.getHour(h12,PM), DEC;
Block[5] = Clock.getMinute(),DEC;
Block[6] = Clock.getSecond(),DEC;
win.println("RTC hora actual es ");
win.println("---------------------");
if(Block[2]<10) {win.print("0");}
win.print(Block[2]);
win.print(".");
if(Block[1]<10) {win.print("0");}
win.print(Block[1]);
win.print(". 20");
win.print(Block[0]);
win.print(" ");
//Clock.setClockMode(false);
win.print(Block[4]);
win.print(":");
win.print(Block[5]);
win.print(":");
win.println(Block[6]);
win.println(" ");
win.println("<- Boton: ajuste hora");
win.println(" ");
win.println("Boton -> start reloj");
while (!digitalRead(GetBtn) && !digitalRead(SetBtn)) {;}
if(digitalRead(SetBtn)) {analogWrite(pinLight, 100);}
// **************** NOW INPUT DATA *******************
if (digitalRead(GetBtn))
{
win.clear();
delay(200);
InputData();
}
win.clear();
// Set Clock Condition
//analogWrite(pinLight, 100);
delay(1000);
}
void loop()
{
startTimer=millis();
if (startTimer > currentMillis+1000)
{
showTime();
if (LightON)
{ LightON=false; analogWrite(pinLight, 0);}
else
{ LightON=true; analogWrite(pinLight, 100);}
currentMillis=millis();
}
matMin.fillScreen(LOW);
matHour.fillScreen(LOW);
Hour = Clock.getHour(h12,PM);
Minute = Clock.getMinute();
// calculate Hour fields
numHour5 = Hour/5;
numHour1 = Hour-(numHour5*5);
//calculate Minute bars
numMinBars = Minute/5;
numMinRect = Minute-(numMinBars*5);
// draw Hour bars and fields
Hori=8;
for(H5rect=0; H5rect<numHour5; H5rect++)
{
matHour.drawRect(yPos, HourPosRect5[H5rect], Vert, Hori,HIGH);
matHour.drawRect(yPos+1, HourPosRect5[H5rect]+1, Vert-2, Hori-2,HIGH);
}
for(H1rect=0; H1rect<numHour1; H1rect++)
{
matHour.drawRect(yPos, HourPosRect1[H1rect], Vert, Hori,HIGH);
matHour.drawRect(yPos+1, HourPosRect1[H1rect]+1, Vert-2, Hori-2,HIGH);
}
Hori = 2;
for(Mbar=0; Mbar < numMinBars; Mbar++)
{
matMin.drawRect(yPos, MinPosBars[Mbar], Vert, Hori,HIGH);
}
Hori=8;
for(Mrect=0; Mrect<numMinRect; Mrect++)
{
matMin.drawRect(yPos, MinPosRect[Mrect], Vert, Hori,HIGH);
matMin.drawRect(yPos+1, MinPosRect[Mrect]+1, Vert-2, Hori-2,HIGH);
}
matMin.write();
matHour.write();
}
void InputData()
{
while (setVal<7) // input date/time values
{
if (digitalRead(GetBtn)) // ajust actual value
{
Block[setVal]++ ;
if (Block[0] > 32) {Block[0] = 22;}
if (Block[1] > 12) {Block[1] = 1;}
if (Block[2] > 31) {Block[2] = 1;}
if (Block[3] > 7 ) {Block[3] = 1;}
if (Block[4] > 23) {Block[4] = 0;}
if (Block[5] > 59) {Block[5] = 0;}
if (Block[6] > 59) {Block[6] = 0;}
delay(100);
}
if (digitalRead(SetBtn)) // set value and goto next
{
setVal++;
delay(100);
}
showInput();
delay(200);
} // ready input date/time values 0 to 5
win.clear();
win.setCursor(0,1);
win.print("Ajuste Hora listo");
while(!digitalRead(SetBtn)) {;}
SetClock();
}
void showInput()
{
win.home();
win.setFont(System5x7);
win.println("ingresar fecha/hora");
win.println("---------------------");
win.setCursor(0,2);
win.println("Ano Mes Dia Sem");
for (dispPos=0; dispPos<4; dispPos++)
{
win.setCursor((dispPos*34),3);
if (dispPos==setVal) {win.setInvertMode(true);} else {win.setInvertMode(false);}
win.setFont(cp437font8x8);
if (Block[dispPos] < 10) {win.print("0"); win.print(Block[dispPos]);} else {win.print(Block[dispPos]);}
win.setFont(System5x7);
}
win.setInvertMode(false);
win.setCursor(0,5);
win.print("Hora Minuto Segundo");
for (dispPos=4; dispPos<7; dispPos++)
{
win.setCursor(((dispPos-4)*36),6);
if (dispPos==setVal) {win.setInvertMode(true);} else {win.setInvertMode(false);}
win.setFont(cp437font8x8);
if (Block[dispPos] < 10) {win.print("0"); win.print(Block[dispPos]);} else {win.print(Block[dispPos]);}
win.setFont(System5x7);
//delay(100);
}
win.setInvertMode(false);
}
void SetClock()
{
Clock.setClockMode(false); // set to 24h
Clock.setSecond(Block[6]);
Clock.setMinute(Block[5]);
Clock.setHour(Block[4]);
Clock.setDoW(Block[3]);
Clock.setDate(Block[2]);
Clock.setMonth(Block[1]);
Clock.setYear(Block[0]);
win.setCursor(30,3);
win.print("* LISTO *");
delay(1000);
win.clear();
}
void showTime()
{
win.setFont(cp437font8x8);
win.setCursor(0,0);
win.print(Clock.getDate(), DEC);
win.print(".");
win.print(Clock.getMonth(Century), DEC);
win.print(".");
//win.print(Clock.getYear(), DEC);
win.print(" ");
win.setCursor(60,0);
win.print(WeekDay[Clock.getDoW()-1]);
win.setFont(fixed_bold10x15);
win.setCursor(20,4);
if ((Clock.getHour(h12, PM)) < 10){win.print("0");}
win.print(Clock.getHour(h12, PM));
win.print(":");
if ((Clock.getMinute()) < 10){win.print("0");}
win.print(Clock.getMinute());
win.print(":");
if ((Clock.getSecond()) < 10){win.print("0");}
win.print(Clock.getSecond());
win.print(" ");
}
The ESP32 Version is this one:
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <SH1106Wire.h>
#include <Max72xxPanel.h>
#include <DS3231.h>
#include <Wire.h>
int pinMin = 7;
int pinHour = 10;
int pinLight = 2;
int GetBtn = 0; // left button
int SetBtn = 1; // right button
//Din connects to pin 6
//CLK connects to pin 4
int numberOfHorizontalDisplays = 10;
int numberOfVerticalDisplays = 1;
int HourPosRect5[4] = {41,51,61,71};
int HourPosRect1[4] = {1,11,21,31};
int MinPosBars[11] = {40,43,46,51,54,57,62,65,68,73,76};
int MinPosRect[4] = {1,11,21,31};
int yPos = 0;
int Hori = 2; // 2 for bars 8 for rectangle
int Vert = 8;
int numHour5;
int numHour1;
int numMinBars;
int numMinRect;
int H5rect;
int H1rect;
int Mbar;
int Mrect;
unsigned long timer1;
unsigned long timer2;
bool LightON;
byte Year ;
byte Month ;
byte Date ;
byte DoW ;
byte Hour ;
byte Minute ;
byte Second ;
bool Century=false;
bool h12 ;
bool PM ;
const char *WeekDay[] = { "Lun", "Mar", "Mie", "Jue", "Vie", "Sab","Dom" };
const char *Mon[] = {"XXX", "ENE", "FEB", "MAR", "ABR", "MAY", "JUN", "JUL", "AGO", "SEP", "OCT", "NOV", "DIC"};
bool END;
int Block[7];
int dispPos=0;
int setVal=0;
int cy;
int cx;
int line = 10;
int chra = 7;
int cleft = 15;
//SSD1306AsciiAvrI2c win;
SH1106Wire win(0x3c, SDA, SCL);
Max72xxPanel matMin = Max72xxPanel(pinMin, numberOfVerticalDisplays, numberOfHorizontalDisplays);
Max72xxPanel matHour = Max72xxPanel(pinHour, numberOfVerticalDisplays, numberOfHorizontalDisplays);
DS3231 Clock;
void setup()
{
pinMode(pinLight, OUTPUT);
pinMode(GetBtn, INPUT);
pinMode(SetBtn, INPUT);
matMin.setIntensity(2);
matMin.setRotation(0);
matHour.setIntensity(2);
matHour.setRotation(0);
matMin.fillScreen(LOW); matMin.write();
matHour.fillScreen(LOW); matHour.write();
Wire.begin();
win.init();
win.flipScreenVertically();
win.setContrast(255);
win.setColor(WHITE);
win.cls();
//win.setFont(ArialMT_Plain_10);
//win.setTextAlignment(TEXT_ALIGN_LEFT);
Clock.setClockMode(false);
//Clock.setSecond(0);
//Clock.setMinute(54);
//Clock.setHour(18);
Block[0] = Clock.getYear(), DEC;
Block[1] = Clock.getMonth(Century), DEC;
Block[2] = Clock.getDate(), DEC;
Block[3] = Clock.getDoW(), DEC;
Block[4] = Clock.getHour(h12,PM), DEC;
Block[5] = Clock.getMinute(),DEC;
Block[6] = Clock.getSecond(),DEC;
cx=cleft;cy=0;win.drawString(cx,cy,"RTC actual time is :");
cy=line;win.drawString(cx,cy,"---------------------------------");
showTime();
cy=5*line;cx=cleft-15;
win.drawString(cx,cy,"<- adjust Hour:Start Clock ->");
win.display();
while (!digitalRead(GetBtn) && !digitalRead(SetBtn)) {;}
if(digitalRead(SetBtn)) {analogWrite(pinLight, 100);}
// **************** NOW INPUT DATA *******************
if (digitalRead(GetBtn))
{
win.cls();
delay(200);
InputData();
}
//win.cls();
// Set Clock Condition
//analogWrite(pinLight, 100);
delay(1000);
}
void loop()
{
timer2=millis();
if (timer2 > timer1+1000)
{
win.clear();
showTime();
win.display();
if (LightON)
{ LightON=false; analogWrite(pinLight, 0);}
else
{ LightON=true; analogWrite(pinLight, 100);}
timer1=millis();
}
matMin.fillScreen(LOW);
matHour.fillScreen(LOW);
Hour = Clock.getHour(h12,PM);
Minute = Clock.getMinute();
// calculate Hour fields
numHour5 = Hour/5;
numHour1 = Hour-(numHour5*5);
//calculate Minute bars
numMinBars = Minute/5;
numMinRect = Minute-(numMinBars*5);
// draw Hour bars and fields
Hori=8;
for(H5rect=0; H5rect<numHour5; H5rect++)
{
matHour.drawRect(yPos, HourPosRect5[H5rect], Vert, Hori,HIGH);
matHour.drawRect(yPos+1, HourPosRect5[H5rect]+1, Vert-2, Hori-2,HIGH);
}
for(H1rect=0; H1rect<numHour1; H1rect++)
{
matHour.drawRect(yPos, HourPosRect1[H1rect], Vert, Hori,HIGH);
matHour.drawRect(yPos+1, HourPosRect1[H1rect]+1, Vert-2, Hori-2,HIGH);
}
Hori = 2;
for(Mbar=0; Mbar < numMinBars; Mbar++)
{
matMin.drawRect(yPos, MinPosBars[Mbar], Vert, Hori,HIGH);
}
Hori=8;
for(Mrect=0; Mrect<numMinRect; Mrect++)
{
matMin.drawRect(yPos, MinPosRect[Mrect], Vert, Hori,HIGH);
matMin.drawRect(yPos+1, MinPosRect[Mrect]+1, Vert-2, Hori-2,HIGH);
}
matMin.write();
matHour.write();
}
void InputData()
{
while (setVal<7) // input date/time values
{
if (digitalRead(GetBtn)) // ajust actual value
{
Block[setVal]++ ;
if (Block[0] > 32) {Block[0] = 22;}
if (Block[1] > 12) {Block[1] = 1;}
if (Block[2] > 31) {Block[2] = 1;}
if (Block[3] > 7 ) {Block[3] = 1;}
if (Block[4] > 23) {Block[4] = 0;}
if (Block[5] > 59) {Block[5] = 0;}
if (Block[6] > 59) {Block[6] = 0;}
delay(100);
}
if (digitalRead(SetBtn)) // set value and goto next
{
setVal++;
delay(100);
}
showInput();
win.display();
delay(200);
} // ready input date/time values 0 to 5
win.cls();
cx=2*chra; cy=line;
win.drawString(cx,cy,"adjust hour ready");
win.display();
while(!digitalRead(SetBtn)) {;}
SetClock();
}
void showInput()
{
win.clear();
cx=chra; cy=0;
win.drawString(cx,cy,"input date and time");
cx=chra; cy=line; win.drawString(cx,cy,"---------------------");
cx=chra; cy=2*line;
win.drawString(cx,cy,"Year Mon Day DoW");
for (dispPos=0; dispPos<4; dispPos++)
{
cx=dispPos*30+chra+8; cy=3*line; // win.setCursor((dispPos*34),3);
//if (dispPos==setVal) {win.setColor(WHITE);} else {win.setColor(BLACK);}
if (dispPos==setVal) {win.drawRect(cx-2,cy+1,16,11);}
if (Block[dispPos] < 10) {win.drawString(cx,cy,"0"); cx+=chra; win.drawString(cx,cy,String(Block[dispPos]));} else {win.drawString(cx,cy,String(Block[dispPos]));}
}
cx=chra; cy=4*line; //win.setCursor(0,5);
win.drawString(cx,cy,"Hour Minute Second");
for (dispPos=4; dispPos<7; dispPos++)
{
cx=(dispPos-4)*40+chra; cy=5*line; //win.setCursor(((dispPos-4)*36),6);
if (dispPos==setVal) {win.drawRect(cx-2,cy+1,16,11);}
//win.setFont(cp437font8x8);
if (Block[dispPos] < 10) {win.drawString(cx,cy,"0"); cx+=chra; win.drawString(cx,cy,String(Block[dispPos]));} else {win.drawString(cx,cy,String(Block[dispPos]));}
//win.setFont(System5x7);
//delay(100);
}
}
void SetClock()
{
Clock.setClockMode(false); // set to 24h
Clock.setSecond(Block[6]);
Clock.setMinute(Block[5]);
Clock.setHour(Block[4]);
Clock.setDoW(Block[3]);
Clock.setDate(Block[2]);
Clock.setMonth(Block[1]);
Clock.setYear(Block[0]);
win.cls();
cx=2*chra; cy=0; //win.setCursor(30,3);
win.drawString(cx,cy,"* Clock time set to : *");
showTime();
win.display();
delay(2000);
}
void showTime()
{
cx=cleft;cy=2*line;
win.drawString(cx,cy,WeekDay[Clock.getDoW()]);cx+=3*chra;
if(Clock.getDate()<10) {win.drawString(cx,cy,"0");cx+=chra;}
win.drawString(cx,cy,String(Clock.getDate()));
if(Clock.getDate()>9) {cx+=chra;}
cx+=chra;win.drawString(cx,cy,".");
cx+=chra; win.drawString(cx,cy,Mon[Clock.getMonth(Century)]);cx+=2*chra;
if(Block[1]>9) {cx+=chra;}
cx+=2*chra;win.drawString(cx,cy,String(Clock.getYear()+2000));
cy=3*line+5;cx=cleft+20;
if(Clock.getHour(h12,PM)<10) {win.drawString(cx,cy,"0");cx+=chra;}
win.drawString(cx,cy,String(Clock.getHour(h12,PM)));
if(Clock.getHour(h12,PM)>9) {cx+=chra;}
cx+=chra;win.drawString(cx,cy,":");
if(Clock.getMinute()<10) {cx+=chra;win.drawString(cx,cy,"0");}
cx+=chra;win.drawString(cx,cy,String(Clock.getMinute()));
if(Clock.getMinute()>9) {cx+=chra;}
cx+=chra;win.drawString(cx,cy,":");
if(Clock.getSecond()<10) {cx+=chra;win.drawString(cx,cy,"0");}
cx+=chra;win.drawString(cx,cy,String(Clock.getSecond()));
//win.display();
}
Just for understanding this strange project is a special clock unique in the world which you can find in the city of Berlin.
I know that NANO works with 5V and ESP with 3.3V
I know that these Matrix displays work with 5V powersupply and 5V logic signal level
I know that these Matrix displays need to be powered externally with a strong powersupply (I am using a 5V 3A powersupply but these displays are pretty small and on the NANO it works with a simple 2A cellphone charger)
I know that the GND of processor and matrix devices need to be connected together
I am also using a levelshifter for the SPA signals. Actually with or without levelshifter there is the same issue.
Somebody has an idea what this strange issue is about ?