I wanted to learn about how 7 segment LCDs work, without having also to learn how to interface to and send correct data to an LCD driver. I'm very proud of how tight I've managed to make this code.
You can see it working here https://www.instagram.com/p/DKJxbdnow4E/ with an earlier version of the code in the background.
It only drives one digit (I strapped 3 digits together on the little panel I salvaged from a dead carbon monoxide monitor) and making it drive all three independently would use another 4 output pins taking the total pin count to 10, unless some external logic circuits were added - but then, might as well add a display driver?
Good fun though.
void setup() {
}
void setPin(int pin, int polarity, bool on){
if(on){ // pin is needed to be activated HIGH or LOW
pinMode(pin,OUTPUT); // so set it to OUTPUT
digitalWrite(pin,polarity); // and assign the specified polarity (HIGH or LOW)
} else { // else
pinMode(pin,INPUT); // set the pin to high impedance
}
}
void setPins(int digit){
// pins 2,3,4,5 are connected to each of the 4 "backplanes" ("common") and pins 6 and 7 are connected to the two segment subsets (in my test LCD: DP,C,B,A and D,E,G,F) in the digit
const char segs[10]={235,96,199,229,108,173,175,224,239,237}; // bit pattern stores segments to "light" for each digit 0 .. 9
unsigned int bitpattern = segs[digit]; // bit pattern for the digit we want to display
unsigned int timeslot = (millis()/2) % 8; // create a cycling timeframe with 8 slots
unsigned int polarity = timeslot % 2; // polarity alternates 01010101 across the 8 time slots
unsigned int segNumber = timeslot / 2; // segment number goes 01234567 across the 8 time slots
unsigned int comNumber = segNumber % 4; // common number goes 01230123 across the 8 time slots
setPin(2, polarity, comNumber==0); // if comNumber = 0, activate common pin 0 with polarity 0 or 1, else set to high impedance
setPin(3, polarity, comNumber==1); // if comNumber = 1, activate common pin 1 with polarity 0 or 1, else set to high impedance
setPin(4, polarity, comNumber==2); // if comNumber = 2, activate common pin 2 with polarity 0 or 1, else set to high impedance
setPin(5, polarity, comNumber==3); // if comNumber = 3, activate common pin 3 with polarity 0 or 1, else set to high impedance
setPin(6, 1-polarity, bitpattern>>segNumber & 1); // if bit "segNumber" (0 to 3) in "bitpattern" is set, activate first subset of segments with opposite polarity, else set to high impedance
setPin(7, 1-polarity, bitpattern>>(segNumber+4) & 1); // if bit "segNumber+4" (4 to 7) in "bitpattern" is set, activate second subset of segments with opposite polarity, else set to high impedance
}
void loop() {
unsigned int digit = millis()/500 % 10; // set digit = 0,1,2,3,4,5,6,7,8,9 changing twice a second
setPins(digit); // call setPins to display the digit on the LCD
}