Search code examples
bluetootharduinoled

How to make a led turn on for 5 seconds after bluetooth command


I want to control an LED by bluetooth module (hc 05) on galileo gen 2. I need the following procedure: after sending a char, let's say '1', an LED connected to pin 2 turns on for 5 seconds and then it turns off and waits for another command. How could I do this?

I tried code: (This is actually for Galileo Gen 2, but my bluetooth works fine, I checked that on other example with turning led on and off)

include TimerOne.h

TTYUARTClass* gSerialOnePtr = &Serial1;
char input;
int led = 2;
long offAt = 0;

enum States  // set values for enum Mode
{   
    on,
    off
};

States currentState, nextState;

void setup()
{
  Timer1.initialize(1000000); // seting interrupt time to 1 sec
  Timer1.attachInterrupt(checkBluetooth); // Declaring ISR Function name
  gSerialOnePtr->begin(9600);        //start serial connection
 pinMode(led, OUTPUT); 
  currentState = off;
}

void loop()
{
  switch(currentState)    // android app sends letters from A to I each letter turn on different Mode.
   { 
     case on://red color
       ledOn();
       break;

     case off://green color
       ledOff();
       break;       

     default: 
       ledOff();
       break;
   }
  currentState = nextState;  //saving next mode in current mode.
}

 void checkBluetooth()        //ISR for timer1
{

    if(gSerialOnePtr->available())  // checking if data arrived from bluetooth module.
    {
      input = gSerialOnePtr->read();  // save character from serial in bt.

      if(input == '1')         
      {
        currentState = on;
      }
      else if(input == '2')         
      {  
        currentState = off;
      }
    }
}

void ledOn()
{
  if( (digitalRead(led) == LOW ) ) 
  { 
    digitalWrite(led, HIGH);
    offAt = millis() + 5000; //store var of now + 5 seconds
  }

  if(digitalRead(led) == HIGH) //if led is on
  {
      if(millis() >= offAt) //see if it's time to turn off LED
      {
         digitalWrite(led, LOW); //it's time. this also re-enables the button
      }
  }
}
void ledOff()
{
  digitalWrite(led, LOW);
}

It's not working yet...


Solution

  • I think that your problem is the line

    currentState = nextState;  //saving next mode in current mode.
    

    Try commenting it. Or, if you want to use it the way I think you want, you have to write

    void setup()
    {
      [...]
      currentState = off;
      nextState = off;
    }
    
    [...]
    
    void checkBluetooth()        //ISR for timer1
    {
        if(gSerialOnePtr->available())
        {
          input = gSerialOnePtr->read();  // save character from serial in bt.
    
          if(input == '1')         
          {
            nextState = on;
          }
          else if(input == '2')         
          {  
            nextState = off;
          }
        }
    }
    

    By the way, I'd also write

    while(gSerialOnePtr->available())
    

    So if you send it a 10 bytes array you don't have to wait for 10 seconds... Personally I'd also reduce the interrupt time to, let's say, 0.1 seconds, but that's not mandatory..

    EDIT:

    To turn off after 5 seconds, I'd write

    NON RETRIGGERABLE METHOD (i.e. if you send a '1' when it's on it will be discarded)

    unsigned long startTime;
    
    void setup()
    {
      [...]
      startTime = 0;
    }
    
    [...]
    
    void ledOn()
    {
        digitalWrite(led, HIGH);
    
        if (millis() - startTime > 5000)
            nextState = off;
    }
    
    void ledOff()
    {
        digitalWrite(led, LOW);
        startTime = millis();
    }
    

    RETRIGGERABLE METHOD (i.e. if you send a '1' when it's on the 5 seconds will start again)

    unsigned long startTime;
    
    void setup()
    {
      [...]
      startTime = 0;
    }
    
    [...]
    
    void checkBluetooth()
    {
        [...]
            if(input == '1')         
            {
                nextState = on;
                startTime = millis();
            }
            else if(input == '2')         
            { 
        [...]
    }    
    
    void ledOn()
    {
        digitalWrite(led, HIGH);
    
        if (millis() - startTime > 5000)
            nextState = off;
    }
    
    void ledOff()
    {
        digitalWrite(led, LOW);
    }