PDA

View Full Version : LCD Countdown Timer, hd44780



k_man
18-01-2006, 01:45
I think I got all the keywords in there :)
Not quite a hd44780
MSC-C162DYRN-2N
http://surplustronics.co.nz/shop/product-LA0300.html

My most satisifying project with a picaxe yet.

Unfortunatly a small bug which I can see no way around.
Due to the fact the minutes is written to the lcd before the seconds

So the screen looks something like this

5:00
4:00
4:59
...
3:00
3:59

Could probably do it with more program space but it's pretty tightly packed as is.
The forums have been a great help :-)

What does it do?
It a prop bomb for airsoft.
On power up it starts counting down from set time.
There are two buttons to disarm the unit.
pushing both at once will have the disarm time.
If you let go you the disarm timer is reset.


help appreciated. (somewhat messy/borrowed code)

SYMBOL RS = 2 ; 0 = Command 1 = Data
SYMBOL E = 3 ; 0 = Idle 1 = Active
SYMBOL DB4 = 4 ; LCD Data Line 4
SYMBOL DB5 = 5 ; LCD Data Line 5
SYMBOL DB6 = 6 ; LCD Data Line 6
SYMBOL DB7 = 7 ; LCD Data Line 7

SYMBOL RSCMDmask = %00000000 ; Select Command register
SYMBOL RSDATmask = %00000100 ; Select Data register

SYMBOL tmin =b0
SYMBOL tsec =b1
SYMBOL dtsec =b2
;b3 also used in display shuffle
SYMBOL counter1=b3


SYMBOL get = b11
SYMBOL byte = b12
SYMBOL rsbit = b13

SYMBOL Beeper = 1
SYMBOL Detinator = 0
SYMBOL Button1 =pin0 ;pin for inputs, number for outputs
SYMBOL Button2 =pin1
SYMBOL Button3 =pin2

let tmin=5 ;start time
;save program line let tsec=1 ;sec +1 to show desired start time
;Disarm timer at start of code


PowerOnReset:

GOSUB InitialiseLcd

;****
EEPROM 10,(">>ARMED<< >>DIFFUSING  :-D DISARMED =-_ ")
; 01234567890123456789012345678901234567890123456789 01234567890
; 1 2 3 4 5 6 7
;LCD Pos $80 - $8F - 0123456789abcdef
; $C0 - $CF
; 1 - 16
; reset diffuse timer
let dtsec=101 ;disarm time, sec x5, +1, 101 = 20 sec

DisplayTopLine:

byte = $80 ;Clear screen
GOSUB SendCmdByte

FOR get = 10 TO 20 ;print armed
READ get,byte
GOSUB SendDataByte
NEXT



;**

DecTime:

b3=tmin
GOSUB wrnum

byte=$3a ; print :
GOSUB SendDataByte

GOSUB WaitSec

b3=tsec
GOSUB wrnum

if tsec=0 then DecMin
tsec =tsec-1

goto DisplayTopLine ;back to begining of count down loop

;**



Diffusing:

byte = $80 ;MoveCursorToStartOf First Line
GOSUB SendCmdByte


FOR get = 24 TO 34 ;print diff
READ get,byte
GOSUB SendDataByte

NEXT

High Beeper
pause 40
low beeper

if dtsec <= 1 then EndDif ;must be <= other -1 won't diffuse
if button1=1 and button2=1 then DecDT3
if button1=1 or button2=1 then DecDT1

goto PowerOnReset



;* Endings

EndBoom:
High Beeper
High Detinator
wait 15
low Beeper
; low Detinator
goto EndEnd



EndDif:

; byte = $01 ;Clear screen
; GOSUB SendCmdByte
; byte = $80 ;pos cursor for time
; GOSUB SendCmdByte


; pause 200


FOR get = 19 TO 64 ;print disar
READ get,byte
GOSUB SendDataByte
NEXT



EndEnd:

END


;****

InitialiseLcd:

FOR get = 0 TO 5
READ get,byte
GOSUB SendInitCmdByte
NEXT

' Nibble commands - To initialise 4-bit mode

