Progressive frecuency of blinking

Hi all :slight_smile:

I'm currently programming a fake bomb, the Counter Strike: GO bomb, for using it in airsoft games.

But there is a part that i dont know how to make.

When bomb is planted, it makes a sound and a led blinking that goes progressively more frecuently, like a marble bouncing in the ground until it stops, from 45 sec. to 0.

And it can't have any delay

Any ideas? :slight_smile:

Thank you and happy new year!!

And it can't have any delay

You need to look into using millis() for timing as in the BlinkWithoutDelay example and Several things at the same time
Save the time an event happens then each time through loop() check whether the required period has elapsed since the event. If not then go round loop() again reading inputs etc. If the period has elapsed then take the required action. For your application change the required period between each blink.

This is what I've done:

Part of the code:
timeCalc = millis() - anteriorMillis;
int progre = map(countdownTime, 45, 0, 1000, 0);

timeCalcVar = timeCalc % progre;

if (timeCalc >= progre && timeCalcVar >= 0 && timeCalcVar <= 150) {
digitalWrite(ledRojo, HIGH);
}
else {
digitalWrite(ledRojo, LOW);
}

This is what i've thought, but it does not blink as i want

You have not posted your whole program so it is not obvious what you have done, but this should give you something to get you started

const byte ledPin = 13;
unsigned long blinkStart;
unsigned long blinkPeriod = 1000;
unsigned long currentMillis;

void setup()
{
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);

  while (blinkPeriod > 0)
  {
    currentMillis = millis();
    if (currentMillis - blinkStart >= blinkPeriod)
    {
      digitalWrite(ledPin, !digitalRead(ledPin));
      blinkStart = blinkStart + blinkPeriod;
      blinkPeriod -= 10;
    }
  }
}

void loop()
{
}

Obviously you will need to make changes to some/all of the parameters but it outputs an ever faster blink to pin 13 over a period of time which is the sort of thing that I think you want.

Here the full program, in case 1 is the part i mean

     #include <Wire.h>
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
//#include <LiquidCrystal.h>


LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
//LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

const byte FILA = 4; //numero de filas del teclado
const byte COLS = 3; //numero de columnas del teclado

