1

So I'm currently working on an automotive set up.

I'm using a 555 timer to emulate a turn-signal alternating voltage pulse (12V to 0V and repeat) for debugging purposes which is output to turnPin/A1.

Here's the goal: When voltage is greater than 1V arduino is to supply constant power to output pin (pin 13) until input voltage is returned to constant 0 (or end of turn signal input) for x-time or as I'll refer to as Timeout.

It seems I've gotten the constant power to apply when input is applied and then turn off constant output when voltage is back to 0V. However I'm having difficulty getting the timeout function to work properly as the LED still remains HIGH.

EDIT: I've reworked the code to use millis(); rather than purely using sensor inputs. I've also added comments to help walk you through what I believe is happened/what I want to happen.

// Constants won't change
const int ledPin = LED_BUILTIN; //using built in led + pin13
const int turnPin = A1;         // the input pin (turn signal alternating 5V/0V/5V/0V & so-forth)

// Variables will change
int ledState = LOW;             // the current state of the output pin
int prevLed = ledState;
int lastVoltage = 1;            // the previous reading from voltage source
int state = 1;                      // the current "state" (see below)
                                // State = 1++: LED OFF -- State = 0: LED ON

// The following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.

long previousMillis = 0;    //the last time the voltage reached 0
long waitTime = 100;    // the wait time

void setup()
{
  pinMode(ledState, OUTPUT);        //set output pin
  pinMode(turnPin, INPUT);          //set input pin NOTE: SIGNAL ALTERNATES 
5V/0V/5V/0V & so forth to emulate a turn signal for this application
  Serial.begin(9600);               //begin serial
}

void loop()
{
  int sensorValue = analogRead(turnPin);        // Read voltage at input pin
  float voltage = sensorValue * (5.0/1023.0);   // Convert
  unsigned long currentMillis = millis();    // set currentMillis as current 
 time


  if (voltage > 1)      //if Voltage greater than 1V
  {
    ledState = HIGH;    //turn led on
    state = 0;          //set state to 0
  }

  if (voltage < 1)      //if voltage less than 1V
  {   
    currentMillis;      //set currentMillis as current time

    if ((millis() - currentMillis) > waitTime) // if (current time minus time voltage was less than 1) is greater than wait time
    {
        ledState = LOW;     //set LED to off
        Serial.print("OFF - TIMED OUT - WAITING FOR INPUT: ");  //output message for debug 
        Serial.println(state);//current state
        state++;              //increment state (time passed)
    }
        else if ((millis() - currentMillis) < waitTime) // if (current time minus time voltage was less than 1) is less than wait time
        {
            ledState = HIGH;    //set LED to on
        }
  }
  digitalWrite(ledPin, ledState);   //send LED status to output
}
  • When voltage > 1 .... larger than one what? potato? .... it is really unclear what you are asking, a few commas in some of your sentences would help – jsotola Jun 1 '18 at 1:39
  • @jsotola "Voltage > 1 Volt" - My apologies thought it was assumed. And No. I didn't read it after I wrote it! My bad! Haha. Updated. – Taylor Jones Jun 1 '18 at 1:46
  • if (sensorValue < 1 > currentMillis + 500) What the heck is this line supposed to mean? – Delta_G Jun 1 '18 at 2:04
  • @Delta_G if sensorValue greater than 1 for greater than current time + 500 then -> Was a late-night I'm-done-for-the-night hoo-rah. – Taylor Jones Jun 1 '18 at 2:06
  • 1
    you assign this variable float voltage = sensorValue * (5.0 / 1023.0); , but you do not use the variable voltage anywhere in your code – jsotola Jun 1 '18 at 4:30
1

Thanks for everyone's input. I've come up with the solution.

Using the while function I was able to create two "states" for the code to be in. A timed-out state and not timed-out state, respectively. While in the timed-out state the output will be 0 and vice-versa for the latter and wait for the voltage to reach 0 for "X" amount of time.

I also integrated a "learn" feature to set the delay based on the alternating input voltage if necessary. Otherwise it will default to the value within the timeoutWait variable.

Code is below. Please let me know if you have any input/suggestions.

/*
  PURPOSE: This application was built for an automotive application. Client replaced OEM turn signal's with aftermarket multicolor
  LED strips controlled by an unknown controller. In order for the turn signal function of the LED strips to work the
  controller had to be powered on. It was undesired to run the LED's every time the vehicle was driven. Therefore, the
  controller needed to be supplied constant power when an input from the OEM turn signal wiring (which alternates 16V/0V/16V/0V...
  and so-forth was applied.

  OVERVIEW: In a nutshell: this application will supply constant output to any specified output (pin 13 in this case) when 5 Volts is
  applied to any specified Analog input (pin A1 in this case). When voltage to the input pin is discontinued after 250milliseconds
  the constant output will be terminated. The application will then wait for voltage to be resupplied to the input pin.

  This application will also support an alternating input source (turn signal in this case). The amount of time to wait before returning
  the output pin to an OFF state is determined one of two methods.

  METHOD 1: Setting a default by amending the timeoutWait variable.
  METHOD 2: Using the Learn Button to time voltage drops and adjust the time-out wait time accordingly (+ 50 milliseconds for any variations in timing)

  USING THE LEARN BUTTON: At any point in time, press and hold the push button for approximately 6-seconds (real time - non simulation). This will
  time the difference in time between Voltage > 1 and Voltage < 1 and set it as the timeoutWait time. NOTE: The variable timeoutWait is not updated!
  The variable blinkRate is updated with this data.

  CIRCUIT: For emulation purposes a circuit was built using a 5V Power Supply connected to an ATTINY microprocessor (to emulate the alternating
  turn signal of 5V/0V/5V/0V alternation every 250milliseconds) connected to pin A1 on an Arduino UNO R3. An LED with a 1kΩ resistor was connected to pin 13.
  The learn button is powered and grounded from the arduino board with a 10kΩ resistor and connected to Digital Pin 2 on the arduino board.*/

// Constants won't change
int output = 13;            // Pin to output voltage
int input = A1;             // Pin to receive voltage
int learnButton = 2;        // Pin to receive signal for learn mode
int waitTime = 500;         // Time to wait in milliseconds
int timeoutWait = 250;      // Time to wait in milliseconds

// These variables will change
int relayState = LOW;       // Track what state the relay is in
bool timeout = false;       // Track if we're timed-out or not
bool learnMode = false;     // Track if we're supposed to be in learn mode or not
int blinkRate = 0;          // Store blink interval in millis (obtained from learn mode)
int lastButtonState = 0;    // Track the last state of the learn button
int buttonState = 0;        // Track the current state of the learn button

// The following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long timerStart = 0;        // Track when timer started
long timerStop = 0;         // Track when timer stopped
long passedTime = 0;        // Track time elapsed =(timerStop - timerStart)
long blinkStart = 0;        // Track when blink HIGH (learn mode)
long blinkStop = 0;         // Track when blink LOW  (learn mode)

void setup()
{
  pinMode(relayState, OUTPUT); // Set output pin
  pinMode(input, INPUT);       // Set input pin
  pinMode(learnButton, INPUT); // Set input pin (learn mode)
}

