Arduino interval per sample read

Im currently creating a project where I can read the current and voltage reading from a appliance.
Below is the code I used to read the parameters:

void rawdata(){
    sumI = 0;
    sumV = 0;

    for (int n=0; n<1000; n++) {
      sampleVoltage = analogRead(VoltagePin);
      sampleCurrent=analogRead(CurrentPin);
    
      CurrentV = ((sampleCurrent*5.0) /1024);//current   
      VoltageV = ((sampleVoltage*5.0)/1024); // voltage
      
      instVoltage = (VoltageV-2.5)*vin; 
      instCurrent = ((CurrentV-2.5)/0.066);         
      
      sumI += instCurrent * instCurrent;
      sumV += instVoltage * instVoltage;
    }
}
  1. How long does arduino take to execute a single line of code? For the analogRead commands, what I have read was I takes 100us to read an analog input? Is there a mathematical way to show to they get the 100us?

  2. How long does the arduino take to read the rest of the lines? From the CurrentV computations to the sumV computations. Is there a way to read the time without using the millis() or micros() function? Is there a fixed time for the execution time of a single code?

  3. From the sumI and sumV calculations, whats the purpose of multiplying the instCurrent and instVoltage by itself?

bembe24:
How long does arduino take to execute a single line of code?

It depends on the line of code. It could be zero time if the compiler optimizes that line away. It could be months if it's a delay function.

bembe24:
what I have read was I takes 100us to read an analog input?

Yep, that's about right

bembe24:
Is there a mathematical way to show to they get the 100us?

Please explain what you're asking there.

bembe24:
Is there a way to read the time without using the millis() or micros() function?

Why don't you want to use micros()?

Look into ATMega328 datasheet (if using Arduino UNO) at ADC description to get idea how long analogRead takes. 1 ADC read takes 13 ADC clock cycles. ADC should run at 50-200kHz so 13 cycles is 65-260 us.
From C code it is hard to say how long execution takes. You need to look how it is translated to assembly if you need to know.

Based on the code that i posted, Is there a way I can find the time execution per line of code using only the datasheets given not using the experiments like millis() or micros() function?

bembe24:
Im currently creating a project where I can read the current and voltage reading from a appliance.
Below is the code I used to read the parameters:

void rawdata(){

sumI = 0;
    sumV = 0;

for (int n=0; n<1000; n++) {
      sampleVoltage = analogRead(VoltagePin);
      sampleCurrent=analogRead(CurrentPin);
   
      CurrentV = ((sampleCurrent5.0) /1024);//current 
      VoltageV = ((sampleVoltage
5.0)/1024); // voltage
     
      instVoltage = (VoltageV-2.5)*vin;
      instCurrent = ((CurrentV-2.5)/0.066);       
     
      sumI += instCurrent * instCurrent;
      sumV += instVoltage * instVoltage;
    }
}




1. How long does arduino take to execute a single line of code? For the analogRead commands, what I have read was I takes 100us to read an analog input? Is there a mathematical way to show to they get the 100us?

2. How long does the arduino take to read the rest of the lines? From the CurrentV computations to the sumV computations. Is there a way to read the time without using the millis() or micros() function? Is there a fixed time for the execution time of a single code?

3. From the sumI and sumV calculations, whats the purpose of multiplying the instCurrent and instVoltage by itself?

bembe24:
VoltageV = ((sampleVoltage*5.0)/1024); // voltage

Why is the divisor 1024 instead of 1023?

  1. The Full Scale of the ADC is 5V (assuming Vref = AVcc = 5V). It is a 10-bit ADC.
  2. (a) So, when the input voltage is 0V; the ADC produces 0b00000000 = 0
    (b) When the input voltage is 5V; the ADC produces 0b11 1111 1111 = 1024 - 1 = 1023.
    (c) When the input voltage is Vin (Sample Voltage); the ADC will produce (5/1023)*Vin.

bembe24:

  1. How long does arduino take to execute a single line of code?
  1. Execution Time of an instruction can best be computed from ASM Coding. For example: Reading
    Low Byte of ADC -
    (a) ASM Code: in r16, ADCL

(b) Binary Code (Mavhine Code): b104 ; 16-bit executable Opcode

(c) Flash Memoy (Code memory) is Word (16-bit) organized.

(d) Atmel says that most of the AVR instructions take 1-CLK period for execution. (I assume that
it includes: Instruction fetching time from flash, internal decoding time, and then actual reading
ADCL data fom prot address 04h.)

(e) In ArduinoUNO ATmega runs at 16 MHz (Period: 0.0625 uS).

(f) So, the execution time of the instruction (a) : 0.0625 uS.

bembe24:
For the analogRead commands, what I have read was I takes 100us to read an analog input? Is there a mathematical way to show to they get the 100us?

