Max/Min thermometer using Nokia 3310 LCD, DS1820 sensor and a 12F675

Started by Bob (G8GFA), Feb 03, 2021, 02:31 PM

Previous topic - Next topic

Bob (G8GFA)

A silly little project in many ways, but it works and does show how tight the machine code produced by Proton is. Temperatures are displayed to the nearest 0.1 of a degree.

Thermometer.jpg


'****************************************************************
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings

    Device = 12F675

    Config FOSC_INTRCIO, WDTE_ON, PWRTE_ON, MCLRE_OFF, BOREN_OFF, CP_OFF, CPD_OFF

;**** End of Fuse Configurator Settings ****
'****************************************************************

    Xtal = 4

    'All_Digital = true   ' Set all proc pins to I/O

    TRISIO  = 0
    GPIO    = 0
    CMCON   = 7
    ANSEL   = 0
   
    Symbol SDIN     =     GPIO.0
    Symbol SCK      =     GPIO.1   
    Symbol DQ       =     GPIO.2
    Symbol Mode     =     GPIO.3
    Symbol RST      =     GPIO.4
    Symbol D_C      =     GPIO.5


   
    Symbol RdOffSet  =    5
    Symbol X_Origin  =    %10000000
    Symbol Y_Origin  =    %01000000
    Symbol NormVid   =    %00001100
    Symbol InvVid    =    %00001101
   
    Dim Temperature     As Word
    Dim TempHigh        As  Temperature.HighByte
    Dim TempH           As  Byte
    Dim TempL           As  Byte
    Dim sign            As  Bit
    Dim MaxTemp         As  Word
    Dim MinTemp         As  Word

    Dim LcdReg          As  Byte
    Dim DispLine        As  Byte
    Dim Offset          As  Word
    Dim Char[6]         As  Byte

    Dim CharPtr         As  Byte
    Dim Loop1           As  Byte
    Dim Loop2           As  Byte
    Dim LoopOut         As  Byte
   
    GoTo Main

'****************************************************************

SndLcdCmd:
    D_C = 0
SndLcdData:
    SCK = 0
    LoopOut = 0
    Repeat
        SDIN = LcdReg.7
        LcdReg = LcdReg << 1
        SCK = 1
        SCK = 0
        Inc LoopOut
    Until LoopOut > 7
    D_C = 1
Return

'****************************************************************
DisplayTemp:
   
    Loop2 = 0 
    Repeat

        Offset = Char[Loop2] * 20
        If Offset > 159 Then  Offset = Offset - 160

        LcdReg  =  Y_Origin + 1            ' cursor  Y DispLine number(0-5)
        GoSub    SndLcdCmd

        LcdReg = 0
        GoSub  SndLcdData
        GoSub  SndLcdData
        CharPtr = CharPtr + 2
                     
        GoSub PrintChar             
        LcdReg  =  X_Origin + CharPtr
        GoSub    SndLcdCmd
       
        LcdReg  =  Y_Origin + 2            ' cursor  Y DispLine number(0-5)
        GoSub    SndLcdCmd

        GoSub PrintChar
        CharPtr = CharPtr + 10
        Inc Loop2
              
    Until Loop2 > 5

Return
'****************************************************************
PrintChar:       
        Loop1 = 1
        Repeat
            If Char[Loop2] < 8 Then '***** Numbers 0- 7 inclusive ******
                LcdReg = CRead font+Offset
            Else
            '****** Characters 8 - 13 (+,-,.,centigrade) ********
                LcdReg = ERead Offset
            EndIf
            Inc Offset
            GoSub  SndLcdData
            Inc Loop1
        Until Loop1 > 10
Return
'****************************************************************
Temp2Dec:

    sign = 0

    If  TempHigh.7 = 1 Then
        Temperature  =  ~Temperature + 1
        sign = 1
    EndIf

    TempH = Temperature >> 4
    TempL = Temperature.LowByte & $0F
    Temperature = TempL * 625

    If TempH > 99 Then             ' if the temp higher than 99'C , instead of the plus signs " 1 "
        Char[0] = 1                   ' hundreds
    Else
        Char[0] = 10                  ' + plus
        If sign = 1 Then Char[0] = 11
    EndIf

    Char[1] = Dig TempH,1            ' Tens
    Char[2] = Dig TempH,0            ' Units
    Char[3] = 12                     ' Decimal point
    Char[4] = Dig Temperature,3      ' first decimal
    Char[5] = 13                     ' Degrees Centigrade