//el keymap define la correspondencia de la tecla pulsada con la tecla mostrada en el teclado físicamente
char keys[FILA][COLS] =
{
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

//Pines correspondientes de las filas y columnas
byte filaPines[FILA] = {9, 8, 7, 6}; //Filas 0 a 3
byte colPines[COLS] = {5, 4, 3}; //Columnas 0 a 3

//crea una instancia de keymap
Keypad teclado = Keypad( makeKeymap(keys), filaPines, colPines, FILA, COLS );

//Entradas/salidas
const byte interruptor = 2;
const byte ledRojo = 13;
const byte ledVerde = 5;
const byte ledAzul = 6;

//Variables
bool activar = false;
const String asterisco = "*******";
String claveintro = "xxxxxxx";
const String clavedefecto = "7355608";
byte indiceTeclado = 0;
const byte tiempoEx = 45; //Tiempo en segundos
byte countdownTime = tiempoEx;
byte estadoBomba = 0;
byte coincide = 0;
char tecla = 0;
unsigned long anteriorMillis = 0;
unsigned long timeCalc = 0;
unsigned long timeCalcVar = 0;
const byte origiCursor = 15;
byte lcdCursor = origiCursor;


void setup() {
  Serial.begin(9600);
  pinMode(activar, INPUT);
  pinMode(ledRojo, OUTPUT);
  pinMode(ledVerde, OUTPUT);
  pinMode(ledAzul, OUTPUT);
  //  cls();

}

void loop() {
  if (digitalRead(interruptor) == HIGH) {
    activar = true;
    Serial.println("PLANTING");
  }


  if (activar) {

    switch (estadoBomba) {
      case 0: // introducir clave

        for (int j = 15; j >= 8; j--) {
          lcd.setCursor(j, 0);
          lcd.print(asterisco);
        }

        tecla = teclado.getKey();
        if (tecla != NO_KEY) {
          claveintro[indiceTeclado] = tecla;
          lcd.setCursor(lcdCursor, 0);
          lcd.print(claveintro);
          indiceTeclado++;
          lcdCursor--;

          Serial.print(tecla);
          Serial.println(" ");
          Serial.print("Clave introducida: ");
          Serial.println(claveintro);
          Serial.print("Indice teclado: ");
          Serial.println(indiceTeclado);

          for (int i = 0; i < 7 && indiceTeclado == 7; i++) {
            if (claveintro[i] == clavedefecto[i]) {
              coincide++;
              Serial.print("Coincide ");
              Serial.println(coincide);
              Serial.println(i);
            }
            while (i == 6) {
              if (coincide == 7) {
                coincide = 0;
                indiceTeclado = 0;
                estadoBomba = 1;
                lcdCursor = origiCursor;
                break;
              }
              else {
                indiceTeclado = 0;
                coincide = 0;
                lcdCursor = origiCursor;
                Serial.println("Clave erronea");
                break;
              }
            }
          }
        }

        break;

      case 1: // cuentra atrás con desactivación
        Serial.println("Cuenta atras");
        anteriorMillis = millis();
        for (int j = 15; j >= 8; j--) {
          lcd.setCursor(j, 0);
          lcd.print(asterisco);
        }

        while (countdownTime != 0 && estadoBomba == 1) {
          timeCalc = millis() - anteriorMillis;
          if (timeCalc >= 1000) {
            countdownTime--;
            anteriorMillis = millis();
            Serial.print("Time remaining: ");
            Serial.println(countdownTime);

            if (countdownTime >= 10) {
              lcd.setCursor(14, 1);
              lcd.print(countdownTime);
            }
            else {
              lcd.setCursor(14, 1);
              lcd.print("0");
              lcd.setCursor(15, 1);
              lcd.print(countdownTime);
            }
          }
          int progre = map(countdownTime, 45, 0, 1000, 0);

          timeCalcVar = timeCalc % progre;

          if (timeCalc >= progre && timeCalcVar <= 100) {
            digitalWrite(ledRojo, HIGH);
            Serial.println(progre);
            Serial.println(timeCalcVar);
          }
          else if(timeCalc <= progre)
            {
            digitalWrite(ledRojo, LOW);
          }

          tecla = teclado.getKey();
          if (tecla != NO_KEY) {
            claveintro[indiceTeclado] = tecla;
            lcd.setCursor(lcdCursor, 0);
            lcd.print(claveintro);
            indiceTeclado++;
            lcdCursor--;

            Serial.print(tecla);
            Serial.println(" ");
            Serial.print("Clave introducida: ");
            Serial.println(claveintro);
            Serial.print("Indice teclado: ");
            Serial.println(indiceTeclado);

            for (int i = 0; i < 7 && indiceTeclado == 7; i++) {
              if (claveintro[i] == clavedefecto[i]) {
                coincide++;
                Serial.print("Coincide ");
                Serial.println(coincide);
                Serial.println(i);
              }
              while (i == 6) {
                if (coincide == 7) {
                  coincide = 0;
                  indiceTeclado = 0;
                  estadoBomba = 2;
                  lcdCursor = origiCursor;
                  break;
                }
                else {
                  indiceTeclado = 0;
                  coincide = 0;
                  Serial.println("Clave erronea");
                  lcdCursor = origiCursor;
                  break;
                }
              }
            }
          }
        }
        if (countdownTime == 0) estadoBomba = 3; //explota
        break;

      case 2: // Desactivación
        Serial.println("Bomb has been defused");
        for (int i = 0; i <= 20; i++) {
          digitalWrite(ledRojo, HIGH);
          delay(50);
          digitalWrite(ledRojo, LOW);
          delay(50);
        }
        countdownTime = tiempoEx;
        estadoBomba = 0;
        break;

      case 3: // Explota
        Serial.println("Bomb exploded");
        digitalWrite(ledRojo, HIGH);
        delay(2000);
        digitalWrite(ledRojo, LOW);
        countdownTime = tiempoEx;
        estadoBomba = 0;
        break;
    }
  }
}

Welcome to the Forum. You have posted code using quote tags instead of code tags. That can be a problem. Please read these two posts:

How to use this forum - please read.
and
Read this before posting a programming question ...

The code tags make the code look

like this

Do not use quote tags!

when posting source code files. It makes it easier to read, and can be copied with a single mouse click. Also, if you don't do it, some of the character sequences in the code can be misinterpred by the forum code as italics or funny emoticons.

Many questions can be answered by simply reading the documentation which is provided with the IDE, available under the help tab, or online here.

If you have already posted without using code tags, open your message and select "modify" from the pull down menu labelled, "More", at the lower left corner of the message. Highlight your code by selecting it (it turns blue), and then click on the "</>" icon at the upper left hand corner. Click on the "Save" button.

aarg:
Welcome to the Forum. You have posted code using quote tags instead of code tags. That can be a problem. Please read these two posts:

How to use this forum - please read.
and
Read this before posting a programming question ...

The code tags make the code look

like this

Do not use quote tags!

when posting source code files. It makes it easier to read, and can be copied with a single mouse click. Also, if you don't do it, some of the character sequences in the code can be misinterpred by the forum code as italics or funny emoticons.

Many questions can be answered by simply reading the documentation which is provided with the IDE, available under the help tab, or online here.

If you have already posted without using code tags, open your message and select "modify" from the pull down menu labelled, "More", at the lower left corner of the message. Highlight your code by selecting it (it turns blue), and then click on the "</>" icon at the upper left hand corner. Click on the "Save" button.

I'm sorry, fixed :slight_smile:

You have this:

        while (countdownTime != 0 && estadoBomba == 1) {
          timeCalc = millis() - anteriorMillis;

Since you placed your time code inside the while loop, nothing outside the while loop can run while the code inside it is running. See reply #2.

aarg:
You have this:

        while (countdownTime != 0 && estadoBomba == 1) {

timeCalc = millis() - anteriorMillis;



Since you placed your time code inside the while loop, nothing outside the while loop can run while the code inside it is running. See reply #2.

That part of the code is running until countdownTime == 0 or claveintro == clavedefecto, so until bomb explodes or defused it wont get out. The bomb code work perfectly, but the part i want to make is led blinking that will blink more quickly until countdownTime == 0, then it will be HIGH

Alferciu:
That part of the code is running until countdownTime == 0 or claveintro == clavedefecto, so until bomb explodes or defused it wont get out. The bomb code work perfectly, but the part i want to make is led blinking that will blink more quickly until countdownTime == 0, then it will be HIGH

Right. You are describing "doing two things at the same time". You are trapped in that while loop, so you can only do one thing. You have to change that.

aarg:
Right. You are describing "doing two things at the same time". You are trapped in that while loop, so you can only do one thing. You have to change that.

But everything inside the While is executing until the while conditions stop matching, it works but not the way i want.

In this part it counts from 45 to 0 sec

          timeCalc = millis() - anteriorMillis;
          if (timeCalc >= 1000) {
            countdownTime--;
            anteriorMillis = millis();
            Serial.print("Time remaining: ");
            Serial.println(countdownTime);

            if (countdownTime >= 10) {
              lcd.setCursor(14, 1);
              lcd.print(countdownTime);
            }
            else {
              lcd.setCursor(14, 1);
              lcd.print("0");
              lcd.setCursor(15, 1);
              lcd.print(countdownTime);
            }
          }

In this other part I convert the 45 secs in the rank of 1000 milisec, the idea is to use that mapping as delay

int progre = map(countdownTime, 45, 0, 1000, 0);

With this part of code I pretend to make the blinking, but the blinking its not like "one second" ON and one second OFF, but in every second 150 milisec ON and the rest off, and even faster

                      timeCalcVar = timeCalc % progre;

          if (timeCalc >= progre && timeCalcVar <= 100) {
            digitalWrite(ledRojo, HIGH);
            Serial.println(progre);
            Serial.println(timeCalcVar);
          }
          else if(timeCalc <= progre)
            {
            digitalWrite(ledRojo, LOW);
          }

up

Alferciu:
When bomb is planted, it makes a sound and a led blinking that goes progressively more frecuently, like a marble bouncing in the ground until it stops, from 45 sec. to 0.

And it can't have any delay

Any ideas? :slight_smile:

Thank you and happy new year!!

try this:

#define COUNTDOWN_PERIOD 45 * 1000UL  // 45 seconds

unsigned long countDownTime = COUNTDOWN_PERIOD;
const byte ledPin = 5;

void setup() 
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  Serial.println(countDownTime / 1000);
}

void loop() 
{
  if(countdown(countDownTime))
  {
    blink(map(countDownTime, 0, COUNTDOWN_PERIOD, 0, 1000));  // from 1 second flash to zero
  }
  else
  {
    Serial.println("Boom");
  }
}

int countdown(unsigned long &remainingTime)
{
  static unsigned long lastMillis = 0;
  if (remainingTime <= 0)
  {
    return 0;
  }
  if(millis() - lastMillis > 1000UL)
  {
    remainingTime -= 1000;
    Serial.println(remainingTime / 1000);
    lastMillis += 1000UL;
  }
  return 1;
}

void blink(unsigned long blinkRate)
{
  static unsigned long lastMillis = 0;
  if(millis() - lastMillis > blinkRate)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    lastMillis = millis();
  }
}

BulldogLowell:
try this:

#define COUNTDOWN_PERIOD 45 * 1000UL  // 45 seconds

unsigned long countDownTime = COUNTDOWN_PERIOD;
const byte ledPin = 5;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  Serial.println(countDownTime / 1000);
}

