Project

General

Profile

Revision cbda92cc

IDcbda92ccdd16fe3b4be2d2e4e511098c0070ecbf
Parent 036b4f9a
Child f4df665c

Added by Thomas Mullins about 11 years ago

Untested current RMS calculation

It's not actually RMS, it's variance. Same general idea.

View differences:

toolbox/current.c
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_SAMPLES-1));
28 99
}
toolbox/current.h
2 2
#define CURRENT_H
3 3

  
4 4
void current_init();
5
int current_read();
5
unsigned int current_read();
6 6

  
7 7
#endif

Also available in: Unified diff