This program is used on a PICAXE 08M2 to read the temperature from a DS18B20 temperature sensor and display it on a 3 digit 7 segment LED display. A MAX7219 LED driver is used to drive the display.

The main processor can also control this chip through 2 inputs; one to control the brightness level, and the other display the temperature in farenheit.

#picaxe 08m2
#no_data

; Project: Word Clock v2.
; File: ReadDisplayTemp.bas
; Description:
;     Read temperature from a DS18B20 and display on a three
;     digit 7 segment LED display using a MAX7219 LED display
;     driver.
;
; Copyright (C) 2014 Marc Symonds
; All rights reserved.
;
; This software may be used and redistributed, with or without
; modification, as long as it is understood that this software
; is provided as-is without any explicit or implied warranties
; of merchantablity or fitness of purpose.

    
; MAX7219 Pins
symbol MAX7219_LOAD = C.1
symbol MAX7219_CLK = C.0
symbol MAX7219_DIN = C.2

; MAX7219 Registers
symbol MAX7219_NOOP = $00
symbol MAX7219_DIGIT0 = $01
symbol MAX7219_DIGIT1 = $02
symbol MAX7219_DIGIT2 = $03
symbol MAX7219_DIGIT3 = $04
symbol MAX7219_DIGIT4 = $05
symbol MAX7219_DIGIT5 = $06
symbol MAX7219_DIGIT6 = $07
symbol MAX7219_DIGIT7 = $08
symbol MAX7219_DECODE_MODE = $09
symbol MAX7219_INTENSITY = $0A
symbol MAX7219_SCAN_LIMIT = $0B
symbol MAX7219_SHUTDOWN = $0C
symbol MAX7219_TEST_MODE = $0F

; DS18B20 Pins
symbol DS18B20_DQ = C.4

; Pins used by main processor to control display.
symbol DISPLAY_F = C.5 ; Display in Farenheit.
symbol DISPLAY_FP = pinC.5
symbol LOW_BRIGHTNESS = C.3 ; Display brightness high or low.
symbol LOW_BRIGHTNESSP = pinC.3


symbol P_Register = b0
symbol P_Data = b1
symbol V_Temp1 = b3
symbol V_Temp2 = b4

symbol V_Neg = b8
symbol V_TempFrac = b9
symbol V_TempWhole = b10
symbol V_Digit0 = b11
symbol V_Digit1 = b12
symbol V_Digit2 = b13

symbol V_Temperature = w3 ; b6 b7

symbol V_LowBrightness = b14

letThereBeLight:
  setfreq m4
  
  ; This long delay is to allow the chip to be more easily programmed later,
  ; because further down we "disconnect" the chip so that it stops looking for
  ; new downloads.

  pause 3000
  
  let V_LowBrightness = 0

  input DISPLAY_F
  input LOW_BRIGHTNESS
  
  gosub MAX7219_Initialise

  ; We are using C.5 (serial in) as an input (to display farenheit), so we need
  ; to stop the chip from scanning the serial in pin looking for a new download.
  ; Once the disconnect command has run, you have to do a hard-reset to download
  ; a new program; see the manual.
  
  disconnect

main:
  setfreq m4
  readtemp12 DS18B20_DQ, V_Temperature
  setfreq m8

  gosub displayTemp

  if LOW_BRIGHTNESSP <> V_LowBrightness then
    let V_LowBrightness = LOW_BRIGHTNESSP
    
    if V_LowBrightness = 0 then
      let P_Data = $05
    else
      let P_Data = $0E
    end if
    
    gosub MAX7219_SetIntensity
  end if
  
  ;pause 1000
  sleep 2
  goto main


; The 3 digit 7 segment display I'm using has some segments that don't work;
; notably the  e  segment of the first character, and the DP segments of the
; first and third characters.
; So the displaying of the temperature below is a bit more complicated than
; would normally be required, to work around the problems with the display.
  