void loop()
{
  if(countdown(countDownTime))
  {
    blink(map(countDownTime, 0, COUNTDOWN_PERIOD, 0, 1000));  // from 1 second flash to zero
  }
  else
  {
    Serial.println("Boom");
  }
}

int countdown(unsigned long &remainingTime)
{
  static unsigned long lastMillis = 0;
  if (remainingTime <= 0)
  {
    return 0;
  }
  if(millis() - lastMillis > 1000UL)
  {
    remainingTime -= 1000;
    Serial.println(remainingTime / 1000);
    lastMillis += 1000UL;
  }
  return 1;
}

void blink(unsigned long blinkRate)
{
  static unsigned long lastMillis = 0;
  if(millis() - lastMillis > blinkRate)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    lastMillis = millis();
  }
}

Thank you very much!!! It works :slight_smile:

I need to make a "flashing" blinking, imagine that in one second of blinking, first 150 msec are HIGH and the rest OFF. But since its a variable delay I have no idea how can I do it

Alferciu:
Thank you very much!!! It works :slight_smile:

I need to make a "flashing" blinking, imagine that in one second of blinking, first 150 msec are HIGH and the rest OFF. But since its a variable delay I have no idea how can I do it

loop() gets called continuosly, so just do:

long lastLedOnPoint;
boolean LedIsON;

