Dear Forum
Let me describe my project.
From a rotary coder I receive impulses with a frequency of about 500kHz.
I have to count these pulses and activate a relay every 1.5 million pulses to activate some other action.
I have coded a test software using a UNO. I use a puls generater giving me pulses in the range of 60KHz up to 1MHz.
I count the pulses and every 100.000 pulses I activate pin 12 on the UNO for about 1 microsecond.
The messuring is done by a osciloscope.
The problem I have is: the delay time of 1 microsecond is not constant and canges with the input frequncy in a random manner. Also the shape of the signal is not very good it has a long triling slope.
Here my code, maybe sombody has an idea whats wrong.
Many thanks for help.
volatile unsigned long count=0;
int Pin = 12;
void pulse ()
{
count = count + 1;
}
void setup()
{
pinMode(2, INPUT);
attachInterrupt(digitalPinToInterrupt(2), pulse, RISING);
}
void loop()
{
if (count > 100000)
{
digitalWrite(Pin, HIGH);
delayMicroseconds(1);
digitalWrite(Pin, LOW);
count = 0;
}
}
Use a timer to produce the output pulse in hardware.
A long trailing slope indicates a too heavy load on the pin, eventually arising from a long cable. It may be a measurement mistake as well.
Use Code Tags </> to present code, see the sticky posts at the forum top.
__builtin_avr_delay_cycles (unsigned long ticks)
You might try using the gcc compiler avr built in function with 16 ticks. It is calling assembly code NOP (no operation) cycles. It is much more precise than delayMicroseconds().
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/AVR-Built-in-Functions.html
Thanks for your ideas, I will try.
regards
have a nice day
To be clear,
You said your encoder can send pulses 500,000 times a second.
Your code is set to trigger at > 100,000 pulses, but you actually need to trigger every 1,500,000 pulses?
Is it even possible for a 16mhz Arduino Uno to “count” from 1 to 100,000 in 20ms to keep up with the encoder?
Sorry for the late answer
It can count up to 500.000 but it does not be within 20ms. The counts represent a distance a vehicle moving.
Thanks for correcting the code,I have to think over to understand the changes.
I have also changed to Amtel Studio 7 and now try to get warm with it.
Thanks very much for your help
regards
I think you cannot count 500kHz in SW without using assembly. You are probably losing some (many) ticks on higher speeds. You need to use a counter for this. Timer/Counter1 is probably the right one for this task. Or you may use an external counter to divide the incoming signal to get some better manageable frequency.
Your state that your maximum pulse rate is 500 KHz. That is, one pulse every 2 microseconds.
attachInterrupt(digitalPinToInterrupt(2), pulse, RISING);
This will take a little over 5 microseconds to execute.
See the discussion of the time taken to enter and exit an interrupt in Nick Gammon's tutorial on interrupts.
As Smajdalf notes, you will need to use the external clock source counter on a 16 bit timer.