1

I am trying to measure AC power using an Arduino with an Atmega328p. In summary, I want to use timer1 to make an interrupt every 400us where I measure two ADC channels (A0 and A1) and put them into an array. The problem is that instead of measuring five mains periods (mains frequency = 50Hz so 20ms * 5), I get instead 13 of these periods (260ms). What am I doing wrong?

volatile int sample_incremental = 0;
void setup() {
 Serial.begin(115200);
 pinMode(voltagePin, INPUT);
 pinMode(currentPin, INPUT);
 set_sample_interrupt();
 sei();
 }
void set_sample_interrupt() {
 //Count to 400us
 OCR1A = 99;
 //Mode 4, CTC
 TCCR1B |= (1 << WGM12);
 //Enable interrupt
 TIMSK1 |= (1 << OCIE1A);
 //Prescaler 64
 TCCR1B |= (1 << CS11) | (1 << CS10);
}
ISR (TIMER1_COMPA_vect) {
 // action to be done every 400 usec
 current_sample[sample_incremental] = analogRead(currentPin) - 504;
 voltage_sample[sample_incremental] = analogRead(voltagePin) - 512;
 if (sample_incremental < (SAMPLES * PERIODREADS))
 sample_incremental++;
 else {
 //Disable interrupt
 TIMSK1 &= ~(1 << OCIE1A);
 sample_incremental = 0;
 finishedReading = true;
 }
}

Where after I do one reading, I stop the interrupt, and SAMPLES * PERIODREADS = 250.

Glorfindel
5781 gold badge7 silver badges18 bronze badges
asked Jan 1, 2018 at 12:23
3
  • Since you've omitted extremely much of your code, I'll guess that you have not declared the variable "sample_incremental" as volatile. Commented Jan 1, 2018 at 12:39
  • Sorry about that, is has a large portion for computing RMS and real power that is not relevant to the question. Unfortunately that is not the problem as I have declared sample_incremental as volatile. Commented Jan 1, 2018 at 12:40
  • please post a graph of what you expect and what you actually get Commented Jan 1, 2018 at 23:34

1 Answer 1

1

The Arduino core library configures the Timer 1 for phase-correct PWM at about 490 Hz. Then you are setting some configuration bits in the timer's control registers without clearing the bits that had previously been set by the Arduino core. If you want to use the timer for your own purposes, and configure it by yourself, you should completely overwrite the core's configuration with your own. For that, use the = operator rather than |=, as in:

OCR1A = 99; //Count to 400us
TIMSK1 = (1 << OCIE1A); //Enable interrupt
TCCR1A = 0;
TCCR1B = (1 << WGM12) //Mode 4, CTC
 | (1 << CS11) | (1 << CS10); //Prescaler 64
answered Jan 1, 2018 at 23:42
1
  • This is the right answer, I fixed it using " TCCR1A = 0; TCCR1B = 0; TCNT1 = 0;" as a "hack" but your reply goes to the problem. Thank you! Commented Jan 2, 2018 at 11:16

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.