20x2 Clock and temperature on LCD 20X4

marks

Senior Member
My interest was sparked recently so I thought I'd try some code using an LCD 20X4
displaying Clock and temperature using
LCDRS2 serial driver
http://www.picaxeforum.co.uk/showthread.php?t=16781

Displays on
Line 1 - Time 12 hour format with seconds
Line 2 - Current Temperature Ds18b20 full range 0.1 resolution(125.0 C to -55.0 C)
Line 3 - Daily Maximum Temperature Hi:
Line 4 - Daily Minimum Temperature Lo:

Code:
	'  -- -- -- -- -- -- -- -- -- -- -- -- -- 
	' |  9 . 5 4 . 1 0  A M                  |

	' |    2 5 . 5 '    C e l s i u s        | Picaxe  20x2  ver C.0

	' |                   H i :     2 6 . 8 '|

	' |                   L o :     2 2 . 9 '| marks
	'  -- -- -- -- -- -- -- -- -- -- -- -- --  
	'  LCDRS2 driver     =    B.4
	'  SDA ds3231        =    B.5
	'  SCL ds3231        =    B.7
	SYMBOL ds18b20       =    B.6
	SYMBOL pushbutton    = PINC.6

	SYMBOL character1    = B2
	SYMBOL character2    = B3
	SYMBOL character3    = B4 : SYMBOL firstdigit      = b4
	SYMBOL character4    = B5 : SYMBOL programdata     = b5
	SYMBOL character5    = B6 : SYMBOL totaldigit      = b6
	SYMBOL character6    = B7 : SYMBOL lineposition    = b7

	SYMBOL hours         = B8
	SYMBOL mins          = B9
	SYMBOL secs          = B10
	SYMBOL day           = B11
	SYMBOL date          = B12
	SYMBOL month         = B13
	SYMBOL year          = B14

        SYMBOL PMAM          = B15 : SYMBOL menu1          = b15
	SYMBOL push          = B16
	SYMBOL recall        = B17 
	     
	SYMBOL tempMSB       = b18 '(W9)
	SYMBOL tempLSB       = b19 '(W9)
	SYMBOL Temperature   = W9  '(b18,b19)
	SYMBOL Maximum       = W10 
	SYMBOL Minimum       = W11

	SYMBOL updatetime    = W12 
	SYMBOL totalminutes  = W13 
	SYMBOL displayedtime = W14
	SYMBOL hold          = W15 

Initialise:
 SETFREQ M16
owout  ds18b20,%1001,($CC,$44)                           ' reset(send skip rom ,send convert t)
 PAUSE 950                                               ' give time to convert
serout b.4,n9600_16,($FE,$41,$FE,$52,$FE,$51)            ' turn on,backlight on,clear screen
serout b.4,n9600_16,($FE,$54,$0,$6,$9,$9,$6,$0,$0,$0,$0) ' load custom character position 8bytes
 SETTIMER T1S_16
Maximum = 0 : Minimum = 2880                             ' zero temperature   

Main: 
      PAUSE 10
	HI2CSETUP I2CMASTER, %11010000, I2Cslow_16, I2CBYTE        ' set to 100kbps default /change to I2Cfast_16 for 400kbps
      PAUSE 20
	HI2CIN 0,(secs,mins,hours,day,date,month,year)             ' read time ds3231
      HI2CSETUP OFF
      low b.5
      IF hours =$0 and mins =$0 THEN:Maximum = 0 :Minimum = 2880 :ENDIF 'zero temperature start of day
      LET date  = BCDTOBIN date                                  'Date from ds3231 needs converting
      LET month = BCDTOBIN month
      LET year  = BCDTOBIN year

	LET secs = BCDTOBIN secs                                   'Time from ds3231 needs converting  
	LET totalminutes = BCDTOBIN mins * 60
	LET hours = BCDTOBIN hours
 
 	PMAM =80  :  IF hours < 12 then :PMAM = 65 : ENDIF         'indicate pm or am
	IF hours > 12 THEN 
	LET updatetime = hours - 12 * 3600 + totalminutes + secs   '12 hour format
	ELSE
	LET updatetime = hours * 3600 + totalminutes + secs         
	ENDIF
 
	LET TIMER = updatetime                                     'up date time from ds3231 
    
