So I thought I would make a code for them. I made the code have as many features yet be as simple to understand as possible. It can be a 12 or 24 hour clock (even automates a am/pm function), have common anode or cathode displays, have anywhere from 1 to 6 displays, and show time in either octal or decimal.
Anyway, I thought I would upload the code, but first here is a picture of the pin mappings (only pay attention to the left digit, the right is for changing how the numbers are displayed): To hook it up, connect each of the same segments together for each pin (the middle segment of all of the digits together, etc.) and connect all of the common pins and connected segment pins to the Arduino.
Any problems, need any help, or if you find any bugs, please tell me.
Code:
Code: Select all
//Driving any number of 7 segment displays using an Arduino, code needs to be modified if displaying more than 6 digits
//defaulted to display as many digits of hours:minutes:seconds as digits there are.
//The displays must have either 1 common anode or 1 common cathode per digit
//The different segments on all the digits are connected together (top to top, bottom to bottom, middle to middle, etc)
//created by Joshua Little on 11/26/2012
//settings
byte twentyFourHours = 0; //set to 1 for a 24 hour clock, set to 0 for a 12 hour clock.
byte decimal = 0; //set to 1 for decimal (normal) numbers or 0 for octal (base 8) numbers. I suggest not turning to octal unless you know what it is or want to learn it
//set the time
byte hours = 16; //use to set time when not using RTC. Change to desired time. note: MUST BE SET IN 24 HOUR TIME!
byte minutes = 14; //how to convert to 24 hour time: if time is pm, then add 12 to the hours. ex: 3 am becomes 3, but 3pm becomes 12 + 3 = 15.
byte seconds = 0;
//set the hardware (display/pins)
byte commonCathode = 1; //set to 1 for common cathode, 0 for common anode
const byte digits = 6; //the amount of digits being driven
byte commonPin[(digits + 1)] = {2, 3, 4, 5, 6, 7}; //The common pins, highest order to least order (example: 10s hours, hours, 10s minutes, minutes). Define as many pins as needed
byte segmentPin[9] = {8, 9, 10, 11, 12, 13, A0, A1}; //The pins for each segment of the display. Define to desired numbers. Refer to picture for map of pins to segments.
//Or you could read this: {top_right, bottom_right, bottom_left, bottom, middle, dot, top, top_right};
//determines what the display shows, so don't modify unless you know what you are doing.
//CHANGING THIS CHANGES THE NUMBERS TO SHOW SOMETHING ELSE (example: if //2 is changed from 93 to 220 and the time is 2:23:65, it will show E:E3:65 instead.
byte numbers[11] = { //the data which tells the arduino what to display for each digit. Recorded in decimal where the first segment pin is worth 1, second 2, third 4, fourth 8, etc.
207, //0
3, //1
93, //2
91, //3
147, //4
218, //5
222, //6
67, //7
223, //8
219 //9
};
//automated
byte pm = 0; //note: this is automated and changing this does NOT affect code. Also, this is currently not programmed to display.
byte commonOn = 0; //Determines whether HIGH or LOW is on or off for the pins. This step is automated, so DO NOT MODIFY
byte commonOff = 0;
byte segmentOn = 0;
byte segmentOff = 0;
unsigned long RAM = 0; //temporary memory used to sense a change.
//if you want to display custom data, remove the timeManipulation() function in the loop and set this data to what you want the displays to display
byte times[7] = {0, 0, 0, 0, 0, 0}; //times split into each digit, changing here does not affect anything
void setup(){
Serial.begin(9600);
for(byte c = 0; c < digits; c++){ //each common pin
pinMode(commonPin[c], OUTPUT);
}
for(byte s = 0; s < 8; s++){ //each segment pin
pinMode(segmentPin[s], OUTPUT);
}
if(commonCathode == 1){ //sets what is on or off for the pins
commonOff = 1;
segmentOn = 1;
}
else{
commonOn = 1;
segmentOff = 1;
}
}
void loop(){
clock(); //simple millis() clock to make sure the display works. I recomend using a RTC clock or some other accurate source to keep time instead.
timeManipulation(); //converts the time into data to put on the display remove this and manipulate the times[] data to display something else
displayTime(); //displays the data on the display
}
void clock(){ //a basic clock using the Arduino's millis() function note: this is not an accurate function to base the clock off of and is mainly used for testing.
if(time != RAM){ //millis()/1000 is the seconds that the Arduino has been on. It resets to 0 after approximitally 50 days, but that should NOT affect this sketch.
seconds++;
RAM = time;
}
if(seconds > 59){ //seconds rollover
seconds = 0;
minutes++;
}
if(minutes > 59){ //minutes rollover
minutes = 0;
hours++;
}
if(hours > 23){
hours = 0;
}
}
void timeManipulation(){ //converts hours, seconds, minutes into data the Arduino can display
if(hours == 0 || hours > 11){ //sets pm
pm = 1;
}
else{
pm = 0;
}
if(decimal == 1){ //for decimal numbers
for(byte t = 0; t < 6; t++){
if(hours > (t*10) - 1){ //checks to see what digit is in the 10s place
times[0] = t;
times[1] = hours - (10*t);
}
if(minutes > (t*10) - 1){ //checks to see what digit is in the 10s place
times[2] = t;
times[3] = minutes - (10*t);
}
if(seconds > (t*10) - 1){ //checks to see what digit is in the 10s place
times[4] = t;
times[5] = seconds - (10*t);
}
}
if(twentyFourHours == 0){
if(hours == 0){ //midnight or 0 hours 24-hour time gets set to 12 hours 12-hour time
times[0] = 1;
times[1] = 2;
}
if(hours > 12){ //converts 24-hours into 12.
times[0] = times[0] - 1;
times[1] = times[1] - 2;
}
}
}
else{ //for octal numbers
times[0] = hours >> 3; //shifts out the 1s digit to keep only the 10s digit
times[1] = hours & 7; //7 is binary 0b111, and the & function keeps only the 1s that are common to both numbers. Example: 0b110 & 0b011 = 0b010 since there is only one 1 in the same place in both numbers
times[2] = minutes >> 3;
times[3] = minutes & 7;
times[4] = seconds >> 3;
times[5] = seconds & 7;
if(twentyFourHours == 0){
if(hours == 0){ //midnight or 0 hours 24-hour time gets set to 12 hours 12-hour time
times[0] = 1;
times[1] = 4;
}
if(hours > 12){ //converts 24-hours into 12.
times[0]--; //subtract 8
if(times[1] > 4){
times[1] = times[1] - 4; // and 4 to make a total of 12
}
else{ //if the second digit is less than 4, then 4 cannot be subtacted directly
times[0]--; //elementary math: borrow 1 from the 10s (or in this case the 8s) place
times[1] = 4 + times[1];// the borrowed 8 plus times[1] minus our subtacted 4 equals 4 plus times[1] (yes, I am doing this mostly for my own benefit)
}
}
}
}
}
void displayTime(){
for(byte d = 0; d < digits; d++){ //for each digit
digitalWrite(commonPin[d], commonOn);
for(byte s = 0; s < 8; s++){ //for each segment of the display
if(bitRead(numbers[times[d]], s) == 1){ //checks each display segment to see if it should be on (numbers[]). Time[d] tells the numbers function what number to display.
digitalWrite(segmentPin[s], segmentOn);
}
}
for(byte f = 0; f < 8; f++){ //turns all of the segments off
digitalWrite(segmentPin[f], segmentOff);
}
digitalWrite(commonPin[d], commonOff); //turns the digit off
}
}