7 Segment Display using SPI

Well now...after talking to myself late into the the night and with a great deal of help from fellow Arduinophile Quazar, we have this sample code for y'all to use to help get up the learning curve for this Serial LED Display from Sparkfun (COM-09230).

Hey!! It worked like a charm! Thank you!

mmmmm.
tried it on a Duemilanove,
MOSI and CSN on a pwn pin (10 and 11) and SCK on pin 12.
only 0000 on the display. (which are not always the numbers I'm looking for :wink: ) anybody tries it on a Duemilanove board?

Fred, try changing the spi bus freq by sending (<<SSPR0) instead of (1<<SPR1). This will divide by 16 and not 64.

Also, check these pins (ref Arduino.cc SPI library page)

pin 13 SCK SPI clock
pin 12 MISO SPI master in, slave out
pin 11 MOSI SPI master out, slave in
pin 10 SS SPI slave select

Hope this helps!

Hey, I got 4 of these and am still floundering a little with the SPI.

Have you used this in a project yet? I got your code to work great, but I am trying to do some other stuff..

I have 1 arduino I want to display

  1. Elapsed Time
  2. Temperature
  3. Calculation (based on those first two numbers)

The whole Master/Slave coding I haven't discovered yet. Any help guys?

Thanks,

BLake

You do have a CHIP SELECT pin assigned that is unique to each device, right?

Hey, I got 4 of these and am still floundering a little with the SPI.

Do you want to want to connect multiple displays to the Arduino?

If so, you need to wire MOSI and SCLK on all chips together, and wire the SS pin (which Sparkfun calls "CSN") of each display to a different digital output on the Arduino.

Then, instead of using a #define'd constant like "SLAVESELECT" as Busaboi's code does, you'd use a variable, and set it to the digital output pin number for the display you want to update.

Thanks guys. As far as the wiring goes I am all set. I have the three displays wires all on the same bus except for the Slave "CSN" wire which is on a different pin on the Arduino. For me, that was the easy part.

The code on the other hand is what I am trying to learn how to do. I was looking for more example code to help me figure this SPI thing out.

@Ran, I was wondering if Slaveselect in Busaboi's code was a special function from the library, so you cleared that up for me. And yes, I need all three displays to simultaneously display constantly updating information.

Also, Busaboi doesn't call up the SPI.h library that I have seen. Is it unnecessary to do so?

Also, Busaboi doesn't call up the SPI.h library that I have seen.

The SPI library is very small. Busaboi just put the code he needed inline.

Assuming his code is good for 1 display (which I think has already been confirmed), simply changing the slave select from a constant to a variable should be all you need to get it to work for 3.

There's not a whole lot to understand with SPI: the really hard part is figuring out the "mode" (clock polarity and phasing), because SPI didn't start out as an official standard. So different chip makers did their own variations, and SPI never got formalized like I2C or USB. Sometimes you also need to be careful with the timing of slave select, or the pacing of transmitted bytes, but usually you can just go as fast as possible.

You've already got that right, so it's just a matter of stuffing bytes into the SPI transmit register in groups of 4 (and, in this case, ignoring the received data).

works just fine for me but i can't figure out how to send commands to change brightness or turn on the colon. anyone know how to do this?

Hi every body,

I'm new with arduino. I tried to display "1234" with serial like this :

 RX      ->  PIN TX  
 VCC   ->  PIN  3.3V
 GND   ->  PIN GND
void setup(){
  Serial.begin(9600);
  delay(100);
  Serial.println(0x79);
  delay(100);
  Serial.println(0x02);
}
void loop() {
 delay(1000);
 Serial.println(1,BIN);
 Serial.println(2,BIN);
 Serial.println(3,BIN);
 Serial.println(4,BIN);
}

It display lot of thing but but "1234" !

I writed this dirty code from the documentation on sparkfun website.

Up ^^

@2xyo - These 7 segment displays have two physical interfaces. This topic thread is about SPI, and you're trying to use the Serial interface.

See the thread at: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1249525950/2 about using Serial with this display. Working code is shown in that thread.

Thanks a lot !

I think it's better to have 4 digit Seg7 display circuit with OneWire interface. :wink:

How to do with "OneWire" ? SPI needs 4 wires when you have 1 master and 1 slave..

example code works for me! Now time to tweak...

SparkFun now offers an alternative design. This one has the interface pins along the top, so you can horizontally stack displays.

Stumbling upon this thread... here is my code for interfacing with the Sparkfun 4 digit, 7-segment LCD via SPI. It demonstrates some of the various command bytes and wraps up most of the functionality into a single function call (once initialized).

I do have one bug yet to be worked out... on initial reset the display usually reads fine, however upon a subsequent reset the display usually turns to "junk" (random elements lit). Pressing the reset button again doesn't fix it but closing and reopening the Serial Monitor always does fix it. I'm guessing it has something to do with the power up sequence of the LCD uC? Any help with this would be greatly appreciated.

Here is my code:

//this project demonstrates SPI control of sparkfun 4 digit, 7-segment LCD
//Setup section demonstrates commanding the LCD via SPI using byte commands.  
//Loop section demonstrates a counting timer uses SendToLCD() function to simplify 
//
//project by Scott Josselyn
//
//note that there are different firmware versions for the sparkfun part that may not support all functions
//Part Product Page: http://www.sparkfun.com/commerce/product_info.php?products_id=9230
//Part Reference Manual:  http://www.sparkfun.com/datasheets/Components/LED/SFE-0012-DS-7segmentSerial-v3.pdf

#define MOSI        11     //SPI MOSI Pin definition - arduino pin 11
#define SCLK        13     //SPI CLOCK Pin definition - arduino pin 13
#define LCD_CS      10     //LCD chip select -arduino pin 10

char outBuff[5];  //output buffer
int lastOutToLCD, outToLCD = 0;
byte decimalBitCode = 0;

void setup() {
  
  //configure serial port
  Serial.begin(9600);
  Serial.println("Intializing...");
  
  //the following configures the lcd
  delay(200);  //not sure if this is required or not but want to make sure the LCD uC has finished loading after powerup
  //configure the pins for SPI communication
  pinMode(MOSI, OUTPUT);
  pinMode(SCLK, OUTPUT);
  pinMode(LCD_CS, OUTPUT);
  digitalWrite(LCD_CS, LOW); //this should be moved to inside the function

  /* Enable SPI, Master, set clock rate fck/128 */
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);  //SPE=enables SPI, MSTR=arduino is master, DORD=MSB first(default)
  //SPR0 =1, SPR1 =1 SPI2x = 0 => SCK Freq fosc/128
  
  //now reset the LCD and have it display "9999"
  SPI_MasterTransmit(0x76);  //send a reset
  delay(200);  //not sure if this helps or not
  SPI_MasterTransmit(9);  //send a 9
  SPI_MasterTransmit(9);  //send a 9
  SPI_MasterTransmit(9);  //send a 9
  SPI_MasterTransmit(9);  //send a 9
  SPI_MasterTransmit(0x77); //send decimal command byte
  SPI_MasterTransmit(0);   //clear all decimals
  Serial.println("LCD should show 9999");
  delay(2000);
  //now dim display
  Serial.println("Dimming Display...");
  SPI_MasterTransmit(0x7a);   //send brightness command byte
  SPI_MasterTransmit(0xfe);   //send min brightness value
  delay(2000);
  Serial.println("Brightening Display...");
  SPI_MasterTransmit(0x7a);   //send brightness command byte
  SPI_MasterTransmit(0x01);   //send max brightness value  
  delay(2000);
  
  for (byte i = 0;i<8; i++){
    decimalBitCode = 1 << i;
    SPI_MasterTransmit(0x77); //send decimal command byte
    SPI_MasterTransmit(decimalBitCode);   //update the decimal position
    delay(1000);    
  }
  
  delay(3000);  //delay 3 secs
  
  Serial.println("Now display a min:sec counter...");
}