loop()
{
    long period = millis() - lastLedOnPoint;
    if (LedIsON == false &&  period > 1000)
    {
          lastLedOnPoint = millis();
          digitalWrite(LEDPin, HIGH);
          LedIsON = true;
    } 
    else if (LedIsON == true && period > 150)
    {
         // turn it off after it has been ON for 150ms
         digitalWrite(LEDPin, LOW);
         LedIsON = false;
    }

}
/code]

arduinodlb:
loop() gets called continuosly, so just do:

long lastLedOnPoint;

boolean LedIsON;

loop()
{
    long period = millis() - lastLedOnPoint;
    if (LedIsON == false &&  period > 1000)
    {
          lastLedOnPoint = millis();
          digitalWrite(LEDPin, HIGH);
          LedIsON = true;
    }
    else if (LedIsON == true && period > 150)
    {
        // turn it off after it has been ON for 150ms
        digitalWrite(LEDPin, LOW);
        LedIsON = false;
    }

}
/code]

Sorry, but you didn't read that period is countinously getting lower so those 150 msec wont work, must be getting lower too

Alferciu:
[..]imagine that in one second of blinking, first 150 msec are HIGH and the rest OFF. But since its a variable delay I have no idea how can I do it

Alferciu:
Thank you very much!!! It works :slight_smile:

I need to make a "flashing" blinking, imagine that in one second of blinking, first 150 msec are HIGH and the rest OFF. But since its a variable delay I have no idea how can I do it

something like this:

(I thought 50ms looks way more cool!)

#define COUNTDOWN_PERIOD 45 * 1000UL  // 60 seconds

unsigned long countDownTime = COUNTDOWN_PERIOD;
const byte ledPin = 5;

void setup() 
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  Serial.println(countDownTime / 1000);
}