displayTemp:
  let V_Neg = 0
  if V_Temperature > $7FFF then
    let V_Temperature = -V_Temperature
    let V_Neg = 1
  end if
  
  if DISPLAY_FP = 1 then
    ; Convert C to F. 115/64 = 1.7968 (1.8 ish), and 512 is 32 * 16 (temp from DS18B20 is in 16th's of a degree).
    let V_Temperature = V_Temperature * 115 / 64 + 512 
  end if
  
  let b9 = V_Temperature & 15 * 10 / 16 ; frac
  let b10= V_Temperature / 16 ; whole

  ; Work out what to display in each of the three digits.
  
  if V_Neg = 1 then
    let V_Digit0 = 10 ; minus sign.
    
    if b10 > 99 then ; Can't display anything below -99, so show EE. If it's below -99 we're probably dead anyway.
      let b12 = 11 ; E
      let b13 = 11 ; E
    elseif b10 > 9 then
      let b12 = b10 / 10
      let b13 = b10 % 10
    else
      let b12 = b10 | $80 ; Turn on DP
      let b13 = b9
    end if      
  else
    if b10 > 99 then
      let b11 = b10 / 100
      let b12 = b10 / 10 % 10
      let b13 = b10 % 10
    elseif b10 < 20 then
      if b10 > 9 then
        let b11 = b10 / 10
      else
        let b11 = 15 ; blank
      end if
      
      let b12 = b10 % 10 | $80 ; Turn on DP
      let b13 = b9
    else
      let b11 = 15
      let b12 = b10 / 10
      let b13 = b10 % 10
    end if
  end if

  ; Display it.
  
  let b0 = MAX7219_DIGIT0
  let b1 = b11
  gosub MAX7219_SendCmdAndDataTo1
  
  let b0 = MAX7219_DIGIT1
  let b1 = b12
  gosub MAX7219_SendCmdAndDataTo1

  let b0 = MAX7219_DIGIT2
  let b1 = b13
  gosub MAX7219_SendCmdAndDataTo1
  
  return

; ********************************************************************************
; *** MAX7219 Functions **********************************************************
; ********************************************************************************

MAX7219_Initialise:
  output MAX7219_LOAD
  output MAX7219_CLK
  output MAX7219_DIN
  
  low MAX7219_LOAD
  low MAX7219_CLK
  low MAX7219_DIN

  pause 10

  gosub MAX7219_TestModeOff
  gosub MAX7219_ShutdownOff

  let b0 = MAX7219_SCAN_LIMIT
  let b1 = $02 ; Using 3 digits.
  gosub MAX7219_SendCmdAndDataTo1

  let b0 = MAX7219_DECODE_MODE
  let b1 = $7 ; Use BCD for digits 0, 1 and 2.
  gosub MAX7219_SendCmdAndDataTo1

  let b1 = $0C ' Max brightness.
  gosub MAX7219_SetIntensity

  return


MAX7219_ShutdownOff:
  let b0 = MAX7219_SHUTDOWN
  let b1 = $01
  goto MAX7219_SendCmdAndDataTo1 ; Return will be peformed by this function

#rem
MAX7219_ShutdownOn:
  let b0 = MAX7219_SHUTDOWN
  let b1 = $00
  goto MAX7219_SendCmdAndDataToBoth ; Return will be peformed by this function
#endrem

MAX7219_TestModeOn:
  let b1 = $01
  goto MAX7219_TestModeSet ; Return will be peformed by this function  
MAX7219_TestModeOff:
  let b1 = $00
MAX7219_TestModeSet:
  let b0 = MAX7219_TEST_MODE
  goto MAX7219_SendCmdAndDataTo1 ; Return will be peformed by this function


MAX7219_SetIntensity:
; b1 = Intensity level for top half.
; b2 = Intensirt level for bottom half.

  let b0 = MAX7219_INTENSITY
; *** Fall-through ***


MAX7219_SendCmdAndDataTo1:
; b0 = Register.
; b1 = Data for chip 1.

  gosub MAX7219_SendCmdAndData

; For 7219 you only need to pulse the LOAD pin to load the data.
  
  pulsout MAX7219_LOAD, 1
  
  return  

MAX7219_SendCmdAndData:
; b0 = Register.
; b1 = Data.
; b3 & b4 used as temp.

  let b3 = b0
  gosub MAX7219_Send

  let b3 = b1
; *** Fall-through is intended. ***
MAX7219_Send:
; b3 = Data to send

  for b4 = 0 to 7
    if b3 > 127 then
      high MAX7219_DIN
    else
      low MAX7219_DIN
    end if

    pulsout MAX7219_CLK, 1    

    b3 = b3 * 2
  next

  low MAX7219_DIN

  return 


#rem
3 Digit/7 Segment display Pins

          1 1 1                      a
          2 1 0 9 8 7               ---
          | | | | | |             f|   |b
         +-----------+             | g |
         |           |              ---
         | 8. 8. 8.  |            e|   |c
         |           |             |   |
         +-----------+              ---  O 
          | | | | | |                d
          1 2 3 4 5 6

 1 = Digit 0 cathode
 2 = Segment e
 3 = Segment d
 4 = Digit 1 cathode
 5 = Segment c
 6 = DP
 7 = Digit 2 cathode
 8 = Segment b
 9 = Segment g
10 = Segment a
11 = Segment f
12 = NC

#endrem

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments Protected by WP-SpamShield Spam Blocker