void loop(){//begin loop
         
      int mins = millis()/60000;   //at some point need to add code to watch for wrap around at 99 min1!1 or whenever millis overflows
      long secs = (millis()/1000 % 60);
      outToLCD = mins*100 + secs;
      decimalBitCode = B00010000;  //code to enable the colon between hundreds and thousands place
      
      //now send it to the LCD (but only if display needs to be changed since last time)
      if (outToLCD != lastOutToLCD) {//begin check for new display data
        SendToLCD( outToLCD, decimalBitCode);
        //send to terminal for debugging
        Serial.print(mins, DEC); Serial.print(":"); Serial.println(secs, DEC);
      }; //end if check for new display data
     
      //update our variable that keeps track of what it was last time.
      lastOutToLCD = outToLCD;  

}//end loop


void SendToLCD( int n, byte decimalCode)
{
  //takes an unsigned int, converts to bcd and outputs the least 4 sig digits to the LCD and places
  //decimals on display are defined defined by decimalCode
  
  //digit1 - digit2 - digit3 - digit4
  //bit 0 = decimal between digit 1 and 2
  //bit 1 = decimal between digit 2 and 3
  //bit 2 = decimal between digit 3 and 4
  //bit 3 = top of colon
  //bit 4 = bottom of colon
  //bit 5 = above and right of digit 3
  
 
        //  Most of the following code section is from http://www.cs.uiowa.edu/~jones/bcd/decimal.html
        uint8_t d4, d3, d2, d1, d0, q = 0;

        if (n < 0) {
            putchar( '-' );
            n = -n;
        }

        d1 = (n>>4)  & 0xF;
        d2 = (n>>8)  & 0xF;
        d3 = (n>>12) & 0xF;

        d0 = 6*(d3 + d2 + d1) + (n & 0xF);
        q = (d0 * 0xCD) >> 11;
        d0 = d0 - 10*q;

        d1 = q + 9*d3 + 5*d2 + d1;
        q = (d1 * 0xCD) >> 11;
        d1 = d1 - 10*q;

        d2 = q + 2*d2;
        q = (d2 * 0x1A) >> 8;
        d2 = d2 - 10*q;

        d3 = q + 4*d3;
        d4 = (d3 * 0x1A) >> 8;
        d3 = d3 - 10*d4;
    
 
      //Now send SPI bytes to LCD
      SPI_MasterTransmit(d3);
      SPI_MasterTransmit(d2);
      SPI_MasterTransmit(d1);
      SPI_MasterTransmit(d0);
      SPI_MasterTransmit(0x77);  //command byte for decimal
     
      SPI_MasterTransmit( decimalCode );  //now place decimal

}


void SPI_MasterTransmit(char cData)
{
  /* Start transmission */
  SPDR = cData;
  /* Wait for transmission complete */
  while(!(SPSR & (1<<SPIF)))
;
}

Is the SPI code that busaboi uploaded in the public domain? I used it for an antenna rotor controller. If I publish my code and include his, am I at risk?

Sigurd