 # Speed up arduino

Correct.
But since I didn’t see any code to help you/us analyse the speed of the code, I thought I’d just add that comment.

hong89: I check the sampling rate by setting high and low at one of the digital pin and monitor with scopemeter.

Oh? I don't see that part. Nor do I see any data declarations.

Look, if it takes a week or two to get any code out of you we will get bored. This is the Programming Questions section. You are supposed to post code, and ask questions about it. Not just "I have some code ... why doesn't it work?".

`````` digitalWrite (10, state);
``````

Where do you set pin 10 to be output?

Where do you set pin 10 low again? What does that line achieve?

``````  A = digitalRead(22);

if(A==1 && a1!=A)
{
if(B==1)
{
p=p-1;
a1=1;
b1=1;
}
count=p;
}

if(A==1 && a1!=A)
{
if(B==0)
{
p=p+1;
a1=1;
b1=0;
}
count=p;
}

if(A==0 && a1!=A)
{
if(B==1)
{
p=p+1;
a1=0;
b1=1;
}
count=p;
}

if(A==0 && a1!=A)
{
if(B==0)
{
p=p-1;
a1=0;
b1=0;
}
count=p;
}
``````

I check the sampling rate by setting high and low at one of the digital pin and monitor with scopemeter.

I still don't see where you are doing that.

I do it in the loop toggle after finished each loop.

``````void loop()
{

digitalWrite (10, state);    //here the code set digital pin 10 to high

Position_Count();
Force();
Flow_Control(2);

Correction(fsrForce, count, corr_Start);

if (Regler_Start == 0)
{
int f = 0-10*25;
Pos_SetValue(353.81,3.8095,22.8571);

Force_SetValue(f);
Potential();
Virtual_System(0.099048,0.2,0,-0.04,150);
}
else
{

}

state =!state;     // toggle the state of out put from digital pin 10 high and low
}
``````

For the A, B is the AB signal from hall sensor. use to count the step of the motor.[quote author=Nick Gammon

Look, if it takes a week or two to get any code out of you we will get bored. This is the Programming Questions section. You are supposed to post code, and ask questions about it. Not just "I have some code ... why doesn't it work?". [/quote]

So in the beginnning I only ask if there any code or method ro replace analogRead() and mapping or division which allow the arduino run faster.

So in the beginnning I only ask if there any code or method ro replace analogRead() and mapping or division which allow the arduino run faster.

If you look at the source of "analogRead", you'll see it breaks down into four distinct sections: 1) Select input 2) start conversion 3) wait for end of conversion 4) read and return result of conversion Of these, 3) takes by far the largest amount of time, around 100 microseconds, and it's a busy-wait, so the processor isn't doing anything else apart from responding to interrupts. It's fairly simple to separate steps 1) and 2) and then go off and do something useful until you need to read the result.

Digital pins default to input, so what you are doing is toggling the pullup resistor for pin 10.

I have a suggestion.

Set up some debugging pins. Make them outputs (unlike pin 10).

Toggle them at the start of various functions. Then you can see (with a logic analyzer) what is taking the most time.

You can do 10000 analogRead in one second, so that hardly accounts for a throughput of 120.

dxw00d: Digital pins default to input, so what you are doing is toggling the pullup resistor for pin 10.

Thanks for the remind =)

