~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to ToyKeeper/battcheck/battcheck.c

  • Committer: Selene Scriven
  • Date: 2015-09-14 19:23:29 UTC
  • mto: (153.1.18 tiny25)
  • mto: This revision was merged to the branch mainline in revision 156.
  • Revision ID: ubuntu@toykeeper.net-20150914192329-0ean5s8qpnnkdbub
updated to BLF-VLD 0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This firmware simply helps calibrate values for voltage readings.
 
3
 * It is not intended to be used as an actual flashlight.
 
4
 *
 
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.
 
10
 *
 
11
 * NANJG 105C Diagram
 
12
 *           ---
 
13
 *         -|   |- VCC
 
14
 *  Star 4 -|   |- Voltage ADC
 
15
 *  Star 3 -|   |- PWM
 
16
 *     GND -|   |- Star 2
 
17
 *           ---
 
18
 *
 
19
 * CPU speed is 4.8Mhz without the 8x divider when low fuse is 0x75
 
20
 *
 
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  #######
 
25
 *
 
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
 
28
 *
 
29
 * FUSES
 
30
 *      I use these fuse settings
 
31
 *      Low:  0x75
 
32
 *      High: 0xff
 
33
 *
 
34
 * STARS (not used)
 
35
 *
 
36
 */
 
37
// set some hardware-specific values...
 
38
// (while configuring this firmware, skip this section)
 
39
#if (ATTINY == 13)
 
40
#define F_CPU 4800000UL
 
41
#define EEPLEN 64
 
42
#define DELAY_TWEAK 950
 
43
#elif (ATTINY == 25)
 
44
#define F_CPU 8000000UL
 
45
#define EEPLEN 128
 
46
#define DELAY_TWEAK 2000
 
47
#else
 
48
Hey, you need to define ATTINY.
 
49
#endif
 
50
 
 
51
 
 
52
/*
 
53
 * =========================================================================
 
54
 * Settings to modify per driver
 
55
 */
 
56
 
 
57
#define OWN_DELAY   // Should we use the built-in delay or our own?
 
58
 
 
59
#define BLINK_PWM   10
 
60
 
 
61
/*
 
62
 * =========================================================================
 
63
 */
 
64
 
 
65
#ifdef OWN_DELAY
 
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)
 
69
{
 
70
    while(n-- > 0)
 
71
        _delay_loop_2(DELAY_TWEAK);
 
72
}
 
73
#else
 
74
#include <util/delay.h>
 
75
#endif
 
76
 
 
77
#include <avr/pgmspace.h>
 
78
#include <avr/interrupt.h>
 
79
#include <avr/wdt.h>
 
80
#include <avr/eeprom.h>
 
81
#include <avr/sleep.h>
 
82
 
 
83
#define STAR2_PIN   PB0
 
84
#define STAR3_PIN   PB4
 
85
#define STAR4_PIN   PB3
 
86
#define PWM_PIN     PB1
 
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
 
91
 
 
92
#define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
 
93
 
 
94
inline void ADC_on() {
 
95
#if (ATTINY == 13)
 
96
    ADMUX  = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
 
97
#elif (ATTINY == 25)
 
98
    ADMUX  = (1 << REFS1) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
 
99
#endif
 
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
 
102
}
 
103
 
 
104
inline void ADC_off() {
 
105
    ADCSRA &= ~(1<<7); //ADC off
 
106
}
 
107
 
 
108
uint8_t get_voltage() {
 
109
    // Start conversion
 
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
 
114
    return ADCH;
 
115
}
 
116
 
 
117
void noblink() {
 
118
    PWM_LVL = (BLINK_PWM>>2);
 
119
    _delay_ms(5);
 
120
    PWM_LVL = 0;
 
121
    _delay_ms(200);
 
122
}
 
123
 
 
124
void blink() {
 
125
    PWM_LVL = BLINK_PWM;
 
126
    _delay_ms(100);
 
127
    PWM_LVL = 0;
 
128
    _delay_ms(200);
 
129
}
 
130
 
 
131
int main(void)
 
132
{
 
133
    // Set PWM pin to output
 
134
    DDRB = (1 << PWM_PIN);
 
135
 
 
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...)
 
139
 
 
140
    // Turn features on or off as needed
 
141
    ADC_on();
 
142
    ACSR   |=  (1<<7); //AC off
 
143
 
 
144
    // blink once on receiving power
 
145
    PWM_LVL = 255;
 
146
    _delay_ms(5);
 
147
    PWM_LVL = 0;
 
148
 
 
149
    uint16_t voltage;
 
150
    uint8_t i;
 
151
    voltage = get_voltage();
 
152
 
 
153
    while(1) {
 
154
        PWM_LVL = 0;
 
155
 
 
156
        // get an average of several readings
 
157
        voltage = 0;
 
158
        for (i=0; i<8; i++) {
 
159
            voltage += get_voltage();
 
160
            _delay_ms(50);
 
161
        }
 
162
        voltage = voltage >> 3;
 
163
 
 
164
        // hundreds
 
165
        while (voltage >= 100) {
 
166
            voltage -= 100;
 
167
            blink();
 
168
        }
 
169
        _delay_ms(1000);
 
170
 
 
171
        // tens
 
172
        if (voltage < 10) {
 
173
            noblink();
 
174
        }
 
175
        while (voltage >= 10) {
 
176
            voltage -= 10;
 
177
            blink();
 
178
        }
 
179
        _delay_ms(1000);
 
180
 
 
181
        // ones
 
182
        if (voltage <= 0) {
 
183
            noblink();
 
184
        }
 
185
        while (voltage > 0) {
 
186
            voltage -= 1;
 
187
            blink();
 
188
        }
 
189
        _delay_ms(1000);
 
190
 
 
191
        // ... and wait a bit for next time
 
192
        _delay_ms(3000);
 
193
 
 
194
    }
 
195
}