arduino speed

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello guyss

 

I wanna check if I could use arduino in a specific high speed application (arduino should sense a voltage and output a control action every 13 micro seconds) so I called the function micro at the beginning and end of the loop and found that it takes around 200 microseconds ..Is this time large or is it wrong to use micros .. I am starting to wonder if the arduni is really that slow or there is another way to check its speed. I tried to get the speed if excuting one instruction by doing the following simple code

and it truned out that Arduino Takes 4 useconds to execute one instruction line

 

byte x=1;
byte y=2;
byte z=0;
unsigned long time=0.0;
unsigned long time1=0;
void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
}

void loop() {

  time=micros();
  z=x+y;
  time1=micros();
  Serial.println(time1-time);

}

time take sto execute one instruction

Last Edited: Sat. Oct 28, 2017 - 08:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the correct image

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry the first image is not the right image. this 2nd one is what i got from teh serial monitor when running the attached code

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what do you mean by duplicate?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Arduino generally runs at 16MHz so it executes one opcode cycle in 1/16,000,000 s that is 62.5ns. If you look at the AVR opcode manual:

 

The ADD opcode takes 1 cycle. So it can execute in one sixteen millionth of a second (62.5ns).

 

However that does not mean that:

  z=x+y;

will necessarily take that. This probably has to fetch x and y from RAM (LDS) and then store the result to z (STS). Each of those are 2 cycles so that's another 6 cycles in addition to the one for the ADD. So I would expect this to execute in 7 cycles ior 7 * 62.5ns = 437.5ns which is roughly 0.5us

 

Of course you are using Arudino that has all kinds of interrupts running and it's not exactly known for the efficiency of its code so maybe some time during those 7 cycles (maybe even several times) it could be vectoring off to interrupt handlers and performing 100's of cycles.

 

The solution would be to cli() before the operation and sei() after so it cannot be interrupted. However the micros() thing itself relies on interrupts - in fact it could be a large part of what is skewing your timing here! So with cli() you will probbaly find that time and time1 are much closer.

 

A better idea would be to run a timer (not the one the Arduino system uses itself) and clear it before the operation then read it after. Be warned that even clearing and reading will take some cycles which must also be accounted for.

 

Best bet is to look at a dissassembly of the code to find out exactly what opcode sequences are involved.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AVRFreak david.prentice shared a nice Arduino code timming platform (thanks) in this post: http://www.avrfreaks.net/comment...

It's the attachment named fpbench_uno.zip, you just need to modify it to suit your code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For the kind of "process control" you seem to be trying, what I would do is hardware PWM. Then, you only need (maybe) a new PWM value once every PWM cycle. You would also probably want one of the AVRs with fast PWM (PLL for clock multiplication). There is at least one of the ATtiny devices that is specifically designed for this service.

 

So, lets run the numbers. Suppose 16MHz MCU clock, and an 8-bit timer with clock prescale of 1. This would give you 256 possible control states (in reality, probably 254, ignoring duty cycles of exactly 1 and exactly 0). The PWM output would have a repetition frequency of 16MHz/256 = 62.5KHz (period = 16us) and a resolution of 62.5ns (1 MCU clock cycle). This is actually much faster than the built-in ADC and it is probably faster than most external ADCs accessed serially. You would also have much longer to process the ADC output value.

 

The point of this is that there are several strategies that are available to you. One of the important learned skills in engineering design is figuring out how to choose a "solution" that actually fits the problem AND fits the technologies that are available to you.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The code that I want it to be excuted super fast has already an interrupt 

what i am doining in this code is that I am putting the ADC in free running mode and whenever an interrupt occurs I read the value of the ADCW and calculate teh control action according to the error and ouput a duty .


int sample=0;
byte duty=0;

int Vout=0;
int current_error=0;

byte duty_action=0;
byte prev_duty_action=0;

int previous_error=0;

int M=1071;  //multiply by 10^(-3)
int  N=920; // multiply by 10^(-3)
int L=987; //multiply by 10^(-3)

