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 μsdigitalRead () was
1900µs , became
0.2µsanalogWrite () was
2000mx , it was
51.2mksanalogRead () was
110 μs , it became
18.2 μs , but you can up to
0.2 μs