Interfacing with a TWI 4-Digit 7-segment Display - Draft

copyright Peter H Anderson, Baltimore, MD, Dec 15, '10


The TWI LED Display Module consists of four 3/4 inch high 7-segment LEDs plus decimal point and two discrete LEDs. It has an I2C interface which minimizes the interface to two power leads, +5 and GRD and two signal leads SDA and SCL. In theory, this permits up to 127 modules on a single two wire interface (TWI). I have found the unit to be well designed and the board is of excellent quality.

It is ideally suited for small procesors where one or two quantities, such as temperature or relative humdity, are being monitored and more brightness than is offered by a text LCD is required. It is attractively priced at nominally $10.00 from Lithuania (http://www.bringyourself.in and also on eBay. Search on "7 segment LED display module".)

I offer this here.

Data Format.

Interface with the PICAXE

A quantity is displayed by sending a command write byte followed by eight bytes. For example;

    ' for the PICAXE-20X2 and many similar

    Ptr = 0
                   ' 0       1        2        3        4        5        6        7
	HI2Cout [60], (@Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc)
In this case the I2C address is 30 and thus the address byte is 30 *2 or 60. Eight values beginning at scratch pad location 0 are sent to the display. Note that in the above @ptrinc is interpetted as 'the value at the poiter address and then increment the ptr address'.

Byte 0 consists of the states of the two discrete LEDs (bits 7 and 6), a data format byte at bit 5 and the brightness of the seven segment displays (0-31).

Thus;

    X = %10100000 + 25
    Put 0, X ' write to scratchpad location 0
Configures for the top LED on, the bottom LED off, data format mode 1 (more later) and an LED intensity setting of 25.

Byte 1 is the intensity of the two discrete LEDs, in the range of 0 to 127.

Bytes 2, 3, 4 and 5 are the ASCII values of the characters (-, space, 0-9, A-F) to be displayed on the four 7-segment LED displays. For example, consider displaying the quantity V of 4321.


    Digit = V / 1000
    Ch = Digit + $30 ' convert to ASCII
    Put 2, Ch

    V = V // 1000 ' remainder
    Digit = V / 100
    Ch = Digit + $30 '
    Put 3, Ch

    V = V // 10
    Digit = V / 10
    Ch = Digit + $30 ' convert to ASCII
    Put 4, Ch

    Digit = V
    Ch = Digit + $30 ' convert to ASCII
    Put 5, Ch

Byte 6 is used for specifying where decimal points are to be located. For example;

    %00000000 ' no decinal point
    %00000001 ' 2345.
    %00000010 ' 234.5
    ...
    %00100000 ' .2345
Byte 7 is obtained by exclusive oring the address command byte (60 in the above) and bytes 0 through 6.

    Ptr = 0
    X = Adr * 2
    For N = 0 to 6
        X =  X ^ @Ptrinc
       'Ptr = Ptr +1
    Next

    Put 7, X


' TWIDispl_1  (PICAXE-20X2)
'
' Illustrates an interface with the 4-Digit TwiDisplay from BringYourself.In
'
' PICAXE-20X2			TWIDisplay
'
' HI2CSDA (term 13) ------------ SDA
' HI2CSCL (term 11) ------------ SCL
'
' Note.  4.7K pullup resistors to +5 VDC on SDA and SCL
'
' copyright, Peter H Anderson, Baltimore, MD, Dec 15, '10
' Observe the copyright.  Use this code, copy the code, but keep the copyright notice.

    Symbol X = B1
    Symbol AdrTimes2 = B2
    Symbol N = B3
    Symbol Whole = B4
    Symbol Fract = B5
    Symbol Digit = B6
    Symbol Ch = B7
    Symbol TF_10 = W5
    Symbol V = W6
   
    AdrTimes2 = 60

    Do
       For TF_10 = 0 to 9 Step 1
          GoSub LEDDisplay
          Pause 1500
       Next
       For TF_10 = 10 to 99 Step 12           
          GoSub LEDDisplay
          Pause 1500
       Next
       For TF_10 = 100 to 2000 Step 123           
          GoSub LEDDisplay
          Pause 1500
       Next
    Loop

 
 LEDDisplay:

           '0   1   2  3   4   5   6 
    Put 0, 63, 127, 0, 0,  0,  0,  2   ' write setup info to scratchpad
    
    
    Whole = TF_10/10
    Fract = TF_10 // 10

    Digit = Whole / 100
    If Digit = 0 Then
       Ch = $20
       Put 2, Ch
       Whole = Whole // 100
       Digit = Whole / 10
       If Digit = 0 Then
          Ch = $20
          Put 3, Ch
       Else
          Ch = Digit + $30
          Put 3, Ch
       End If
       Whole = Whole // 10
       Digit = Whole
       Ch = Digit + $30
       Put 4, Ch
       
    Else
       Ch = Digit + $30
       Put 2, Ch
       Whole = Whole // 100
       Digit = Whole / 10
       Ch = Digit + $30
       Put 3, Ch
       Whole = Whole // 10
       Digit = Whole
       Ch = Digit + $30
       Put 4, Ch     

    End If

    Ch = Fract + $30
    
    Put 5, Ch

    Ptr = 0
    X = AdrTimes2
     
    For N = 0 to 6
      X =  X ^ @ptrinc
      'Ptr = Ptr +1
    Next
    
    Put 7, X

    Hi2cSetup I2CMaster, 60, I2CSlow, I2CByte 

    Ptr = 0;
       
    HI2Cout [AdrTimes2], (@Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc)

    Ptr = 0
    SerTxd (#@Ptrinc, #@Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, @Ptrinc, #@Ptrinc, #@Ptrinc, CR, LF)  ' for debugging
     
    Return
                                                     


Arduino

// TWIDisp (Arduino - ATMega328)
//
// Arduino                      TwiDisplay from http://www.bringyourself.in
//
// 18 (Analog 4) --------------- SDA   Note that 4.7K pullups to +5 VDC are 
// 19 (Analog 5) --------------- SCL   required on both SDA and SCL
//                       +5 ---- VDD 
//                       GRD --- VSS 
//
// Displays values using a fixed decimal point with leading zero suppression.
//
//       0.0 - 0.9
//       1.0 - 9.9
//      10.0 - 99.9
//     100.0 - 999.9
// 
// copyright, Peter H Anderson, Baltimore, MD,  Dec, '10
// Observe the copyright.  Use it, copy it, but leave the copyright.

#include <Wire.h> //I2C library

#define TRUE 1
#define FALSE 0

void setup(void)
{
   Serial.begin(9600);
   Wire.begin();
   delay(5000);
   Serial.println(">>>>>>>>>>>>>>>>>>>>>>>>");  // just to be sure things are working
}

void loop(void)
{
   int TF_10;
   
   while(1)
   {
       // generate some temperature values
       
       for (TF_10 = 0; TF_10 < 10; TF_10++) // step of 1
       {
           LEDDisplay(TF_10);
           delay(1500);
       }
       
       for (TF_10 = 10; TF_10 < 100; TF_10+=12) // step 12
       {
           LEDDisplay(TF_10);
           delay(1500);
       }
    
       for (TF_10 = 100; TF_10 < 1000; TF_10+=123)  // step 123
       {
           LEDDisplay(TF_10);
           delay(1500);
       }  
       
       for (TF_10 = 1000; TF_10 < 10000; TF_10+=1234)  // step 1234
       {
           LEDDisplay(TF_10);
           delay(1500);
       }  
   } 
             
}
    
void LEDDisplay(int TF_10)
 {
    byte a[8] = {(1<<5) + 31, 127, 0, 0, 0, 0, 0, 0}, fract, digit, n;
    // data format 1
    byte address = 30; // I2C address
    int whole;
 
    whole = TF_10 / 10;
    fract = TF_10 % 10;

    digit = whole / 100;
    
    if (digit == 0) // leading zero suppression
    {
       a[2] = ' ';
       whole = whole % 100;
       digit = whole / 10;
       if (digit == 0)
       {
          a[3] = ' ';
       }
       else
       {
          a[3] = digit + '0';
       }
       whole = whole % 10;
       digit = whole;
       a[4] = digit + '0';
    }
    else
    {
       a[2] = digit + '0';
       whole = whole % 100;
    
       digit = whole / 10;
       a[3] = digit + '0';
       whole = whole % 10;
       digit = whole;
       a[4] = digit + '0';     
    }
    
    a[5] = fract + '0';
    a[6] = 2;
    
    a[7] = 2 * address;
    
    for (n=0; n<7; n++)
    {
       a[7] = a[7] ^ a[n]; // compute parity byte
    }
   
    Wire.beginTransmission(address);

    for (n=0; n<8; n++)
    {
        Wire.send(a[n]);

    }
    
    Wire.endTransmission();
 }