Revision e2a3c71f
ID | e2a3c71f71fc38f72a7175df2e257c5b024bee41 |
Parent | 2dde134c |
Added shutoff when current is sensed when enabling tool
Also made a number of fixes to current sensing, which was quite broken.
toolbox/current.c | ||
---|---|---|
3 | 3 |
#include <avr/interrupt.h> |
4 | 4 |
#include <math.h> |
5 | 5 |
|
6 |
// TODO the ADC is run once every 2ms no matter what these numbers |
|
7 |
// say. They're not used. Actual samples/cycle is around 8.3 |
|
6 | 8 |
#define CYCLES_PER_SECOND 60 // wall power |
7 |
#define SAMPLES_PER_CYCLE 16
|
|
8 |
#define N_SAMPLES 48
|
|
9 |
#define SAMPLES_PER_CYCLE 8
|
|
10 |
#define N_SAMPLES 24
|
|
9 | 11 |
|
10 | 12 |
unsigned int samples[N_SAMPLES]; |
11 | 13 |
int sample_idx; |
... | ... | |
18 | 20 |
/* TODO reduce power consumption with DIDR* */ |
19 | 21 |
|
20 | 22 |
/* |
21 |
* COM1A = COM1B = 0, disconnect pins |
|
22 |
* WGM1 = 4, clear timer on compare A |
|
23 |
* CS1 = 1, no prescaler |
|
24 |
*/ |
|
25 |
TCCR1B = _BV(WGM12) | _BV(CS10); |
|
26 |
|
|
27 |
/* Timer is cleared on A, ADC is triggered on B */ |
|
28 |
OCR1A = F_CPU / SAMPLES_PER_CYCLE / CYCLES_PER_SECOND; |
|
29 |
OCR1B = OCR1A; |
|
30 |
|
|
31 |
/* |
|
32 | 23 |
* REFS = 0, Vcc reference (set to 2 for internal 1.1V reference) |
33 | 24 |
* MUX = 8, PB3(ADC8) |
34 | 25 |
*/ |
... | ... | |
36 | 27 |
|
37 | 28 |
/* |
38 | 29 |
* ADLAR = 0, right adjust result |
39 |
* ADTS = 5, start on timer 1 compare match B |
|
40 | 30 |
*/ |
41 |
ADCSRB = _BV(ADTS2) | _BV(ADTS0);
|
|
31 |
ADCSRB = 0;
|
|
42 | 32 |
|
43 | 33 |
/* |
44 | 34 |
* ADEN = 1, enable |
45 | 35 |
* ADSC = 0, don't start yet |
46 |
* ADATE = 1, auto trigger
|
|
36 |
* ADATE = 0, no auto trigger
|
|
47 | 37 |
* ADIE = 1, enable interrupt |
48 | 38 |
* ADPS = 6, prescale clock by 64 |
49 | 39 |
*/ |
50 |
ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1); |
|
40 |
ADCSRA = _BV(ADEN) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1); |
|
41 |
} |
|
42 |
|
|
43 |
void current_start_adc() { |
|
44 |
ADCSRA |= _BV(ADSC); |
|
51 | 45 |
} |
52 | 46 |
|
53 | 47 |
ISR(ADC_vect) { |
54 | 48 |
unsigned int old, new; |
55 | 49 |
|
56 |
/* clear the timer interrupt flag so that the ADC will be triggered again |
|
57 |
* next time the timer resets */ |
|
58 |
TIFR |= _BV(OCF1B); |
|
59 |
|
|
60 | 50 |
new = ADC; |
61 | 51 |
|
62 | 52 |
/* put sample into ring buffer */ |
toolbox/current.h | ||
---|---|---|
2 | 2 |
#define CURRENT_H |
3 | 3 |
|
4 | 4 |
void current_init(); |
5 |
void current_start_adc(); |
|
5 | 6 |
unsigned int current_read(); |
6 | 7 |
|
7 | 8 |
#endif |
toolbox/main.c | ||
---|---|---|
21 | 21 |
TS_DENY, |
22 | 22 |
TS_REQ_DIS, |
23 | 23 |
TS_MISSING_ID, |
24 |
TS_ON |
|
24 |
TS_ON, |
|
25 |
TS_OVER_CURRENT |
|
25 | 26 |
}; |
26 | 27 |
|
27 | 28 |
static enum toolstate_t toolstate = TS_INIT; |
... | ... | |
31 | 32 |
static uint16_t current; |
32 | 33 |
//static uint16_t current_max_warn, current_max_hard; |
33 | 34 |
|
35 |
// watch for current spike when tool turns on |
|
36 |
#define CURRENT_STARTUP_THRESH 10 |
|
37 |
#define CURRENT_STARTUP_TIMEOUT 200 // ms |
|
38 |
static uint8_t current_startup_timeout; |
|
39 |
static uint16_t current_startup_value; |
|
40 |
|
|
34 | 41 |
static inline void set_coil(char coil, char bit) { |
35 | 42 |
coils = (coils & ~(1 << coil)) | (bit << coil); |
36 | 43 |
} |
... | ... | |
92 | 99 |
if (get_coil(MB_COIL_EN)) { |
93 | 100 |
tool_enable(); |
94 | 101 |
toolstate = TS_ON; |
102 |
current_startup_timeout = CURRENT_STARTUP_TIMEOUT / TICK_MS; |
|
103 |
current_startup_value = current + CURRENT_STARTUP_THRESH; |
|
95 | 104 |
} else if (!get_coil(MB_COIL_NEW)) { |
96 | 105 |
toolstate = TS_DENY; |
97 | 106 |
} else if (!serno_equal(current_user, latest_reading)) { |
... | ... | |
125 | 134 |
break; |
126 | 135 |
|
127 | 136 |
case TS_MISSING_ID: |
128 |
if (!get_coil(MB_COIL_EN)) { |
|
137 |
if (current_startup_timeout > 0 && current > current_startup_value) { |
|
138 |
tool_disable(); |
|
139 |
set_coil(MB_COIL_EN, 0); |
|
140 |
toolstate = TS_OVER_CURRENT; |
|
141 |
led_blink_start(500, 16, RED); |
|
142 |
} else if (!get_coil(MB_COIL_EN)) { |
|
129 | 143 |
tool_disable(); |
130 | 144 |
toolstate = TS_OFF; |
131 | 145 |
} else if (get_coil(MB_COIL_REQ_DIS)) { |
... | ... | |
138 | 152 |
serno_zero(current_user); |
139 | 153 |
toolstate = TS_OFF; |
140 | 154 |
} |
155 |
if (current_startup_timeout > 0) { |
|
156 |
current_startup_timeout--; |
|
157 |
} |
|
141 | 158 |
break; |
142 | 159 |
|
143 | 160 |
case TS_ON: |
144 | 161 |
led_green(); |
145 |
if (!get_coil(MB_COIL_EN)) { |
|
162 |
if (current_startup_timeout > 0 && current > current_startup_value) { |
|
163 |
tool_disable(); |
|
164 |
set_coil(MB_COIL_EN, 0); |
|
165 |
toolstate = TS_OVER_CURRENT; |
|
166 |
led_blink_start(500, 16, RED); |
|
167 |
} else if (!get_coil(MB_COIL_EN)) { |
|
146 | 168 |
tool_disable(); |
147 | 169 |
serno_zero(current_user); |
148 | 170 |
toolstate = TS_OFF; |
... | ... | |
150 | 172 |
toolstate = TS_REQ_DIS; |
151 | 173 |
} else if (!serno_equal(current_user, latest_reading)) { |
152 | 174 |
toolstate = TS_MISSING_ID; |
153 |
led_blink_start(500, 6, YELLOW); // TODO made 10 seconds |
|
175 |
led_blink_start(500, 16, YELLOW); |
|
176 |
} |
|
177 |
if (current_startup_timeout > 0) { |
|
178 |
current_startup_timeout--; |
|
179 |
} |
|
180 |
break; |
|
181 |
|
|
182 |
case TS_OVER_CURRENT: |
|
183 |
if (led_blink_done() && !serno_equal(current_user, latest_reading)) { |
|
184 |
toolstate = TS_OFF; |
|
185 |
serno_zero(current_user); |
|
154 | 186 |
} |
155 | 187 |
break; |
156 | 188 |
|
toolbox/time.c | ||
---|---|---|
2 | 2 |
#include <avr/io.h> |
3 | 3 |
#include <avr/interrupt.h> |
4 | 4 |
#include "time.h" |
5 |
#include "current.h" |
|
5 | 6 |
|
6 | 7 |
/* F_CPU / PRESCALE = OCR * 1000 + ERROR */ |
7 | 8 |
#define OCR (F_CPU / PRESCALE / 1000UL) |
... | ... | |
23 | 24 |
ready = 1; |
24 | 25 |
ms = 0; |
25 | 26 |
} |
27 |
if (ms % 2 == 0) { |
|
28 |
current_start_adc(); // TODO don't do this here |
|
29 |
} |
|
26 | 30 |
} |
27 | 31 |
|
28 | 32 |
void time_init() { |
Also available in: Unified diff