1 
1 
#include "current.h"

2 
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 10


8 
#define N_SAMPLES 20


9 


10 
unsigned int samples[N_SAMPLES];


11 
int sample_idx;


12 


13 
unsigned int sum;


14 
unsigned long sum_sq;

3 
15 

4 
16 
void current_init() {


17 


18 
/*


19 
* COM0A = 0, disconnect pin


20 
* WGM0 = 2, clear timer on compare


21 
*/


22 
TCCR0A = _BV(WGM01);


23 


24 
/*


25 
* CS0 = 5, 1024 prescaler


26 
*/


27 
TCCR0B = _BV(CS02)  _BV(CS00);


28 


29 
OCR0A = F_CPU / 1024 / SAMPLES_PER_CYCLE / CYCLES_PER_SECOND;


30 

5 
31 
/*

6 
32 
* REFS = 0, Vcc reference (set to 2 for internal 1.1V reference)

7 
33 
* MUX = 8, PB3(ADC8)

8 
34 
*/

9 
35 
ADMUX = _BV(MUX3);


36 

10 
37 
/* TODO reduce power consumption with DIDR* */


38 

11 
39 
/*

12 
40 
* ADLAR = 0, right adjust result

13 

* ADTS = 0, free running mode


41 
* ADTS = 3, start on timer 0 compare match A

14 
42 
*/

15 

ADCSRB = 0;


43 
ADCSRB = _BV(ADTS1)  _BV(ADTS0);


44 

16 
45 
/*

17 
46 
* ADEN = 1, enable

18 

* ADSC = 1, start now


47 
* ADSC = 0, don't start yet

19 
48 
* ADATE = 1, auto trigger

20 

* ADIE = 0, disable interrupt

21 

* ADPS = 3, prescale clock by 8


49 
* ADIE = 1, enable interrupt


50 
* ADPS = 4, prescale clock by 16

22 
51 
*/

23 

ADCSRA = _BV(ADEN)  _BV(ADSC)  _BV(ADATE)  _BV(ADPS1)  _BV(ADPS0);


52 
ADCSRA = _BV(ADEN)  _BV(ADATE)  _BV(ADIE)  _BV(ADPS2);

24 
53 
}

25 
54 

26 

int current_read() {

27 

return ADC;


55 
ISR(ADC_vect) {


56 
unsigned int old, new;


57 


58 
new = ADC;


59 


60 
/* put sample into ring buffer */


61 
old = samples[sample_idx];


62 
samples[sample_idx++] = new;


63 
if (sample_idx == N_SAMPLES)


64 
sample_idx = 0;


65 


66 
/* keep a running total of samples and samples squared */


67 
sum += new;


68 
sum = old;


69 
sum_sq += new*new;


70 
sum_sq = old*old;


71 
}


72 


73 
/*unsigned char isqrt(unsigned int x) {


74 
unsigned int sqrt, mulmask;


75 
sqrt = 0;


76 
mulmask = 0x80;


77 
if (x > 0) {


78 
while (mulmask) {


79 
sqrt = mulmask;


80 
if (sqrt * sqrt > x)


81 
sqrt &= ~mulmask;


82 
mulmask >>= 1;


83 
}


84 
}


85 
return sqrt;


86 
}*/


87 


88 
unsigned int current_read() {


89 
unsigned int _sum;


90 
unsigned long _sum_sq;


91 


92 
cli();


93 
_sum = sum;


94 
_sum_sq = sum_sq;


95 
sei();


96 


97 
/* calculate the variance using sum and sum_sq */


98 
return (N_SAMPLES*_sum_sq  _sum*_sum) / (N_SAMPLES*(N_SAMPLES1));

28 
99 
}
