We didn't have any rotary encoders to hand so fudged it with a rotary potentiometer and some push buttons. If we were to make this again, we'd go for a slightly more sophisticated menu system and use a single rotary encoder with button built in. But this will do for now!
Here's the component layout. There are loads of extra connections for power and ground connections. There's nothing worse than soldering up a board and having to tack two or more wires together because there's nowhere on the board to add on another ground wire or power cable. This time, we made sure there are plenty!
Define CONF_WORD = 0x3f71
Define CLOCK_FREQUENCY = 4
AllDigital
Config PORTA = Input
Config PORTB = Output
Config PORTC = Output
Config PORTD = Output
Config PORTE = Output
Symbol white_led_pin = PORTD.1
Symbol uv_led_pin1 = PORTD.2
Symbol uv_led_pin2 = PORTD.3
Symbol uv_led_pin3 = PORTC.4
Symbol uv_led_pin4 = PORTC.5
Symbol uv_led_pin5 = PORTD.4
Symbol uv_led_pin6 = PORTD.5
Symbol uv_led_pin7 = PORTD.6
Symbol uv_led_pin8 = PORTB.4
Symbol speaker = PORTE.2
PORTB = 0x00
PORTD = 0x00
ADCON1 = 00001110b 'AN0 is analogue, all others digital
Define ADC_CLOCK = 3
Define ADC_SAMPLEUS = 50
Dim state As Byte
Dim lastmenu As Word
Dim menu As Word
Dim tmpw As Word
Dim tmp As Byte
Dim setting As Byte
Dim lastsetting As Byte
Dim uvled As Byte
Dim brightwhite As Byte
Dim brightuv As Byte
Dim buttonpressed As Byte
Dim timermins As Byte
Dim timersecs As Byte
Dim intrcnt As Byte
Dim seccount As Word
Dim redrawtimer As Byte
Dim led_counter As Byte
Define LCD_BITS = 4
Define LCD_DREG = PORTB
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 5
Define LCD_RWREG = PORTB
Define LCD_RWBIT = 6
Define LCD_EREG = PORTB
Define LCD_EBIT = 7
Define LCD_READ_BUSY_FLAG = 0
Define LCD_DATAUS = 200
Define LCD_INITMS = 200
init:
'allow everything to settle
WaitMs 500
Lcdinit 0 '0=no cursor
Lcdcmdout LcdClear
state = 0
menu = 0
lastmenu = 0
setting = 0
lastsetting = 0
uvled = 0
buttonpressed = 0
intrcnt = 0
redrawtimer = 0
led_counter = 0
Read 2, brightwhite
Read 3, brightuv
If brightwhite > 10 Then brightwhite = 10
If brightuv > 10 Then brightuv = 10
timermins = 1
timersecs = 28
Gosub resettimer
'create a timer to fire every 1m/s
'(we use this for the countdown AND to control the LEDs)
T1CON = 0x00
T1CON.T1OSCEN = 1
T1CON.TMR1CS = 0
T1CON.TMR1ON = 0
Gosub preload_timer
'enable global and peripheral interrupts
INTCON.GIE = 1
INTCON.PEIE = 1
PIE1.TMR1IE = 1
PIR1.TMR1IF = 0
state = 0
loop:
'-----------------------------------------------------------------------
'read the value from RA0 to see if the user has changed the menu setting
'-----------------------------------------------------------------------
Adcin 0, menu
If menu > lastmenu Then
tmpw = menu - lastmenu
Else
tmpw = lastmenu - menu
Endif
If tmpw > 3 Then
'dial has been moved more than the error in reading the A/C
'so convert this to a setting value
If menu >= 0 And menu < 340 Then
'setting one:
setting = 1
Else
If menu >= 340 And menu < 680 Then
'centre position: off
setting = 0
Else
If menu >= 680 And menu <= 1024 Then
'setting two
setting = 2
Endif
Endif
Endif
Endif
'----------------------------------------------------
'if the setting has changed, update the state machine
'----------------------------------------------------
If setting <> lastsetting Then
'stop the timer
T1CON.TMR1ON = 0
'turn off any leds (they'll come back on again in a minute)
Low white_led_pin 'turn off the white LED(s)
Gosub turn_uv_off
'something has changed: update the state as necessary
Select Case setting
Case 1 'start the uv leds again
state = 1
uvled = 1
Case 0
state = 0
uvled = 0 'turn off the UV LEDs
Case 2
state = 2
uvled = 0 'make sure uv LEDs are off
EndSelect
Endif
lastsetting = setting
lastmenu = menu
'---------------------
'decide what to do now
'---------------------
Select Case state
Case 0
'redraw the opening menu
Gosub drawmenu1a
state = 3 'wait for user to select a menu option
Case 1
'start flashing the UV LEDs, one row at a time
Gosub resettimer
Lcdcmdout LcdClear
Lcdout "Time remaining:"
Gosub drawtimer
state = 5
redrawtimer = 0
'start timer1 interrupt
Gosub preload_timer
T1CON.TMR1ON = 1
Case 2
'show the white LEDs only
Read 2, brightwhite
If brightwhite > 10 Then brightwhite = 10
Gosub drawmenu2
Gosub turn_uv_off
'start timer1 interrupt
Gosub preload_timer
T1CON.TMR1ON = 1
state = 4 'wait for the user to select up/down
Case 3
'user can select between brightness and timer or hit select
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub drawmenu1b
state = 7
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
state = 8
Gosub drawmenu4
Endif
Case 4
'White LED is running
'user can press up/down to select the white light brightness
Gosub is_button_one_pressed
If buttonpressed = 1 Then
If brightwhite < 10 Then
brightwhite = brightwhite + 1
Gosub drawmenu2
Endif
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Low white_led_pin
Write 2, brightwhite
Gosub drawsaved
For tmp = 1 To 10
WaitMs 200
Next tmp
Gosub drawmenu2
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
If brightwhite > 0 Then
brightwhite = brightwhite - 1
Gosub drawmenu2
Endif
Endif
Case 5
'UV lights are running
'user can press up/down to increase/decrease the CURRENT time by one sec
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub increase_time_one_sec
redrawtimer = 1
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub decrease_time_one_sec
redrawtimer = 1
Endif
If redrawtimer = 1 Then
redrawtimer = 0
Gosub drawtimer
Endif
'check the timer hasn't hit zero
If timermins = 0 And timersecs = 0 Then
'stop the timer
T1CON.TMR1ON = 0
'draw zero zero
Gosub drawtimer
'time out, do nothing until menu selector moved
Low white_led_pin
Gosub turn_uv_off
state = 6
Endif
Case 6
'play a tune
FreqOut speaker, 440, 200
FreqOut speaker, 392, 200
FreqOut speaker, 440, 200
FreqOut speaker, 392, 200
state = 13
Case 7
'user can select between brightness and timer or hit select
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub drawmenu1a
state = 3
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Read 3, brightuv
If brightuv > 10 Then brightuv = 10
Gosub drawmenu3
state = 9
Endif
Case 8
'set the timer minutes
Gosub is_button_three_pressed
If buttonpressed = 1 Then
state = 10
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
state = 11
Gosub drawmenu4
Endif
Case 9
'set the UV brightness
'user can press up/down to select the UV light brightness
Gosub is_button_one_pressed
If buttonpressed = 1 Then
If brightuv < 10 Then
brightuv = brightuv + 1
Gosub drawmenu3
Endif
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Gosub turn_uv_off
Write 3, brightuv
Gosub drawsaved
For tmp = 1 To 10
WaitMs 200
Next tmp
Gosub drawmenu1a
state = 3
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
If brightuv > 0 Then
brightuv = brightuv - 1
Gosub drawmenu3
Endif
Endif
Case 10
'set the UV timer seconds
Gosub is_button_one_pressed
If buttonpressed = 1 Then
state = 8
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
state = 12
Gosub drawmenu4
Endif
Case 11
'use up/down to change the timer minutes
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub increase_time_one_min
Gosub drawmenu4
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub decrease_time_one_min
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Write 10, timermins
Write 11, timersecs
state = 8
Gosub drawmenu4
Endif
Case 12
'use up/down to change the timer seconds
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub increase_time_one_sec
Gosub drawmenu4
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub decrease_time_one_sec
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Write 10, timermins
Write 11, timersecs
state = 10
Gosub drawmenu4
Endif
Case 13
'do nothing: wait for the user to move the menu selector to something else
EndSelect
Goto loop
End
drawmenu1a:
Lcdcmdout LcdClear
Lcdout " UV brightness "
Lcdcmdout LcdLine2Home
Lcdout " UV timer <"
Return
drawmenu1b:
Lcdcmdout LcdClear
Lcdout " UV brightness <"
Lcdcmdout LcdLine2Home
Lcdout " UV timer "
Return
drawmenu2:
Lcdcmdout LcdClear
Lcdout "Brightness: "
If brightwhite < 100 Then Lcdout " "
If brightwhite < 10 Then Lcdout " "
Lcdout #brightwhite
Return
drawmenu3:
Lcdcmdout LcdClear
Lcdout "Brightness: "
If brightuv < 100 Then Lcdout " "
If brightuv < 10 Then Lcdout " "
Lcdout #brightuv
Return
drawmenu4:
Lcdcmdout LcdClear
Lcdout " Minutes: "
If timermins < 10 Then Lcdout " "
Lcdout #timermins
If state = 8 Then Lcdout " <"
Lcdcmdout LcdLine2Home
Lcdout " Seconds: "
If timersecs < 10 Then Lcdout " "
Lcdout #timersecs
If state = 10 Then Lcdout " <"
Return
drawsaved:
Lcdcmdout LcdClear
Lcdout " Settings saved"
Return
resettimer:
Read 10, timermins
Read 11, timersecs
If timermins = 255 Then timermins = 1
If timersecs = 255 Then timersecs = 30
If timermins = 0 And timersecs = 0 Then
timermins = 1
timersecs = 30
Endif
Return
increase_time_one_sec:
timersecs = timersecs + 1
If timersecs > 59 Then
timersecs = 0
timermins = timermins + 1
Endif
Return
decrease_time_one_sec:
If timersecs > 0 Then
timersecs = timersecs - 1
Else
If timermins > 0 Then
timersecs = 59
timermins = timermins - 1
Else
'timer is already at zero
timersecs = 0
timermins = 0
Endif
Endif
Return
increase_time_one_min:
If timermins < 99 Then
timermins = timermins + 1
Endif
Return
decrease_time_one_min:
If timermins > 0 Then
timermins = timermins - 1
Endif
Return
drawtimer:
Lcdcmdout LcdLine2Home
Lcdout " "
If timermins < 10 Then Lcdout " "
Lcdout #timermins
Lcdout "m "
If timersecs < 10 Then Lcdout " "
Lcdout #timersecs
Lcdout "sec"
Return
is_button_one_pressed:
buttonpressed = 0
If PORTA.1 = 1 Then
'debounce the button press
WaitMs 1
If PORTA.1 = 1 Then
While PORTA.1 = 1
'do nothing
Wend
buttonpressed = 1
Endif
Endif
Return
is_button_two_pressed:
buttonpressed = 0
If PORTA.2 = 1 Then
'debounce the button press
WaitMs 1
If PORTA.2 = 1 Then
While PORTA.2 = 1
'do nothing
Wend
buttonpressed = 1
Endif
Endif
Return
is_button_three_pressed:
buttonpressed = 0
If PORTA.3 = 1 Then
'debounce the button press
WaitMs 1
If PORTA.3 = 1 Then
While PORTA.3 = 1
'do nothing
Wend
buttonpressed = 1
Endif
Endif
Return
preload_timer:
'at 4mhz (crystal) we have 1m clock cycles per second
'if we count up to 1,000 that's 1 millisecond
'so let's preload timer1 with 65,535 - 1,000 = 64,535
'(which in hex is 0xFC17)
TMR1H = 0xfc
TMR1L = 0x17
Return
turn_uv_off:
Low uv_led_pin1
Low uv_led_pin2
Low uv_led_pin3
Low uv_led_pin4
Low uv_led_pin5
Low uv_led_pin6
Low uv_led_pin7
Low uv_led_pin8
Return
turn_uv_on:
High uv_led_pin1
High uv_led_pin2
High uv_led_pin3
High uv_led_pin4
High uv_led_pin5
High uv_led_pin6
High uv_led_pin7
High uv_led_pin8
Return
On Interrupt
Save System
If PIR1.TMR1IF = 1 Then
PIR1.TMR1IF = 0
Gosub preload_timer
seccount = seccount + 1
If seccount >= 1000 Then
seccount = 0
Gosub decrease_time_one_sec
redrawtimer = 1
Endif
led_counter = led_counter + 1
If led_counter > 10 Then led_counter = 0
Select Case state
Case 4
If led_counter >= brightwhite And brightwhite < 10 Then
Low white_led_pin
Else
High white_led_pin
Endif
Case 5
If led_counter >= brightuv And brightuv < 10 Then
Gosub turn_uv_off
Else
Gosub turn_uv_on
Endif
EndSelect
Endif
Resume
Define CLOCK_FREQUENCY = 4
AllDigital
Config PORTA = Input
Config PORTB = Output
Config PORTC = Output
Config PORTD = Output
Config PORTE = Output
Symbol white_led_pin = PORTD.1
Symbol uv_led_pin1 = PORTD.2
Symbol uv_led_pin2 = PORTD.3
Symbol uv_led_pin3 = PORTC.4
Symbol uv_led_pin4 = PORTC.5
Symbol uv_led_pin5 = PORTD.4
Symbol uv_led_pin6 = PORTD.5
Symbol uv_led_pin7 = PORTD.6
Symbol uv_led_pin8 = PORTB.4
Symbol speaker = PORTE.2
PORTB = 0x00
PORTD = 0x00
ADCON1 = 00001110b 'AN0 is analogue, all others digital
Define ADC_CLOCK = 3
Define ADC_SAMPLEUS = 50
Dim state As Byte
Dim lastmenu As Word
Dim menu As Word
Dim tmpw As Word
Dim tmp As Byte
Dim setting As Byte
Dim lastsetting As Byte
Dim uvled As Byte
Dim brightwhite As Byte
Dim brightuv As Byte
Dim buttonpressed As Byte
Dim timermins As Byte
Dim timersecs As Byte
Dim intrcnt As Byte
Dim seccount As Word
Dim redrawtimer As Byte
Dim led_counter As Byte
Define LCD_BITS = 4
Define LCD_DREG = PORTB
Define LCD_DBIT = 0
Define LCD_RSREG = PORTB
Define LCD_RSBIT = 5
Define LCD_RWREG = PORTB
Define LCD_RWBIT = 6
Define LCD_EREG = PORTB
Define LCD_EBIT = 7
Define LCD_READ_BUSY_FLAG = 0
Define LCD_DATAUS = 200
Define LCD_INITMS = 200
init:
'allow everything to settle
WaitMs 500
Lcdinit 0 '0=no cursor
Lcdcmdout LcdClear
state = 0
menu = 0
lastmenu = 0
setting = 0
lastsetting = 0
uvled = 0
buttonpressed = 0
intrcnt = 0
redrawtimer = 0
led_counter = 0
Read 2, brightwhite
Read 3, brightuv
If brightwhite > 10 Then brightwhite = 10
If brightuv > 10 Then brightuv = 10
timermins = 1
timersecs = 28
Gosub resettimer
'create a timer to fire every 1m/s
'(we use this for the countdown AND to control the LEDs)
T1CON = 0x00
T1CON.T1OSCEN = 1
T1CON.TMR1CS = 0
T1CON.TMR1ON = 0
Gosub preload_timer
'enable global and peripheral interrupts
INTCON.GIE = 1
INTCON.PEIE = 1
PIE1.TMR1IE = 1
PIR1.TMR1IF = 0
state = 0
loop:
'-----------------------------------------------------------------------
'read the value from RA0 to see if the user has changed the menu setting
'-----------------------------------------------------------------------
Adcin 0, menu
If menu > lastmenu Then
tmpw = menu - lastmenu
Else
tmpw = lastmenu - menu
Endif
If tmpw > 3 Then
'dial has been moved more than the error in reading the A/C
'so convert this to a setting value
If menu >= 0 And menu < 340 Then
'setting one:
setting = 1
Else
If menu >= 340 And menu < 680 Then
'centre position: off
setting = 0
Else
If menu >= 680 And menu <= 1024 Then
'setting two
setting = 2
Endif
Endif
Endif
Endif
'----------------------------------------------------
'if the setting has changed, update the state machine
'----------------------------------------------------
If setting <> lastsetting Then
'stop the timer
T1CON.TMR1ON = 0
'turn off any leds (they'll come back on again in a minute)
Low white_led_pin 'turn off the white LED(s)
Gosub turn_uv_off
'something has changed: update the state as necessary
Select Case setting
Case 1 'start the uv leds again
state = 1
uvled = 1
Case 0
state = 0
uvled = 0 'turn off the UV LEDs
Case 2
state = 2
uvled = 0 'make sure uv LEDs are off
EndSelect
Endif
lastsetting = setting
lastmenu = menu
'---------------------
'decide what to do now
'---------------------
Select Case state
Case 0
'redraw the opening menu
Gosub drawmenu1a
state = 3 'wait for user to select a menu option
Case 1
'start flashing the UV LEDs, one row at a time
Gosub resettimer
Lcdcmdout LcdClear
Lcdout "Time remaining:"
Gosub drawtimer
state = 5
redrawtimer = 0
'start timer1 interrupt
Gosub preload_timer
T1CON.TMR1ON = 1
Case 2
'show the white LEDs only
Read 2, brightwhite
If brightwhite > 10 Then brightwhite = 10
Gosub drawmenu2
Gosub turn_uv_off
'start timer1 interrupt
Gosub preload_timer
T1CON.TMR1ON = 1
state = 4 'wait for the user to select up/down
Case 3
'user can select between brightness and timer or hit select
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub drawmenu1b
state = 7
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
state = 8
Gosub drawmenu4
Endif
Case 4
'White LED is running
'user can press up/down to select the white light brightness
Gosub is_button_one_pressed
If buttonpressed = 1 Then
If brightwhite < 10 Then
brightwhite = brightwhite + 1
Gosub drawmenu2
Endif
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Low white_led_pin
Write 2, brightwhite
Gosub drawsaved
For tmp = 1 To 10
WaitMs 200
Next tmp
Gosub drawmenu2
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
If brightwhite > 0 Then
brightwhite = brightwhite - 1
Gosub drawmenu2
Endif
Endif
Case 5
'UV lights are running
'user can press up/down to increase/decrease the CURRENT time by one sec
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub increase_time_one_sec
redrawtimer = 1
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub decrease_time_one_sec
redrawtimer = 1
Endif
If redrawtimer = 1 Then
redrawtimer = 0
Gosub drawtimer
Endif
'check the timer hasn't hit zero
If timermins = 0 And timersecs = 0 Then
'stop the timer
T1CON.TMR1ON = 0
'draw zero zero
Gosub drawtimer
'time out, do nothing until menu selector moved
Low white_led_pin
Gosub turn_uv_off
state = 6
Endif
Case 6
'play a tune
FreqOut speaker, 440, 200
FreqOut speaker, 392, 200
FreqOut speaker, 440, 200
FreqOut speaker, 392, 200
state = 13
Case 7
'user can select between brightness and timer or hit select
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub drawmenu1a
state = 3
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Read 3, brightuv
If brightuv > 10 Then brightuv = 10
Gosub drawmenu3
state = 9
Endif
Case 8
'set the timer minutes
Gosub is_button_three_pressed
If buttonpressed = 1 Then
state = 10
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
state = 11
Gosub drawmenu4
Endif
Case 9
'set the UV brightness
'user can press up/down to select the UV light brightness
Gosub is_button_one_pressed
If buttonpressed = 1 Then
If brightuv < 10 Then
brightuv = brightuv + 1
Gosub drawmenu3
Endif
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Gosub turn_uv_off
Write 3, brightuv
Gosub drawsaved
For tmp = 1 To 10
WaitMs 200
Next tmp
Gosub drawmenu1a
state = 3
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
If brightuv > 0 Then
brightuv = brightuv - 1
Gosub drawmenu3
Endif
Endif
Case 10
'set the UV timer seconds
Gosub is_button_one_pressed
If buttonpressed = 1 Then
state = 8
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
state = 12
Gosub drawmenu4
Endif
Case 11
'use up/down to change the timer minutes
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub increase_time_one_min
Gosub drawmenu4
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub decrease_time_one_min
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Write 10, timermins
Write 11, timersecs
state = 8
Gosub drawmenu4
Endif
Case 12
'use up/down to change the timer seconds
Gosub is_button_one_pressed
If buttonpressed = 1 Then
Gosub increase_time_one_sec
Gosub drawmenu4
Endif
Gosub is_button_three_pressed
If buttonpressed = 1 Then
Gosub decrease_time_one_sec
Gosub drawmenu4
Endif
Gosub is_button_two_pressed
If buttonpressed = 1 Then
Write 10, timermins
Write 11, timersecs
state = 10
Gosub drawmenu4
Endif
Case 13
'do nothing: wait for the user to move the menu selector to something else
EndSelect
Goto loop
End
drawmenu1a:
Lcdcmdout LcdClear
Lcdout " UV brightness "
Lcdcmdout LcdLine2Home
Lcdout " UV timer <"
Return
drawmenu1b:
Lcdcmdout LcdClear
Lcdout " UV brightness <"
Lcdcmdout LcdLine2Home
Lcdout " UV timer "
Return
drawmenu2:
Lcdcmdout LcdClear
Lcdout "Brightness: "
If brightwhite < 100 Then Lcdout " "
If brightwhite < 10 Then Lcdout " "
Lcdout #brightwhite
Return
drawmenu3:
Lcdcmdout LcdClear
Lcdout "Brightness: "
If brightuv < 100 Then Lcdout " "
If brightuv < 10 Then Lcdout " "
Lcdout #brightuv
Return
drawmenu4:
Lcdcmdout LcdClear
Lcdout " Minutes: "
If timermins < 10 Then Lcdout " "
Lcdout #timermins
If state = 8 Then Lcdout " <"
Lcdcmdout LcdLine2Home
Lcdout " Seconds: "
If timersecs < 10 Then Lcdout " "
Lcdout #timersecs
If state = 10 Then Lcdout " <"
Return
drawsaved:
Lcdcmdout LcdClear
Lcdout " Settings saved"
Return
resettimer:
Read 10, timermins
Read 11, timersecs
If timermins = 255 Then timermins = 1
If timersecs = 255 Then timersecs = 30
If timermins = 0 And timersecs = 0 Then
timermins = 1
timersecs = 30
Endif
Return
increase_time_one_sec:
timersecs = timersecs + 1
If timersecs > 59 Then
timersecs = 0
timermins = timermins + 1
Endif
Return
decrease_time_one_sec:
If timersecs > 0 Then
timersecs = timersecs - 1
Else
If timermins > 0 Then
timersecs = 59
timermins = timermins - 1
Else
'timer is already at zero
timersecs = 0
timermins = 0
Endif
Endif
Return
increase_time_one_min:
If timermins < 99 Then
timermins = timermins + 1
Endif
Return
decrease_time_one_min:
If timermins > 0 Then
timermins = timermins - 1
Endif
Return
drawtimer:
Lcdcmdout LcdLine2Home
Lcdout " "
If timermins < 10 Then Lcdout " "
Lcdout #timermins
Lcdout "m "
If timersecs < 10 Then Lcdout " "
Lcdout #timersecs
Lcdout "sec"
Return
is_button_one_pressed:
buttonpressed = 0
If PORTA.1 = 1 Then
'debounce the button press
WaitMs 1
If PORTA.1 = 1 Then
While PORTA.1 = 1
'do nothing
Wend
buttonpressed = 1
Endif
Endif
Return
is_button_two_pressed:
buttonpressed = 0
If PORTA.2 = 1 Then
'debounce the button press
WaitMs 1
If PORTA.2 = 1 Then
While PORTA.2 = 1
'do nothing
Wend
buttonpressed = 1
Endif
Endif
Return
is_button_three_pressed:
buttonpressed = 0
If PORTA.3 = 1 Then
'debounce the button press
WaitMs 1
If PORTA.3 = 1 Then
While PORTA.3 = 1
'do nothing
Wend
buttonpressed = 1
Endif
Endif
Return
preload_timer:
'at 4mhz (crystal) we have 1m clock cycles per second
'if we count up to 1,000 that's 1 millisecond
'so let's preload timer1 with 65,535 - 1,000 = 64,535
'(which in hex is 0xFC17)
TMR1H = 0xfc
TMR1L = 0x17
Return
turn_uv_off:
Low uv_led_pin1
Low uv_led_pin2
Low uv_led_pin3
Low uv_led_pin4
Low uv_led_pin5
Low uv_led_pin6
Low uv_led_pin7
Low uv_led_pin8
Return
turn_uv_on:
High uv_led_pin1
High uv_led_pin2
High uv_led_pin3
High uv_led_pin4
High uv_led_pin5
High uv_led_pin6
High uv_led_pin7
High uv_led_pin8
Return
On Interrupt
Save System
If PIR1.TMR1IF = 1 Then
PIR1.TMR1IF = 0
Gosub preload_timer
seccount = seccount + 1
If seccount >= 1000 Then
seccount = 0
Gosub decrease_time_one_sec
redrawtimer = 1
Endif
led_counter = led_counter + 1
If led_counter > 10 Then led_counter = 0
Select Case state
Case 4
If led_counter >= brightwhite And brightwhite < 10 Then
Low white_led_pin
Else
High white_led_pin
Endif
Case 5
If led_counter >= brightuv And brightuv < 10 Then
Gosub turn_uv_off
Else
Gosub turn_uv_on
Endif
EndSelect
Endif
Resume
Here's a video showing the final UV controller:
In the end we went for a 10ms PWM on the LEDs. Originally we thought 30 would be fine, but it introduced noticeable flicker on the LEDs when running normally. Although the camera shows flicker on the white LEDs, in reality they appear as uniformly lit.
The video demonstrates:
- variable UV brightness
- changing the countdown time-out value
- an amazingly melodic tune when the countdown has elapsed
- using variable brightness white LEDs for aligning silkscreen masks before exposure
That's all the electronics done - now we need to find a suitable box to enclose it all in and actually start making some silkscreens!