Hello guys, I'm developing a project in which the timing have to be pretty accurate. Right now, I'm blinking some leds in my protoboard and depending on an array it will blink led 1,2,3 or 4. So my main problem is that I can blink them each 5 seconds with ISR but I can not figure out how to turn on them the led only for a second inside the ISR. Any suggestions?
As far as I've read, it is not a good implementation to change register of timers out of the setup function, so one of my ideas which would be to turn on another timer to make another ISR when the main ISR start is actually discarded.
define accurate... how long does your loop take ?
Fire ISR each second rather than 5 sec.
Four interruptions LED is off, on the fifth it is on, then the cycle repeats
do you really need to use an interrupt?
consider
struct Led {
byte pin;
bool active;
unsigned long msecPeriodOn;
unsigned long msecPeriodOff;
unsigned long msecPeriod;
unsigned long msecLst;
};
Led leds [] = {
{ 10 },
{ 11 },
{ 12 },
{ 13 },
};
const size_t N_Leds = sizeof(leds)/sizeof(Led);
enum { Off = HIGH, On = LOW };
unsigned long msec;
// -------------------------------------
void
setLed (
Led *p,
unsigned long msecPeriodOn,
unsigned long msecPeriodOff )
{
p->active = true;
p->msecPeriodOn = msecPeriodOn;
p->msecPeriodOff = msecPeriodOff;
}
// -----------------------------------------------------------------------------
void
loop (void)
{
msec = millis ();
Led *p = leds;
for (unsigned n = 0; n < N_Leds; n++, p++) {
if (! p->active)
continue;
if ((msec - p->msecLst) > p->msecPeriod) {
if (On == digitalRead (p->pin)) {
digitalWrite (p->pin, Off);
p->msecPeriod = p->msecPeriodOff;
}
else {
digitalWrite (p->pin, On);
p->msecPeriod = p->msecPeriodOn;
}
p->msecLst = msec;
}
}
Serial.println ();
}
// -----------------------------------------------------------------------------
void
setup (void)
{
Serial.begin (9600);
Led *p = leds;
for (unsigned n = 0; n < N_Leds; n++, p++) {
digitalWrite (p->pin, Off);
pinMode (p->pin, OUTPUT);
}
setLed (& leds [0], 1000, 4000);
setLed (& leds [1], 2000, 3000);
setLed (& leds [2], 3000, 2000);
setLed (& leds [3], 500, 500);
}
Still waiting to see why LED blinking would have to be "pretty accurate", and how accurate. Also waiting to see the code...
LED blinking is just a small example for a bigger project, where I have to turn on some lasers. The code right now is just a blinking code with ISR on timer1, so it is not relevant I think
As far as i read, millis is not as accurate as hardware interruptions, is it?
Mmm that's sounds ok, but is the only real solution?
Consider micros for better granularity.
Have you looked at the accuracy of the CPU clock on your board? Some Arduino use resonators instead of crystals and have pretty bad frequency accuracy.
This is only one reason why, when talking about accuracy, it is essential to use explicit definitions. Please provide them, you've already been asked...
I don't think it's the only one...
Do you need a solution or do you want to organize a competition for helpers?
The solution you proposed in your first post would be extremely cumbersome, if not impossible. So you have to remain open to any and all solutions.
It is an original arduino UNO. Thanks for your hint I will go and check it.
I'm not sure about which accuracy are we talking about but for example I will have to send signals like every 1e-3 or 1e-4 seconds. I'm not totally sure about the system requirements but it has to be as precise as possible, I will check for it.
so every 100 usec.
what type of signals? simply toggling as I/O line
what kind of application?
I have to output 5V to various diode lasers. It's just turning on and off the output pin. I'm turning on directly on PORTB, like PORTB = 1, 2,4,8... because I've read is a fastest operation than digitalWrite
Can you please attach a sketch of the output you are looking for? I'm confuse with the the 5 seconds and the 100usec. What is the length of the pulses at 100us? Are you saying that you want some 100us pulse train to last for 5 seconds?
what determines how long the diode is on and when it gets turned on? could these be counts incremented in the ISR without any intervention outside of the ISR?
it won't be real-time if something outside the ISR needs to communicate this timing
@byfuentes
It's not you who asked a couple of weeks ago how to generate multiple 1 MHz signals?
Something very similar requirements you have
You can try my AVR_Slow_PWM Library, for example with
// You can assign any interval for any timer here, in microseconds
uint32_t PWM_Period1 = 5000000L;
// You can assign any duty_cycle for any PWM here, from 0-100
float PWM_DutyCycle1 = 20.0;
Hmmmm. Yeah. If you don't want to talk about the actual application, that's okay. But now I think a precise definition of your requirement is overdue. Mainly, I'm wondering, how complex is the modulation that you are applying to the lasers? Are you communicating information or is the pulse train only used to establish a duty cycle?