int pin = 5; // D7 D7 D7
const int MIDDLE = pin++; // D6 D8
const int TOP_LEFT = pin++; // D6 D8
const int TOP = pin++; // D6 D8
const int TOP_RIGHT = pin++; // D5 D5 D5
const int BOTTOM_LEFT = pin++; // D9 D11
const int BOTTOM = pin++; // D9 D11
const int BOTTOM_RIGHT = pin++; // D9 D11
const int DOT = pin++; // D10 D10 D10 D12
// all segment values in our display
// for example ". " would be buffer[7][0] == HIGH
int buffer[8][2];
// the time in ms for each segment to be illuminated
const int dwell = 3; // 11 or fewer ms. to eliminate flicker on Wokwi
const int duty = 1; // Time each illuminated segment will be left off after illuminating.
// the duty cycle is therefore ( dwell / duty )
// frame rate
float frameRate = 0.0; // observed frame rate
float movingAverage10frameRate = 0.0;
float averageSegmentsIlluminated = 0.0;
void setup() {
// set all segment pins to digital output
int pin = MIDDLE;
for (int i=0; i < sizeof( buffer ); i++)
pinMode( pin++, OUTPUT );
// set each digit ground pin to digital output
pinMode( A0, OUTPUT ); // 10s digit
pinMode( A1, OUTPUT ); // 1s digit
Serial.begin(115200);
}
void loop() {
int duration = 400;
for ( int i=0; i<99; i++ ){
display( i, duration );
Serial.print( "Avg. segments: " );
Serial.print( averageSegmentsIlluminated );
Serial.print( "\tFrame rate: ");
Serial.println( frameRate );
}
}
void display( int twodigit, int duration ){
byte ones = twodigit % 10;
byte tens = (byte)(int) twodigit / 10;
setGlyph( tens, 0 );
setGlyph( ones, 1 );
illuminate( duration );
}
void setGlyph( byte pattern, int digit ){
if ( pattern == ' ' )
setBlank( digit );
if ( pattern == 0 )
set0( digit );
if ( pattern == 1 )
set1( digit );
if ( pattern == 2 )
set2( digit );
if ( pattern == 3 )
set3( digit );
if ( pattern == 4 )
set4( digit );
if ( pattern == 5 )
set5( digit );
if ( pattern == 6 )
set6( digit );
if ( pattern == 7 )
set7( digit );
if ( pattern == 8 )
set8( digit );
if ( pattern == 9 )
set9( digit );
if ( pattern == '.' )
setDot( digit );
}
/* Illuminates both digits for approximately the time specified.
// Note this function reads the constants: dwell, duty
// Where dwell specifies how many ms each segment needs illumination per cycle
// and where duty specifies the sleep time after each segment's illumination cycle.
//
// Outputs
// The following two metrics are updated after each two-digit-illumination cycle:
// 1. averageSegmentsIlluminated This is a count of segments that were illuminated.
// For instance, for "11" the count would be four.
// 2. frameRate The number of complete two-digit cycles per second.
*/
void illuminate( unsigned long int duration ){
unsigned long startTime = millis();
unsigned long stopTime = startTime + duration;
int frames = 0;
while ( millis() < stopTime ) {
int segments = 0;
segments += illuminateDigit( 0, dwell, duty );
segments += illuminateDigit( 1, dwell, duty );
averageSegmentsIlluminated = 0.5f * ( averageSegmentsIlluminated + segments );
frames++;
}
float actualSeconds = ( millis() - startTime ) / 1000.0f;
frameRate = 0.5f * ( frameRate + ( frames / actualSeconds ) );
}
// connect the ground circuit for only unit 0
int illuminateDigit( int digit, int msOn, int msOff ) {
if ( digit == 0 ) {
digitalWrite( A0, LOW ); // turn on unit 0
digitalWrite( A1, HIGH ); // turn off unit 1
}
if ( digit == 1 ){
digitalWrite( A0, HIGH ); // turn off unit 0
digitalWrite( A1, LOW ); // turn on unit 1
}
int segments = 0;
if ( buffer[0][digit] == HIGH ) {
digitalWrite( MIDDLE, HIGH );
delay( msOn );
digitalWrite( MIDDLE, LOW );
delay( msOff );
segments++;
}
if ( buffer[1][digit] == HIGH ) {
digitalWrite( TOP_LEFT, HIGH );
delay( msOn );
digitalWrite( TOP_LEFT, LOW );
delay( msOff );
segments++;
}
if ( buffer[2][digit] == HIGH ) {
digitalWrite( TOP, HIGH );
delay( msOn );
digitalWrite( TOP, LOW );
delay( msOff );
segments++;
}
if ( buffer[3][digit] == HIGH ) {
digitalWrite( TOP_RIGHT, HIGH );
delay( msOn );
digitalWrite( TOP_RIGHT, LOW );
delay( msOff );
segments++;
}
if ( buffer[4][digit] == HIGH ) {
digitalWrite( BOTTOM_LEFT, HIGH );
delay( msOn );
digitalWrite( BOTTOM_LEFT, LOW );
delay( msOff );
segments++;
}
if ( buffer[5][digit] == HIGH ) {
digitalWrite( BOTTOM, HIGH );
delay( msOn );
digitalWrite( BOTTOM, LOW );
delay( msOff );
segments++;
}
if ( buffer[6][digit] == HIGH ) {
digitalWrite( BOTTOM_RIGHT, HIGH );
delay( msOn );
digitalWrite( BOTTOM_RIGHT, LOW );
delay( msOff );
segments++;
}
if ( buffer[7][digit] == HIGH ) {
digitalWrite( DOT, HIGH );
delay( msOn );
digitalWrite( DOT, LOW );
delay( msOff );
segments++;
}
return segments;
}
void digitsOff(){
digitalWrite( A0, HIGH ); // turn off unit 0
digitalWrite( A1, HIGH ); // turn off unit 1
}
void digitsOff( int ms ){
digitsOff();
delay( ms );
}
// set all segments off for the specified digit
void setBlank( int digit ) {
buffer[0][digit] = LOW;
buffer[1][digit] = LOW;
buffer[2][digit] = LOW;
buffer[3][digit] = LOW;
buffer[4][digit] = LOW;
buffer[5][digit] = LOW;
buffer[6][digit] = LOW;
buffer[7][digit] = LOW;
}
// set only the dot the the specified digit
// note this unsets any other glyph set in the digit. You only get the dot!
void setDot( int digit ) {
buffer[0][digit] = LOW;
buffer[1][digit] = LOW;
buffer[2][digit] = LOW;
buffer[3][digit] = LOW;
buffer[4][digit] = LOW;
buffer[5][digit] = LOW;
buffer[6][digit] = LOW;
buffer[7][digit] = HIGH; // DOT
}
// set a 0 figure in the the specified digit
void set0( int digit ) {
buffer[0][digit] = LOW;
buffer[1][digit] = HIGH; // TOP_LEFT
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = HIGH; // BOTTOM_LEFT
buffer[5][digit] = HIGH; // BOTTOM
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw a right-justified 1 figure in the active display(s)
void set1( int digit ) {
buffer[0][digit] = LOW;
buffer[1][digit] = LOW;
buffer[2][digit] = LOW;
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = LOW;
buffer[5][digit] = LOW;
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw a 2 figure in the active display(s)
void set2( int digit ) {
buffer[0][digit] = HIGH; // MIDDLE
buffer[1][digit] = LOW;
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = HIGH; // BOTTOM_LEFT
buffer[5][digit] = HIGH; // BOTTOM
buffer[6][digit] = LOW;
buffer[7][digit] = LOW;
}
// draw a 3 figure in the active display(s)
void set3( int digit ) {
buffer[0][digit] = HIGH; // MIDDLE
buffer[1][digit] = LOW;
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = LOW;
buffer[5][digit] = HIGH; // BOTTOM
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw a 4 figure in the active display(s)
void set4( int digit ) {
buffer[0][digit] = HIGH; // MIDDLE
buffer[1][digit] = HIGH; // TOP_LEFT
buffer[2][digit] = LOW;
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = LOW;
buffer[5][digit] = LOW;
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw a 5 figure in the active display(s)
void set5( int digit ) {
buffer[0][digit] = HIGH; // MIDDLE
buffer[1][digit] = HIGH; // TOP_LEFT
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = LOW;
buffer[4][digit] = LOW;
buffer[5][digit] = HIGH; // BOTTOM
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw a 6 figure in the active display(s)
void set6( int digit ) {
buffer[0][digit] = HIGH; // MIDDLE
buffer[1][digit] = HIGH; // TOP_LEFT
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = LOW;
buffer[4][digit] = HIGH; // BOTTOM_LEFT
buffer[5][digit] = HIGH; // BOTTOM
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw a 7 figure in the active display(s)
void set7( int digit ) {
buffer[0][digit] = LOW;
buffer[1][digit] = LOW;
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = LOW;
buffer[5][digit] = LOW;
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw an 8 figure in the active display(s)
void set8( int digit ) {
buffer[0][digit] = HIGH; // MIDDLE
buffer[1][digit] = HIGH; // TOP_LEFT
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = HIGH; // BOTTOM_LEFT
buffer[5][digit] = HIGH; // BOTTOM
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}
// draw a 9 figure in the active display(s)
void set9( int digit ) {
buffer[0][digit] = HIGH; // MIDDLE
buffer[1][digit] = HIGH; // TOP_LEFT
buffer[2][digit] = HIGH; // TOP
buffer[3][digit] = HIGH; // TOP_RIGHT
buffer[4][digit] = LOW;
buffer[5][digit] = HIGH; // BOTTOM
buffer[6][digit] = HIGH; // BOTTOM_RIGHT
buffer[7][digit] = LOW;
}