📜 ⬆️ ⬇️

Accelerate your Arduino

About 3 months ago, like many pseudo-electronics, I bought myself, in my view at that time, the most sophisticated microprocessor board from the Arduino family, namely, Seeeduino Mega, based on the Atmega1280 processor. Indulging in the revolving servo drive and blinking LED, the question arose: “why did I buy it?”.

I work as one of the leading designers at one large Zelenograd military plant, and at the moment I am leading a project to develop a metrological measuring instrument. In this problem there is an infinite number of problems that require individual solutions. One of these tasks is to control a stepper motor without noise and with a step not 1.8 degrees, as stated in the documentation of a stepper motor, but up to 0.0001 degrees. It would seem that the task is complex and unsolvable, but, having tinker a little with the control schemes, I came to the conclusion that everything is real and possible. It requires only the generation of two signals of a specific shape and with a phase shift and frequency of voltage changes up to 1 MHz. (A detailed study of the stepper motor and the disclosure of all the secrets of control will be written in the next article) Immediately ghosts of hope began to appear in my head that I had not spent 1,500 rubles for my little red Seeeduino, and, having gathered my enthusiasm, I began to understand.

Initial horror:


By connecting the microprocessor board to the oscilloscope, and writing a cycle digitalWrite (HIGH), and below digitalWrite (LOW), I found a rather dull meander with a frequency of 50 Hz on the oscilloscope. A nightmare. This is a collapse, I thought, against the background of the required 1 MHz.
Further, through an oscillograph, I studied a few more execution speeds:
AnalogRead () - execution speed 110 µs.
AnalogWrite () - 2000 µs
SerialPrintLn () - at a speed of 9600 about 250 μs, and at a maximum speed of about 3 μs.
DigitalWrite () - 1800mks
DigitalRead () - 1900mks

With this, I burst into tears and almost threw out my Seeeduino. But it was not there!
')

You never know what you can do till you try!


I will not tell you my spiritual torment and describe three long days of study, I'd rather say everything as it is!
Having picked up all possible documentation on the Arduino and on the Atmega1280 processor, examining the experience of foreign colleagues , I want to offer some tips on how to replace read / write:

Improving AnalogRead ()

#define FASTADC 1

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void setup() {
int start ;
int i ;

#if FASTADC
// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;
#endif

Serial.begin(9600) ;
Serial.print("ADCTEST: ") ;
start = millis() ;
for (i = 0 ; i < 30000 ; i++)
analogRead(0) ;
Serial.print(millis() - start) ;
Serial.println(" msec (30000 calls)") ;
}

void loop() {
}


Result: 18.2 microsec speed versus 110 microsec former.
By the way, the maximum speed of the ADC Atmega is just 16µs. As an option - use another chip, sharpened just under the ADC, which will reduce the speed to 0.2mks (read below why)

Improving digitalWrite ()

Each Arduino / Seeeduino / Feduino / Orduino / Other Duino has ports. Each port is 8 bits, which you first need to configure to write. For example, on my Seeeduino PORTA - from 22 to 30 feet. Now everything is simple. We manage from 22 to 30 feet with the help of functions
PORTA = B00001010 (bit, legs 23 and 25 - HIGH)
or
PORTA = 10 (decimal, all the same)
Result = 0.2 μs vs. 1800 μs , which is achieved by the usual digitalWrite ()

Improving digitalRead ()

Almost the same as in the improvement with digitalWrite (), but now we tune the legs to INPUT, and use, for example:
if (PINA == B00000010) {...} (if HIGH is present on leg 23, and LOW is present on 22 and 24-30)
The result of doing this if () is 0.2 μs versus 1900 μs , which is achieved by the usual digitalRead ()

Improving the PWM modulator, or analogWrite ()

So, there is evidence that digitalRead () is executed 0.2 μs, and the PWM modulator has a resolution of 8 bits, the minimum switching time of the PWM is 51.2 μs against 2000 μs.
Use the following code:
int PWM_time=32; //, analogWrite(PIN, 32)
for (int k=0;k<PWM_time) PORTA=B00000001;
for (int k=0;k<256-PWM_time) PORTA=B00000000;

So we got a PWM with a frequency of 19 kHz against 50 Hz.

Let's sum up


digitalWrite () was 1800 μs , became 0.2 μs
digitalRead () was 1900µs , became 0.2µs
analogWrite () was 2000mx , it was 51.2mks
analogRead () was 110 μs , it became 18.2 μs , but you can up to 0.2 μs

Source: https://habr.com/ru/post/141442/


All Articles