[quote author=Nick Gammon link=topic=101224.msg763060#msg763060 date=1334645784] Set up some debugging pins. Make them outputs (unlike pin 10). [/quote]

Sorry that, may I know how to set up the debugging pins?

I have use simple code as below, without the analogRead(0), the output frequency from pin 10 is 57kHz, after add in the analogRead(0), the frequency become 4kHz left. So what is the reason behind that slower the output frequency?

``````int state;

void setup()
{
Serial.begin(9600);

state = HIGH;
pinMode(10, OUTPUT);

}

void loop()
{

digitalWrite (10, state);

state =!state;
}
``````

Thanks for the help.

Regards

So what is the reason behind that slower the output frequency?

I'd expect more like 8kHz, but an analogRead takes (from my memory) around 104us, most of it, as I've already said, is spent in a busy-wait for the end-of-conversion. digitalWrite is also quite slow, but still doesn't quite account for the 4kHz vs 8kHz expected.

You are mis-interpreting the results.

Making your sketch a bit more efficient, to rule out problems with digitalWrite:

``````byte state;

void setup()
{
state = HIGH;
pinMode(10, OUTPUT);
}

void loop()
{
if (state)
PORTB |= _BV (2);
else
PORTB &= ~_BV (2);
state =!state;
}
``````

Results: Certainly the frequency is 4.46 kHz, but the width of one pulse is 112 uS (see above).

This is because it takes two toggles of pin 10 to provide a single period. So the "frequency" is actually two analog reads, not one.

Now considering the advertised time for analogRead is 100 uS, and the measured time is 112 uS, the extra can be accounted for by the time for the toggling of the pin, the loop, and the if test. Plus analogRead has a certain amount of overhead translating the pin number to a hardware port. But still, it isn't too far off (12 uS) predicted times.

Hi, currently my program is too slow(120Hz) ...

4.46 8.92 kHz (because you double it) is a lot faster than 120 Hz. In fact 37 74 times as fast. Having said that, floating point maths is slow, this is an 8 bit integer processor.

(edited to allow for the fact that you do two conversions per period).

The ADC converter takes 13 ADC clock cycles where each one is 1/125000 seconds, so it has to take 104 uS, as AWOL said. My measured time of 112 uS is in fact only 8 uS more than that.

According to the datasheet:

By default, the successive approximation circuitry requires an input clock frequency between 50 kHz and 200 kHz to get maximum resolution. If a lower resolution than 10 bits is needed, the input clock frequency to the ADC can be higher than 200 kHz to get a higher sample rate.

So you could change the prescaler if you don't mind a lower resolution. But I would be looking elsewhere, since there is a big difference between being able to do analogReads at a rate of 8.92 kHz and your reported throughput of 120 Hz.

Thanks a lot for the information.

Now I have frequency of 1.2kHz with three analog input and two digital input.

In before I notice that just 120Hz is because I had put "Serial.print" in the program. After take out the serial print to the serial monitor, it getting faster.

In the other case, I have to connect an ethernet shield to my mega 2560, with that I worry that in the end the sampling rate for the system will go below 1kHz.This is the reason I would like to use ADC in my project.

In the other case, I have to connect an ethernet shield to my mega 2560, with that I worry that in the end the sampling rate for the system will go below 1kHz.This is the reason I would like to use ADC in my project.

If the goal is to send the data to another computer, send raw data and let the other computer do the number crunching. Presumably, you won't be sending data to something slower than an Arduino.

What you can do is combine some of the ideas presented here. First, do the analog reading with an interrupt, that way you can be processing the data and sending the result while you are taking the next one.

``````const byte adcPin = 0;

void setup ()
{
Serial.begin (115200);
// set the analog reference (high two bits of ADMUX) and select the
// to 0 (the default).

}  // end of setup

{
byte low, high;

// cause the results of each conversion to be discarded,

void loop ()
{
// if last reading finished, process it
{
}

// if we aren't taking a reading, start a new one
{
// start the conversion
}

}  // end of loop
``````

This code was run on a Uno, not a Mega2560.

The above sketch does a non-blocking analog conversion (Pin A0 in this case). When complete it uses Serial.write to send the two bytes (high byte, low byte) to the computer.

As you can see here: The bytes are being sent as fast as they can (once every 170 uS). Since 115200 baud takes 1/11520 seconds per byte (86.8 uS) then this is what you expect. The analog conversions take 104 uS each, so they can fit inside the time needed to send 16 bits to the computer.

Now as PaulS suggested, do all your calculations on the computer (not the Arduino) so you don’t slow down the sampling rate. You can see that you would have a maximum of about 66 uS to do calculations before you started to slow it down.

This gives you a sampling frequency of 5.88 kHz, which is faster than your requirements (1/.000170).

Hi Nick Gammon,

Sorry that I’m not understand about the code

Here is my original code,

``````int fsrPin = 0;     // the FSR and 10K pulldown are connected to a0
int fsrVoltage;     // the analog reading converted to voltage
unsigned long fsrResistance;  // The voltage converted to resistance, can be very big so make "long"
unsigned long fsrConductance;
long fsrForce;       // Finally, the resistance converted to force

void setup(void) {
Serial.begin(9600);   // We'll send debugging information via the Serial monitor
}

void loop(void) {

// analog voltage reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
fsrVoltage = map(fsrReading, 0, 1023, 0, 5000);
Serial.print("Voltage reading in mV = ");
Serial.println(fsrVoltage);

if (fsrVoltage == 0) {
Serial.println("No pressure");
} else {
// The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
// so FSR = ((Vcc - V) * R) / V        yay math!
fsrResistance = 5000 - fsrVoltage;     // fsrVoltage is in millivolts so 5V = 5000mV
fsrResistance *= 10000;                // 10K resistor
fsrResistance /= fsrVoltage;
Serial.print("FSR resistance in ohms = ");
Serial.println(fsrResistance);

fsrConductance = 1000000 / fsrResistance;           // we measure in micromhos so
Serial.print("Conductance in microMhos: ");
Serial.println(fsrConductance);

// Use the two FSR guide graphs to approximate the force
if (fsrConductance <= 100)                  //range 0-2N
{
fsrForce = fsrConductance / 20;
Serial.print("Force in Newtons: ");
Serial.println(fsrForce);
}

else
{
fsrForce = fsrConductance / 50;                //range 80N-100N
Serial.print("Force in Newtons: ");
Serial.println(fsrForce);
}

}
Serial.println("--------------------");
delay(1000);
}
``````

How can I combine the code as given by you?

There's very little point speeding-up that code; you're spending far longer transmitting serial characters than you are converting analogue inputs. (One bit at 9600 bps takes about the same as a single A/D conversion)

Now as PaulS suggested, do all your calculations on the computer (not the Arduino) so you don't slow down the sampling rate. You can see that you would have a maximum of about 66 uS to do calculations before you started to slow it down.

I'm just using arduino to deal with the calculation without computer help

I had combine some code form ethernet shield and add in the code from AWOL from another discussion(http://arduino.cc/forum/index.php/topic,101718.msg763256.html#msg763256), when without signal read in, the sampling rate is 888Hz, with the signal read in the sampling rate drop to 780Hz.

So if I use another ADC to deal with the analog signal and using only the digitalRead() of the arduino, this will increase the sampling rate right? (but I'm not familiar on how to give the clock input for the ADC)

Many thanks~~~

You are still concentrating on the wrong parts of your code. You can speed up communications, making it 12 times faster, by changing the 9600 baud rate to 115200. Your maximum sampling rate is going to be impacted far more by the stupid delay(1000) in the code than by the few nanoseconds the ADC takes.

Your maximum sampling rate is going to be impacted far more by the stupid delay(1000) in the code than by the few nanoseconds the ADC takes.

I think, to be fair, that's a hundred thousand or so nanoseconds

I think, to be fair, that's a hundred thousand or so nanoseconds

True. but OP wants to shave time off that, while keeping the slow baud rate and humongous delays.

It's like cutting the handle off a toothbrush before putting it in the backpack next to the cast iron dutch oven and canned beans.