/* Author: Matt Wesolowski. Go Green. Date: 9/1/2015 Revision#: 34,236,209,156 (Good approximation) How it works: Multiplexing Change "pause" below to ~500, run the program and then change pause to about ~250. Run again. Continue to decrease the size of "pause". :) That should be enough to give you a perfect explaination. I've found the display works best with pause of 6ms. Very simple way creating ANY (speedometer?) numberic display if you are not a programmer, like me... I've done my best to comment EVERYTHING to make things clear. I know when I google things, I hate it when programmers do not annotate their code (HELP me learn). */ //Define internal variables unsigned long count = 1; unsigned int sec = 0; //Input default time when clock starts up byte minute = 55; byte hour = 12; #define pause 6 /* Why have a pause? I've found that there are artifacts of adjacent digits with a lower pause value. Anyone know why this is? Having the pause clears things up and provides a great way of demoing this code. Name | Arduino Pin | PORT | BIT | OTHER A Pin 4 D B0001.0000 LSB, 1 place in a binary number B Pin 5 D B0010.0000 2 place in a binary number C Pin 6 D B0100.0000 4 place in a binary number D Pin 7 D B1000.0000 MSB, 8 place in a binary number Digit1 Pin 3 D B0000.1000 Controls common anode of least significant Digit1, HIGH sets digit as active, LOW inactive Digit2 Pin 9 B B0000.0010 Controls common anode of Digit2 Digit3 Pin 10 B B0000.0100 Controls common anode of Digit3 Digit4 Pin 11 B B0000.1000 Controls common anode of most significant Digit4 */ void setup(){ DDRD = DDRD | B11111100; //Initialize Pins 2-7 as OUTPUTS //These bits ^^ map to the Tx & Rx pins on the Arduino respectively, so I left them alone. DDRB = DDRB | B00111111; //Initialize Pins 8-13 as OUTPUTS // These bits ^^ map to the crystal pins and are not usable. //Increase PWM Frequency TCCR1B = TCCR1B & B00000010; //Sets PWM Frequency to ~32KHz for D9 & D10 TCCR2B = TCCR2B & B00000010; //Sets PWM Frequency to ~32KHz for D3 & D11 /* The purpose of speeding up the PWM frequency is so that I can eventually PWM the pins assosicated with the anodes of the 7-segment leds. This will allow me to dim the clock. A higher PWM speed will reduce the flickering of the display. Dimming the display never worked in the past. This is because of my previously SLOW-to-execute code. Using direct port/pin manipulation is less intuitive, but it speeds things up dramatically */ } void loop(){ // BEGINNING OF LOOP //Count Seconds if( millis()/1000 == count ){ sec++; count++; } //Count Minutes if( sec == 60 ){ minute++; sec=0; } //Count Hours if( minute == 60 ){ hour++; minute=0; } //Reset if( hour == 13 ){ //I like my 12 hour time best. Plus, clock is hardwired to only display either a 1 or nothing on Digit4 hour = 1; minute = 0; sec = 0; } //Writing to Digit 1 /*Notice below that I have commented out my SLOW, but intuitive code. The code below the commented code is a direct substitute and is essentially doing the same thing. BUT using direct port/pin manipulation is MUCH faster. I kept the slow, commmented-out code as a good comparison for new programmers. Everything looks much more clean without all my annotations.*/ //digitalWrite(digit1,HIGH); //Sources current to the common anode on Digit1 //digitalWrite(digit2,LOW); //Set the other digits OFF so we can focus on Digit1 //digitalWrite(digit3,LOW); //digitalWrite(digit4,LOW); PORTB = PORTB & B00000000; // Set anode of digit2:4 OFF PORTD = PORTD | B00001000; // Set anode of digit1 ON // ^^ This is directly controlling your ATmega328 chip and is behind the scenes of all of the Arduino functions if( minute == 0 || minute == 10 || minute == 20 || minute == 30 || minute == 40 || minute == 50 ){ //digitalWrite(A,LOW); //0000 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00001000; //This one line can replace the above four lines. } if( minute == 1 || minute == 11 || minute == 21 || minute == 31 || minute == 41 || minute == 51 ){ //digitalWrite(A,HIGH); //0001 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD | B00001000; //Clear register. Having a 1 prevents Digit1 from turning OFF PORTD = PORTD | B00010000; //Send binary 1 to decoder } if( minute == 2 || minute == 12 || minute == 22 || minute == 32 || minute == 42 || minute == 52 ){ //digitalWrite(A,LOW); //0010 //digitalWrite(B,HIGH); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00001000; //Clear register PORTD = PORTD | B00100000; //Send binary 2 to decoder } if( minute == 3 || minute == 13 || minute == 23 || minute == 33 || minute == 43 || minute == 53 ){ //digitalWrite(A,HIGH); //0011 //digitalWrite(B,HIGH); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00001000; PORTD = PORTD | B00110000; //Send binary 3 to decoder } if( minute == 4 || minute == 14 || minute == 24 || minute == 34 || minute == 44 || minute == 54 ){ //digitalWrite(A,LOW); //0100 //digitalWrite(B,LOW); //digitalWrite(C,HIGH); //digitalWrite(D,LOW); PORTD = PORTD & B00001000; PORTD = PORTD | B01000000; //Send binary 4 to decoder } if( minute == 5 || minute == 15 || minute == 25 || minute == 35 || minute == 45 || minute == 55 ){ //digitalWrite(A,HIGH); //0101 //digitalWrite(B,LOW); //digitalWrite(C,HIGH); //digitalWrite(D,LOW); PORTD = PORTD & B00001000; PORTD = PORTD | B01010000; //Send binary 5 to decoder } if( minute == 6 || minute == 16 || minute == 26 || minute == 36 || minute == 46 || minute == 56 ){ //digitalWrite(A,LOW); //0110 //digitalWrite(B,HIGH); //digitalWrite(C,HIGH); //digitalWrite(D,LOW); PORTD = PORTD & B00001000; PORTD = PORTD | B01100000; //Send binary 6 to decoder } if( minute == 7 || minute == 17 || minute == 27 || minute == 37 || minute == 47 || minute == 57 ){ //digitalWrite(A,HIGH); //0111 //digitalWrite(B,HIGH); //digitalWrite(C,HIGH); //digitalWrite(D,LOW); PORTD = PORTD & B00001000; PORTD = PORTD | B01110000; //Send binary 7 to decoder } if( minute == 8 || minute == 18 || minute == 28 || minute == 38 || minute == 48 || minute == 58 ){ //digitalWrite(A,LOW); //1000 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(D,HIGH); PORTD = PORTD & B00001000; //Clear register PORTD = PORTD | B10000000; //Send binary 8 to decoder } if( minute == 9 || minute == 19 || minute == 29 || minute == 39 || minute == 49 || minute == 59 ){ //digitalWrite(A,HIGH); //1001 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(D,HIGH); PORTD = PORTD & B00001000; PORTD = PORTD | B10010000; //Send binary 9 to decoder } delay(pause); //Writing to Digit 2 //digitalWrite(digit1,LOW); //digitalWrite(digit2,HIGH); //Sources current to the common anode of Digit2 //digitalWrite(digit3,LOW); //digitalWrite(digit4,LOW); PORTD = PORTD & B00000000; // Set anode of digit1 OFF PORTB = PORTB & B00000000; // Set anode of digit3:4 OFF PORTB = PORTB | B00000010; // Set anode of digit2 ON, Pin 9 if( minute >= 0 && minute <= 9 ){ //digitalWrite(A,LOW); //0000 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; //Send binary 0 to decoder aka Digit 2 } if( minute >= 10 && minute <=19 ){ //digitalWrite(A,HIGH); //0001 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B00010000; //Send binary 1 to decoder. Display 1 in Digit2 } if( minute >= 20 && minute <= 29 ){ //digitalWrite(A,LOW); //0010 //digitalWrite(B,HIGH); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B00100000; } if( minute >= 30 && minute <= 39 ){ //digitalWrite(A,HIGH); //0011 //digitalWrite(B,HIGH); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B00110000; } if( minute >= 40 && minute <= 49 ){ //digitalWrite(A,LOW); //0100 //digitalWrite(B,LOW); //digitalWrite(C,HIGH); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B01000000; } if( minute >= 50 && minute <= 59 ){ //digitalWrite(A,HIGH); //0101 //digitalWrite(B,LOW); //digitalWrite(C,HIGH); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B01010000; } delay(pause); //Writing to Digit 3 //digitalWrite(digit1,LOW); //digitalWrite(digit2,LOW); //digitalWrite(digit3,HIGH); //digitalWrite(digit4,LOW); PORTD = PORTD & B00000000; // Set anode of digit1 OFF PORTB = PORTB & B00000000; // Set anode of digit2&4 OFF PORTB = PORTB | B00000100; // Set anode of digit3 ON if( hour == 1 || hour == 11 ){ //digitalWrite(A,HIGH); //0001 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B00010000; } if( hour == 2 || hour == 12 ){ //digitalWrite(A,LOW); //0010 //digitalWrite(B,HIGH); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B00100000; } if( hour == 3 ){ //digitalWrite(A,HIGH); //0011 //digitalWrite(B,HIGH); //digitalWrite(C,LOW); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B00110000; } if( hour == 4 ){ //digitalWrite(A,LOW); //0100 //digitalWrite(B,LOW); //digitalWrite(C,HIGH); //digitalWrite(D,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B01000000; } if( hour == 5 ){ //digitalWrite(A,HIGH); //0101 //digitalWrite(B,LOW); //digitalWrite(C,HIGH); //digitalWrite(b3,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B01010000; } if( hour == 6 ){ //digitalWrite(A,LOW); //0110 //digitalWrite(B,HIGH); //digitalWrite(C,HIGH); //digitalWrite(b3,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B01100000; } if( hour == 7 ){ //digitalWrite(A,HIGH); //0111 //digitalWrite(B,HIGH); //digitalWrite(C,HIGH); //digitalWrite(b3,LOW); PORTD = PORTD & B00000000; PORTD = PORTD | B01110000; } if( hour == 8 ){ //digitalWrite(A,LOW); //1000 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(b3,HIGH); PORTD = PORTD & B00000000; PORTD = PORTD | B10000000; } if( hour == 9 ){ //digitalWrite(A,HIGH); //1001 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(b3,HIGH); PORTD = PORTD & B0000000; PORTD = PORTD | B10010000; } if( hour == 10 ){ //digitalWrite(A,LOW); //0000 //digitalWrite(B,LOW); //digitalWrite(C,LOW); //digitalWrite(b3,LOW); PORTD = PORTD & B00000000; } //Notice there is intentionally no pause here. //This is because the pins that control the numbers in digits1-3 are not needed to control the number on digit4. //Digit4 is controlled only by Pin 11. //Writing to Digit 4 if( hour > 9){ //digitalWrite(digit4,HIGH); //Allows common anode of digit4 to source current PORTB = PORTB | B00001000; // Set anode of digit4 ON } delay(pause); } //END OF LOOP