I'm currently working on quite a large project requiring a large number of I/O and reasonably fast response time. I'm planning to use an Arduino Mega because of the large amount of GPIO I most likely need.
I am using a rotary encoder that gives a max output frequency of 20kHz and two line scan cameras that need to operate at a max speed of 80kHz and in sync with the rotary encoder. So with Quadrature Decoding I can count every rising and falling edge of the A and B signal of the encoder to multiply the frequency by 4, giving me the needed 80kHz.
I have the Quadrature Decoding working, using some test code in an Arduino Uno. I simulated the rotary encoder using a second Arduino Uno giving me two outputs at a set frequency one of them 90 degrees out of phase. I tested the quadrature decoder using this setup at different speeds, but it stopped working at a frequency greater than 25kHz (giving me 100kHz total at the output of the quadrature decoder), which of course is more than what I need for my project. But I am concerned that, with much more code required for all the other devices and thus resulting in more CPU usage, the code can't keep up with the frequent triggering interrupts. Even at 20kHz (or 80kHz at output).
So my question is, how likely is it that my code needed for this project can't keep up with the frequent interrupts generated by the encoder? And if so, how can I reduce CPU usage required by the quadrature decoder?
I have attached a simple schematic that shows what the Arduino Mega has to control in this project.
Thank you for your reaction.
These do help reduce CPU usage significantly. But it is important that my entire program runs of this 80kHz frequency, and has to be in sync with it, without missing any triggers and with as few delay as possible. I don't think that would work if I have to read the SPI or I2C registers constantly, that probably would make too slow. That is why, in my test code, the program uses the external interrupt pins to compute the quadrature decoder as fast as possible.
I've also noticed a new problem. The test code I made counts the triggers per second, which is close to 80000. This count was inconsistent and deviated with max +/- 250 per second while the input frequency was very precise. Also, if I would make it so that a pin outputs this counting as a frequency, the interrupt would interfere with the job and I can only output a frequency close to 20kHz, which is very instable. Does anyone know how to output this 80kHz frequency received from the quadrature decoder to a digital pin?
#include <Encoder.h>
Encoder rotaryEncoder(2, 3); // Select the two hardware interrupt pins on Arduino Uno
void setup() {
DDRB |= (1 << DDB3);//pin 11 is in output mode
}
long positionEncoder = -999;
void loop() {
long newEncoder;
newEncoder = rotaryEncoder.read();
if(newEncoder != positionEncoder) {
PORTB |= (1 << PORTB3); //make pin 11 high
positionEncoder = newEncoder;
}
else{
PORTB &= ~(1 << PORTB3); //make pin 11 low
}
}
Before we troubleshoot a problem, we generally work though the basics and confirm we’re solving the correct problem. You may know these things but we don’t. So, let’s start at the beginning:
How do you know your waveform generator is working correctly?
Which encoder library are you using?
Do you have an oscilloscope?
What else can you tell us about the project? How do five motors interact that only affect one encoder? There’s probably few more things I could ask but let’s start with the above.
Do you need to know direction of your encoder? Or just the speed? The latter would simplify things as you could put both signals on a single PORT and enable the pin change interrupt on that PORT, and then you can simply count interrupts.
Anyway, encoders are simple enough to roll your own code - and rid yourself of the library's overhead as you don't need that flexibility.
How is that video device controlled? If you have to go through SPI, you will have delays, and may have a hard time keeping up (max. frequency is 8 MHz, that's 100 clock ticks or up to 100 bits of data per encoder tick on a standard 16 MHz Arduino). If you have to send commands over I2C... no chance. I remember the Arduino can do up to about 1 MHz, that'd be like 12 bits per encoder tick, which is less than the I2C header.
WattsThat:
Before we troubleshoot a problem, we generally work though the basics and confirm we’re solving the correct problem. You may know these things but we don’t. So, let’s start at the beginning:
How do you know your waveform generator is working correctly?
Which encoder library are you using?
Do you have an oscilloscope?
What else can you tell us about the project? How do five motors interact that only affect one encoder? There’s probably few more things I could ask but let’s start with the above.
I have an oscilloscope, and I simulated the encoder A and B signal with a second Arduino (see Rotary_Encoder_Simulator.ino) . I have used the oscilloscope to confirm its frequency and phase.
I used an encoder library from here: Encoder Library, for Measuring Quadarature Encoded Position or Rotation Signals
About the project: We are using a PLC to control a machine, but we are looking to replace the PLC with a cheaper alternative, like an Arduino Mega. The machine's has to inspect textile in order to find errors using line scan cameras. 5 motors are needed to control speed, prevent knobs from going into the machine and some other things.
wvmarle:
Do you need to know direction of your encoder? Or just the speed? The latter would simplify things as you could put both signals on a single PORT and enable the pin change interrupt on that PORT, and then you can simply count interrupts.
Anyway, encoders are simple enough to roll your own code - and rid yourself of the library's overhead as you don't need that flexibility.
How is that video device controlled? If you have to go through SPI, you will have delays, and may have a hard time keeping up (max. frequency is 8 MHz, that's 100 clock ticks or up to 100 bits of data per encoder tick on a standard 16 MHz Arduino). If you have to send commands over I2C... no chance. I remember the Arduino can do up to about 1 MHz, that'd be like 12 bits per encoder tick, which is less than the I2C header.
Yes I need to know the direction of the encoder. The line scan camera may only provide new data to the PC. This means, if the system would go back a couple of steps, the camera cannot trigger. Then if the machine would proceed, it has to skip the amount of steps it went back in order to not trigger the camera a second time at the same locations.
The camera has a direct connection to the PC (via Ethernet), so the PC deals with all the incomming video data. The camera also has a trigger input pin. When this pin is set high, the camera captures a frame and sends it to the PC. The camera has to send a frame at a 80kHz frequency to the PC.
IMO, you’ll find too many bottlenecks with the current plan. For a one off project, a Mega will not have sufficient bandwidth to deal with an encoder, serial comms and closing motor control loops in real time without the use of processor hardware help along with some gotta learn it the hard way programming. Could it be done? Absolutely. Is it practical for a one-of project? I doubt it.
I believe will find the task much simpler by dumping the Arduino idea and moving the encoder data directly into the PC and deal with it there.
WattsThat:
I believe will find the task much simpler by dumping the Arduino idea and moving the encoder data directly into the PC and deal with it there.
Could be - the PC is of course much faster, but may also be less time reliable unless you can use a an interrupt (IRQ or whatever it's called in newfashioned PCs - I recall the ISA bus had specific connections for this). So you're replacing one issue with another.
I for one would highly prefer to solve this on an Arduino as there at least I know it can be done, and how it can be done.
FYI, an Arduino DUE has 2 hardware quadrature decoders. Each of these 2 hadware quadrature decoder can be used for position or speed measurement.
I have done some tests with these decoders and by simulating a quadrature encoder on the same board, the board was able to log up to 42 million edges/s with PHA/PHB connected to one of the Timer Counters. This is done without interruptions. I provided example sketches for speed and position measurement in the DUE sub forum.
Question: does the direction of rotation of the encoder ever change? If it doesn't, you don't need a quadrature decoder at all, a simple logical XOR (like SN74LS86A 74HC86, or a separate Arduino?) will give you a 40kHz square wave.