To be honest, this problem is best solved with digital electronics, because their circuit uses 4 transistors and a lot of discretes. I once did it using
an ATTINY13V (I think) which was good because it is only 8-pin SOIC, and then (depending on if you have a high power load) a MOSFET+RELAY or
a couple of MOSFETS (and resistors of course). For driving just an LED you wouldn't need relay/FETs.
The processor runs a simple switch debounce program. It could also perform auto-power-off, etc.
The code is here, it is quite inefficient, I didn't even use processor sleep, but I was in a hurry to get something out the door.
(I think it was compiled with IAR compiler).
/********************************
ATTINY13 or ATTINY13v
VDD is pin 8, GND is pin 4
Lamp output is pin 5 (high=lamp on, low=lamp off)
Suitable driver is PIP3105-P (Input pin connects to
pin 5, Source connects to GND, and Drain connects to lamp).
Switch is connected between pin 6 and GND.
When shorted to ground, the lamp is turned on (i.e. lamp
pin goes high).
Pin 7 (general purpose output) also does the same thing,
(maybe invert the output in a later code version).
Programming:
C:\c_root\Electronics\switchproject\code\Release\Exe>c:\WinAVR\bin\avrdude.exe
-c avrisp2 -p t13 -P com6 -U flash:w:switchproject_project.hex
*********************************/
#include <iotiny13.h>
#include <intrinsics.h>
#include <avr_macros.h>
#include <stdio.h>
// Port B
#define LAMP 0x01
#define BUTTON 0x02
#define GENOUT 0x04
// inputs
#define SWITCH_ON (PINB & BUTTON) == 0
#define SWITCH_OFF (PINB & BUTTON) != 0
// outputs
#define LAMP_ON PORTB |= LAMP
#define LAMP_OFF PORTB &= ~LAMP
#define GENOUT_ON PORTB |= GENOUT
#define GENOUT_OFF PORTB &= ~GENOUT
// global vars
char changed;
// delay in hundreths of a sec
void
delay_cs(int v)
{
int i;
for (i=0; i<v; v++)
{
__delay_cycles(187);
}
}
int
main( void )
{
int state;
// initialise
PORTB=0;
DDRB=0x05; // LAMP pin is output as well as GENOUT, the rest of port B is inputs
PORTB=0x3a; // enable pull-ups on all input pins
LAMP_OFF;
GENOUT_OFF;
// end of initialisation
changed=0;
state=0; // assume switch is off
while(1)
{
// Check if we need to turn the lamp on
if ((SWITCH_ON) && state==0) // is the light just switched on now?
{
__delay_cycles(1000); // wait a bit for contact bounce allowance
if (SWITCH_ON) // no contact bounce
{
LAMP_ON;
GENOUT_ON;
state=1;
}
}
// Check if we need to turn the lamp off
if ((SWITCH_OFF) && state==1) // is the light just switched off now?
{
__delay_cycles(1000); // wait a bit for contact bounce allowance
if (SWITCH_OFF) // no contact bounce
{
LAMP_OFF;
GENOUT_OFF;
state=0;
}
}
} // end while
return 0;
}