ClockDisplay:
  hours = TIMER /3600
   LET character1 = hours DIG 1+"0"
   LET character2 = hours DIG 0
  mins  = TIMER //3600/60 
   LET character3 =  mins DIG 1
   LET character4 =  mins DIG 0
  secs  = TIMER //3600//60
   LET recall = secs DIG 0 : IF character6  = recall  THEN clockdisplay 'wait for change in seconds
   LET character5 =  secs DIG 1
   LET character6 =  secs DIG 0
  
IF character1 = "0" THEN  :  character1 = " "  :  ENDIF                 ' zero blanking character1
    serout b.4,n9600_16,($FE,$46,character1,#character2,".",#character3,#character4,".",#character5,#character6," ",PMAM,"M")'cursor home

Convert: hold=0
owout ds18b20,%1001,($CC,$44)                      ' reset(send skip rom ,send convert t) 
IF pushbutton = 1 THEN cfselection 
owout ds18b20,%0001,($CC,$BE)                      ' reset(send skip rom ,send read lsb msb)
owin  ds18b20,%0000,(tempMSB,tempLSB)              ' read in result ds18b20

      Temperature = Temperature + 880
   IF Temperature > Maximum THEN LET Maximum = Temperature: ENDIF  'Hi:
   IF Temperature < Minimum THEN LET Minimum = Temperature: ENDIF  'Lo:
                          GOSUB Temp    

    serout b.4,n9600_16,($FE,$45, 1,2,character1,character3,character4,character5,".",character6,0)                'cursor position1  line2,degrees
Let Temperature=Maximum : GOSUB Temp

Hi: serout b.4,n9600_16,($FE,$45,10,3," Hi:",character1,character3,character4,character5,".",character6,0)         'cursor position10 line3,degrees 
Let Temperature=Minimum : GOSUB Temp

Lo: serout b.4,n9600_16,($FE,$45,10,4," Lo:",character1,character3,character4,character5,".",character6,0,$FE,$48) 'cursor position10 line4,degrees,cursor off
goto main

cfSelection:
If Hold > 1600 then Menu
inc hold
If pushbutton = 1 THEN cfselection
push = push + 1//2

goto convert

   Temp:
   If push = 0 THEN
                   serout b.4,n9600_16,($FE,$45, 9,2," Celsius   ")' cursor position9  line2
   Temperature=Temperature * 5 / 8 -550
               ELSE
                   serout b.4,n9600_16,($FE,$45, 9,2," Fahrenheit")' cursor position9  line2
   Temperature=Temperature * 9 / 8 -670
               ENDIF
       let character1 =32                           ' character1(Signbit)    Display + (43) space (32)
     IF Temperature >  64865 THEN
     Temperature = -Temperature
       let character1 =45                           ' character1(Signbit)    Display - (45)
        ENDIF                                       ' resolution to 0.1
      
BINTOASCII Temperature,character2,character3,character4,character5,character6
IF character3 = "0" THEN : character3 = " "                 ' zero blanking 
IF character4 = "0" THEN : character4 = " " : ENDIF : ENDIF ' zero blanking 
                           RETURN 

Menu:menu1=0 
                   serout b.4,n9600_16,($FE,$51,$FE,$46,"      Set Time")    'clear screen , cursor home
                   serout b.4,n9600_16,($FE,$45, 7,3,"  .  ")                'cursor position7  line3
    
 Selection:on menu1 goto hour,minute,program     
      hour:                        firstdigit=2 : totaldigit=24  :lineposition=7 :goto Selection1'hours entered (00-23) 24 hour format
    minute:  hours=programdata  :  firstdigit=6 : totaldigit=60  :lineposition=10:goto Selection1'mins  entered (00-59)

 Selection1: let recall = 0 :IF pushbutton = 1 THEN Selection1
           SelectionDisplay1:hold = 0
                      LET character1 = recall DIG 1
 	             serout b.4,n9600_16,($FE,$45,lineposition,3,#character1)            
          IF pushbutton=0 THEN SelectionDisplay1
                       Select1:  IF hold > 600 then Selection2
                        INC hold : IF pushbutton = 1 THEN Select1
                  recall = recall + 10 : IF character1 = firstdigit THEN Selection1 : GOTO SelectionDisplay1

 Selection2: let programdata = recall : IF pushbutton = 1 THEN Selection2
     SelectionDisplay2: hold = 0
                  LET character1 = programdata DIG 1
                  LET character2 = programdata DIG 0
                   serout b.4,n9600_16,($FE,$45,lineposition,3,#character1,#character2)
          IF pushbutton=0 THEN SelectionDisplay2
       Select2:IF hold > 600 then : inc menu1 : goto Selection :endif
        INC hold : IF pushbutton = 1 THEN Select2
     INC programdata : IF character2 = 9 OR programdata = totaldigit THEN Selection2 : GOTO SelectionDisplay2
      
 Program:          serout b.4,n9600_16,($FE,$51)     'clear screen 
  IF pushbutton = 1 THEN program                     'release to program  
     mins=programdata
      LET  date  = BINTOBCD date                     'convert data going to ds3231
 	LET  month = BINTOBCD month
 	LET  year  = BINTOBCD year
 	LET  hours = BINTOBCD hours
      LET  mins  = BINTOBCD mins
      
      PAUSE 10
 	HI2CSETUP I2CMASTER, %11010000, I2Cslow_16, I2CBYTE       'set to 100kbps default /change to I2Cfast_16 for 400kbps 
 	PAUSE 20 
	HI2COUT 0, ($00, mins, hours, $00, date, month, year)     'prog time ds3231 (seconds,mins,hour,day,date,month,year)
	GOTO initialise
If we push the button it will toggle between Celsius or Fahrenheit.
If we hold the button we can program the time
Push to select digit - Hold to save
when we release on the final minute the Ds3231sn will be programmed.

Default code of I2c is set to 100 kbps so should also work with Ds1307
Time and Temperature is updated every second.

To Do's - add more funtions later like alarms, date
- would make a good temperature controller
- feel freee to comment

Wishlist - Gimme my 20x2 Shield LOL!
 

Attachments

Last edited:

marks

Senior Member
Its great to have a break hope everyone enjoying the long weekend !
Progress is slow but gave me a chance to do a bit

Display has been rearranged and added the date and day.
Added some programed characters just making A M P C F slightly smaller.
Temp has changed will now read an extended range of the Ds18b20
outside the recommended range .
push the button to select either Celsius or Fahrenheit 0.1 resolution with 0.05 to 0.09
rounded up.
Still much the same hold the button to program
the days will cycle around Sunday to saturday ,just hold on the day we want
we then program the date 26/04/11 and time 01.02 in the normal way.
still cycles arround within 1 second so no need to learn new commands and up the speed yet.
 

Attachments

Last edited:

marks

Senior Member
Well finaly got around to adding alarm(1)( 2)( 3)
will be displayed in the left bottom corner.
underneath the number will show its status ( see pic in previous post )
( on) = on
( _ ) = off
( ) and if nothing no time has been programmed.
1 will control b.1 output high when on,
2 = b.2
3 = b.3
As before hold to program cycles arround days and alarms.
select alarm 1 enter start time and end time (is programmed in eerom).
if power is restored after a failure and time is between the programmed times
output will be on(so doesnt mater if we miss the start.)

also removed set timer from the program so could get rid of a lot of unnecessary code.
so we just rely on our rtc and everything still updates within a sec(must work out 1 day)

hmmm i guess i must now think of how i want temp control to work lol !
 

Attachments

Nice!

WOW! being very new to electronics and only doing things like turning inputs and outputs on this is amazing. i hope you do more great projects for me to have a look at. Good job
Trevor B
 

rbright

Member
Suitability for use on a AXE401

MaskS you have done a great job here especially like the find of the LCDRS2 here in Perth where I can pickup without the delays/cost of delivery.

This code look excellent for porting over to as AXE401 28x2 Shield Base I've just received after waiting for 2 week delivery from Queensland.

Any intention to develop some data logging options - you have all the basis there.

Do you have a Perth supplier for the DS3231SN not familiar with this updated RTC
Cheers
 

marks

Senior Member
Hi rbright,
it always good to get some feedback ,thanks trevorboultwood too !
I think everyone has trouble sourcing the ds3231( but it is worth it !)
I find ebay easy for most stuff lol
http://www.ebay.com.au/itm/2PCS-DS3231-DS3231SN-SOP16-DALLS-IC-/320671994849?pt=LH_DefaultDomain_0&hash=item4aa98a53e1
you'll proballly need these too.
http://www.ebay.com.au/itm/5-pcs-SOP-20-SOP20-DIP-20-pin-Adapter-PCB-SMD-/390104632917?pt=LH_DefaultDomain_0&hash=item5ad40c4e55

Hmm I wish I had the 28x2 and the axe401 !
data logging does sound interesting I may look into down the track
however at the moment I dont know much about it.
next on the list is to add temperature control
and am keen to start a different project(really must make a second project board that would make things easier lol)
 

rbright

Member
Why Use Ds3231

I understand the DS3231 may only be available in a 16 pin surface mounted (SO) package against the older DS1307 which is available in a 8 pin DIL package.

The DS3231 has an internal crystal but besides that is there any reason why a 1307 can't be used - it still has the SCL & SDA lines for I2C communications? Notice the 3231 has inbuilt alarm functions but your code seems to handle that externally.

You mentioned the need for another project board well that is a good reason to move up to a 28X2 shield board ( AXE401) then you can do future development even on veroboard.

We have another long weekend in 2 weeks here in Perth so maybe you can keep bashing the code out.

Regards
 

marks

Senior Member
Hi rbright,
thanks for your enthusiasm lol,
i have used a ds1307 before the code is written with that in mind.
thats why the default speed is at 100kbps so should just be a hardware change
for those who wish to use it.
2.2k resistors is a good choice for pullups on the ds1307
i would think 2.2k would also be ok for the ds3231 at 100 or 400kbps
i was a bit concerned about using sop20 package (ds3231) too
but all went ok lol.( and the improvement in accuracy is really good).

the 28x2 shield microzed has sold out lol, i am tempted to try a newer ver 20x2 also
so might order 1 soon .
 
Great Project!

Hi rbright,
thanks for your enthusiasm lol,
i have used a ds1307 before the code is written with that in mind.
thats why the default speed is at 100kbps so should just be a hardware change
for those who wish to use it.
2.2k resistors is a good choice for pullups on the ds1307
i would think 2.2k would also be ok for the ds3231 at 100 or 400kbps
i was a bit concerned about using sop20 package (ds3231) too
but all went ok lol.( and the improvement in accuracy is really good).

the 28x2 shield microzed has sold out lol, i am tempted to try a newer ver 20x2 also
so might order 1 soon .
Marks, I really love this project. Thanks for creating and posting it. Your coding is very efficient. I only wish I was a better code writer. I like this project so much, I've had custom PCB's made (see attached). I'm using the LCD drivers from PH Anderson,
http://www.phanderson.com/lcd106/lcd107.html

They are cheap and easy to use. Your code is working perfectly, however one modification I'd like to make is to use an interrupt for the push button; to have it turn the LCD backlight on or off. Since I'm in the US, I always use Fahrenheit and don't need Celsius functionality.
I've not had good luck with interrupts in the past, and I'm not sure how to toggle the LCD backlight on/off which each press of the button.
the code to turn backlight on is Serout B.4, T19200_16, ("?Bff"). And to turn off would be Serout B.4, T19200_16, ("?B00")

Any coding help you could offer would be greatly appreciated.

Again, thanks for the EXCELLENT project, well-written code, and a fantastic example of a practical Picaxe project.
 

Attachments

marks

Senior Member
Hi aviatorbja,
Wow your circuit board looks good and you move your serial at lightning speed.

I haven't really come up with a final hardware solution waiting to see how the code evolves.
I like to keep things basic to get a feel how responsive it works.
for example the switch has a slight delay we could improve this by uping the speed
or adding a resistor and cap to the switch.
adding temp control is going to take a bit of extra code am looking at a0 and b0 for temperature contolled outputs,and if we dont use them can be timers also
so will have five controllable outputs.
at the moment a portc pin goes low with the weekday.
interfacing ideas solid state relays look good.

sorry I cant bash out the code as quick as hippy or westaus55 it takes me a lot longer!
I did look at that link quite interesting the lcd117 a lot more commands there.! lol
I rewrote the above code for fahrenheit default and switch now turns light on or off
I'll leave it for you to convert.
 

Attachments

  • 13.8 KB Views: 57
Hi aviatorbja,
Wow your circuit board looks good and you move your serial at lightning speed.

I haven't really come up with a final hardware solution waiting to see how the code evolves.
I like to keep things basic to get a feel how responsive it works.
for example the switch has a slight delay we could improve this by uping the speed
or adding a resistor and cap to the switch.
adding temp control is going to take a bit of extra code am looking at a0 and b0 for temperature contolled outputs,and if we dont use them can be timers also
so will have five controllable outputs.
at the moment a portc pin goes low with the weekday.
interfacing ideas solid state relays look good.

sorry I cant bash out the code as quick as hippy or westaus55 it takes me a lot longer!
I did look at that link quite interesting the lcd117 a lot more commands there.! lol
I rewrote the above code for fahrenheit default and switch now turns light on or off
I'll leave it for you to convert.
Thanks for the code re-right marks. Amazing what the 20x2 is capable of. My board works fine except the ds3231 footprint is the wrong size so I had to make some modifications there. That's my fault for not double checking the footprint width. The LCD Driver at 19200 baud works fine with the 20x2.

This is a fun project, thanks again.

-Brian
 

marks

Senior Member
Temperature Controller

Hmm temp control what a real head spinner lol!
amazingly still cycles around quickly so left the speed for now at 16 mhz.
Code:
	'  -- -- -- -- -- -- - - -- -- -- -- -- -- 
	' |  9 . 2 4 . 1 0   A M       2 8 . 1 ' C|

	' |1 0 / 0 6 / 2 0 1 1   F r i d a y      | Picaxe  20x2  ver C.0

	' |A   B   1   2   3   H i     2 9 . 8 ' C|
        '      o  
	' |    n   _           L o     2 2 . 9 ' C| marks
	'  -- -- -- -- -- -- - - -- -- -- -- -- --
have added outputs (A) = a.0 and (B) = b.0 underneath the character will display its status.
(on) = on
( _ ) = off
( ) = nothing has been programmed (starttime 0000 and finishtime 0000)
displays A or B when in Timer mode
Example to program select (AlarmA)
if we want this output on all the time program (starttime 0000 and finishtime 24)
or what time we require it to be on example (starttime 1900 and finishtime 0500)

next temperature mode
if no data is programmed it will just be a timer (starttemp 0000 and finishtemp 0000)
if start and finish data is the same it will have the same result so must be different.
To program select (TempA)
we can select negative or positive then enter the four digits. -0550 to +1250
so lets program our starttemp (+ 0245 'c) ie 24.5 degrees c
and our finishtemp ( + 0271 'c) these are saved to eeprom.
the character (A) or (B) wil be displayed if timer is off ,
if timer mode is on ie between the programmed times
the character will change to a (H)eating ie it knows our start temp is lower
if temps were reversed it would then display a (C)ooling.
Display status underneath the character.
(on) = on triggered at starttemp and on until finishtemp reached
( _ ) = off
( x ) = off between set temperatures and returning to starttemp

The switch now just turns backlight on and off we still hold to go to programming mode.
After thinking about it aviatorbja is probaly wright we dont really need to select between
Fahrenheit and Celsius most users I guess would also cut and paste to there desired requirements lol
notes about 8 lines to change to Fahrenheit just uncomment and comment out Celsius.
havent tested Fahrenheit hopefully aviatorbja will let me know lol.
 

Attachments

Hmm temp control what a real head spinner lol!
amazingly still cycles around quickly so left the speed for now at 16 mhz.
Code:
	'  -- -- -- -- -- -- - - -- -- -- -- -- -- 
	' |  9 . 2 4 . 1 0   A M       2 8 . 1 ' C|

	' |1 0 / 0 6 / 2 0 1 1   F r i d a y      | Picaxe  20x2  ver C.0

	' |A   B   1   2   3   H i     2 9 . 8 ' C|
        '      o  
	' |    n   _           L o     2 2 . 9 ' C| marks
	'  -- -- -- -- -- -- - - -- -- -- -- -- --
have added outputs (A) = a.0 and (B) = b.0 underneath the character will display its status.
(on) = on
( _ ) = off
( ) = nothing has been programmed (starttime 0000 and finishtime 0000)
displays A or B when in Timer mode
Example to program select (AlarmA)
if we want this output on all the time program (starttime 0000 and finishtime 24)
or what time we require it to be on example (starttime 1900 and finishtime 0500)

next temperature mode
if no data is programmed it will just be a timer (starttemp 0000 and finishtemp 0000)
if start and finish data is the same it will have the same result so must be different.
To program select (TempA)
we can select negative or positive then enter the four digits. -0550 to +1250
so lets program our starttemp (+ 0245 'c) ie 24.5 degrees c
and our finishtemp ( + 0271 'c) these are saved to eeprom.
the character (A) or (B) wil be displayed if timer is off ,
if timer mode is on ie between the programmed times
the character will change to a (H)eating ie it knows our start temp is lower
if temps were reversed it would then display a (C)ooling.
Display status underneath the character.
(on) = on triggered at starttemp and on until finishtemp reached
( _ ) = off
( x ) = off between set temperatures and returning to starttemp

The switch now just turns backlight on and off we still hold to go to programming mode.
After thinking about it aviatorbja is probaly wright we dont really need to select between
Fahrenheit and Celsius most users I guess would also cut and paste to there desired requirements lol
notes about 8 lines to change to Fahrenheit just uncomment and comment out Celsius.
havent tested Fahrenheit hopefully aviatorbja will let me know lol.
Wow! That is some IMPRESSIVE coding there marks. I will convert this code for my phanderson LCD driver and see how it works. I don't really need temp control, but I'll figure out something.
 
Some Help needed with SerOut command

Hello, I'm having fun with Mark's program.

perhaps someone knows how to handle this situation:
In marks' code, the command to position the LCD cursor is:
serout b.4,n9600_16,($FE,$45, lineposition,3,"hello")
which would place the cursor at the column stored in the variable lineposition on Row 3

In my code, since I'm using PH Anderson's LCD module, the command would be:
serout b.4,n9600_16,("?xnn?y2","hello"), where nn is the column number 0-19 and the text is placed on the 3rd row (row 0 is the top row).

I'm struggling with how to pass a variable inside the quotes. I can't figure out how to use the lineposition variable.

Meanwhile, I've posted some photos of my board. I haven't yet built the chassis yet. I'm using a battery pack, thus the Vbat readout.
 

Attachments

westaust55

Moderator
You will need to use the BINTOASCII command to obtain the two characters is ASCII format
Say your value is in b5 then
BINTOASCII b5, b6, b7, b8

Then in the SerOut command
"?x",b7,b8,"?y2" etc
 
Last edited:

marks

Senior Member
Hi aviatorbja,
westaust55 always comes through with impressive ideas !
based on similiar idea you could give this a try too.
serout b.4,n9600_16,("?x",lineposition,"?y2","hello")
lineposition = 48 (position 0) (my position 1)
but upto only
lineposition = 57 (position 9)
or you could use a second variable

so for most of my program you could just add 47 to the existing line positon number.
i noticed that i use position 7, 10 and 13 for programming days months years
it could be changed to 4,7,10
so this would become 51,54,57
hope it works !
 

westaust55

Moderator
Adding 48 to a single digit value is the same as binary to ASCII conversion.
BUt if you have a double digit binary/decimal value then you will need to send each decimal digit as a separate ASCII character code. (ie 10 needs to be sent as "1" and "0")

Further to my earlier post, for the line:
BINTOASCII b5, b6, b7, b8​

you can save a byte where the hundreds digit is not used/required by, for example:
BINTOASCII b5, b7, b7, b8​
which saves using the b6 byte variable
 
Got the code working fine thanks to Westaust and Marks.
Fahrenheit works just fine and I've compared to an accurate analogue gauge that I have.
I've not yet set the rig up for alarms or temperature control, but I may look into that. For now, I'm displaying battery pack voltage.

Thanks again Marks for this EXCELLENT project. Quite amazing what this little chip can do!

I've posted the modified code for anyone using the PH Anderson LCD driver module.
 

Attachments

Top