Return
'****************************************************************
DisplayMaxMin:

    LcdReg  =  Y_Origin + 5            ' cursor  Y DispLine number(0-5)
    GoSub    SndLcdCmd
   
DisplayLabel:
   
    Loop2 = 0
    Repeat
        Offset = Char[Loop2] * 5
        Loop1 = 0
        Repeat
            LcdReg = CRead SmallFont+Offset
            LcdReg = ~LcdReg
            GoSub  SndLcdData
            Inc Offset
            Inc Loop1
        Until Loop1 > 4
        LcdReg = $ff
        GoSub  SndLcdData
        Inc Loop2
    Until Loop2 > 5
Return
'****************************************************************
GetTemp:

    OWrite DQ, 1, [$CC, $44]      ' Start temperature conversion
    Snooze 6
    OWrite DQ, 1, [$CC, $BE]
    ORead DQ, 0, [Temperature.LowByte, Temperature.HighByte, Skip 6]

Return
'****************************************************************
Main:
'****************** GLCD Initialisation ***********************

    High RST

    LcdReg  =  $21 '%00100001       'LCD Extended Commands.
    GoSub    SndLcdCmd
    LcdReg  =  $d8'C0 '%10101001       'Set LCD Vop (Contrast).
    GoSub    SndLcdCmd
    LcdReg  =  $06 '%00000110       'Set Temp coefficent.
    GoSub    SndLcdCmd
    LcdReg  =  $13 '%00010011       'LCD bias mode 1:48.
    GoSub    SndLcdCmd
    LcdReg  =  $20 '%00100000       'LCD Standard Commands, Horizontal addressing mode.
    GoSub    SndLcdCmd
    LcdReg  =  NormVid
    GoSub    SndLcdCmd
    
'********** Draw screen frame. ***********
    Loop2 = 0
    Repeat
        LcdReg  =  Y_Origin + Loop2
        GoSub    SndLcdCmd
        LcdReg  =  X_Origin        ' X pos left
        GoSub    SndLcdCmd
        Loop1 = 0
        Repeat
            LcdReg = $00
            If Loop2 = 0  Then LcdReg = $03
            If Loop2 > 3  Then LcdReg = $FF
            If Loop1 < 2  Then LcdReg = $FF
            If Loop1 > 81 Then LcdReg = $FF
            GoSub   SndLcdData
            Inc Loop1
        Until Loop1 > 84
        Inc Loop2
    Until Loop2 > 5
   
    LcdReg  =  Y_Origin + 4
    GoSub    SndLcdCmd
    LcdReg  =  X_Origin + 4        ' X pos left
    GoSub    SndLcdCmd
   
    Char[0] = 11
    Char[1] = 14
    Char[2] = 15
    Char[3] = 16
    Char[4] = 11
    Char[5] = 19
   
    GoSub DisplayLabel   
   
    LcdReg  =  X_Origin + 51        ' X pos left
    GoSub    SndLcdCmd

    Char[2] = 17
    Char[3] = 18
           
    GoSub DisplayLabel
   
    GoSub GetTemp
    MaxTemp = Temperature
    MinTemp = Temperature
   
 ' *********** Main program Loop1 ***********
    While
   
        LcdReg  =  NormVid                       'LCD in normal mode.
        If Mode = 0 Then LcdReg  = InvVid
        GoSub    SndLcdCmd 
       
        If Temperature.15 = MaxTemp.15 And Temperature > MaxTemp Then MaxTemp = Temperature
        If Temperature.15 = 0 And MaxTemp.15 > 0 Then MaxTemp = Temperature

        If Temperature.15 = MinTemp.15 And Temperature < MinTemp Then MinTemp = Temperature
        If Temperature.15 > 0 And MinTemp.15 = 0 Then MinTemp = Temperature
       
        LcdReg  =  X_Origin + RdOffSet  ' cursor  X  (0-83)
        GoSub    SndLcdCmd
        GoSub Temp2Dec
        CharPtr = RdOffSet
        GoSub DisplayTemp
       
        LcdReg  =  X_Origin + 1             ' cursor  X  (0-83)
        GoSub    SndLcdCmd
        Temperature = MaxTemp
        GoSub Temp2Dec
        GoSub DisplayMaxMin

        LcdReg  =  X_Origin + 48       ' cursor  X  (0-83)
        GoSub  SndLcdCmd
        Temperature = MinTemp
        GoSub Temp2Dec
        GoSub DisplayMaxMin
       
        GoSub GetTemp
    Wend
   
