Go Down

Topic: Arduino interval per sample read (Read 540 times) previous topic - next topic

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:

Code: [Select]
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?

pert

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.

what I have read was I takes 100us to read an analog input?
Yep, that's about right

Is there a mathematical way to show to they get the 100us?
Please explain what you're asking there.

Is there a way to read the time without using the millis() or micros() function?
Why don't you want to use micros()?

Smajdalf

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.
On 8-bit (i.e. Uno) use "byte" instead of "int" if possible - it is faster and saves resources!

bembe24

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?

GolamMostafa

#4
Mar 13, 2017, 05:33 am Last Edit: Mar 13, 2017, 05:43 am by GolamMostafa
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:

Code: [Select]
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?
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.

1. How long does arduino take to execute a single line of code?
3. 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.

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?
Code: [Select]

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!               



MasterT

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.

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:

Code: [Select]
     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"...

jlsilicon

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

GolamMostafa

#8
Mar 16, 2017, 02:13 pm Last Edit: Mar 16, 2017, 02:23 pm by GolamMostafa
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:

Code: [Select]
     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"...

Quote
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:

Code: [Select]
     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?

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.
On 8-bit (i.e. Uno) use "byte" instead of "int" if possible - it is faster and saves resources!

GolamMostafa

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.
Quote
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.)

6. (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.)

Smajdalf

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.
On 8-bit (i.e. Uno) use "byte" instead of "int" if possible - it is faster and saves resources!

dlloyd

Quote
3. 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)?

GolamMostafa

#13
Mar 19, 2017, 07:39 pm Last Edit: Mar 20, 2017, 06:16 am by GolamMostafa
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.
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.
Quote
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.

Jiggy-Ninja

Code: [Select]
[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.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy