Go Down

Topic: record analogvoltage after emission of pulses (Read 126 times) previous topic - next topic


Hello guys ,

So lets explain my situation .

I send 10 pulses with the duty cycle increasing each pulse , on an interupt based event each 4.16 second.

After the emission of the 1st pulse i want to start mesuring the voltage on a condensator that will receive the energy. I want to have a sample rate ADC of 10khZ and stream the value on the serial port until lets say 100ms after the emission of the last pulse.

I wanted to do it with an interupt but i discover that the analogread function itself is an interupt and can't work on an isr.

SO i don't really know how the algorithm should work in this example for the ADC recording and streaming on the serial port .

Does somone here had to do something similar in the past and can help me ?

Thank to all of you guys.


Code: [Select]
 Name: testinterupt.ino
 Created: 07/12/2017 18:18:41
 Author: Houbix

// the setup function runs once when you press reset or power the board
#include <eRCaGuy_Timer2_Counter.h>
#include <digitalWriteFast.h>

volatile int frequence=10000;

unsigned long timeelapsed;

void setup() {
TCCR3B = 0;                //stop the timer
TCCR3A = 0;
TIFR3 = 0xFF;              //ensure all interrupt flags are cleared
OCR3A = 65000;
OCR3B = 65000;//timer runs at 16MHz / 65000 / 1024 (prescaler) = 4.16s period
TCNT3 = 0;                           //clear the timer
TIMSK3 |= (1<<OCIE3B)|(1 << OCIE3A);                //enable timer interrupts
TCCR3A |= (1<< COM3A1)| (0<< COM3A0) | (0 << COM3B1) | (1 << COM3B0) | (0 << WGM31) | (0 << WGM30);
TCCR3B |= (0 << WGM33) | (1 << WGM32) | (1 << CS32) | (1 << CS30); // 1024 // ctc
pinMode(5, OUTPUT);
pinMode(2, OUTPUT);
pinMode(10, OUTPUT);


// the loop function runs over and over again until power down or reset
void loop() {
while (1)

void timer1init()
TCCR1B = 0;                //stop the timer
TCCR1A = 0;
TCCR1B |=  (1 << WGM12) | (1 << CS12) ; // 256 prescale ctc activated
OCR1A = 10;
TIMSK1 |=  (1 << OCIE1A);
ISR(TIMER1_COMPA_vect)// 6250 hz interupt for adc sampling beacuse 10 khz is a lot i think

// code to read the adc value and stream it
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));


ISR(TIMER3_COMPB_vect)// interuption toute les 4.16 sec

//digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));

frequence = frequence + 5000;

if (frequence >= 50000)
frequence = 10000; // reset la frequence si jamais on depasse 50KHZ

float period = 1000000 / frequence;
float  tempsON[11];
float tempsOFF[11];

for (int i = 1; i <= 10; i++)// remplis prealablement le tableau des valeurs TON et TOFF
tempsON[i] = 0.1*i*period;
tempsOFF[i] = period - 0.1*i*period;

for (int i = 1; i <= 10; i++) // envoi des 10 pulse
unsigned long previousT = timer2.get_count();// reinitialise les timer pour avoir un bon délai
digitalWriteFast(10, HIGH);
unsigned long currenT = previousT;
timeelapsed = 0;

while (((float)timeelapsed)<(tempsON[i])) // delai TON
currenT = timer2.get_count();
timeelapsed = (int)(currenT - previousT) / 2;

unsigned long previousT2 = currenT;
digitalWriteFast(10, LOW);
unsigned long currenT2 = previousT2;
timeelapsed = 0;

while ((float)timeelapsed<tempsOFF[i]) // delai TOFF
currenT2 = timer2.get_count();
timeelapsed = (int)(currenT2 - previousT2) / 2;




You can get 10-bit A/D conversions at up to 15 kHz so your 10 kHz requirement is possible.  The easiest way to get a rapid series of samples is to put the A/D in Free Running mode.  You'll get an interrupt every 13.5 A/D clock cycles.  Your main limitation will be the choice of clock rates. The only rate close to what you want is 9259.259... samples per second (16 MHz / 128 prescale / 13.5 cycles per sample).

Remember that if you want to send 4 digits and a separator 10,000 times per second you need to send 50,000 characters per second.  That will require over 500,000 baud serial communication.  You may want to check that your hardware can achieve that first.

If your serial line can't sustain 500,000 baud you should probably add something like an FRAM or EEPROM chip to buffer the data.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp


Why do you feel you need a timer interrupt for something that's happening every 4 seconds?  Interrupts are for things too fast for code.  Also, you've got WAY too much code in that second ISR and a busy wait which is a huge no-no in an ISR.

I wanted to do it with an interupt but i discover that the analogread function itself is an interupt and can't work on an isr.
Where did you hear that?  It isn't true.  There is an interrupt you can use to be notified when a conversion completes in free running mode, but analogRead has a busy wait until the conversion is done.  It does not use any interrupt and will work just fine in an ISR.

If at first you don't succeed, up - home - sudo - enter.


Code: [Select]
// the loop function runs over and over again until power down or reset
void loop() {
while (1)
So you take the whole Arduino framework designed to make it easy and efficient to write good code and put it aside?

10KHz is pretty fast for an Arduino. Without messing with more registers, that is as fast as you can go on the common 16MHz Arduinos. Note: you didn't tell us which Arduino you have. Maybe you have one of the faster ones?

The trick is to work out how much data you must send and how quickly. Do you know how to calculate this?

Then do it without using interrupts.
"The problem is in the code you didn't post."

Go Up