void loop() 
{
  if(countdown(countDownTime))
  {
    blink(map(countDownTime, 0, COUNTDOWN_PERIOD, 0, 1000));  // from 1 second flash to zero
  }
  else
  {
    Serial.println("Boom");
  }
}

int countdown(unsigned long &remainingTime)
{
  static unsigned long lastMillis = 0;
  if (remainingTime <= 0)
  {
    return 0;
  }
  if(millis() - lastMillis > 1000UL)
  {
    remainingTime -= 1000;
    Serial.println(remainingTime / 1000);
    lastMillis += 1000UL;
  }
  return 1;
}

void blink(unsigned long blinkRate)
{
  static unsigned long lastMillis = 0;
  if(digitalRead(ledPin) && millis() - lastMillis > 50UL && blinkRate > 50UL)
  {
    digitalWrite(ledPin, LOW);
  }
  if(millis() - lastMillis > blinkRate)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    lastMillis = millis();
  }
}

Alferciu:
Sorry, but you didn't read that period is countinously getting lower so those 150 msec wont work, must be getting lower too

Sorry, this statement made it sound fixed:

Alferciu:
Thank you very much!!! It works :slight_smile:

I need to make a "flashing" blinking, imagine that in one second of blinking, first 150 msec are HIGH and the rest OFF. But since its a variable delay I have no idea how can I do it

So I am having trouble understanding exactly what values you want. If you can explain the maths you want, we can help you with the code.

is it

  1. "ON for blink_rate, OFF for 1 second - blink rate" or
  2. "ON for blink_rate, OFF for blink_rate, up to 1 second" or
  3. "ON for blink_rate, OFF for blink_rate" or
  4. "ON for 150ms, OFF for blink_rate - 150ms" or
  5. something else....

BulldogLowell:
(I thought 50ms looks way more cool!)

ore even better:

void blink(unsigned long blinkRate)
{
  static unsigned long lastMillis = 0;
  static bool ledState = false;
  if(digitalRead(ledPin) && (millis() - lastMillis > 50UL) && blinkRate > 50UL)
  {
    digitalWrite(ledPin, LOW);
  }
  if(millis() - lastMillis > blinkRate)
  {
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
    lastMillis = millis();
  }
}

BulldogLowell:
something like this:

(I thought 50ms looks way more cool!)

#define COUNTDOWN_PERIOD 45 * 1000UL  // 60 seconds

unsigned long countDownTime = COUNTDOWN_PERIOD;
const byte ledPin = 5;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  Serial.println(countDownTime / 1000);
}

void loop()
{
  if(countdown(countDownTime))
  {
    blink(map(countDownTime, 0, COUNTDOWN_PERIOD, 0, 1000));  // from 1 second flash to zero
  }
  else
  {
    Serial.println("Boom");
  }
}

int countdown(unsigned long &remainingTime)
{
  static unsigned long lastMillis = 0;
  if (remainingTime <= 0)
  {
    return 0;
  }
  if(millis() - lastMillis > 1000UL)
  {
    remainingTime -= 1000;
    Serial.println(remainingTime / 1000);
    lastMillis += 1000UL;
  }
  return 1;
}

void blink(unsigned long blinkRate)
{
  static unsigned long lastMillis = 0;
  if(digitalRead(ledPin) && millis() - lastMillis > 50UL && blinkRate > 50UL)
  {
    digitalWrite(ledPin, LOW);
  }
  if(millis() - lastMillis > blinkRate)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    lastMillis = millis();
  }
}

THANK YOU VERY MUCH!! Thats what I was exactly looking for, you made my day :slight_smile: :slight_smile: :slight_smile:

As soon as I finish the full code I will upload it here

arduinodlb:
So I am having trouble understanding exactly what values you want. If you can explain the maths you want, we can help you with the code.

is it

  1. "ON for blink_rate, OFF for 1 second - blink rate" or
  2. "ON for blink_rate, OFF for blink_rate, up to 1 second" or
  3. "ON for blink_rate, OFF for blink_rate" or
  4. "ON for 150ms, OFF for blink_rate - 150ms" or
  5. something else....

Remember the sound of a marble bouncing in the ground, that was what I mean, BulldogLowell catched the idea, test the code :slight_smile: