Turn relay on from Bluetooth for certain amount of seconds

I am working on two way communication between arduino and android phone. Currently everything is working, however I have couple of issues I have been trying to solve recently.

How I can ignite ignition for 5 seconds? I mean if IgnitionPin is on HIGH, run it for 5 seconds then automatically turn off? There is an easy way with delay, but it will not work in my case as don't want any other delays to slow up my script.

SoftwareSerial BTserial(12,13);

char choice;

// Buttons
int IgnitionPin = 10;

const int loopDelay = 50;

unsigned int ignitionCountTime = 0;
unsigned int ignitionRunTime = 50; 
bool ignitionRun = false;

void setup() 
{
  Serial.begin(115200);
  Serial.println("Enter AT commands:");

  BTserial.begin(115200);  

  sensors.begin(); 

  // Set Pin as an output pin
  digitalWrite(IgnitionPin, HIGH);
  
  pinMode(IgnitionPin, OUTPUT);
}
 
void loop()
{
  // read it and store it in 'val'
  if (BTserial.available())
  {
    choice = BTserial.read();
    Serial.write(BTserial.read());
  }

  if( choice == 'm' )
  {
    digitalWrite(IgnitionPin, HIGH);
    ignitionRun = true;
  }

  while (digitalRead(IgnitionPin) == HIGH)
  {
    ignitionCountTime = ignitionCountTime + 1;

    if ((ignitionCountTime == ignitionRunTime) && (digitalRead(IgnitionPin) == HIGH))
    {
      ignitionRun = false;
      ignitionCountTime = 0;
      digitalWrite(IgnitionPin , LOW);
    }
  }
 
 delay(loopDelay);
}

Non-blocking timing tutorials:
Blink without delay().
Beginner's guide to millis().
Several things at a time.

I have removed all other questions and tried your solution but my relay is blinking constantly. I am not sure how to exit and why it does not exit the loop even with ignitionRun = false

Are you keeping us up on what code that you are using? If you make changes to the code, post the latest version in a new post, please.

where does choice get updated? won't it always be == to 'm' each iteration of loop()?

shouldn't the delay be inside the while loop? otherwise it just races thru the count and sets the pin LOW

I have updated my code with your proposal. Now it seems to work better. However now after sending command "m" relay is ON for amount of time specified, but then after sending another "m" command nothing happens. How to make it work so that after sending command "m" relay would stay ON for 5 seconds and then go OFF. Then after sending "m" again it would perform the same action?

SoftwareSerial BTserial(12,13);

char choice;

const int loopDelay = 50;

int IgnitionPin = 10;
unsigned long ignitionInterval = 30000;
unsigned long ignitionCountTime = 0;

void setup() 
{
  BTserial.begin(115200);  

  digitalWrite(IgnitionPin, HIGH);
  pinMode(IgnitionPin, OUTPUT);
}

void loop()
{
  if (BTserial.available())
  {
    choice = BTserial.read();
  }

  if( choice == 'm' )
  {
    digitalWrite(IgnitionPin, HIGH);
    ignitionCountTime = millis();
  }

  if (ignitionCountTime >= ignitionInterval)
  {
    digitalWrite(IgnitionPin, LOW);
  }

 choice = '\0';
 delay(loopDelay);
}

countTime i surely > interval after the first 30 sec

need to check for the difference between the current time and the timeStamp capture when 'm' received

  if ( (ignitionCountTime - millis()) >= ignitionInterval)

why is the delay() needed?

Yeah, delay is not necessary. Basically I have got now bunch of different suggestions how to get code optimized and delay is not needed as you say. I have got following code where everything works as it should, but the only question is still left, how to make delay for certain amount of seconds? Currently it does not counting real time but ticks?

SoftwareSerial BTserial(12,13);

char choice;

int ignitionState;
unsigned long ignitionInterval = 50;
unsigned long ignitionCountTime = 0;

void setup() 
{
  BTserial.begin(115200);  

  pinMode(IgnitionPin, OUTPUT);
  digitalWrite(IgnitionPin, LOW);
}

void loop()
{
  if (BTserial.available())
  {
    choice = BTserial.read();
  }

  if(choice == 'm')
  {
    ignitionState = HIGH;
    digitalWrite(IgnitionPin, ignitionState);
    ignitionCountTime = 0;
  }

  if (ignitionState == HIGH) 
  {
    ignitionCountTime = ignitionCountTime + 1;

    if (ignitionCountTime >= ignitionInterval) 
    {
      ignitionState = LOW;
    }

    digitalWrite(IgnitionPin, ignitionState);
  }

choice = '\0';
}

interval is currently 30 sec. isn't this what you want?

Do you mean

EDIT:

SoftwareSerial BTserial(12,13);

char choice;

int ignitionState;
unsigned long currentMillis;
const unsigned long period = 3000; //the value is a number of milliseconds, ie 1 second

void setup() 
{
  BTserial.begin(115200);  

  pinMode(IgnitionPin, OUTPUT);
  digitalWrite(IgnitionPin, LOW);
}

void loop()
{
  if (BTserial.available())
  {
    choice = BTserial.read();
  }

  if(choice == 'm')
  {
    ignitionState = HIGH;
    digitalWrite(IgnitionPin, ignitionState);
    currentMillis = millis();
  }

  if (ignitionState == HIGH) 
  {
    if (millis() - currentMillis >= period)
    {
      ignitionState = LOW;
    }

  digitalWrite(IgnitionPin, ignitionState);
}

choice = '\0';
}

yes, my mistake

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.