Problem with "if" nested inside 2 nested "for" loops

I am using a nice little Arduino pro mini to run this code, and I have one problem with it.
The code generates trains of pulses, in this case 6 at a time, 200µS long, and with 1530 µS inbetween them.
The program has 2 sections, one calles "oneShot". I have no problem with that one.
The other is called "ranDom", and in that one I have a problem with an "IF" statement which gets ignored.
The "IF" statement is related to a millis timer, which takes it's time limit from a random generator which runs previous to the "IF" statement.
When I try to create a break in the pulse trains with the "IF" statement I get no break, but if I use the random delay number from the random generator (at present between 300mS and 2000mS) in a simple "delay ();" then the program pauses as it should, and resumes afterwards.
I have no problem with the short microseconds delays, but would like to recoup the long milliseconds delays for future tasks, should they arise. (Or just because long delays are bad practice.)

*ranDom() is in line 37 - 67 and the problematic "IF" statement is in line 62, commented out here to show how the program functions well with the "delay" instead.

#include <digitalWriteFast.h>

int outpulse = 100;
int burstPulses = 6; //  microseconds of burstlength
int pulseLength = 200;       // microseconds of on-time
int OffTime = 1530;          // microseconds of off-time ( 100BPS = 10000, 500BPS = 2000, 600BPS = 1530 )
int Frequency_Value = 1000;    // baseret på 1 sec mellem lynene, -randomisering
int Random_Frequency_Value;
unsigned long currentMicros = 0;
unsigned long previousMicros = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
const byte interruptPin2 = 2;        // modtager signal til one shot
const byte interruptPin3 = 3;        // modtager signal til random


void setup()
{
  Serial.begin(9600);
  pinMode(9, OUTPUT); //til sync output pulse
  pinMode(12, OUTPUT); //til coil 1 Fiberled
  attachInterrupt(digitalPinToInterrupt(interruptPin2), oneShotISP, RISING);
  attachInterrupt(digitalPinToInterrupt(interruptPin3), ranDomISP, RISING);
}


void loop()
{}


void ranDomISP()
{
  previousMillis = millis();
  ranDom();
}

void ranDom()
{

  for (int h = 1; h = 1; )
  {
    digitalWrite (9, HIGH);
    delayMicroseconds (outpulse);
    digitalWrite (9, LOW);

    for (int i = 1; i <= burstPulses; i++)
    {
      cli();                                  //disabler interrupts for mindre jitter
      digitalWriteFast (12, HIGH);             //sets pin12 HIGH
      delayMicroseconds(pulseLength);         //  pulselength
      digitalWriteFast (12, LOW);
      sei();                                    // interrupts tilbage så klokken kører igen

      delayMicroseconds (OffTime);       // Offtime
    }

    randomSeed( analogRead(4) + analogRead(5) + analogRead(8) + analogRead(10) + analogRead(11) );
    Random_Frequency_Value = random ((0.3 * Frequency_Value), (2 * Frequency_Value));

    delay (Random_Frequency_Value);
    currentMillis = millis();
    //if (currentMillis - previousMillis >= Random_Frequency_Value)
    {
      previousMillis = currentMillis;
    }
  }
}


void oneShotISP()
{
  oneShot();
}

void oneShot()

{
  digitalWrite (9, HIGH);
  delayMicroseconds (outpulse);
  digitalWrite (9, LOW);
  for (int i = 1; i <= burstPulses; i++)
  {
    cli();    //disabler interrupts for mindre jitter
    digitalWriteFast (12, HIGH);           //sets pin12 HIGH
    delayMicroseconds(pulseLength);   //  pulselength
    digitalWriteFast (12, LOW);

    sei();     // interrupts tilbage så klokken kører igen

    delayMicroseconds (OffTime);       // Offtime
  }
}






Is that deliberate?

If you deliberately put in odd constructs, it's best to comment them, to show you know what you're doing.

One of the oddest for constructs I have seen.