'***** Numbers 0-7 inclusive ******
Font:

    CData   $F8,$FC,$06,$06,$06,$86,$C6,$66,$FC,$F8,_   ' 0
            $3F,$7F,$CC,$C6,$C3,$C1,$C0,$C0,$7F,$3F,_
       
            $00,$10,$18,$1C,$FE,$FE,$00,$00,$00,$00,_   ' 1
            $00,$80,$C0,$C0,$FF,$FF,$C0,$C0,$00,$00,_
       
            $18,$1C,$06,$06,$06,$06,$06,$06,$FC,$F8,_   ' 2
            $F0,$F8,$C8,$CC,$C6,$C6,$C3,$C1,$C1,$C0,_
       
            $06,$06,$06,$06,$86,$C6,$66,$36,$1E,$0E,_   ' 3
            $60,$E0,$C0,$C0,$C0,$C1,$C3,$C6,$7E,$3C,_  

            $00,$80,$E0,$78,$1E,$06,$FE,$FE,$00,$00,_   ' 4
            $0E,$0F,$0D,$0C,$0C,$0C,$FF,$FF,$0C,$0C,_ 
      
            $FC,$FE,$86,$86,$86,$86,$86,$86,$86,$06,_   ' 5
            $70,$F1,$C1,$C1,$C1,$C1,$C1,$C1,$7F,$3F,_
       
            $FC,$FE,$06,$06,$06,$06,$06,$06,$06,$04,_   ' 6
            $7F,$FF,$C3,$C3,$C3,$C3,$C3,$C3,$FF,$7E,_
       
            $04,$06,$06,$06,$06,$86,$C6,$66,$3E,$1C,_   ' 7
            $00,$00,$00,$FE,$FF,$01,$00,$00,$00,$00
           
           
 '******  Characters 8 - 13 (8,9,+,-,.,Centigrade) ********


    EData   $78,$FC,$86,$86,$86,$86,$86,$86,$FC,$78,_   ' 8
            $3E,$7F,$C1,$C1,$C1,$C1,$C1,$C1,$7F,$3E,_
           
            $FC,$FE,$06,$06,$06,$06,$06,$06,$FE,$FC,_   ' 9
            $41,$C3,$C3,$C3,$C3,$C3,$C3,$C3,$FF,$7F,_
           
            $80,$80,$80,$80,$F8,$F8,$80,$80,$80,$80,_   ' +
            $01,$01,$01,$01,$1F,$1F,$01,$01,$01,$01,_
           
            $80,$80,$80,$80,$80,$80,$80,$80,$80,$80,_   ' -
            $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,_
           
            $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,_   ' .
            $00,$00,$00,$60,$F0,$F0,$60,$00,$00,$00,_
           
            $0E,$CA,$EE,$60,$60,$60,$60,$E0,$C0,$00,_   ' Degrees C
            $00,$7F,$FF,$C0,$C0,$C0,$C0,$E0,$60,$00          
           

