root / toolbox / current.c @ db11713d
History  View  Annotate  Download (2.1 KB)
1 
#include "current.h" 

2 
#include <avr/io.h> 
3 
#include <avr/interrupt.h> 
4 
#include <math.h> 
5  
6 
#define CYCLES_PER_SECOND 60 // wall power 
7 
#define SAMPLES_PER_CYCLE 16 
8 
#define N_SAMPLES 48 
9  
10 
unsigned int samples[N_SAMPLES]; 
11 
int sample_idx;

12  
13 
unsigned int sum; 
14 
unsigned long sum_sq; 
15  
16 
void current_init() {

17  
18 
/* TODO reduce power consumption with DIDR* */

19  
20 
/*

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 
* REFS = 0, Vcc reference (set to 2 for internal 1.1V reference)

33 
* MUX = 8, PB3(ADC8)

34 
*/

35 
ADMUX = _BV(MUX3); 
36 
DIDR1 = _BV(ADC8D); 
37  
38 
/*

39 
* ADLAR = 0, right adjust result

40 
* ADTS = 5, start on timer 1 compare match B

41 
*/

42 
ADCSRB = _BV(ADTS2)  _BV(ADTS0); 
43  
44 
/*

45 
* ADEN = 1, enable

46 
* ADSC = 0, don't start yet

47 
* ADATE = 1, auto trigger

48 
* ADIE = 1, enable interrupt

49 
* ADPS = 6, prescale clock by 64

50 
*/

51 
ADCSRA = _BV(ADEN)  _BV(ADATE)  _BV(ADIE)  _BV(ADPS2)  _BV(ADPS1); 
52 
} 
53  
54 
ISR(ADC_vect) { 
55 
unsigned int old, new; 
56  
57 
/* clear the timer interrupt flag so that the ADC will be triggered again

58 
* next time the timer resets */

59 
TIFR = _BV(OCF1B); 
60  
61 
new = ADC; 
62  
63 
/* put sample into ring buffer */

64 
old = samples[sample_idx]; 
65 
samples[sample_idx++] = new; 
66 
if (sample_idx == N_SAMPLES)

67 
sample_idx = 0;

68  
69 
/* keep a running total of samples and samples squared */

70 
sum += new; 
71 
sum = old; 
72 
sum_sq += new*new; 
73 
sum_sq = old*old; 
74 
} 
75  
76 
/*unsigned char isqrt(unsigned int x) {

77 
unsigned int sqrt, mulmask;

78 
sqrt = 0;

79 
mulmask = 0x80;

80 
if (x > 0) {

81 
while (mulmask) {

82 
sqrt = mulmask;

83 
if (sqrt * sqrt > x)

84 
sqrt &= ~mulmask;

85 
mulmask >>= 1;

86 
}

87 
}

88 
return sqrt;

89 
}*/

90  
91 
unsigned int current_read() { 
92 
unsigned int _sum; 
93 
unsigned long _sum_sq; 
94  
95 
cli(); 
96 
_sum = sum; 
97 
_sum_sq = sum_sq; 
98 
sei(); 
99  
100 
/* calculate the variance using sum and sum_sq */

101 
return (N_SAMPLES*_sum_sq  (unsigned long)_sum*_sum) / 
102 
(N_SAMPLES*(N_SAMPLES1));

103 
} 