Go Down

Topic: Seven segment display class. (Read 1 time) previous topic - next topic

Ty Breizh

Apr 05, 2010, 08:01 pm Last Edit: Apr 05, 2010, 08:27 pm by Ty_Breizh Reason: 1
My first Arduino class (my first class ever!), suitable for common cathode or common anode display types.
Displays hex digits 0..F, plus eight segment test patterns.
Up to eight custom patterns available, subject to recompilation.

Comments welcome.

SevenSegment.h
Code: [Select]
#include <WProgram.h>
const byte N_PATTERNS = 32;
const byte N_SEGMENTS = 8;
const byte MAX_DIGITS = 8;

class SevenSeg {
 public:
   void begin (byte commonCathode,   // true for common cathode, false for common anode
               unsigned long onTime, // segment on time in microseconds
               const byte segmentPins[N_SEGMENTS],
               byte nDigits,         // number of digits
               const byte digitPins [],
               byte* display);       // user's display file.
   void update (void);   //  must be called at least once per "loop"
   void setDP (byte dpPos); // sets the digit for decimal place
   void setOnTime (unsigned long onTime) {segmentOnTime =onTime;}
   void blankDisplay (void);
 private:
   byte segmentOn;
   byte digitOn;
   byte digits;          // total number of digits
   byte digit;           // current digit
   byte segment;         // current segment
   byte displayPattern;
   byte mask;
   unsigned long segmentTime;
   unsigned long segmentOnTime;
   byte segmentPin [N_SEGMENTS]; // pin numbers for segments
   byte digitPin   [MAX_DIGITS]; // pin numbers for anode/cathode
   byte* displayFile;
   byte dpDigit;
};


SevenSegment.cpp
Code: [Select]
#include <SevenSeg.h>

#define digitOff       ((LOW + HIGH) - digitOn)
#define segmentOff     ((LOW + HIGH) - segmentOn)

static const byte DP = 0x80;
static const byte patterns [N_PATTERNS] = {
     0x3F, 0x06, 0x5B, 0x4F,  // +ve logic segment patterns
     0x66, 0x6D, 0x7D, 0x07,
     0x7F, 0x67, 0x77, 0x7C,
     0x39, 0x5E, 0x79, 0x71,
     0x01, 0x02, 0x04, 0x08,  // single segment test patterns.
     0x10, 0x20, 0x40, 0x80}; //remaining codes all zero.

void SevenSeg::begin (boolean commonCathode,
                     unsigned long onTime,
                     const byte segmentPins[N_SEGMENTS],
                     byte nDigits,
                     const byte digs [],
                     byte* disp)
{
 if (commonCathode) {
   digitOn   = LOW;
   segmentOn = HIGH;
 } else {
   digitOn   = HIGH;
   segmentOn = LOW;
 }

 segmentOnTime  = onTime;
 for (int i = 0; i < N_SEGMENTS; i++)
   segmentPin [i] = segmentPins [i];

 digits = (nDigits > MAX_DIGITS) ? MAX_DIGITS : nDigits;
 for (int i = 0; i < digits; i++) {
   digitPin [i] = digs[i];
 }
 displayFile = disp;
 
 for (int i = 0; i < digits; i++) {
   pinMode (digitPin[i], OUTPUT);
 }
 for (int i = 0; i < N_SEGMENTS; i++) {
   pinMode (segmentPin[i], OUTPUT);
 }
 blankDisplay ();  

 dpDigit        = MAX_DIGITS;  // default to no decimal place displayed
 digit          = 0;
 segment        = 0;
 displayPattern = 0;
 mask           = 1;
 segmentTime    = 0;
}

void SevenSeg::blankDisplay (void)
{
 for (int i = 0; i < digits; i++) {
   digitalWrite (digitPin[i], digitOff);
 }
 for (int i = 0; i < N_SEGMENTS; i++) {
   digitalWrite (segmentPin[i], segmentOff);
 }
}

void SevenSeg::update (void)
{
 unsigned long now = micros ();
 if (now - segmentTime > segmentOnTime) {
   segmentTime = now;
   digitalWrite (segmentPin [segment], segmentOff);
   segment++;
   mask <<= 1;
   if (segment >= N_SEGMENTS) {
     segment = 0;
     mask = 1;
     digitalWrite (digitPin [digit], digitOff);
     digit++;
     if (digit >= digits) {
       digit = 0;
     }
     displayPattern = patterns [displayFile [digit] & (N_PATTERNS-1)];
     displayPattern |= (dpDigit == digit)? DP : 0;
     digitalWrite (digitPin [digit], digitOn);
   }
   if (displayPattern & mask) {
     digitalWrite (segmentPin[segment], segmentOn);
   }  
 }
}

void SevenSeg::setDP (byte dpPos)
{
 dpDigit = dpPos;
}