4. analogRead(0) function, as I have understood for myself, consists of:
   (a) Channel selction via ADMMUX :            in      r16, ADMUX   
                                                              andi       r16, 0b11110000
                                                              out    ADMUX, r16
   (b) Start the ADC (single conversion):        in      r16, ADCSRA
                                                              ori     r16, 0x40
                                                              out     ADCSRA, r16
   (c) Check if conversion complete:      LC:    in      r16, ADCSRA    ; by polling ADIF flag bit
                                                              rol      r16
                                                              rol      r16
                                                              rol      r16
                                                              rol      r16
                                                              brcc    LC
    (d) Clear ADIF flag bit:                           in      r16, ADCSRA
                                                              ori     r16, 0x10
                                                              out    ASCSRA
    (e) Read ADCL:                                     in      r16, ADCL

         Read ADCH:                                    in      r17, ADCH
                                                              
5. According to my calculation, the execution time for the function analogRead(0):                                  17 (number of Single Word instructions in Step-4) x 0.0625 uS =  1.0625 uS!

If I understand correctly, you need to know timing to define sampling frequency. Change your approach, set sampling period precise, by switching adc to free running mode, or using TimerOne library. Than you don't care how long takes code inside main loop.

The time to read a sample from the A-D converted is dominated by the speed of the conversion; actual instruction timing is mostly irrelevant, because the code looks like:

     start_conversion()
     while (conversion_not_complete())
         ;  // Do nothing but wait
     read_conversion_result();