SmallFont:

    CData   $3E,$51,$49,$45,$3E,_       ' 0
            $00,$42,$7F,$40,$00,_       ' 1
            $42,$61,$51,$49,$46,_       ' 2
            $21,$41,$45,$4B,$31,_       ' 3
            $18,$14,$12,$7F,$10,_       ' 4
            $27,$45,$45,$45,$39,_       ' 5
            $3C,$4A,$49,$49,$30,_       ' 6
            $01,$71,$09,$05,$03,_       ' 7
            $36,$49,$49,$49,$36,_       ' 8
            $06,$49,$49,$29,$1E,_       ' 9
            $08,$08,$3E,$08,$08,_       ' +
            $08,$08,$08,$08,$08,_       ' -
            $00,$60,$60,$00,$00,_       ' .
            $03,$03,$78,$48,$48,_       ' Degrees C
            $7E,$04,$08,$04,$7E,_       ' M char 14
            $78,$14,$12,$14,$78,_       ' A char 15
            $42,$24,$18,$24,$42,_       ' X char 16
            $00,$42,$7E,$42,$00,_       ' I char 17
            $7E,$04,$18,$20,$7E,_       ' N char 18
            $00,$00,$00,$00,$00         ' Space - char 19

 

top204

Excellent code Bob, and many thanks for the compliment.

You're in for a treat with the next compiler update, although I may have placed it in the current version 3.7.5.5. :-)

Instead of writing tables in flash memory code as:
    CData  $F8,$FC,$06,$06,$06,$86,$C6,$66,$FC,$F8,_   ' 0
           $3F,$7F,$CC,$C6,$C3,$C1,$C0,$C0,$7F,$3F,_
       
           $00,$10,$18,$1C,$FE,$FE,$00,$00,$00,$00,_   ' 1
           $00,$80,$C0,$C0,$FF,$FF,$C0,$C0,$00,$00,_
       
           $18,$1C,$06,$06,$06,$06,$06,$06,$FC,$F8,_   ' 2
           $F0,$F8,$C8,$CC,$C6,$C6,$C3,$C1,$C1,$C0,_
       
           $06,$06,$06,$06,$86,$C6,$66,$36,$1E,$0E,_   ' 3
           $60,$E0,$C0,$C0,$C0,$C1,$C3,$C6,$7E,$3C

With the line continuation required after every line, you will be able to do:

    CData {$F8,$FC,$06,$06,$06,$86,$C6,$66,$FC,$F8,   ' 0
           $3F,$7F,$CC,$C6,$C3,$C1,$C0,$C0,$7F,$3F,
       
           $00,$10,$18,$1C,$FE,$FE,$00,$00,$00,$00,   ' 1
           $00,$80,$C0,$C0,$FF,$FF,$C0,$C0,$00,$00,
       
           $18,$1C,$06,$06,$06,$06,$06,$06,$FC,$F8,   ' 2
           $F0,$F8,$C8,$CC,$C6,$C6,$C3,$C1,$C1,$C0,
       
           $06,$06,$06,$06,$86,$C6,$66,$36,$1E,$0E,   ' 3
           $60,$E0,$C0,$C0,$C0,$C1,$C3,$C6,$7E,$3C}

Notice the starting and ending curly braces and the lack of any line continuation characters for the data items in the block? :-) This makes code so much easier to write and read, and I implemented it because I use it all the time with C++, so I thought it would come in handy for the users of Proton8 and Proton24.

Also, the Dim As Flash, Dim As Flash8, Dim As Flash16, Dim As Flash24, Dim As Flash32, Dim As FlashF, and Dim As FlashD directives for making flash memory tables are extremely good to write and read, and make code more efficient. The next manual update has better details of them. They are an optional name change from the Code, Code8, Code16, Code24, Code32, and CodeF directives. I originally used the name "Code" because the flash memory on PICs was always known as "Code Memory", but now it is known as "Flash Memory" in some datasheets and application notes etc... But I'm sure they will change it later to "Program Memory" like AVR devices have.

Note that the curly braces are optional, and the standard method is still, and always will be, supported.

keytapper

Compliments for the masterpiece!! I never realized that a 12F675 would drive a PCD8544.
Ignorance comes with a cost

Dompie

I thought I knew all the Proton commands, but another surprise: Snooze. The Proton manual filled in my ignorance once again. Handy command.
Nice program and in a 12F !!

Johan