How to turn on/off a blinking output from the same button

I am trying to control some external devices using a relay from an Arduino board. I can get the signal to blink or flash.. But I cant turn it off. Using the MIT App Inventor . The various buttons sends a character. press same button to turn on and the same button again to turn off. Below is the code so far. I have two different blink codes written as I was testing both approaches. Thanks!


int Received=0;
int vibrate_state = 0;
int audible_state = 0;
int flash_state = 0;
int blueled_state = 0;
int allsignals_state = 0;
 

void setup()
{
  
  Serial.begin(9600);
  pinMode(vibrate, OUTPUT);
  pinMode(audible, OUTPUT);
  pinMode(flash, OUTPUT);
  pinMode(blueled, OUTPUT);
 
}

void loop()
{
 
 if(Serial.available()>0)
 { 
    
    Received = Serial.read();
    char Rec = char(Received);
    if (Rec != '0')
    {
    Serial.println(Rec); //This is to visualise the received character
    }
    
 }

////////////////VIBRATE/////////////////////
if (vibrate_state == 0 && Received == 'v') 
  {
    digitalWrite(vibrate, (millis() / 500) %2);
    }
if (vibrate_state ==1 && Received == 'v')
  {
    digitalWrite(vibrate,LOW);
    vibrate_state=0;
    Received=0;
  }
///////////////////////////////////////////



////////////////AUDIBLE/////////////////////
if (audible_state == 0 && Received == 's')
  {
    digitalWrite(audible,HIGH);
    audible_state=1;
    Received=0;
    }
if (audible_state ==1 && Received == 's')
  {
    digitalWrite(audible,LOW);
    audible_state=0;
    Received=0;
  }
///////////////////////////////////////////




////////////////FLASH/////////////////////
if (flash_state == 0 && Received == 'f')
  {
    digitalWrite(flash,HIGH);
    delay(125);
    digitalWrite(flash,LOW);
    delay(125);
  }
if (flash_state ==1 && Received == 'f')
  {
    digitalWrite(flash,LOW);
    flash_state=0;
    Received=0;
  }
///////////////////////////////////////////




  
////////////////BLUELED/////////////////////
if (blueled_state == 0 && Received == 'b')
  {
    digitalWrite(blueled,HIGH);
    blueled_state=1;
    Received=0;  
  }
if (blueled_state ==1 && Received == 'b')
  {
    digitalWrite(blueled,LOW);
    blueled_state=0;
    Received=0;
  }
 ///////////////////////////////////////////




////////////////ALLSIGNALS/////////////////////
if (allsignals_state == 0 && Received == 'a')
  {
    digitalWrite(vibrate,HIGH);
    digitalWrite(flash,HIGH);
    digitalWrite(audible,HIGH);
    allsignals_state=1;
    Received=0;  
  }
if (allsignals_state ==1 && Received == 'a')
  {
    digitalWrite(vibrate,LOW);
    digitalWrite(flash,LOW);
    digitalWrite(audible,LOW);
    allsignals_state=0;
    Received=0;
  }
 ///////////////////////////////////////////
 
 
}

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

You need to detect when the button becomes pressed rather than when it is pressed

See the StateChangeDetection example in the IDE

Before we get to your problem, I'd like to draw your attention to something. You should always attempt to factor the logic of your code to avoid repetition. There are multiple sections like this:

////////////////BLUELED/////////////////////
if (blueled_state == 0 && Received == 'b')
{
digitalWrite(blueled,HIGH);
blueled_state=1;
Received=0;
}
if (blueled_state ==1 && Received == 'b')
{
digitalWrite(blueled,LOW);
blueled_state=0;
Received=0;
}

Both tests check for 'b', so you should nest them:

if (Received == 'b') {
  if (blueled_state == 0)
  {
    digitalWrite(blueled, HIGH);
    blueled_state = 1;
  }
  else
  {
    digitalWrite(blueled, LOW);
    blueled_state = 0;
  }
  Received = 0;
}

