Hello. Over the last few days, I have been writing a program for a 8-digit 7-segment driven by a dual 74hc595 setup that I designed in tinkercad while attending my career technical center. The link for the project will be at the end of this post if you want a visualization of the hardware. The problem that I initially had was displaying 8 characters at a time using a for() loop that displayed the same character on every "digit" of the display. Now, despite having multiplexed the entire display with two nested for loops, iterating each individual segment through each individual digit without having any problems, when taking the "draw the whole letter then go to the next digit" approach, the display began to flicker. I figured as maybe the dual-shift register setup didnt have enough power to flicker through all 8 digits 8 segments at a time, that the solution would be to do what I originally did but only display segments if they should be displayed. However, the same flickering issue reoccurred, even though I was only displaying the segments of a single digit. I tried this program on both an Arduino Uno and and Arduino Mega with similar flickering affects. I'm hoping someone can tell me this is a simple problem with my code, and not a physical constraint of the arduino or the shift registers, as I don't have the money to buy "better" versions of either. The code seems to work in TinkerCad, so I'm stumped on this. Thanks for the help
Here's my code:
// ArduinoSTL - Version: Latest
//Timer//
long startTime = millis();
long thisTime;
long elapsedTime;
//Pins//
int dataPin = 2;
int latchPin = 3;
int clockPin = 4;
int order[8] {4, 6, 8, 7, 6, 3, 2, 1};
char chars[1] {'A'};
byte cBytes[1] {B11111100};
bool debug=false;
void testSetup()
{
}
void testLoop()
{
}
void setup()
{
//Debug
Serial.begin(9600);
//Pins
pinMode(dataPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
//"Just to be safe"
digitalWrite(latchPin,LOW);
digitalWrite(clockPin,LOW);
if(debug){testSetup();}
}
void loop()
{
//Timer
thisTime=millis();
for(int i=0; i<8; i++)
{
displayChar('A', 1, i);
}
if(debug){testLoop();}
//Timer
elapsedTime=thisTime-startTime;
}
void testOrder()
{
for(int i=0; i<8; i++)
{
pushByte(255-1, true);
pushByte(powTwo(i));
Serial.println(powTwo(i));
dump();
delay(1000);
}
}
byte changeOrder(byte b, int o[8])
{
}
void pushBit(int i)
{
bool b = convInt(i);
digitalWrite(clockPin, LOW);
digitalWrite(dataPin, b);
digitalWrite(clockPin, HIGH);
}
//Push 8 bits
void pushByte(byte B){pushByte(B, false);} //Default
void pushByte(byte B, bool msb)
{
bool bArray[8];
byteToArray(B, bArray);
//Push bit per boolean array value
if(!msb){
for(int i=0;i<8;i++)
{
pushBit(bArray[i]);
}
}else if(msb)
{
for(int i=7;i>=0;i--)
{
pushBit(bArray[i]);
}
}
}
//PULL THE LEVER
void dump()
{
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
}
//Convert 0 or 1 to true or false (not in that order LOL)
bool convInt(int i)
{
if(i==0){return false;}
else if(i==1){return true;}
else{Serial.println("Error in convInt, 1 or 0 not used");}
return false;
}
//Because I can't remember
int powTwo(int i){return pow(2, i)+.5;}
//Display char segment at index(i)
void displayChar(char c, int digit){displayChar(c, digit, false, 0);} //default
void displayChar(char c, int digit, int i){displayChar(c,digit,true,i);} //Display char segment at index(i)
void displayChar(char c, int digit, bool index, int i)
{
bool cArray[8];
digit-=1; //Programming starts with 0, we want the user to input the digit starting with 1
digit = powTwo(digit); // Convert digit to binary value
digit=255-digit; //Flipped bc "anode", duh
//Converts ASCII byte to "svenByte"
for(int i=0;i<sizeof(chars)/sizeof(chars[1]);i++)
{
if(c==chars[i]){
c=cBytes[i];
}
else if(c!=0)
{
c=0;
Serial.println("displayChar byte conversion failure");
}
}
//changeOrder(c)
byteToArray(c, cArray);
if(!index){
pushByte(digit, true); //Push ground bit first
pushByte(c);
dump(); //PULL THE LEVER!!!
}
else{
if(cArray[i]){
pushByte(digit, true);
pushByte(powTwo(i));
dump();
}
}
}
//Convert byte to boolean array
bool byteToArray(byte B, bool *bo)
{
for(int i=7;i>=0;i--)
{
int p=(powTwo(i));
if(B>=p)
{
bo[i]=true;
B-=p;
}
else{bo[i]=false;}
}
return bo;
}
bool timer(int time){
if(elapsedTime % time == 0){return true;}
else{return false;}
}
And here's the link to the TinkerCad setup:
Click me
(the link expires in 360-something hours, I can refresh it if necessary. Feel free to make changes, as I made a back-up of the file