EEPROM 0,( $33 ) ; %0011---- %0011---- 8-bit / 8-bit
EEPROM 1,( $32 ) ; %0011---- %0010---- 8-bit / 4-bit

' Byte commands - To configure the LCD

EEPROM 2,( $28 ) ; %00101000 %001LNF00 Display Format
EEPROM 3,( $0C ) ; %00001100 %00001DCB Display On
EEPROM 4,( $06 ) ; %00000110 %000001IS Cursor Move

; L : 0 = 4-bit Mode 1 = 8-bit Mode
; N : 0 = 1 Line 1 = 2 Lines
; F : 0 = 5x7 Pixels 1 = N/A
; D : 0 = Display Off 1 = Display On
; C : 0 = Cursor Off 1 = Cursor On
; B : 0 = Cursor Steady 1 = Cursor Flash
; I : 0 = Dec Cursor 1 = Inc Cursor
; S : 0 = Cursor Move 1 = Display Shift

EEPROM 5,( $01 ) ; Clear Screen

RETURN

SendInitCmdByte:

PAUSE 15 ; Delay 15mS

SendCmdByte:

rsbit = RSCMDmask ; Send to Command register




SendDataByte:

pins = byte & %11110000 | rsbit ; Put MSB out first
PULSOUT E,1 ; Give a 10uS pulse on E
pins = byte * %00010000 | rsbit ; Put LSB out second
PULSOUT E,1 ; Give a 10uS pulse on E

rsbit = RSDATmask ; Send to Data register next

RETURN

;****

WaitSec:
;Check for buttons etc
for counter1=1 to 244
if button1=1 or button2=1 then Diffusing

next counter1
;for some reason it didn't like the counter over 254

for counter1=1 to 254
if button1=1 or button2=1 then Diffusing

next counter1

return



DecMin:

if tmin=0 then EndBoom

High Beeper
pause 100
low beeper

tmin =tmin-1
tsec =59

goto DisplayTopLine



wrnum:
byte = b3 / 10

GOSUB wrdigit
byte = b3 // 10



wrdigit:
byte = byte +"0"
GOSUB SendDataByte

return

;*


DecDT1:

dtsec =dtsec -1
pause 80

goto DisplayTopLine


; DecDT2:
; dtsec =dtsec-1
; pause 50
; goto Diffusing1


DecDT3:

dtsec = dtsec - 2
pause 80

goto DisplayTopLine

hippy
18-01-2006, 02:20
Try changing ...

GOSUB WaitSec
b3=tsec
GOSUB wrnum

to ...

b3=tsec
GOSUB wrnum
GOSUB WaitSec

k_man
18-01-2006, 05:06
It didn't like that.
5:I5
4:I5
Locks up

hippy
18-01-2006, 11:25
I hadn't studied your code, and it does look like there are 'side effects' with GOTO's out of GOSUB's which consequently never return. That 'GOSUB abuse' probably explains the lock-up.

Although I appreciate all the effort which has gone into to crafting the program, it's obviously hit a point where what it does isn't quite right and that needs fixing. It's probably a good idea to take what you have, call it a prototpe, and rewrite the code from scratch using what you now know. It will probably take a lot less than you imagine. That's not criticism of what you've done, and it's no more than what happens in most projects.

The problem you have is that there is the delay between updating the seconds and the minutes and that's related to the design. It's probably possible to hack it to work but that may take longer to do than rewrite ...

<code><pre><font size=2>
tmins = 5
tsecs = 0
MinsLoop:
GOSUB DisplayMins
SecsLoop:
GOSUB DisplaySecs
MainProgram
IF tmins = 0 AND tsecs = 0 THEN Explode
GOSUB WaitOneSecondAndHandleDefusing
IF tsecs = 0 THEN UpdateMins
UpdateSecs:
tsecs = tsecs-1
GOTO SecsLoop
UpdateMins:
tmins = tmins-1
tsecs = 59
GOTO MinsLoop
Explode:
::
END
WaitOneSecondAndHandleDefusing:
::
RETURN </font></pre></code>