Thank you for pointing me in the right direction. I wasn't looking in the right place. I hope I corrected it properly. :+1:

Thank you, much appreciated.

I did the nested version for the blueled. and it works. :+1:
But for the vibrate and flash, the 'else' function stops the blinking function. In this instance would the else function not be used?

You have to show your code. I sincerely hope you did not go back and edit the code in the original post...

I only added the </> around the code in the original post so that it would show up properly.

At this point, posting only the lines of one of the sections you changed, would be just fine. I looked at the ones you mentioned and they are definitely "do-able".

You did not define the pins.

So I just made some up. Compiled, but not tested.

const uint8_t vibrate = 2;
const uint8_t audible = 3;
const uint8_t flash = 4;
const uint8_t blueled = 5;

bool vibrate_state;
bool audible_state;
bool flash_state;
bool blueled_state;
bool allsignals_state;
uint32_t vibrate_start;
uint32_t flash_start;

void setup() {
  Serial.begin(9600);
  pinMode(vibrate, OUTPUT);
  pinMode(audible, OUTPUT);
  pinMode(flash, OUTPUT);
  pinMode(blueled, OUTPUT);
}

void loop() {
  if (Serial.available()) {
    uint8_t Received = Serial.read();
    Serial.println(Received);
    switch (Received) {
      case 'v':
        vibrate_state = !vibrate_state;
        digitalWrite(vibrate, vibrate_state ? HIGH : LOW);
        if (vibrate_state) {
          vibrate_start = millis();
        }
        break;
      case 's':
        audible_state = !audible_state;
        digitalWrite(audible, audible_state ? HIGH : LOW);
        break;
      case 'f':
        flash_state = !flash_state;
        digitalWrite(vibrate, flash_state ? HIGH : LOW);
        if (flash_state) {
          flash_start = millis();
        }
        break;
      case 'b':
        blueled_state = !blueled_state;
        digitalWrite(blueled, blueled_state ? HIGH : LOW);
        break;
      case 'a':
        allsignals_state = !allsignals_state;
        digitalWrite(vibrate, allsignals_state ? HIGH : LOW);
        digitalWrite(flash, allsignals_state ? HIGH : LOW);
        digitalWrite(audible, allsignals_state ? HIGH : LOW);
        digitalWrite(blueled, allsignals_state ? HIGH : LOW);
        if (allsignals_state) {
          vibrate_start = flash_start = millis();
        }
        break;
    }
  }
  if (vibrate_state && millis() - vibrate_start > 500) {
    digitalWrite(vibrate, digitalRead(vibrate) == HIGH ? LOW : HIGH);
    vibrate_start = millis();
  }
  if (flash_state && millis() - flash_start > 125) {
    digitalWrite(flash, digitalRead(flash) == HIGH ? LOW : HIGH);
    flash_start = millis();
  }
}

To get a responsive sketch, you can not use delay, but luckily you don't have to.

@Whandall

Your code is what I was looking for. I added it to the audible and flash as those need to 'blink' as well. I tweaked a few and all is working with one exception. The allsignals is to perform as a blinking operation as well. (blinking 3 items at once)
I tried to modify it as such, but it just does nothing. It starts at Line " case 'a': " of the function that I am concentrating on.

const uint8_t vibrate=12;
const uint8_t audible=11;
const uint8_t flash=10;
const uint8_t blueled=9;

bool vibrate_state;
bool audible_state;
bool flash_state;
bool blueled_state;
bool allsignals_state;
uint32_t vibrate_start;
uint32_t audible_start;
uint32_t flash_start;
 

void setup()
{
  
  Serial.begin(9600);
  pinMode(vibrate, OUTPUT);
  pinMode(audible, OUTPUT);
  pinMode(flash, OUTPUT);
  pinMode(blueled, OUTPUT);
 
}