void loop()
{
  int sensorValue = analogRead(input);          // Read voltage at input pin
  float voltage = sensorValue * (5.0 / 1023.0); // Convert
  buttonState = digitalRead(learnButton);       // Read the learnButton pin
  Serial.begin(9600);                           //  Begin serial communication

  if (buttonState == HIGH)  // If the learnButton is pressed
  {
    learnMode = true;   // Enter learnMode
  }
  delay(50);        // Debounce

      if (voltage > 1)    // If Voltage is Greater Than 1 Volt
  {
    timeout = false;  // Set timeout state to FALSE since there's no reason to timeout
    passedTime = 0;   // Reset passedTime variable
    timerStart = 0;   // Reset timerStart variable
    timerStop = 0;    // Reset timerStop variable
  }

  if (voltage < 1)  //If Voltage is Less Than 1 Volt
  {
    timerStart = millis();                 // Start the timeout timer
    delay(waitTime);                       // How long should we wait until it times out?
    timerStop = millis();                  // Stop the timeout timer
    passedTime = (timerStop - timerStart); // Calculate how much time we waited

    if (passedTime >= waitTime) //If the calculated time is greater than or equal to our wait time
    {
      sensorValue;      // Re-check the Voltage first

      if (voltage < 1)  // If the voltage is still Less Than 1 Volt
      {
        timeout = true; // Set timeout state to TRUE since the voltage has been less than 1 Volt for >= our Wait Time
        timerStart = 0; // Reseet timerStart variable
        timerStop = 0;  // Reset timerStop variable
        passedTime = 0; // Reset passedTime variable
      }
    }
  }

  while (timeout == true)                    // If TIMEOUT = TRUE
  {
    relayState = LOW;                        // Set the relay state to LOW/OFF
    sensorValue = analogRead(input);         // Read voltage at input pin
    voltage = sensorValue * (5.0 / 1023.0);  // Convert
    digitalWrite(output, relayState);        // Tell the relay to turn off

    if (voltage > 1)    // if the voltage is Greater Than 1 Volt
    {
      timeout = false;  // Set timeout state to FALSE since there's no reason to timeout
      timerStart = 0;   // Reseet timerStart variable
      timerStop = 0;    // Reset timerStop variable
      passedTime = 0;   // Reset passedTime variable

    }

    if (voltage < 1)
    {
      timeout = true; // Set timeout state to TRUE since the voltage has been less than 1 Volt
      timerStart = 0; // Reseet timerStart variable
      timerStop = 0;  // Reset timerStop variable
      passedTime = 0; // Reset passedTime variable
    }
  }

  while (timeout == false)  // If TIMEOUT = FALSE
  {
    sensorValue = analogRead(input);        // Read voltage at input pin
    voltage = sensorValue * (5.0 / 1023.0); // Convert
    relayState = HIGH;                      // Set the relay to ON/HIGH since we're not timed out
    digitalWrite(output, relayState);       // The the relay to turn on
    buttonState = digitalRead(learnButton); // Read the learnButton pin

    if (buttonState == HIGH)  // If the learnButton is pressed
    {
      learnMode = true; // Enter learnMode
    }
    delay(50);        // Debounce

    if (voltage < 1)  // If the voltage is Less Than 1 Volt
    {
      timerStart = millis();                // Start the timeout timer

      if (blinkRate > 100)          // If blinkRate is Greater Than 100
      {
        timeoutWait = blinkRate + 50; // Set timeoutWait to blinkRate value + 50 milliseconds for any variations in timing
      }
      else                // If blinkRate is not Greater Than 100
      {
        timeoutWait = timeoutWait; // Leave default value alone
      }

      delay(timeoutWait);                     // How long should we wait to timeout in this state?
      timerStop = millis();                   // Stop the timeout timer
      passedTime = (timerStop - timerStart);  // Calculate how much time we waited

      if (passedTime >= timeoutWait)  //If the calculated time is greater than or equal to our assigned wait time
      {
        sensorValue;        //Re-check the sensor first

        if (voltage < 1)    //If the sensor read less than 1 Volt
        {
          relayState = LOW; //Set the relay state to OFF/LOW.
          timeout = true;   //Keep us in the timed out state.
          timerStart = 0;   //Reset timerStart variable.
          timerStop = 0;    //Reset timerStop variable.
          passedTime = 0;   //Resed passedTime variable.
        }
      }
    }
  }
  while (learnMode == true)  // If LEARNMODE = TRUE
  {
    sensorValue = analogRead(input);        // Read voltage at input pin
    voltage = sensorValue * (5.0 / 1023.0); // Convert
    Serial.println("LEARN MODE ACTIVE");  // Print to Serial Monitor

    while (voltage > 1)
    {
      sensorValue = analogRead(input);        // Read voltage at input pin
      voltage = sensorValue * (5.0 / 1023.0); // Convert
      blinkStart = millis();          // Set blinkStart as running millis();
      Serial.print("Start: ");          // Print to Serial Monitor
      Serial.println(blinkStart);       // Print to Serial Monitor
      delay(50);                // Debounce
    }
    while (voltage < 1)
    {
      sensorValue = analogRead(input);        // Read voltage at input pin
      voltage = sensorValue * (5.0 / 1023.0); // Convert
      blinkStop = millis();           // Set blinkStop as running millis();
      Serial.print("Stop: ");         // Print to Serial Monitor
      Serial.println(blinkStop);        // Print to Serial Monitor
      delay(50);                // Debounce
    }

    blinkRate = (blinkStop - blinkStart);   // Calculate blinkRate
    Serial.print("Blink Interval: ");     // Print to Serial Monitor
    Serial.println(blinkRate);          // Print to Serial Monitor
    delay(50);                  // Debounce
    learnMode = false;              // Exit learnMode
  }
  digitalWrite(output, relayState);       // Send relayState
}
0

It's hard to know where to start here. :)


 if (currentMillis + 500)

OK, what is that doing? It is adding 500 to currentMillis so that will be true almost all the time.


if (status = 3)

That is assigning 3 to status and then checking if it is non-zero, which it will be (it will be 3).


int turnPin = A1;
...

  int sensorValue = analogRead(A1);

Why not write:

  int sensorValue = analogRead(turnPin);

float voltage = sensorValue * (5.0 / 1023.0);

You calculate voltage but never use it. Why bother?


As for your question regarding if (currentMillis + 500) I wanted this statement to take the current time and add 500 to it and then check ...

OK, then this is the way to do that:

// see if 1/2 a second is up
if (currentMillis - previousMillis >= 500)
   {
   previousMillis = currentMillis;  // reset previousMillis
   ... do something ...
   }

BTW, previousMillis is also a variable you weren't using anywhere else.

  • Thanks for the input Nick! I've cleaned the code up a bit more - just a few minor oversights I missed. Thanks for pointing them out. As for your question regarding if (currentMillis + 500) I wanted this statement to take the current time and add 500 to it and then check if the voltage is still less than 1V - if it is then execute the ledState = LOW – Taylor Jones Jun 1 '18 at 15:42
  • See my amended answer. – Nick Gammon Jun 1 '18 at 21:45

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.