Driving 7-segment displays with Arduino

Post here to let others know of a project you're working on.

Moderators: Chuckt, Garth, bitfogav

Post Reply [phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable
User avatar
Saimaster13
I practically live here!
I practically live here!
Posts: 176
Joined: Mon Aug 13, 2012 4:23 am
Location: Sarasota, Florida
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Driving 7-segment displays with Arduino

Post by Saimaster13 » Tue Nov 27, 2012 4:16 am

I had some 7 segment displays lying around that look like these:
Image

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):
7-segment display - 2 pin, small, green, common cathode.jpg
7-segment display - 2 pin, small, green, common cathode.jpg (40.2 KiB) Viewed 7836 times
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
  }
}
Joshua

User avatar
brad
Site Admin
Site Admin
Posts: 2578
Joined: Fri Mar 26, 2010 10:30 pm
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Re: Driving 7-segment displays with Arduino

Post by brad » Tue Nov 27, 2012 6:20 am

Another great project!

Have you kept it on for a few days to see how well it keeps time?

User avatar
Saimaster13
I practically live here!
I practically live here!
Posts: 176
Joined: Mon Aug 13, 2012 4:23 am
Location: Sarasota, Florida
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Re: Driving 7-segment displays with Arduino

Post by Saimaster13 » Tue Nov 27, 2012 9:08 am

Have you kept it on for a few days to see how well it keeps time?
Nope. I did only make this last night though.

Actually, this morning I realized there was something wrong with my clock function, and I made a little change (I've updated the code in this post.)
I could probably measure if it is off and compensate in the code to make it accurate, but what I really want to do is add a real time clock into it and have it tell time off of that. I already ordered some RTCs and I'm waiting for them to arrive.

I do have another microcontroller clock (which I bought pre-programmmed as a kit) but it goes 1 minute fast per day, so in a week it is 7 minutes fast. Again, it would be simple enough to compensate for this (every day minutes = minutes - 1; or something similar. seconds = seconds - 1; every x amount of time would be optimal.)
Joshua

User avatar
bitfogav
Moderator
Moderator
Posts: 915
Joined: Sun Mar 28, 2010 9:03 pm
Location: United Kingdom
Contact:

Re: Driving 7-segment displays with Arduino

Post by bitfogav » Tue Nov 27, 2012 9:33 am

I really do like your initiative Josh :mrgreen: Nice to see someone else sharing code here.
If you don't know what Voltage your country is using, you shouldn't be doing electronics ;-)

Post Reply
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable

Who is online

Users browsing this forum: No registered users and 15 guests