#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define K_TDIGIT 8333ul //30Hz over 4 digits is 8333uS per digit
#define K_TBLANKING 500ul //blanking time between digits
#define K_DIGITOFF LOW
#define K_DIGITON HIGH
#define K_TUPDATEPOT 250ul //250mS between pot updates (4Hz)
// LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);
const uint8_t potPin = A0;
// Segment pins: a, b, c, d, e, f, g
const uint8_t segmentPins[7] = {2, 3, 4, 5, 6, 7, 8};
// Digit control pins (D1–D4)
const uint8_t digitPins[4] = {9, 10, 11, 12};
// Segment patterns for digits 0–9 (for common anode — 0 = ON, 1 = OFF)
const byte digits[10][7] =
{
{0, 0, 0, 0, 0, 0, 1}, // 0
{1, 0, 0, 1, 1, 1, 1}, // 1
{0, 0, 1, 0, 0, 1, 0}, // 2
{0, 0, 0, 0, 1, 1, 0}, // 3
{1, 0, 0, 1, 1, 0, 0}, // 4
{0, 1, 0, 0, 1, 0, 0}, // 5
{0, 1, 0, 0, 0, 0, 0}, // 6
{0, 0, 0, 1, 1, 1, 1}, // 7
{0, 0, 0, 0, 0, 0, 0}, // 8
{0, 0, 0, 0, 1, 0, 0} // 9
};
uint8_t digitsToDisplay[4];
char szStr[10];
void setup()
{
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Value:");
// Set segment and digit pins as outputs
for (int i = 0; i < 7; i++)
pinMode(segmentPins[i], OUTPUT);
for (int i = 0; i < 4; i++)
pinMode(digitPins[i], OUTPUT);
}
void loop()
{
uint16_t
valPot;
static uint32_t
tReadPot = 0ul;
uint32_t
tNow = millis();
if( (tNow - tReadPot) >= K_TUPDATEPOT )
{
tReadPot = tNow;
valPot = analogRead(potPin); // Read potentiometer (0–1023)
sprintf( szStr, "%4d", valPot );
lcd.setCursor(0, 1);
lcd.print(szStr); // Display value on LCD
UpdateNumber( valPot );
}
// Display the same value on 7-segment display
Update7SegDisplay();
}//loop
void UpdateNumber( uint16_t val )
{
digitsToDisplay[0] = (val / 1000) % 10;
digitsToDisplay[1] = (val / 100) % 10;
digitsToDisplay[2] = (val / 10) % 10;
digitsToDisplay[3] = val % 10;
}//UpdateNumber
void Update7SegDisplay( void )
{
static uint8_t
digState = 0,
digIdx = 0;
static uint32_t
tBlank = 0ul,
tDigit = 0ul;
uint8_t
seg;
uint32_t
tNow = micros();
switch( digState )
{
case 0:
if( (tNow - tDigit) >= K_TDIGIT )
{
tDigit = tNow;
//turn off current digit
digitalWrite(digitPins[digIdx], K_DIGITOFF);
//set segments for next digit
digIdx++;
if( digIdx == 4 )
digIdx = 0;
for(seg=0; seg<7; seg++)
digitalWrite(segmentPins[seg], digits[digitsToDisplay[digIdx]][seg]);
tBlank = tNow;
digState = 1;
}//if
break;
case 1:
if( (tNow - tBlank) >= K_TBLANKING )
{
//turn on new digit and return to state 0 to time its display
digitalWrite(digitPins[digIdx], K_DIGITON);
digState = 0;
}//if
break;
}//switch
}//Update7SegDisplay