Pages: [1]   Go Down
Author Topic: Seven segment display class.  (Read 1407 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 14
Ni francais, ni breton.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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:
#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:
#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;
  }
}
« Last Edit: April 05, 2010, 01:27:33 pm by Ty_Breizh » Logged

CATALUNYA
Offline Offline
Full Member
***
Karma: 1
Posts: 112
I started my electronics career with MICROCHIP PIC16 microcontrollers and assembler. After 10 years without touching electronics, I restarted it as a hobby (and sometimes work) with ATMEL and Arduinos.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Very nice!   smiley-grin
I'll test it.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*
 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:
/*
 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:
/*
 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!)
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 9
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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);
  }
}
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 200
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1]   Go Up
Jump to: