I fabbed a circuit for a bicycle dynamo hub USB charger that fits inside an old bike light body.
I want to use external interrupts to wake the microcontroller, an ATtiny45, and switch between three control states: off, charging on, and headllamp on.
My concern is that when I come to a stop, the charge in the capacitors(3 4F supercaps) will dissipate and the microcontroller will shut down. How do I maintain the control state so that after a stop, the headlight will turn back on when I star moving again and the microcontoller powers back up? I dont want to have to turn the light back on every time I stop. Is this something I use the BOD for?
Write the state to eeprom; doing that at power down might be a bit tricky but you can do it when the state changes (hopefully that is not too often as you basically only have 100,000 write cycles for one eeprom location).
I’m looking at the EEPROM documentation for the ATtiny45. I want to use my external interrupt to increment the address location so I can spread out the erase/write cycles over all the EEPROM addresses. The sample code in the datasheet uses to declare address; how can I use there instead? Atmel studio doesn’t seem to like declaring a byte variable…
the sample code is this:
void EEPROM_write(unsigned char ucAddress, unsigned char ucData)
/* Wait for completion of previous write */
while(EECR & (1<<EEPE))
/* Set Programming mode */
EECR = (0<<EEPM1)|(0<<EEPM0);
/* Set up address and data registers */
EEAR = ucAddress;
EEDR = ucData;
/* Write logical one to EEMPE */
EECR |= (1<<EEMPE);
/* Start eeprom write by setting EEPE */
EECR |= (1<<EEPE);
If there are other components that require 5V and not 3.2, then the following becomes a bit more complicated.
My thought is that a DC-DC (95-97% efficient) would bridge the supercaps and a LiFePO4 pack (also provides diode isolation.) The lithium pack referenced is unique in that there is never any lithium metal produced in the charge-discharge process and the cells are capable of being charged by float-charging to within 95% of their capacity (the literature is somewhat murky on the subject, but I have experiments running for well over a year where the cells are float-charged at 3.45V) A better, more expensive, design would be to use a legitimate LiFePO4 charger module in place of the DC/DC.
So, if you have a free pin on the t85, you can monitor the capacitor bank* and when the bank stops charging, you write your volatile data to EEPROM and then go into deep-sleep awakening when the capacitors charge sufficiently to provide a pin-change interrupt.
There are several ways to monitor the capacitor bank, you can do it with an analog or with a digital pin. A very simple way is to simply use a small, low current relay with a small value resistor in series with the coil. When the capacitors charge up, the relay closes and when the capacitors discharge, the relay releases. This can be a real relay or a reed-type relay.
You should provide a switch to isolate the LiFePO4 cells should you intend on not using the bike for an extended period. Lithium batteries are not fond of being drained below a specified threshold: 2.5 Volts for LiFePO4
dynamo ---> caps ----> DC/DC ----> LiFePO4 ----> Tiny85
Alternate for 5V: 2 LiFePO4 cells in series:
dynamo ---> caps ----> DC/DC ----> LiFePO4 ----> 5V LDO reg -----> Tiny85
I guess that wouldn't work, because I'd have to store the address of the current state in EEPROM too, which means i'd have to write to it on every button press...
All you need to do is:
When you are ready to read a state upon power up, read EEPROM memory locations from 1 to 10, looking for the first one that has a number that represents a valid state, 1, 2, or 3. If another number is in the memory location, ignore it and look at the next memory location. When you find the state, leave it in a variable, and put the memory location where you found it in another variable. If you don't find a valid state, write your favorite state in location 1 (that means your program has never run since the EEPROM was last erased, so initialize it to something).
When you are ready to write a state, write 0xFF into the EEPROM location you read earlier, and write the new state into the next memory location. When you exceed memory location 10, start back over with location 1. Using 10 memory locations is just an example, you could use more or less. With 10 you get a million writes, and your bike, dynamo, muscles, and bones will be worn out by then.
Here is another semi-sorta-kinda similar method you could adapt to ATtiny45, storing the state one bit at a time:
I have one EEPROM address(0) that holds the address value where the control value is stored. On a restart, the program reads the address value from (0) and reads the value stored at the corresponding address. On a button press, the value of the state is incremented, all the way up to 255, and I use a modulus to get the 1, 2, or 3 from the 0-255 value stored in the EEPROM. Only when the state value overflows do I progress no the next address location and update the address value at (0). This way I can cycle all the way through one address before I rewrite the Address value, which gives me 85 value updates per change of the address value. or 8,500,000 cycles. That should get me where I need to go.
One question, though...
Is there a way to write a value to EEPROM when I program the chip?
alternately, will the value be zero if I don't?
I will need to set or at least know an initial address value in the (0) location and an initial state value in location (1), but this value can't get set in void setup() when the chip restarts.