void loop() {
 if (Serial.available()) {
    uint8_t Received = Serial.read();
    Serial.println(Received);
    switch (Received) {
      case 'v':
        vibrate_state = !vibrate_state;
        digitalWrite(vibrate, vibrate_state ? HIGH : LOW);
        if (vibrate_state) {
          vibrate_start = millis();
        }
        break;
      case 's':
        audible_state = !audible_state;
        digitalWrite(audible, audible_state ? HIGH : LOW);
        if (audible_state) {
          audible_start = millis();
        }
        break;
      case 'f':
        flash_state = !flash_state;
        digitalWrite(flash, flash_state ? HIGH : LOW);
        if (flash_state) {
          flash_start = millis();
        }
        break;
       case 'b':
        blueled_state = !blueled_state;
        digitalWrite(blueled, blueled_state ? HIGH : LOW);
        break;
      case 'a':
        allsignals_state = !allsignals_state;
        digitalWrite(vibrate, vibrate_state ? HIGH : LOW);
        digitalWrite(flash, flash_state ? HIGH : LOW);
        digitalWrite(audible, audible_state ? HIGH : LOW);
        if (allsignals_state) {
          vibrate_start = millis();
          audible_start = millis();
          flash_start = millis();
        }
        break;
    }
  }
  if (vibrate_state && millis() - vibrate_start > 500) {
    digitalWrite(vibrate, digitalRead(vibrate) == HIGH ? LOW : HIGH);
    vibrate_start = millis();
  }
  if (audible_state && millis() - audible_start > 125) {
    digitalWrite(audible, digitalRead(audible) == HIGH ? LOW : HIGH);
    audible_start = millis();
  }
  if (flash_state && millis() - flash_start > 125) {
    digitalWrite(flash, digitalRead(flash) == HIGH ? LOW : HIGH);
    flash_start = millis();
  }
}

Many thanks to making the on/off function work for the blinking signal.!! :star_struck:

Code is normally written, not searched, what did stop you from creating it yourself?

flash was already blinking.

This creates a case in which the starting timestamps could be different,
if a couple of milliseconds don't matter, that's ok.

To make the 'a' option control all the blinking, you could add

vibrate_state = audible_state = flash_state = blueled_state = allsignals_state;

I tried that and it doesn't perform anything. I tried writing it as:


const uint8_t vibrate=12;
const uint8_t audible=11;
const uint8_t flash=10;
const uint8_t blueled=9;

bool vibrate_state;
bool audible_state;
bool flash_state;
bool blueled_state;
bool allsignals_state;
uint32_t vibrate_start;
uint32_t audible_start;
uint32_t flash_start;
 

void setup()
{
  
  Serial.begin(9600);
  pinMode(vibrate, OUTPUT);
  pinMode(audible, OUTPUT);
  pinMode(flash, OUTPUT);
  pinMode(blueled, OUTPUT);
 
}

void loop() {
 if (Serial.available()) {
    uint8_t Received = Serial.read();
    Serial.println(Received);
    switch (Received) {
      case 'v':
        vibrate_state = !vibrate_state;
        digitalWrite(vibrate, vibrate_state ? HIGH : LOW);
        if (vibrate_state) {
          vibrate_start = millis();
        }
        break;
      case 's':
        audible_state = !audible_state;
        digitalWrite(audible, audible_state ? HIGH : LOW);
        if (audible_state) {
          audible_start = millis();
        }
        break;
      case 'f':
        flash_state = !flash_state;
        digitalWrite(flash, flash_state ? HIGH : LOW);
        if (flash_state) {
          flash_start = millis();
        }
        break;
       case 'b':
        blueled_state = !blueled_state;
        digitalWrite(blueled, blueled_state ? HIGH : LOW);
        break;
      case 'a':
        allsignals_state = !allsignals_state;
        digitalWrite(vibrate, vibrate_state ? HIGH : LOW);
        if (vibrate_state) {
          vibrate_start = millis();
        }
        digitalWrite(flash, flash_state ? HIGH : LOW);
        if (flash_state) {
          flash_start = millis();
        }
        digitalWrite(audible, audible_state ? HIGH : LOW);
        if (audible_state) {
          audible_start = millis();
        }
        break;
    }
  }
  if (vibrate_state && millis() - vibrate_start > 500) {
    digitalWrite(vibrate, digitalRead(vibrate) == HIGH ? LOW : HIGH);
    vibrate_start = millis();
  }
  if (audible_state && millis() - audible_start > 125) {
    digitalWrite(audible, digitalRead(audible) == HIGH ? LOW : HIGH);
    audible_start = millis();
  }
  if (flash_state && millis() - flash_start > 125) {
    digitalWrite(flash, digitalRead(flash) == HIGH ? LOW : HIGH);
    flash_start = millis();
  }
}