Simple example sketch:
Code: [Select]
#include <SevenSeg.h>

const byte segments [N_SEGMENTS] = {2, 3, 4, 5, 6, 7, 8, 9}; // pin numbers for segments
const byte digits   []   = {10, 11, 12, 13};                 // pin numbers for anode/cathode
byte displayFile [4];
SevenSeg myDisplay;

void setup ()
{
 myDisplay.begin (false, 400L, segments, 4, digits, displayFile);
}

void loop ()
{
 updateClock ();
 myDisplay.update ();
}

const unsigned long countTime = 1000L;
void updateClock (void)
{
 static byte seconds = 0;
 static byte minutes = 0;
 static unsigned long updateTime = 0;
 unsigned long now = millis ();
 if (now - updateTime > countTime) {
   updateTime = now;
   seconds++;
   if (seconds >= 60) {
     seconds = 0;
     minutes++;
     if (minutes >= 60) {
       minutes = 0;
     }
   }
   displayFile [0] = seconds % 10;
   displayFile [1] = seconds / 10;
   displayFile [2] = minutes % 10;
   displayFile [3] = minutes / 10;
 }
}

suby


NanoDano

I just got my Arduino this week and this was also my first library. Mine is a little lighter and may help other beginners seeing another implementation. One note is that I do not have a variable for common anode/cathode. I was assuming the user would wire that pin accordingly themselves. It does have a variable for right hand decimal point (RHDP).

Initialize the class by passing your pin numbers as arguments. The write function takes an integer argument 0-9 and prints out the readable version on the seven segment display.

SevenSegment.h
Code: [Select]

/*
SevenSegment.h - Seven Segment Display Library

These functions print readable numbers to seven segment display

Created 1 August 2010
By NanoDano
nanodano@ph33d.us
*/

#ifndef _SevenSegment_h
#define _SevenSegment_h

#include "WProgram.h"

/*************************************************
* Definitions
*************************************************/

class SevenSegment {
     public:
           SevenSegment(int anodeA, int anodeB, int anodeC, int anodeD, int anodeE, int anodeF, int anodeG, int RHDP); // Pass NULL for RHDP if unavailable
           void write(int input);
     private:
           int _anodeA;
           int _anodeB;
           int _anodeC;
           int _anodeD;
           int _anodeE;
           int _anodeF;
           int _anodeG;
           int _RHDP;
};

#endif



SevenSegment.cpp
Code: [Select]

/*
SevenSegment.cpp - Seven Segment Display Library

These functions print readable numbers to seven segment display

The circuit:
* Seven segment display hooked to Arduino

Created 1 August 2010
By NanoDano
nanodano@ph33d.us
*/

#include "SevenSegment.h"


SevenSegment::SevenSegment(int anodeA, int anodeB, int anodeC, int anodeD, int anodeE, int anodeF, int anodeG, int RHDP) {
      pinMode(anodeA, OUTPUT);
      pinMode(anodeB, OUTPUT);
      pinMode(anodeC, OUTPUT);
      pinMode(anodeD, OUTPUT);
      pinMode(anodeE, OUTPUT);
      pinMode(anodeF, OUTPUT);
      pinMode(anodeG, OUTPUT);
     _anodeA = anodeA;
     _anodeB = anodeB;
     _anodeC = anodeC;
     _anodeD = anodeD;
     _anodeE = anodeE;
     _anodeF = anodeF;
     _anodeG = anodeG;
     if (RHDP) {
           pinMode(RHDP, OUTPUT);
           _RHDP = RHDP;
     }
}

