2
* This firmware simply helps calibrate values for voltage readings.
3
* It is not intended to be used as an actual flashlight.
5
* It will read the voltage, then read out the raw value as a series of
6
* blinks. It will provide up to three groups of blinks, representing the
7
* hundreds digit, the tens digit, then the ones. So, for a raw value of 183,
8
* it would blink once, pause, blink eight times, pause, then blink three times.
9
* It will then wait longer and re-read the voltage, then repeat.
14
* Star 4 -| |- Voltage ADC
19
* CPU speed is 4.8Mhz without the 8x divider when low fuse is 0x75
21
* define F_CPU 4800000 CPU: 4.8MHz PWM: 9.4kHz ####### use low fuse: 0x75 #######
22
* /8 PWM: 1.176kHz ####### use low fuse: 0x65 #######
23
* define F_CPU 9600000 CPU: 9.6MHz PWM: 19kHz ####### use low fuse: 0x7a #######
24
* /8 PWM: 2.4kHz ####### use low fuse: 0x6a #######
26
* Above PWM speeds are for phase-correct PWM. This program uses Fast-PWM,
27
* which when the CPU is 4.8MHz will be 18.75 kHz
30
* I use these fuse settings
37
// set some hardware-specific values...
38
// (while configuring this firmware, skip this section)
40
#define F_CPU 4800000UL
42
#define DELAY_TWEAK 950
44
#define F_CPU 8000000UL
46
#define DELAY_TWEAK 2000
48
Hey, you need to define ATTINY.
53
* =========================================================================
54
* Settings to modify per driver
57
#define OWN_DELAY // Should we use the built-in delay or our own?
62
* =========================================================================
66
#include <util/delay_basic.h>
67
// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
68
static void _delay_ms(uint16_t n)
71
_delay_loop_2(DELAY_TWEAK);
74
#include <util/delay.h>
77
#include <avr/pgmspace.h>
78
#include <avr/interrupt.h>
80
#include <avr/eeprom.h>
81
#include <avr/sleep.h>
87
#define VOLTAGE_PIN PB2
88
#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2
89
#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
90
#define ADC_PRSCL 0x06 // clk/64
92
#define PWM_LVL OCR0B // OCR0B is the output compare register for PB1
94
inline void ADC_on() {
96
ADMUX = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
98
ADMUX = (1 << REFS1) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
100
DIDR0 |= (1 << ADC_DIDR); // disable digital input on ADC pin to reduce power consumption
101
ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL; // enable, start, prescale
104
inline void ADC_off() {
105
ADCSRA &= ~(1<<7); //ADC off
108
uint8_t get_voltage() {
110
ADCSRA |= (1 << ADSC);
111
// Wait for completion
112
while (ADCSRA & (1 << ADSC));
113
// See if voltage is lower than what we were looking for
118
PWM_LVL = (BLINK_PWM>>2);
133
// Set PWM pin to output
134
DDRB = (1 << PWM_PIN);
136
// Set timer to do PWM for correct output pin and set prescaler timing
137
TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
138
TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
140
// Turn features on or off as needed
142
ACSR |= (1<<7); //AC off
144
// blink once on receiving power
151
voltage = get_voltage();
156
// get an average of several readings
158
for (i=0; i<8; i++) {
159
voltage += get_voltage();
162
voltage = voltage >> 3;
165
while (voltage >= 100) {
175
while (voltage >= 10) {
185
while (voltage > 0) {
191
// ... and wait a bit for next time