​ ​ ​ ​ Easy 4 digit LED display
Results 1 to 10 of 10

Thread: Easy 4 digit LED display

  1. #1
    Member
    Join Date
    Jul 2010
    Location
    Colorado USA
    Posts
    92

    Default Easy 4 digit LED display

    The TM1637 LED display is widely available, cheap, and an easy way to add a four
    digit LED display to a PICAXE project. Borrowing code from the link below I wrote
    a version which runs much faster and the code size is reduced. It has been tested from
    4 to 32 mhz on M2 parts and also at 64 mhz on X2 parts. The code could be made
    to run even faster by converting the subroutines to macros.

    http://www.picaxeforum.co.uk/showthr...ghlight=tm1637


    Code:
    ;TM1637_test.bas
    
    #picaxe 08m2
    
    ;segment data for TM1637
         ;(  0   1   2   3   4   5   6   7   8   9   A   b   C   d   E   F  dash blank)
    DATA 0,($3f,$06,$5b,$4f,$66,$6d,$7d,$07,$7f,$6f,$77,$7c,$39,$5e,$79,$71, $40, $00)
    
    
    ;for TM1637
    symbol dio = C.1                        ;TM1637 data pin to 08m2 leg 6
    symbol clk = C.2                        ;TM1637 clock pin to 08m2 leg 5
    symbol  D3 = b2
    symbol  D2 = b3                         ;for all 4 digits
    symbol  D1 = b4
    symbol  D0 = b5
    
    
    gosub brightness                        ;set display brightness
    
    for b1 = 0 to 17                        ;sequence thru all character
      D3 = b1:D2 = b1                       ;bytes stored in the data 
      D1 = b1:D0 = b1
      gosub DISPLAY
      pause 1000
    next b1
    end
    
    ;===========================================================================  
    
    ;Group of subroutines to read the values from data and output to the display
    
    DISPLAY:
      ;Enable sequential movement (from one digit to next)
      call i2CStart
      b0 = $40
      call i2CWrByte
      call i2CStop
      
      ;Move to first digit
      call i2CStart 
      b0 = $C0
      call i2CWrByte
    
      ;First value
      read D3,b0
      call i2CWrByte
      
      ;Second value
      read D2,b0
      if b1 = 17 then                                         
      b0 = b0 + 128                         ;add 128 to turn on colon
      endif                                             
      call i2CWrByte              
    
      ;Third value
      read D1,b0
      call i2CWrByte
    
      ;Fourth value
      read D0,b0
      call i2CWrByte
      
      call i2CStop
      return
    
    i2CStart:
      high clk
      high dio
      low dio
      low clk
      return
      
    i2CStop:
      low clk
      low dio
      high clk
      high dio
      return
    
    ;Send a byte
    i2CWrByte:  ;outpinC.1 = dio
      outpinC.1 = bit0:pulsout clk, 1
      outpinC.1 = bit1:pulsout clk, 1
      outpinC.1 = bit2:pulsout clk, 1
      outpinC.1 = bit3:pulsout clk, 1
      outpinC.1 = bit4:pulsout clk, 1
      outpinC.1 = bit5:pulsout clk, 1
      outpinC.1 = bit6:pulsout clk, 1
      outpinC.1 = bit7:pulsout clk, 1
      pulsout clk, 1
      return
    
    ;Set the brightness ($88 = on, $88 to $8F are the brightness levels)
    brightness:
      call i2CStart
      b0 = $89
      call i2CWrByte
      call i2CStop
      return
      
    ;===========================================================================

    Cheers to All
    Last edited by pxgator; 23-09-2017 at 02:16. Reason: updated code

  2. #2
    Senior Member
    Join Date
    May 2013
    Location
    Ireland
    Posts
    228

    Default

    Quote Originally Posted by pxgator View Post
    The TM1637 LED display is widely available, cheap, and an easy way to add a four
    digit LED display to a PICAXE project. Borrowing code from the link below I wrote
    a version which runs much faster and the code size is reduced. It has been tested from
    4 to 32 mhz on M2 parts and also at 64 mhz on X2 parts. The code could be made
    to run even faster by converting the subroutines to macros.

    Code:
    ;TM1637_test.bas
    
    #picaxe 08m2
    
    ;segment data for TM1637
         ;(  0   1   2   3   4   5   6   7   8   9   A   b   C   d   E   F  dash blank)
    DATA 0,($3f,$06,$5b,$4f,$66,$6d,$7d,$07,$7f,$6f,$77,$7c,$39,$5e,$79,$71, $40, $00)
    
    
    ;for TM1637
    symbol dio = C.1                        ;TM1637 data pin to 08m2 leg 6
    symbol clk = C.2                        ;TM1637 clock pin to 08m2 leg 5
    symbol  D3 = b2
    symbol  D2 = b3                         ;for all 4 digits
    symbol  D1 = b4
    symbol  D0 = b5
    
    
    gosub brightness                        ;set display brightness
    
    for b1 = 0 to 17                        ;sequence thru all character
      D3 = b1:D2 = b1                       ;bytes stored in the data 
      D1 = b1:D0 = b1
      gosub DISPLAY
      pause 1000
    next b1
    end
    
    ;===========================================================================  
    
    ;Group of subroutines to read the values from data and output to the display
    
    DISPLAY:
      ;Enable sequential movement (from one digit to next)
      call i2CStart
      b0 = $40
      call i2CWrByte
      call i2CStop
      
      ;Move to first digit
      call i2CStart 
      b0 = $C0
      call i2CWrByte
    
      ;First value
      read D3,b0
      call i2CWrByte
      
      ;Second value
      read D2,b0
      if b1 = 17 then                                         
      b0 = b0 + 128                         ;add 128 to turn on colon
      endif                                             
      call i2CWrByte              
    
      ;Third value
      read D1,b0
      call i2CWrByte
    
      ;Fourth value
      read D0,b0
      call i2CWrByte
      
      call i2CStop
      return
    
    i2CStart:
      high clk
      high dio
      low dio
      low clk
      return
      
    i2CStop:
      low clk
      low dio
      high clk
      high dio
      return
    
    ;Send a byte
    i2CWrByte:  ;outpinC.1 = dio
      outpinC.1 = bit0:pulsout clk, 1
      outpinC.1 = bit1:pulsout clk, 1
      outpinC.1 = bit2:pulsout clk, 1
      outpinC.1 = bit3:pulsout clk, 1
      outpinC.1 = bit4:pulsout clk, 1
      outpinC.1 = bit5:pulsout clk, 1
      outpinC.1 = bit6:pulsout clk, 1
      outpinC.1 = bit7:pulsout clk, 1
      pulsout clk, 1
      return
    
    ;Set the brightness ($88 = on, $88 to $8F are the brightness levels)
    brightness:
      call i2CStart
      b0 = $89
      call i2CWrByte
      call i2CStop
      return
      
    ;===========================================================================

    Cheers to All
    Thanks very much for the code.

    I have ordered a few of these screens and planning on trying to implement one into my project.

    Would you be able to put up a schematic diagram in terms of pin conecction from screen to PICAXE please?

    I am using PICAXE14M2 if that makes a difference.

    Thanks very much.

    Andrei.

  3. #3
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    23,736

    Default

    It seems to be an I2C connection, so just two signals plus power ...

    Code:
    symbol dio = C.1 ;TM1637 data pin to 08m2 leg 6
    symbol clk = C.2 ;TM1637 clock pin to 08m2 leg 5
    Not studied the TM1367 datasheet but I would have thought the bit-banged I2C software could be replaced by HI2C commands to simplify things, improve speeds and reduce memory. That would swap the two pins around; CLK on C.1, SDA on C.2.
    Last edited by hippy; 12-09-2017 at 10:20.

  4. #4
    Member
    Join Date
    Jul 2010
    Location
    Colorado USA
    Posts
    92

    Default

    Quote Originally Posted by Andrei IRL View Post
    Thanks very much for the code.

    I have ordered a few of these screens and planning on trying to implement one into my project.

    Would you be able to put up a schematic diagram in terms of pin conecction from screen to PICAXE please?

    I am using PICAXE14M2 if that makes a difference.

    Thanks very much.

    Andrei.
    The code is using bit banged I2C so any pins that can be outputs could be used.
    I've never been able to get the correct data on this part in order to use real I2C.
    The bit banged I2C is quite quick with my code.


    Cheers to All

    P.S. Even the available Arduino code examples for
    this part uses bit banged I2C.

  5. #5
    Senior Member
    Join Date
    Oct 2013
    Location
    Stockport, UK. On a good day, Cornwall UK
    Posts
    360

    Question Risk of "Magic Smoke"

    Quote Originally Posted by pxgator View Post
    The code is using bit banged I2C so any pins that can be outputs could be used.
    I've seen a few example of using bit-banged I2C in the forum, but none seem to have addressed this issue :-

    Code:
    From the PIC datasheet:
    
    Both the SCL and SDA connections are bidirectional open-drain lines, each requiring pull-up resistors for the supply voltage
    Presumably there is no way to manually configure an Output Pin to be open-drain, so how are potential clashes to be avoided (i.e. PIC o/p @ logic 1, other bus member at logic 0).

    Would a simple resistor (or diode?) do the job, or is an external transistor necessary?

  6. #6
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    23,736

    Default

    I am sure that some of my example code has dealt with the open-drain issue; that is achieved by only using INPUT and LOW commands, never setting the pin high.

    There used to be issues with earlier PICAXE devices because they had fixed input and output pins, but with the modern M2 and X2 devices that is not a problem.

    I would recommend using the same pins for bit-banging as the PICAXE uses for hardware does because it's then easy to switch between the two, and it also helps when developing code knowing that the other mechanism works. That applies to SPI and UART connections as much as to I2C.

    This is example code I have for an old 08M which uses INPUT and LOW only -

    Code:
    ; *****************************************************************************
    ; *                                                                           *
    ; *     I2C Test Program for the PICAXE-08M                     I2C6.BAS      *
    ; *                                     ^^^                                   *
    ; *****************************************************************************
    ; *                                                                           *
    ; *     This is an version of I2C3.BAS specifically designed to run on the    *
    ; *     PICAXE-08M using its bi-directional port abilities.                   *
    ; *                                                                           *
    ; *     The core I2C routines use just 140 bytes of code.                     *
    ; *                                                                           *
    ; *****************************************************************************
    
    ;                              --.---.-- +V
    ;                               .|. .|.
    ;                               | | | | 2 x 4K7
    ;                               |_| |_|
    ;        PICAXE-08M              |   |           I2C Eeprom / Ram
    ;       .----------.             |   |             .----------.
    ;       |       X1 |-------------^---|-------------| SDA   A2 |---.
    ;       |          |                 |             |       A1 |---{
    ;       |       X4 |-----------------^-------------| SCL   A0 |---{
    ;       `----------'                               |       WP |---{
    ;                                                  `----------'  _|_ 0V
    
    ; *****************************************************************************
    ; *                                                                           *
    ; *     Define the I2C device being used                                      *
    ; *                                                                           *
    ; *****************************************************************************
    
                                                    ; 24LC256, Word Addressed
    
            Symbol  I2C_ADDRESS     = %10100000     ; $A0
    
    ; *****************************************************************************
    ; *                                                                           *
    ; *     Variables                                                             *
    ; *                                                                           *
    ; *****************************************************************************
    
            Symbol  tstAdr          = b0
            Symbol  tstVal          = b1
    
            Symbol  i2cAdr          = w1    ' b3:b2
            Symbol  i2cAdrLsb       = b2
            Symbol  i2cAdrMsb       = b3
    
            Symbol  i2cVal          = b4
    
            Symbol  i2cDataByte     = b5
            Symbol  i2cAckBit       = b6
            Symbol  i2cBitCount     = b7
    
    ; *****************************************************************************
    ; *                                                                           *
    ; *     Bit-Banged I/O definitions                                            *
    ; *                                                                           *
    ; *****************************************************************************
    
            Symbol  SDA             = 1
            Symbol  SCL             = 4
    
            Symbol  SDA_PIN         = pin1
            Symbol  SCL_PIN         = pin4
    
    ; *****************************************************************************
    ; *                                                                           *
    ; *     Main Program Code                                                     *
    ; *                                                                           *
    ; *****************************************************************************
    
            ; Wait for Terminal Window Pop-Up
    
            Pause 1000
    
            ; Initialise the I2C comms
    
            Gosub InitI2cDevice
    
            ; Test I2C
    
            For i2cAdr = $00 To $3F
              i2cVal = i2cAdr+3
              Gosub WriteI2cData
              Gosub ReadI2cData
              i2cVal = i2cVal-3
              If i2cVal <> i2cAdr Then
                SerTxd( "Er" )
              End If
            Next
    
            SerTxd( "Ok" )
    
            End
    
    ; *****************************************************************************
    ; *                                                                           *
    ; *     High-Level I2C Interface Routines                                     *
    ; *                                                                           *
    ; *****************************************************************************
    
    WriteI2cData:
    
            Gosub I2cSendHeader
    
            i2cDataByte = i2cVal
            Gosub I2cSendByte
    
            Gosub InitI2cDevice
    
            Pause 20                        ; 20mS to allow write
    
            Return
    
    ReadI2cData:
    
            Gosub I2cSendHeader
    
            Gosub I2cStart
    
            i2cDataByte = I2C_ADDRESS | $01
            Gosub I2cSendByte
    
            Input SDA                       ; SDA = 1 / Tri-State SDA
            For i2cBitCount = 0 To 7
              Gosub I2cStrobeScl
              i2cVal= i2cVal * 2 | i2cAckBit
            Next
    
    InitI2cDevice:
    
            Low SCL                         ; SCL = 0
            Low SDA                         ; SDA = 0
            Input SCL                       ; SCL = 1
            Input SDA                       ; SDA = 1
            Return
    
    ; *****************************************************************************
    ; *                                                                           *
    ; *     Low-Level I2C Interface                                               *
    ; *                                                                           *
    ; *****************************************************************************
    
    I2cSendHeader:
    
            Gosub I2cStart
    
            i2cDataByte = I2C_ADDRESS & $FE
            Gosub I2cSendByte
    
            i2cDataByte = i2cAdrMsb
            Gosub I2cSendByte
    
            i2cDataByte = i2cAdrLsb
    
    I2cSendByte:
    
            For i2cBitCount = 0 TO 7
              If i2cDataByte < $80 Then
                Low SDA                     ; SDA = 0
              Else
                Input SDA                   ; SDA = 1
              End If
              Gosub I2cStrobeScl
              i2cDataByte = i2cDataByte * 2
            Next
            Input SDA                       ; SDA = 1 / Tri-State SDA
            Gosub I2cStrobeScl
    ; ---   if i2cAckBit = 1 Then
    ; ---     SerTxd( "ACK FAILED",CR,LF )
    ; ---   end if
            Return
    
    I2cStart:
    
            Input SDA                       ; SDA = 1
            Input SCL                       ; SCL = 1
            Low SDA                         ; SDA = 0
            Low SCL                         ; SCL = 0
            Return
    
    I2cStrobeScl:
    
            Input SCL                       ; SCL = 1
            Do
            Loop Until SCL_PIN = 1
            i2cAckBit = SDA_PIN
            Low SCL                         ; SCL = 0
            Return
    
    ; *****************************************************************************
    ; *                                                                           *
    ; *     End of program                                                        *
    ; *                                                                           *
    ; *****************************************************************************

  7. #7
    Senior Member
    Join Date
    Oct 2013
    Location
    Stockport, UK. On a good day, Cornwall UK
    Posts
    360

    Default

    Quote Originally Posted by hippy View Post
    I am sure that some of my example code has dealt with the open-drain issue; that is achieved by only using INPUT and LOW commands, never setting the pin high.
    Very clever - I'd not thought of that.

  8. #8
    Member
    Join Date
    Jul 2010
    Location
    Colorado USA
    Posts
    92

    Default

    I have used the code posted above with 08M2's, 14M2's, and 20X2's on many TM1637 LED
    display projects. All have and still are working perfectly. Maybe the TM1637 is not truly
    an I2C device??

    Cheers to All

  9. #9
    Technical Support
    Join Date
    Jan 1970
    Location
    UK
    Posts
    23,736

    Default

    Quote Originally Posted by pxgator View Post
    Maybe the TM1637 is not truly an I2C device??
    It seemed to be from the datasheets I looked at and the bit-banged code earlier. Talking of which -

    Code:
      outpinC.1 = bit7:pulsout clk, 1
      pulsout clk, 1
      return
    That's a bit iffy as PhilHornby noted above. It is clocking in an ACK from the I2C device which, if bit7 just happens to have set C.1 high, will be trying to pull that high to 0V. Admittedly only for a short period of time.

  10. #10
    Member
    Join Date
    Jul 2010
    Location
    Colorado USA
    Posts
    92

    Default

    Thanks for the info hippy but like I mentioned above the code and
    setup that I use with PICAXE chips and the TM1637 have worked
    trouble free for a long time. I've never experienced any errors.

    Cheers to All

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •