Hi there!
First of all, thank you very much Don for the circuit and other support on the forums!
I have created my own version of the circuit (this is how I like to learn new things, and I just needed to understand it first). I also wanted the disabling functionality when going to the dealer, so I would have less explaining to do and I am quite lazy so I did not want to disconnect the module every time like wookie_666 .
If anyone could verify my circuit, before I stick it into my car that would be great (I am not an EE and this is my first time making a circuit)
I had changed the pinout, so the Don's circuit translates to this one as follows:
P3 is now P0
P2 is now P4
The P0 pin is now sensing the SS switch state using a third optocoupler.
I also have un-soldered the power led from the digispark and currently the peak current while the circuit is working is below 45mA and it drops to ~8-5mA while in the sleep state (not that it matters really).
Since the code below enables the internal pull-ups on the unused pins, do not solder the unused pins to ground, since they will be high and you could damage your chip.
Here is the code:
Code:
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
const byte MAX_PULSES = 5;
const byte SS_LED_IN = 0; // P3 -> P0
const byte DBG_LED_OUT = 1;
const byte SS_SWITCH_IN = 2;
const byte SS_SWITCH_OUT = 4; // P2 -> P4
const byte UNUSED_0 = 3;
const byte UNUSED_1 = 5;
const byte ENABLED_BYTE = 0x55;
const byte DISABLED_BYTE = 0xAA;
void setup() {
// I/O modes
pinMode(SS_SWITCH_OUT, OUTPUT);
pinMode(DBG_LED_OUT, OUTPUT);
pinMode(SS_SWITCH_IN, INPUT);
pinMode(SS_LED_IN, INPUT);
pinMode(UNUSED_0, INPUT); // unused
pinMode(UNUSED_1, INPUT); // unused
// I/O states
digitalWrite(SS_SWITCH_OUT, LOW);
digitalWrite(DBG_LED_OUT, LOW);
digitalWrite(SS_SWITCH_IN, LOW);
digitalWrite(SS_LED_IN, LOW);
digitalWrite(UNUSED_0, HIGH); // unused
digitalWrite(UNUSED_1, HIGH); // unused
light(LOW);
// disable unused peripherals (timer1 is required for delay)
power_timer0_disable();
power_usi_disable();
power_adc_disable();
ADCSRA = 0;
// maximum sleep mode
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
void loop() {
// boot loader takes ~5s
// read persistend enabled state
byte enabled = (eeprom_read_byte(0x0000) != DISABLED_BYTE); // treat everything not equal to DISABLED_BYTE as enabled
// read the button state
byte ssPressed = digitalRead(SS_SWITCH_IN);
if (ssPressed) {
// blinks with led will delay by an additional ~1s each
blink(1);
blink(1);
}
// after waiting reread the button state - if it is still pressed, then swap the disabled info
if (ssPressed && digitalRead(SS_SWITCH_IN)) {
blink(2);
enabled = !enabled;
// save to eeprom
eeprom_write_byte(0x0000, enabled ? ENABLED_BYTE : DISABLED_BYTE);
} else if (enabled) {
byte counter = 0;
while (counter++ < MAX_PULSES && digitalRead(SS_LED_IN) == HIGH) {
blink(1); // blink once for every retry
digitalWrite(SS_SWITCH_OUT, HIGH);
delay(1024);
digitalWrite(SS_SWITCH_OUT, LOW);
}
}
blink(3); // blink 3 times as a bye bye
// disable everything else, for minimal power consumption
power_all_disable();
power_timer1_disable();
wdt_disable();
noInterrupts();
sleep_enable();
while(1) {
sleep_mode();
// should not happen
}
}
volatile byte currentState = LOW;
// blinks n-times, and delays by n*192ms + 832ms, eg. 1 blink = 1024ms, 2 blinks = 1216ms
// after blinking leaves the LED in the same state it was in (currentState)
void blink(int times) {
while(times--) {
digitalWrite(DBG_LED_OUT, LOW);
delay(96);
digitalWrite(DBG_LED_OUT, HIGH);
delay(96);
digitalWrite(DBG_LED_OUT, LOW);
}
delay(832);
digitalWrite(DBG_LED_OUT, currentState);
}
// changes the state of the LED
void light(byte state) {
currentState = state;
digitalWrite(DBG_LED_OUT, currentState);
}
The simplified flow diagram:
(the above picture has an error, it should be SS LED lit? OR <5 pulses sent?)
And the schematics:
And the finished product (need to clean it up and isolate it):
Bookmarks