You should not be delaying in an ISR. In general, millis() does not increment during an ISR. Also, you should NOT be spending milliseconds in an ISR anyhow! The processor has other work to do (like incrementing the millis() counter).

Is there a time constraint regarding the time from when pin 2 or pin 3 goes HIGH and when the pulse train should begin? You may not need interrupts at all.

TheMemberFormerlyKnownAsAWOL

Deliberate, not knowing it to be odd or anything. Just wanted it to run forever.

ToddL1962

About the "for" construct, its intended function is to run over and over forever.

With regard to the interrupts, I use it because it is an elegant way to start a program.

Could we please adress at the question I asked:
Why does delay work, whereas "IF" testing a millis counter does not.

#define EVER ;;
...
...
for (EVER)

"Just wanted it to run forever"
In an interrupt?

@ TheMemberFormerlyKnownAsAWOL

Forever meaning untill I shut the board down, remove pover to it.

Polling would potentially be faster than an interrupt, without the added problems of lost timer interrupts, etc

@ @ TheMemberFormerlyKnownAsAWOL

AS I see it, the interrupt is related to the isp.
as soon as this isp pointe the processor to the void ranDom it is executing an ordinary program, and nit an ISP or ISR.
But I may be wrong...

perhape, but I only execute the isp one time, per day, then the program runs for the remaining hours of the day. Shut down in the evening, and restart in the morning.

Yes, I believe that too.

At that point the code has not returned from the ISR so the rules as to what you can/can't do in an ISR still apply wether or not you call another function

The return instruction for an ISR is different to the return instruction of a simple function.

If you don't execute that instruction, you haven't returned from the interrupt.

Interrupts are not for elegance. They are for events that require low latency responses. For example, pulling data off a buffer before it gets overwritten. If you needed a quick response in this application you would probably want to chain timer events in order to generate the pulse train. If not, I would just do it in loop().

An interrupt is a "context" the processor is running in. No matter what function you call it is running in the interrupt context.

If there are not time constraints I would poll the inputs.

todd,

This is the ISR:

void ranDomISP()
{
    ranDom();
}
It is invoked by the interrupt that is called when pin 
3 is pulled high.
As you see, it is short and sweet, as it should be.
You also see that it hands the processor over to theprogram: (which unfortunately will not format correctly here, the first 8 lines)

void ranDom()
{

for (int h = 1; h = 1; )
{
digitalWrite (9, HIGH);
delayMicroseconds (outpulse);
digitalWrite (9, LOW);

for (int i = 1; i <= burstPulses; i++)
{
  cli();                                  //disabler interrupts for mindre jitter
  digitalWriteFast (12, HIGH);             //sets pin12 HIGH
  delayMicroseconds(pulseLength);         //  pulselength
  digitalWriteFast (12, LOW);
  sei();                                    // interrupts tilbage så klokken kører igen

  delayMicroseconds (OffTime);       // Offtime
}

randomSeed( analogRead(4) + analogRead(5) + analogRead(8) + analogRead(10) + analogRead(11) );
Random_Frequency_Value = random ((0.3 * Frequency_Value), (2 * Frequency_Value));

delay (Random_Frequency_Value);

}
}


This program contains a long milliseconds delay, the actual length being calculated in the random function, and which is between 300 and 2000 milliseconds.

The processor calculates this delay, and ececutes it flawlessly, does this not mean that as soon as the ISR has executed, the processot is back to normal, and fully recovered from whatever constraints the interrupt imposed upon it?

The important thing to remember is that the interrupt isn't over until after ranDom() returns
(The compiler may even have inclined ranDom() !)
Your code tags need some work.

What does it mean, to return. ranDom() returns. how do I make ranDom() return?

It returns when it reaches the final }

Have another look at reply #13

No it is not short. Remove the call to ranDom() and replace it with the contents of of the ranDom() function. Is it short then? NO! You have a delay that could be up to 2 seconds! In an ISR!

1 Like