Project

General

Profile

Statistics
| Branch: | Revision:

root / toolbox / current.c @ master

History | View | Annotate | Download (1.54 KB)

1
#include "current.h"
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <math.h>
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
8
#define CYCLES_PER_SECOND 60 // wall power
9
#define SAMPLES_PER_CYCLE  8
10
#define N_SAMPLES 24
11

    
12
unsigned int samples[N_SAMPLES];
13
int sample_idx;
14

    
15
unsigned int sum;
16
unsigned long sum_sq;
17

    
18
void current_init() {
19

    
20
  /* TODO reduce power consumption with DIDR* */
21

    
22
  /*
23
   * REFS = 0, Vcc reference (set to 2 for internal 1.1V reference)
24
   * MUX = 8, PB3(ADC8)
25
   */
26
  ADMUX = _BV(MUX3);
27

    
28
  /*
29
   * ADLAR = 0, right adjust result
30
   */
31
  ADCSRB = 0;
32

    
33
  /*
34
   * ADEN = 1, enable
35
   * ADSC = 0, don't start yet
36
   * ADATE = 0, no auto trigger
37
   * ADIE = 1, enable interrupt
38
   * ADPS = 6, prescale clock by 64
39
   */
40
  ADCSRA = _BV(ADEN) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1);
41
}
42

    
43
void current_start_adc() {
44
  ADCSRA |= _BV(ADSC);
45
}
46

    
47
ISR(ADC_vect) {
48
  unsigned int old, new;
49

    
50
  new = ADC;
51

    
52
  /* put sample into ring buffer */
53
  old = samples[sample_idx];
54
  samples[sample_idx++] = new;
55
  if (sample_idx == N_SAMPLES)
56
    sample_idx = 0;
57

    
58
  /* keep a running total of samples and samples squared */
59
  sum += new;
60
  sum -= old;
61
  sum_sq += (unsigned long)new*new;
62
  sum_sq -= (unsigned long)old*old;
63
}
64

    
65
unsigned int current_read() {
66
  unsigned int _sum;
67
  unsigned long _sum_sq;
68

    
69
  cli();
70
  _sum = sum;
71
  _sum_sq = sum_sq;
72
  sei();
73

    
74
  /* calculate the variance using sum and sum_sq */
75
  return (N_SAMPLES*_sum_sq - (unsigned long)_sum*_sum) /
76
    (N_SAMPLES*(N_SAMPLES-1));
77
}