Stairs Light Timer
A general-purpose 5s to 21m timer programmable
with a single button
by Stefano Purchiaroni
This timer uses a PIC12F683 microcontroller to handle
the timing, as well the setting operations. The user can adjust the time using
a single button, adding steps of 5 seconds (short click), or resetting the time to 5 seconds (long click).
Two Led show the timer state and feedback the user about setting being applied
through the button.
The circuit is designed to lay into a small plastic box. Due to the Relays size, it shall be disposed horizontally, connecting its
terminals to the board using wires. A hole on the button side, as another large
one for the external connections shall be realised. A wall adapter shall supply 12 volts power to the circuit.
The schematic is simple: the microcontroller
drives the relays and a state signalling Led through a transistor, and uses
another Led to gives feedbacks in front of the button actions.
As all the functions are managed with a single
button, both short and long pressions are handled:
Action on the button (P1)
|
Operation
|
Led (D1)
|
Short
|
Increase
time of 5s
|
One
blink
|
Long
|
Reset
time to 5s
|
Three
blinks
|
The timer can be programmed in the 5s – 21m
range, since the variable where the number of 5 seconds units is stored is an
unsigned short (8 bit). Its contents is stored in EEPROM to remember its value
also when the circuit is not powered.
The circuit may be implemented on any
proto-board. For a cleaner realisation, a Pcb layout is supplied.
Click to have a
fullres mirrored image for Pcb realisation, using your preferred method.
The microcontroller must be programmed using
the Hex file available clicking here.
Hereafter a 3D view of the mounted timer:
In addition, here the prototype. Notice the
horizontal position of the Relay, to fit it in the box:
The source code is supplied in the next pages.
/***********************************************************************************
General
purpose timer
It needs:
- One
button to program the delay
- One
regulator to feed the PIC (78L05)
- One led
grounded via a 180 ohm resistor
- One npn
transistor with base seried to 2K7 resistor, to activate a rel่
- One 100nF
ceramic capacitor on Vdd as noise protection
Abstract:
- When the
input contact is grounded, the time count begins and the output is set
- At time
expiration, the output is unset and the count stops
- If the
input is stroked during count, the count restarts adding extra time
- Each
short pression on program button increases delay of +5 seconds (led: 1 blink)
- A long
pression on program button reset delay time to 5 seconds (led: 3 blinks)
- The time
delay is stored in flash
MCU: PIC12F683
Oscillator: Internal, 4.000
MHz
Compilator: mikroC v8.2.0.0
Author:
stefano.purchiaroni@email.it
www.purchiaroni.com
Changes log:
-
26.02.2016 : Creation of the program
***********************************************************************************/
// Pin usage
#define PrgPin
F1 // Input from the
programming button
#define OnPin
F2 // Input from the
external "ON" button
#define OutPin F5 // Output to the transistor
base, to drive a rel่
#define LedPin
F4 // Output to a
led
// Constants
#define CycDly
10 // Milliseconds
between cycles
#define LongButton 200 // Number of cycle to consider a
long pression
// On buttons level when pressed
#define ButOn
0
// Initial EEPROM address to add to byte offset for
store/retrieve operations
#define EEPROM_OFFSET 10
// Variables
unsigned short tic = 5; // [ Volatile ] Time increment
(seconds)
unsigned short tim; // [ Flash ] Programmed number of tic
unsigned short curprg; // [ Volatile ] Current Prog Button
state
unsigned short curon; // [ Volatile ] Current On Button
state
unsigned short prvprg = 0; // [ Volatile ] Previous Prog Button
state
unsigned short prvon; // [ Volatile ] Previous On Button
state
int n
= 0; // [ Volatile ] Number of
remaining 10ms cycles with output set
int b
= 0; // [ Volatile ] Duration
(cycles) of pressed state of Prog button
void Blink(int n) {
// Blink the led n times
int i;
for (i=1;i<=n;i++)
{
GPIO.LedPin
= 1;
Delay_ms(150);
GPIO.LedPin
= 0;
Delay_ms(150);
}
}
void StoreByte(unsigned short b, unsigned int offs) {
// Write a byte on EEprom
EEPROM_Write(EEPROM_OFFSET + offs, b);
Delay_ms(25);
}
unsigned short RetrieveByte(unsigned int offs) {
// Read a byte from EEprom
unsigned short b;
b =
EEPROM_Read(EEPROM_OFFSET + offs);
Delay_ms(25);
return b;
}
void main() {
int i;
ANSEL = 0; // Configure AN pins as digital
CMCON0 = 7;
// Turn off the comparators
TRISIO =
0xFF; // Start with all pin as
input
// Set the
output pins direction
TRISIO.OutPin
= 0; // To transistor driving rel่
TRISIO.LedPin
= 0; // Led
// Set
internal pull-up resistors on the input pin
OPTION_REG.F7
= 0; // Enable pull-up
WPU.OnPin = 1;
WPU.PrgPin =
1;
// Init the
output pins value
GPIO.OutPin =
0;
GPIO.LedPin =
0;
// Bonjour
Blink(3);
// Retrieve
tim value from flash
tim =
RetrieveByte(0);
if (tim ==
0xFF) tim = 1; // First reading
// Main loop
do {
// Manage
"ON" external button event, starting the countdown
if
(Button(&GPIO, 2, 1, ButOn)) { // "ON" button pressed
n = tim * tic
* 100; // (Re)initialize the
number of 10 ms cycles to wait
}
if (n == 0)
{ // We are out of
countdown
GPIO.LedPin = 0; //
Led off
GPIO.OutPin = 0; //
Output off
// Get
programming button new state
curprg =
Button(&GPIO, 1, 1, ButOn);
// Detect
long pression
if
(b==LongButton) { // Long
pression detected
tim =
1; // Reset time
delay duration
StoreByte(tim,0); // Store new value in flash
Blink(2); //
Announce reset
}
// Detect
short pression
if
((prvprg) && (!curprg) && (b<LongButton)) {
tim++;
//
Increase time delay (number of tic)
Blink(1); //
Signal the change via one blink
StoreByte(tim,0); //
Store new value in flash
}
// Count
pression time cycle
if
(curprg) b++; // Count
pressed state cycles
else b=0; // At release, reset pressed
state cycles counter
prvprg =
curprg; // Save button state
}
else {
// We are in
countdown
GPIO.LedPin = 1; // Led on
GPIO.OutPin = 1; //
Output on
n--;
// Decrement cycles
count
}
Delay_ms(CycDly);
// Fit 10ms per cycle
}
while(1);
//
endless loop
}