I'm currently creating a button box that features 9 2-digit displays. These will be split into banks of 3 to display 3 different 6 digit numbers pulled from whatever game it's attached to (KSP is up first).
The digits are connected to the first 3 shift registers, and segments all connected to the 4th shift register.
Currently I am trying to get the segment code working.
I had 2 digits set up to test and was able to give it a value which it prints on the displays.
At first I had ghosting problems, but fixed it by creating a function to turn all pins off before moving to the next digit (as suggested in many other similar posts on this forum).
I couldn't find a library supporting sev seg displays and more than 2 shift registers but did find one that allowed me to treat the 74HC595 pins as normal pins using something similar to digital write
reg.pinOn/Off(shPin#)`
vs.
digitalWrite(#, HIGH/LOW)
Using this as a base I (attempted to) write my own seven seg driving code, which worked for 2 digits! I then moved up to 6 digits aaaand hello flickering.
Previously there were delays of 1ms after switching all digits/segments off, and another delay of 1ms after switching them back on. I've since removed these and it's appeared to have no impact on the visual output.
This is my first proper coding project, having avoided it most my life due it generally confusing me. I did look at writing directly to the shift register and shifting the 0's and 1's out directly but made a mess of it which prompted me to find the ShiftOutX library.
I feel like the Arduino isn't able to process my code fast enough / my code is too badly written to refresh the display at the rate required due to the fact that removing the delay function had no effect. Or I've put something somewhere I shouldn't.
So far I've;
- Swapped the order that the digit and segments pins get switched on/off - segments first is darker but flickers at the same rate.
- Added 0.47uf caps between the vcc and gnd of each 74HC595. Unfortunately I don't have any 0.1uf caps to hand so this could also be a culprit but I'd like to check the code out before ordering more parts (again).
- Split all off <sdOff()> into segOff() and digOff() but this did nothing more than increase the size of the code.
Any thoughts or input would be greatly appreciated!
Hardware:
Arduino Pro Micro
4 x 74HC595 Shift Registers
3 x Common Cathode 18 pin 7 seg displays (E20561-J-PG-0-W) (Datasheet here)
6 x 1k resistors (1 on each digit, 1k just used for testing)
Code:
#include <ShiftOutX.h>
#include <ShiftPinNo.h>
shiftOutX reg(4, 6, 5, MSBFIRST, 4);
uint64_t value = 123456;
uint64_t segPin[8] = {shPin26, shPin27, shPin28, shPin29, shPin30, shPin31, shPin32, shPin25};
uint64_t digPin[6] = {shPin1, shPin2, shPin3, shPin4, shPin5, shPin6};
//int nSegs = 2;
int i = 0;
int digit1 = 0;
int digit2 = 0;
int digit3 = 0;
int digit4 = 0;
int digit5 = 0;
int digit6 = 0;
int segVal = 0;
int digVal = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void sdOff() {
reg.pinOn(digPin[0]); // digits vvv
reg.pinOn(digPin[1]);
reg.pinOn(digPin[2]);
reg.pinOn(digPin[3]);
reg.pinOn(digPin[4]);
reg.pinOn(digPin[5]);
reg.pinOff(segPin[0]); // segments vvv
reg.pinOff(segPin[1]);
reg.pinOff(segPin[2]);
reg.pinOff(segPin[3]);
reg.pinOff(segPin[4]);
reg.pinOff(segPin[5]);
reg.pinOff(segPin[6]);
reg.pinOff(segPin[7]);
delay(1);
}
void segTable(int segVal) {
if (segVal == 48) { //0
reg.pinOn(segPin[0]);
reg.pinOn(segPin[1]);
reg.pinOn(segPin[2]);
reg.pinOn(segPin[3]);
reg.pinOn(segPin[4]);
reg.pinOn(segPin[5]);
}
else if (segVal == 49) { //1
reg.pinOn(segPin[1]);
reg.pinOn(segPin[2]);
}
else if (segVal == 50) { //2
reg.pinOn(segPin[0]);
reg.pinOn(segPin[1]);
reg.pinOn(segPin[3]);
reg.pinOn(segPin[4]);
reg.pinOn(segPin[6]);
}
else if (segVal == 51) { //3
reg.pinOn(segPin[0]);
reg.pinOn(segPin[1]);
reg.pinOn(segPin[2]);
reg.pinOn(segPin[3]);
reg.pinOn(segPin[6]);
}
else if (segVal == 52) { //4
reg.pinOn(segPin[1]);
reg.pinOn(segPin[2]);
reg.pinOn(segPin[5]);
reg.pinOn(segPin[6]);
}
else if (segVal == 53) { //5
reg.pinOn(segPin[0]);
reg.pinOn(segPin[2]);
reg.pinOn(segPin[3]);
reg.pinOn(segPin[5]);
reg.pinOn(segPin[6]);
}
else if (segVal == 54) { //6
reg.pinOn(segPin[0]);
reg.pinOn(segPin[2]);
reg.pinOn(segPin[3]);
reg.pinOn(segPin[4]);
reg.pinOn(segPin[5]);
reg.pinOn(segPin[6]);
}
else if (segVal == 55) { //7
reg.pinOn(segPin[0]);
reg.pinOn(segPin[1]);
reg.pinOn(segPin[2]);
}
else if (segVal == 56) { //8
reg.pinOn(segPin[0]);
reg.pinOn(segPin[1]);
reg.pinOn(segPin[2]);
reg.pinOn(segPin[3]);
reg.pinOn(segPin[4]);
reg.pinOn(segPin[5]);
reg.pinOn(segPin[6]);
}
else if (segVal == 57) { //9
reg.pinOn(segPin[0]);
reg.pinOn(segPin[1]);
reg.pinOn(segPin[2]);
reg.pinOn(segPin[5]);
reg.pinOn(segPin[6]);
}
}
void digTable(int digVal) {
if (digVal == 0) {
reg.pinOff(digPin[0]);
}
else if (digVal == 1) {
reg.pinOff(digPin[1]);
}
else if (digVal == 2) {
reg.pinOff(digPin[2]);
}
else if (digVal == 3) {
reg.pinOff(digPin[3]);
}
else if (digVal == 4) {
reg.pinOff(digPin[4]);
}
else if (digVal == 5) {
reg.pinOff(digPin[5]);
}
}
void loop() {
// put your main code here, to run repeatedly:
char valueArray[7];
dtostrf(value, 6, 0, valueArray);
int digit1 = valueArray[0];
int digit2 = valueArray[1];
int digit3 = valueArray[2];
int digit4 = valueArray[3];
int digit5 = valueArray[4];
int digit6 = valueArray[5];
int digit[6] = {digit1, digit2, digit3, digit4, digit5, digit6};
for (int i = 0; i <= 5; i++) {
digTable(digVal = i);
segTable(segVal = digit[i]);
sdOff();
i++;
segTable(segVal = digit[i]);
digTable(digVal = i);
sdOff();
i++;
segTable(segVal = digit[i]);
digTable(digVal = i);
sdOff();
i++;
segTable(segVal = digit[i]);
digTable(digVal = i);
sdOff();
i++;
segTable(segVal = digit[i]);
digTable(digVal = i);
sdOff();
i++;
digTable(digVal = i);
segTable(segVal = digit[i]);
sdOff();
}
/* value = value + 1;
if (value == 999999) {
value = 0;
}*/
}
void disp(char valueArray[]) {
}
Here's a roughly done schematic covering how the displays and shift registers are wired up
Latch goes to pin 4 on the pro micro, Clock to 5 and Data/Ser to 6.
Not shown is a 1k resistor on each digit line. (1k used for testing purposes as I'd had a mountain of them to hand)
First time posting on a forum so if I've missed something please let me know.
I'm also aware I could just get a MAX LED driver and be done with it, but so far on this part of the project I've gone through MCP23018's, MCP23017's and now finally these shift registers, so it's more a point of making it work with what I've got instead of giving up and buying another chip again.