unsigned long time1=0;
unsigned long time2=0;


                                                                                              
ISR(ADC_vect)
{
  cli();
  
  sample=ADCW;
  
  Vout=sample*(5000/1023); // milli volt
  
  current_error=5000-Vout; //millivolt

if(current_error==0)
{
  duty=160;
}
else
{

duty_action=(M*current_error)-(N*previous_error)+(L*prev_duty_action)*(10^(-3)); //3ashan el constants

duty=duty_action*(160)*(10^(-3))*100; //ashan darbna fi alf //fi meya ashan lw 0.6 tb2a 60%

}

if((duty/100)>160)
{
  duty=160;
}

custom_Awrite(duty);
previous_error=current_error;
prev_duty_action=duty_action;
}

void setup() {
  Serial.begin(115200);
 
   TCCR1A=(1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (1<<COM1B0) | (0<<COM1C1) | (0<<COM1C0) | (0<<WGM11) | (0<<WGM10); // WGbits determine the mode
                                                                                                                   // COM bits determine inverted or not                                                                                                                   //  1 1= inverting but 1 0= non inverting
   TCCR1B=(0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);   //CS=clock source 16 mhz //ICN=input canceller noise :off

   TCNT1H=0x00; // timer 1

   TCNT1L=0x00; //timer 1 

   ICR1H=0x00;
   ICR1L=0xA0; //top=160 decimal 

   pinMode(11,OUTPUT);


   DIDR0 |=(1<<DIDR0);                           
   
   ADMUX |= (1<<ADLAR)|(1<<REFS0)|(0<REFS1);
   
   
   ADCSRB|=(0<<ADTS0)|(0<<ADTS1)|(0<<ADTS2);
 
   ADCSRA |=(1<<ADATE);  
   ADCSRA |=(1<<ADIE);
   
   ADCSRA |=(0<<ADPS0)|(0<<ADPS1)| (1<<ADPS2);  
   
   ADCSRA |= (1<<ADSC);      //Starts a new conversion
   
 
}


void custom_Awrite(byte duty) 
{

 OCR1AH=0x00;
 OCR1AL=duty;
 
}

void loop() {
  // put your main code here, to run repeatedly:

}
Last Edited: Fri. Oct 27, 2017 - 07:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

what do you mean by duplicate?

He means that you have 2 posts about the same thing one here and another about the same thing in the megaAVR and tinyAVR forum! Don't do that!

 

The Arduino speed depends on how hard you throw them.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don't need

cli();

Interrupts are automatically disabled when entering the ISR. Also. 5000/1023 is 4 in your code due to integer math, probably not what you want, you need to remove the parenthesis. Just use

sample * 1250UL / 256

it makes your life simpler and math faster because divide by 256 is just a byte shift.

But anyway, this math done correctly will still be expensive, there will be a 16x16 bit multiply. If you want absolute speed, you should do a lookup table with all 1024 values from 0 to 5000. It will take 2Kb, but that's the usual trade-of: memory for speed.

Last Edited: Fri. Oct 27, 2017 - 08:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In free running mode, the maximum possible internal ADC rate is 16K samples per second at 10 bits resolution. Thus, the absolute fastest that your feedback loop can update is once every 62.5 microseconds. That is hardly ultra-fast!

 

Adding interrupt, in this case, will NOT slow the sample rate, only adds delay between the already slow analog conversion and the feedback. So long as the sum of the interrupt response time (latency plus time spent executing the interrupt) and the added signal processing takes no more than 62.5us, it only adds to the delay. Once the response plus processing time exceeds that, you start missing ADC conversions. Also, do not overlook the fact that there is a lot of context saving and restoring (that is invisible in your code) for interrupts. There is also a latency time between the assertion of the interrupt and when the interrupt begins executing. So, even the simplest interrupt might take longer (maybe a lot longer) than you expect.

 

Also be aware that there is, already, a built in delay between the value being measured and the result. The ADC samples the analog value at the beginning of the conversion. At its fastest possible clock rate, the answer is ready 62.5 microseconds later. The interrupt will begin processing a bit more than a half microsecond after that (depending on the instruction that was being executed when the interrupt turned on). Signal processing might add another few microseconds. So, you are probably around 70 microseconds delay between when the analog value is sampled and when you CAN update your control loop.

 

Adding any debugWrite() will slow it even more, possibly by milliseconds (depending on baud rate).

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Fri. Oct 27, 2017 - 08:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The Arduino speed depends on how hard you throw them.

:)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For reasons that are not entirely clear OP has chosen to split this to a second thread:

 

http://www.avrfreaks.net/forum/u...

 

So this one locked. 

Topic locked