(You can see the actual code here: https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_analog.c#L77)

The ADC initialization code is what determines how fast the A2D goes (within its limits.) It says 125kHz - 8 us per clock, or ... just about 100us for the full 13 clocks needed for a conversion.

There have been numerous discussions on using faster clocks (resulting in quicker conversion with less precision, apparently.) Google "Arduino analogread speed"...

If you skim to the bottom in the following posting below,
it is explained how to get High-Speed using the Arduino with the ADC ,

such as 120KHz to 500Khz at 10bits resolution.

  • I use it myself.

https://forum.arduino.cc/index.php?topic=418989.6

westfw:
The time to read a sample from the A-D converted is dominated by the speed of the conversion; actual instruction timing is mostly irrelevant, because the code looks like:

     start_conversion()

while (conversion_not_complete())
        ;  // Do nothing but wait
    read_conversion_result();



(You can see the actual code here: https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_analog.c#L77)

The [ADC initialization code](https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring.c#L353) is what determines how fast the A2D goes (within its limits.) It says 125kHz - 8 us per clock, or ... just about 100us for the full 13 clocks needed for a conversion.

There have been numerous discussions on using faster clocks (resulting in quicker conversion with less precision, apparently.) Google "Arduino analogread speed"...

full 13 clocks needed for a conversion.

  1. The following C codes, posted by you, after compilation (as I have understood) produces about 13
    lines of ASM codes. These codes take about 13 clock cycles for execution:
     start_conversion()
    while (conversion_not_complete())
        ;  // Do nothing but wait
    read_conversion_result();

   ASM Codes:
   
   (a) Start the ADC (single conversion):        in      r16, ADCSRA
                                                             ori     r16, 0x40
                                                             out     ADCSRA, r16
   (b) Check if conversion complete:      LC:   in      r17, ADCSRA    ; by polling ADIF flag bit
                                                             andi    r17, 0b00010000
                                                             ldi       r16, 0x10
                                                             cp       r17, r16
                                                             brne    LC
   (c) Clear ADIF flag bit:                           in      r16, ADCSRA
                                                             ori     r16, 0x10
                                                             out    ASCSRA
   (d) Read ADCL:                                     in      r16, ADCL

        Read ADCH:                                    in      r17, ADCH

[\code]

2. (a) Considering lowest clock frequency of 32 KHz for ATmega328, the execution time: 
         13x(1/32000) = 406 uS
    (b) Considering standard frequency of 16 MHz (ArduinoUNO), the execution time: 
         13x(1/16000000) = 0.8125 uS
    (c) Considering highest frequency of 20 MHz for ATmega328, the execution time: 
         13x(1/20000000) = 0.65 uS

3. ATmega328 data sheet says that the ADC conversion time: 13uS - 260 us.

4. Time f Step-3 does not match with Time of Step-2.

5. why is this so?

Conversion itself takes 13 ADC_clock cycles. They are generally slower than main clock (should be 50-200 kHz for 10 bit accurancy). Waiting for the conversion is hidden in (b) last line: BRNE LC.

Smajdalf:
Conversion itself takes 13 ADC_clock cycles. They are generally slower than main clock (should be 50-200 kHz for 10 bit accurancy). Waiting for the conversion is hidden in (b) last line: BRNE LC.

They are generally slower than main clock (should be 50-200 kHz for 10 bit accuracy).

  1. Thanks for the quoted information which has led me to calculate the ADC conversion time of ATmega328
    in an authentic way:

  2. External crystal frequency of ArduinoUNO: 16 MHz.

  3. ATmega328 of ArduinoUNO has come with CKDIV8 Fuse programmed.
    (Ref: System Clock Prescaler-P60 of data sheets.)

  4. Now, the system clock frequency CLK = 16 MHz/8 = 2 MHz

  5. (a) Let us take 125 KHz for clkADC.
    (200 KHz could not be taken due to division factor limitation of ADC Prescaler - P308 of data sheets.)

(b) The prescaling factor of the ADC: 16.
(Ref: Prescaling and Conversion Timing-P308 of data sheets.)

(c) Conversion time of ADC: 13 x (1/125 K) = 104 uS. (It is within: 13uS - 260uS.)

  1. (a) Let us take 62.50 KHz for clkADC.
    (50 KHz could not be taken due to division factor limitation of ADC Prescaler - P308 of data sheets.)

(b) The prescaling factor of the ADC: 32.
(Ref: Prescaling and Conversion Timing-P308 of data sheets.)

(c) Conversion time of ADC: 13 x (1/62.50 K) = 208 uS. (It is within: 13uS - 260uS.)

GolamMostafa:
3. ATmega328 of ArduinoUNO has come with CKDIV8 Fuse programmed.
(Ref: System Clock Prescaler-P60 of data sheets.)

Fuses must be changed for Arduino Uno (default clock source is internal RC oscillator, not external ceramic resonator) and it runs at 16MHz without prescaling. Otherwise your calchlations look fine.

  1. From the sumI and sumV calculations, whats the purpose of multiplying the instCurrent and instVoltage by itself?

Yeah, I'm wondering too. Where'd you get the code from?
V2 and I2 are useful for calculating power in resistive DC circuits, but I think this is AC.
No mention of measuring phase angle between V and I, so I guess apparent power (VA) is what you're after?
Or perhaps energy (VAh)?

Smajdalf:
Fuses must be changed for Arduino Uno (default clock source is internal RC oscillator, not external ceramic resonator) and it runs at 16MHz without prescaling. Otherwise your calchlations look fine.

Smajdalf:
Fuses must be changed for Arduino Uno (default clock source is internal RC oscillator, not external ceramic resonator) and it runs at 16MHz without prescaling. Otherwise your calchlations look fine.

and it runs at 16MHz without prescaling.

  1. Forum members are also saying that the CKDIV8 Fuse is not programmed.
    (EFuse = 0x05, HFuse=0xDE, and LFuse = 0xFF).

  2. If ATmega328 of ArduinoUNO is running at 16 MHz, the ADC conversion time range:
    13 uS - 104 uS (ADC Clock prescaler: 1/16 and 1/128).

  3. Thanks for the feedback.

[quote author=GolamMostafa link=msg=3173156 date=1489379626]                                                           
5. According to my calculation, the execution time for the function analogRead(0):                                  17 (number of Single Word instructions in Step-4) x 0.0625 uS =  1.0625 uS!

[/quote]
The first problem is that not all instructions take 1 clock cycle. The datasheet's instruction set reference will tell you exactly how long each statement will take. A small detail.

The second problem is the statements themselves. You see that brcc line? That means Branch if Carry Cleared. It is a conditional instruction, so evaluating how long the function takes is not just a matter of summing up all the lines. It branches to a line above it (to LC:), so that also means it is a loop. How long the function takes will depend on how many times that brcc statement branches back to the LC: label.

How many times does it branch? That's the interesting question, isn't it.

Jiggy-Ninja:

The first problem is that not all instructions take 1 clock cycle. The datasheet's instruction set reference will tell you exactly how long each statement will take. A small detail.

The second problem is the statements themselves. You see that brcc line? That means Branch if Carry Cleared. It is a conditional instruction, so evaluating how long the function takes is not just a matter of summing up all the lines. It branches to a line above it (to LC:), so that also means it is a loop. How long the function takes will depend on how many times that brcc statement branches back to the LC: label.

How many times does it branch? That's the interesting question, isn't it.
[/quote]

  1. Data sheets (P433) says: brcc takes 1/2 cycles. As I have learnt - the control will take 1 cycle time to
        move to the direction where the condition is satisfied; the other direction will take 2 cycles.

  2. The brcc LC is certainly a loop. How many times will it branch? I never thought about it - thinking now!
        In fact, what we see in the from of ASM (C) instructions, they are the timing functions of the 'State
        Machines' within the microcontroller/microprocessor engaged in the propagation of information across
        high speed gates and flip-flops. So, number of branching could be approximated to a one-dimensional
        negligible time like sin& ----> &.

  3. Anyway, thanks for bringing forward a thought provoking issue which we find very rarely in a Public
        Forum - a conglomerate of Merchants.

GolamMostafa:
So, number of branching could be approximated to a one-dimensional
negligible time like sin& ----> &.

What? If you want (or are not careful) you can stay in a loop forever. Eternity is negligible for you?

Smajdalf:
What? If you want (or are not careful) you can stay in a loop forever. Eternity is negligible for you?

You are right; but, I have assumed that the conversion will come to an end shortly and the loop will be stopped.

No. Waiting for conversion to finish takes most of the time if main clock is 16 MHz and you want to stay in specs to maintain 10 bit resolution.