Project

General

Profile

Statistics
| Branch: | Revision:

root / toolbox / current.c @ f15d9227

History | View | Annotate | Download (1.85 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

    
37
  /*
38
   * ADLAR = 0, right adjust result
39
   * ADTS = 5, start on timer 1 compare match B
40
   */
41
  ADCSRB = _BV(ADTS2) | _BV(ADTS0);
42

    
43
  /*
44
   * ADEN = 1, enable
45
   * ADSC = 0, don't start yet
46
   * ADATE = 1, auto trigger
47
   * ADIE = 1, enable interrupt
48
   * ADPS = 6, prescale clock by 64
49
   */
50
  ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1);
51
}
52

    
53
ISR(ADC_vect) {
54
  unsigned int old, new;
55

    
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
  new = ADC;
61

    
62
  /* put sample into ring buffer */
63
  old = samples[sample_idx];
64
  samples[sample_idx++] = new;
65
  if (sample_idx == N_SAMPLES)
66
    sample_idx = 0;
67

    
68
  /* keep a running total of samples and samples squared */
69
  sum += new;
70
  sum -= old;
71
  sum_sq += (unsigned long)new*new;
72
  sum_sq -= (unsigned long)old*old;
73
}
74

    
75
unsigned int current_read() {
76
  unsigned int _sum;
77
  unsigned long _sum_sq;
78

    
79
  cli();
80
  _sum = sum;
81
  _sum_sq = sum_sq;
82
  sei();
83

    
84
  /* calculate the variance using sum and sum_sq */
85
  return (N_SAMPLES*_sum_sq - (unsigned long)_sum*_sum) /
86
    (N_SAMPLES*(N_SAMPLES-1));
87
}