void SevenSegment::write(int input) {
     switch (input) {
           case 0:
                 digitalWrite(_anodeF, HIGH);
                 digitalWrite(_anodeG, LOW);
                 digitalWrite(_anodeE, HIGH);
                 digitalWrite(_anodeD, HIGH);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, HIGH);
                 break;
           case 1:
                 digitalWrite(_anodeF, LOW);
                 digitalWrite(_anodeG, LOW);
                 digitalWrite(_anodeE, LOW);
                 digitalWrite(_anodeD, LOW);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, LOW);
                 break;
           case 2:
                 digitalWrite(_anodeF, LOW);
                 digitalWrite(_anodeG, HIGH);
                 digitalWrite(_anodeE, HIGH);
                 digitalWrite(_anodeD, HIGH);
                 digitalWrite(_anodeC, LOW);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, HIGH);
                 break;
           case 3:
                 digitalWrite(_anodeF, LOW);
                 digitalWrite(_anodeG, HIGH);
                 digitalWrite(_anodeE, LOW);
                 digitalWrite(_anodeD, HIGH);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, HIGH);
                 break;
           case 4:
                 digitalWrite(_anodeF, HIGH);
                 digitalWrite(_anodeG, HIGH);
                 digitalWrite(_anodeE, LOW);
                 digitalWrite(_anodeD, LOW);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, LOW);
                 break;
           case 5:
                 digitalWrite(_anodeF, HIGH);
                 digitalWrite(_anodeG, HIGH);
                 digitalWrite(_anodeE, LOW);
                 digitalWrite(_anodeD, HIGH);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, LOW);
                 digitalWrite(_anodeA, HIGH);
                 break;
           case 6:
                 digitalWrite(_anodeF, HIGH);
                 digitalWrite(_anodeG, HIGH);
                 digitalWrite(_anodeE, HIGH);
                 digitalWrite(_anodeD, HIGH);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, LOW);
                 digitalWrite(_anodeA, HIGH);
                 break;
           case 7:
                 digitalWrite(_anodeF, LOW);
                 digitalWrite(_anodeG, LOW);
                 digitalWrite(_anodeE, LOW);
                 digitalWrite(_anodeD, LOW);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, HIGH);
                 break;
           case 8:
                 digitalWrite(_anodeF, HIGH);
                 digitalWrite(_anodeG, HIGH);
                 digitalWrite(_anodeE, HIGH);
                 digitalWrite(_anodeD, HIGH);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, HIGH);
                 break;
           case 9:
                 digitalWrite(_anodeF, HIGH);
                 digitalWrite(_anodeG, HIGH);
                 digitalWrite(_anodeE, LOW);
                 digitalWrite(_anodeD, HIGH);
                 digitalWrite(_anodeC, HIGH);
                 digitalWrite(_anodeB, HIGH);
                 digitalWrite(_anodeA, HIGH);
                 break;
     }
}


Sketch Example
Code: [Select]

/*
SevenSegCount

This sketch shows how to use the SevenSegment class to easily
print readable numbers 0-9 on a seven segment display

The circuit:
* Seven Segment display hooked up to Arduino

Created 1 August 2010
By NanoDano
nanadano@ph33d.us

*/

#include <SevenSegment.h>

void setup() {
}

void loop() {
 //Initialize a SevenSegment class named ss  
 SevenSegment ss(7, 8, 9, 10, 11, 13, 12, 6);
 
 // Print out each number from 0 to 9
 for (int i = 0; i < 10; i++) {
   ss.write(i);
   delay(250);
 }
}


A couple final remarks: my code in this post is unrelated to the original posters code. I made this independently and they aren't meant to be used together. I felt it was unnecessary to create a new thread for the same topic though. This is my first library too so it is meant to be lightweight. (This is my first post, too!)

cmj

I'm working on a simple class of my own.. I haven't gotten to creating the library yet as I still wish to add multiplexing support.

I'm using it to display a simple time stamp right now.  I know my code isn't as concise as a good programmer, or done correctly.  I am a beginner trying to get into software driven electronics.

My issue is occasionally the screen displays some crazy things.  Segments light up in a fashion that's not defined in the code.  Since I wasn't thinking and started with pin0 I can't necessarily troubleshoot via serial.  

Does anyone see any major discrepancies in my code?

Code: [Select]

int s, m, h;
int time[4];

void setup()
{
 for(int i = 0; i < 7; i++)
 {
   pinMode(i, OUTPUT);
   digitalWrite(i, HIGH);
 }
 pinMode(12, OUTPUT);
 digitalWrite(12, HIGH);
 pinMode(13, INPUT);
 digitalWrite(13, LOW);
}

                     // 0    1   2   3   4   5  6    6  8   9
const byte numDef[10]= {64, 121, 36, 48, 25, 18, 2, 120, 0, 24};

void loop()
{
 int buttonState = digitalRead(13);
 
 if (buttonState == HIGH)
 {displayTime();}
 
static unsigned long count = 0;

if (millis() - count >= 1000)
{count = millis(); s++;}

if (s > 59)
{m++; s = 0;}

if (m > 59)
{h++; m = 0;}

if (h > 23)
{h = 0;}
 
}

void displayTime()
{
 time[0] = h/10;
 time[1] = h - time[0]*10;
 time[2] = m/10;
 time[3] = m - time[0]*10;  
 
 for (int i = 0; i < 4; i++)
 {
   setSegments(time[i]);
 }
 

}

void setSegments(int num)
{
 byte segments = numDef[num];
 for (int s = 0; s < 7; s++)
 {
   int bitVal = bitRead(segments, s);
   digitalWrite(s, bitVal);
 }
 delay(250);
 clearSegments();
 delay(50);
}

void clearSegments()
{
 for (int i = 0; i < 7; i++)
 {
   digitalWrite(i, HIGH);
 }
}


novice

cmj,
problems with projects are best dealt with in "Arduino Forum ? Hardware ? Interfacing". Otherwise anarchy rules.

There are two nice examples above that you could implement and understand as a first step.

Go Up