0

I have a two pins for two blinks leds but I need delay the second signal from first. I start the first signal and I need start the second signal 50ms later. The first signal is 500ms HIGH and 500ms LOW, and the second signal is 400ms LOW and 600ms HIGH. If I start the second signal 50ms later, I can center the high period of the first signal with the low period of the second signal.

This is my code:

long DelaySecondSignal = 50;
int A = 1;

while (A == 1)
{
    long millis_actuales = millis();

        //Control Salida_A
        if (millis_actuales - TiempoTranscurrido_SalidaA > (Estado_SalidaA ? 500 : 400)) {
            digitalWrite(SalidaA, Estado_SalidaA = !Estado_SalidaA);
            TiempoTranscurrido_SalidaA = millis_actuales;
        }

        if (millis_actuales > DelaySecondSignal)
        {
            //Control Salida_B
            if (millis_actuales - TiempoTranscurrido_SalidaB > (Estado_SalidaB ? 500 : 600)) {
                digitalWrite(SalidaB, Estado_SalidaB = !Estado_SalidaB);
                TiempoTranscurrido_SalidaB = millis_actuales;
            }
        }
}

TiempoTranscurrido_?? is a int and Estado_Salida? is a boolean.

I need start the second signal with 50ms of delay but "if (millis_actuales > DelaySecondSignal)" no work.

Thanks.

1

Your problem is that you are treating both signal separately. Instead you need to think about the events of turning LEDs on and off and where they lie on a combined timeline:

     0    100   200   300   400   500   600   700   800   900  1000
     |-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
     ^  ^                       ^  ^
  1 on  2 off                2 on  1 off
  1: ooooooooooooooooooooooooooooooo
  2: oooo                       oooooooooooooooooooooooooooooooooo

You see how I have looped the time around so that the turning off of the second signal, which would normally come at 1050ms, in fact comes at 50ms. By just working in a single 1000ms block of time as a loop things become much simpler.

You can do it now with just a simple set of delays, now you have it laid out in a single timeline like that:

void loop() {
    digitalWrite(led1, HIGH);
    delay(50);
    digitalWrite(led2, LOW);
    delay(400);
    digitalWrite(led2, HIGH);
    delay(50);
    digitalWrite(led1, LOW);
    delay(500);
}

All the delay() calls add up to 1000ms and it keeps looping around.

If you want to make it non-blocking you should set it up with a small finite state machine. There are 4 steady states which are the four spaces between the events on the timeline. There are 4 transitions, which are the events on the timeline. So you:

Start in state 0 with both LEDs on (which is how they are at the start of the timeline).

  • 0: When 50ms have passed turn off LED 2 and move to state 1.
  • 1: When 400ms have passed turn on LED 2 and move to state 2.
  • 2: When 50ms have passed turn off LED 1 and move to state 3.
  • 3: When 500ms have passed turn on LED 1 and move to state 0.
  • This example work perfect, I can change the duty cycle and work. I have another question, How make this example without "delay()"? – Berto Dec 20 '16 at 16:58
  • Like I say in the second half of my answer - with a Finite State Machine. – Majenko Dec 20 '16 at 16:59
0

I'd just base everything of millis.

int A = 1;

while (A == 1)
{
    int phase = millis() % 1000;// modulo 1 second

    // turn on A for the first 500ms of a period, and off for the rest    
    if( phase<500 )
        digitalWrite(SalidaA, HIGH);
    else
        digitalWrite(SalidaA, LOW);

    // turn on B for the first 50ms, and last 550ms of a period, and off for the rest
    if( phase<50 || phase>=450 )
        digitalWrite(SalidaB, HIGH);
    else
        digitalWrite(SalidaB, LOW);

}
  • I did not explain myself well. This example works but not well, for example if I change the length of the period, no work ok until after 1 second. For example, I have a Rate that is "150". I divide 60 seconds beetwen 150 and I have 0.4. Now I need repeat 50% HIGH - 50% LOW of cycle in 400ms in period A, but for example the period B is 35% HIGH - 65% LOW (35*400/100 = 140ms HIGH and 400-140= 260ms LOW). – Berto Dec 20 '16 at 17:15
  • Majenko does not have this problem in his example because he repeats the cycle all time, so I asked if he knows how to do the same example with the milis() function. I need a similar PWM function with center aligned. – Berto Dec 20 '16 at 17:20
  • Just multiply all the numbers by this 0.4. So 1000 becomes 400; 50 becomes 20 etc. – Gerben Dec 20 '16 at 21:06
  • Now work, I changed "millis() % 1000;" by "millis() % 400;" and work ok but I DON'T KNOW WHY IT WORK, sorry. :( – Berto Dec 21 '16 at 16:43
  • Do you know how modulo works? It's like like looking at a clock and saying; I don't care about the hours or minutes, I just want to know the seconds. After that you say; the first 5 seconds of every minute I want output A HIGH, the next 20 seconds LOW, and the rest of every minute HIGH again. For output B I want the output to be HIGH the first 30 seconds of every minute, and LOW the other 30 seconds. – Gerben Dec 21 '16 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.