This didn't perform either. I am trying to get the allsignal_state to read the code at the bottom where the timestamp can be altered.

BTW- How do I show text highlighted in this?

I GOT IT!!!

The allsignals_state = !allsignals_state; had no funtion to call to. I removed that line and added the flash_state, vibrate_state and audible_state command lines to each function. Now it performs as needed.

@Whandall I never thought to use the 'if' function as the end for each function. I sincerely appreciate your input and helping me with this.

Many thanks to the the Arduino Forum!

:+1: :grinning: :grinning: :+1:

const uint8_t vibrate=12;
const uint8_t audible=11;
const uint8_t flash=10;
const uint8_t blueled=9;

bool vibrate_state;
bool audible_state;
bool flash_state;
bool blueled_state;
bool allsignals_state;
uint32_t vibrate_start;
uint32_t audible_start;
uint32_t flash_start;
 

void setup()
{
  
  Serial.begin(9600);
  pinMode(vibrate, OUTPUT);
  pinMode(audible, OUTPUT);
  pinMode(flash, OUTPUT);
  pinMode(blueled, OUTPUT);
 
}

void loop() {
 if (Serial.available()) {
    uint8_t Received = Serial.read();
    Serial.println(Received);
    switch (Received) {
      case 'v':
        vibrate_state = !vibrate_state;
        digitalWrite(vibrate, vibrate_state ? HIGH : LOW);
        if (vibrate_state) {
          vibrate_start = millis();
        }
        break;
      case 's':
        audible_state = !audible_state;
        digitalWrite(audible, audible_state ? HIGH : LOW);
        if (audible_state) {
          audible_start = millis();
        }
        break;
      case 'f':
        flash_state = !flash_state;
        digitalWrite(flash, flash_state ? HIGH : LOW);
        if (flash_state) {
          flash_start = millis();
        }
        break;
       case 'b':
        blueled_state = !blueled_state;
        digitalWrite(blueled, blueled_state ? HIGH : LOW);
        break;
      case 'a':
        vibrate_state = !vibrate_state;
        digitalWrite(vibrate, vibrate_state ? HIGH : LOW);
        if (vibrate_state) {
          vibrate_start = millis();
        }
        flash_state = !flash_state;
        digitalWrite(flash, flash_state ? HIGH : LOW);
        if (flash_state) {
          flash_start = millis();
        }
        audible_state = !audible_state;
        digitalWrite(audible, audible_state ? HIGH : LOW);
        if (audible_state) {
          audible_start = millis();
        }
        break;
    }
  }
  if (vibrate_state && millis() - vibrate_start > 500) {
    digitalWrite(vibrate, digitalRead(vibrate) == HIGH ? LOW : HIGH);
    vibrate_start = millis();
  }
  if (audible_state && millis() - audible_start > 125) {
    digitalWrite(audible, digitalRead(audible) == HIGH ? LOW : HIGH);
    audible_start = millis();
  }
  if (flash_state && millis() - flash_start > 125) {
    digitalWrite(flash, digitalRead(flash) == HIGH ? LOW : HIGH);
    flash_start = millis();
  }
}

Then you made some error,

Nope, you programmed something different.

There is a difference between switching all blinking on and off,
and flipping all the individual blinking states.

If that is what you wanted, you did not express it before.