Code runs properly only when Arduino is connected to PC

I am developing a simple Arduino-based device that is intended to operate completely standalone with no connection to a PC. The device is a fairly straightforward turn signal light controller for motorcycle use. I connect to a PC only for programming the device, testing and troubleshooting.

I have run into a situation: certain parts of the code (having to do with operating a multi-state push button) work properly only when the Arduino is connected to the PC. As soon as I disconnect the device, the pushbutton code stops working properly.

The oddest part is that I have parallel code for a Left pushbutton and for a Right pushbutton. Apart from the Left/Right differences, the code for the two buttons is identical. When the Arduino is disconnected from the PC the Right pushbutton code stops working, but the Left pushbutton code continues to work as it should. When connected, both pushbuttons works fine.

I do have the Serial.begin(9600) command in setup, but I do not use any Serial commands in the code except when I need to troubleshoot something--like now.

I have not included any code because I am looking for general pointers about what might cause this sort of behavior and how to troubleshoot it since when the Arduino is connected via USB, the code works and there is nothing to troubleshoot. Very frustrating.

Thanks in advance for any suggestions.

Peter

(deleted)

99% missing or faulty GND connection.

I do have the Serial.begin(9600) command in setup

I just did a little test.

I took the Blink example and put a Serial.begin right after the Led pin setup to see what happens.

Well it works with the arduino hooked up to the PC but not when only hooked up to a power supply.

If you need to do debugging look at having a flag to set so for each Serial command test for the flag.

OK just tested by bridging the TX and RX pins (Loop back) and it now runs sans the PC.

It's a Nano. A cheapo clone, and I suppose I could have a bad one.

With respect to GND connections, I have rechecked those. In addition, bad grounds would show up in other parts of this circuit.

With respect to the code, it would take you longer to understand what I've written than you'd be interested in spending, but I will say this: The code in question calls a subroutine that reads the state of the Right hand turn signal switch (a momentary pushbutton) and returns one of 4 states: 1= single push, 2=double push, 3=long push, and 4=very long push. Here is my loop code:

if (Momentary == true)
{
    rb = checkRButton();          //Read the right button and return code
    if (rb == 1)                        //Single push returns 1, double-push returns 2
    {
      R_SIGNAL_ON=true;
      L_SIGNAL_ON=false; 
      SIGNAL_COUNT=0;           // additional push restarts the counter
    }
    if (rb == 3) HAZARD_LONG();   //long push returns 3, extra long push returns 4

}

if (Momentary == false)
{
  if (digitalRead(Rin) == LOW)  //logic LOW indicates switch is ON
  {
      R_SIGNAL_ON=true;
      L_SIGNAL_ON=false; 
  }
  else
  {
    R_SIGNAL_ON=false;
  } 
}

Momentary is a variable set by reading the state of a data pin which is basically an ON/OFF selector switch. When the selector is ON, Momentary is set TRUE to indicate that the motorcycle's turn signal control is a momentary pushbutton type as opposed to an ON/OFF toggle switch.

When the Nano is connected to a PC and Momentary is True, the code properly reads the state of the pushbutton switch, and my code does what it is supposed to do based on that. When the Nano is NOT connected to a PC, then as soon as the device is powered up, it acts as though the pushbutton is being held closed. The checkRbutton code apparently returns a code of 3 because the device launches the HAZARD_LONG routine which runs a 4-way hazard flasher.

I can turn that hazard routine off with another pushbutton, and after that, the Rbutton appears unresponsive.

If Momentary is false, indicating that the turn signal switch is an ON/OFF toggle, then the code above functions properly whether the Nano is connected to the PC or not.

As I said earlier, the Left turn signal uses exactly the same code (but with its own set of variables to avoid confusion with the variables used for the checkRbutton subroutine) and the Left button continues to function properly when Momentary is true whether the device is connected to as PC or not.

I have checked that the checkRButton and checkLbutton code is the same, and I can see nothing in it that should have anything to do with whether the Nano is connected to the PC. If you feel like you want to see that code, I am happy to include it.

Peter

justone:
I just did a little test.

I took the Blink example and put a Serial.begin right after the Led pin setup to see what happens.

Well it works with the arduino hooked up to the PC but not when only hooked up to a power supply.

If you need to do debugging look at having a flag to set so for each Serial command test for the flag.

OK just tested by bridging the TX and RX pins (Loop back) and it now runs sans the PC.

Interesting. Do you mean that with the Serial.begin line in place, and no connection to the PC, the LED does not blink?

I have tried my code with the Serial.begin line commented out, and it didn’t change the misbehavior. I have not tried bridging TX and RX, but will do so. That’s safe to do? Just a jumper?

(deleted)

That’s safe to do? Just a jumper?

Well to be safe just use a 1K or a 2.2K resistor as the jumper.

But at least post your code as it works on the PC and not some butchered up code in trying to make it work

without the PC.

justone:
I just did a little test.

I took the Blink example and put a Serial.begin right after the Led pin setup to see what happens.

Well it works with the arduino hooked up to the PC but not when only hooked up to a power supply.

I find this extraordinary. I have never noticed any problem with my Arduno programs running when powered without a USB connection.

I think the following slightly modified version of the Blink example reflects what @justone did.

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(500);              // wait for a half second
  Serial.println("I'm blinking ...");

}

When my Uno is connected to the USB port the LED flashes and if I open a terminal I see the message repeating.

If I disconnect the Uno from the USB port and power it from a pack of 3 x AA cells (4.5v) connected to GND and the 5v pin the LED flashes in exactly the same way.

...R

Here is the complete code (Part 2, the button codes) that works when the PC is connected. Maybe I have missed something.

int checkLButton()  //Separate routnes needed for each button. Otherwise they step on each other's variables.
{ 
 int Levent = 0;
 // Read the state of the button
 LbuttonVal = digitalRead(Lin);
 //Serial.print ("Pin is: "); Serial.print(TestPin); Serial.print("   value is: "); Serial.println(buttonVal);
 //buttonVal=-buttonVal;
 // Button pressed down
 if (LbuttonVal == LOW && LbuttonLast == HIGH && (millis() - LupTime) > debounce) {
 LdownTime = millis();
 LignoreUp = false;
 LwaitForUp = false;
 LsingleOK = true;
 LholdEventPast = false;
 LlongHoldEventPast = false;
 if ((millis()-LupTime) < DCgap && LDConUp == false && LDCwaiting == true) LDConUp = true;
 else LDConUp = false;
 LDCwaiting = false;
 }
 // Button released
 else if (LbuttonVal == HIGH && LbuttonLast == LOW && (millis() - LdownTime) > debounce) { 
 if (not LignoreUp) {
 LupTime = millis();
 if (LDConUp == false) LDCwaiting = true;
 else {
 Levent = 2;
 LDConUp = false;
 LDCwaiting = false;
 LsingleOK = false;
 }
 }
 }
 // Test for normal click event: DCgap expired
 if ( LbuttonVal == HIGH && (millis()-LupTime) >= DCgap && LDCwaiting == true && LDConUp == false && LsingleOK == true) {
 Levent = 1;
 LDCwaiting = false;
 }
 // Test for hold
 if (LbuttonVal == LOW && (millis() - LdownTime) >= holdTime) {
 // Trigger "normal" hold
 if (not LholdEventPast) {
 Levent = 3;
 LwaitForUp = true;
 LignoreUp = true;
 LDConUp = false;
 LDCwaiting = false;
 //downTime = millis();
 LholdEventPast = true;
 }
 // Trigger "long" hold
 if ((millis() - LdownTime) >= longHoldTime) {
 if (not LlongHoldEventPast) {
 Levent = 4;
 LlongHoldEventPast = true;
 }
 }
 }
 LbuttonLast = LbuttonVal;
 
 return Levent;
}
int checkRButton()
{ 
 int Revent = 0;
 // Read the state of the button
 RbuttonVal = digitalRead(Rin);
 //Serial.print ("Pin is: "); Serial.print(TestPin); Serial.print("   value is: "); Serial.println(buttonVal);
 //buttonVal=-buttonVal;
 // Button pressed down
 if (RbuttonVal == LOW && RbuttonLast == HIGH && (millis() - RupTime) > debounce) {
 RdownTime = millis();
 RignoreUp = false;
 RwaitForUp = false;
 RsingleOK = true;
 RholdEventPast = false;
 RlongHoldEventPast = false;
 if ((millis()-RupTime) < DCgap && RDConUp == false && RDCwaiting == true) RDConUp = true;
 else RDConUp = false;
 RDCwaiting = false;
 }
 // Button released
 else if (RbuttonVal == HIGH && RbuttonLast == LOW && (millis() - RdownTime) > debounce) { 
 if (not RignoreUp) {
 RupTime = millis();
 if (RDConUp == false) RDCwaiting = true;
 else {
 Revent = 2;
 RDConUp = false;
 RDCwaiting = false;
 RsingleOK = false;
 }
 }
 }
 // Test for normal click event: DCgap expired
 if ( RbuttonVal == HIGH && (millis()-RupTime) >= DCgap && RDCwaiting == true && RDConUp == false && RsingleOK == true) {
 Revent = 1;
 RDCwaiting = false;
 }
 // Test for hold
 
 if (RbuttonVal == LOW && (millis() - RdownTime) >= holdTime) {
 // Trigger "normal" hold
 if (not RholdEventPast) {
 Revent = 3;
 RwaitForUp = true;
 RignoreUp = true;
 RDConUp = false;
 RDCwaiting = false;
 //downTime = millis();
 RholdEventPast = true;
 }
 // Trigger "long" hold
 if ((millis() - RdownTime) >= longHoldTime) {
 if (not RlongHoldEventPast) {
 Revent = 4;
 RlongHoldEventPast = true;
 }
 }
 }
 RbuttonLast = RbuttonVal;
 
 return Revent;
}

int checkHButton()
{ 
 int Hevent = 0;
 // Read the state of the button
 HbuttonVal = digitalRead(HazPin);
 //Serial.print ("Pin is: "); Serial.print(TestPin); Serial.print("   value is: "); Serial.println(buttonVal);
 //buttonVal=-buttonVal;
 // Button pressed down
 if (HbuttonVal == LOW && HbuttonLast == HIGH && (millis() - HupTime) > debounce) {
 HdownTime = millis();
 HignoreUp = false;
 HwaitForUp = false;
 HsingleOK = true;
 HholdEventPast = false;
 HlongHoldEventPast = false;
 if ((millis()-RupTime) < DCgap && HDConUp == false && HDCwaiting == true) HDConUp = true;
 else HDConUp = false;
 HDCwaiting = false;
 }
 // Button released
 else if (HbuttonVal == HIGH && HbuttonLast == LOW && (millis() - HdownTime) > debounce) { 
 if (not HignoreUp) {
 HupTime = millis();
 if (HDConUp == false) HDCwaiting = true;
 else {
 Hevent = 2;
 HDConUp = false;
 HDCwaiting = false;
 HsingleOK = false;
 }
 }
 }
 // Test for normal click event: DCgap expired
 if ( HbuttonVal == HIGH && (millis()-HupTime) >= DCgap && HDCwaiting == true && HDConUp == false && HsingleOK == true) {
 Hevent = 1;
 HDCwaiting = false;
 }
 // Test for hold
 
 if (HbuttonVal == LOW && (millis() - HdownTime) >= holdTime) {
 // Trigger "normal" hold
 if (not HholdEventPast) {
 Hevent = 3;
 HwaitForUp = true;
 HignoreUp = true;
 HDConUp = false;
 HDCwaiting = false;
 //downTime = millis();
 HholdEventPast = true;
 }
 // Trigger "long" hold
 if ((millis() - HdownTime) >= longHoldTime) {
 if (not HlongHoldEventPast) {
 Hevent = 4;
 HlongHoldEventPast = true;
 }
 }
 }
 HbuttonLast = HbuttonVal;
 
 return Hevent;
}

Hi,

Can you please post a complete copy of your code please?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Do you have a DMM?

Thanks.. Tom... :slight_smile:

The code does not behave differently, depending on the power source. The bug must sit outside the controller. A circuit diagram were helpful.

Here is the complete code Part 1, the variables. The button click code got posted first–sorry.

//#include <SoftwareSerial.h>
unsigned long LOOPTIME;         //The current time from millis()
unsigned long HAZARD_TIME;      //(ms) last time hazard was toggled
unsigned long SIGNAL_TIME;      //(ms) last time signal light was toggled
int FLASH_INTERVAL=500;         //desired length (in ms) of a regular flash half-cycle
int FLASH_INTERVAL_SHORT=600;   //desired length (in ms) of a short flash half-cycle
int FLASH_INTERVAL_LONG=1100;   //desired length (in ms) of a long flash half-cycle
int MAX_SIGNAL_COUNT;           //maximum number of signal half-cycles before cancellation.  Set later by Pot.
int MAX_HAZARD_COUNT=12000;     //desired max number of hazard half-cycles before cancellation
int SIGNAL_COUNT;               //number of half-cycles the signals have been blinking since turn on
int HAZARD_COUNT;               //number of half-cycles the hazard lights have been blinking
int HAZARD_LIGHTS_STATE=0;      //0,1 current state of hazard light outputs 
int HAZARD_S_STATE=0;           //0,1 current state of HAZARD_S function
int HAZARD_L_STATE=0;           //0,1 current state of HAZARD_L function
int L_OUT_STATE;                //0,1 current state of L_OUT
int R_OUT_STATE;                //0,1 current state of R_OUT
boolean L_SIGNAL_ON=false;
boolean R_SIGNAL_ON=false;

int DelayPotInput=A2;           //Potentiometer is used to set signal flash maximum 
int DelayPotValue;
int DimPotInput=A1;              //Potentiometer used to set PWM delay
int DimPotValue;
int PWMBrightness;
int CancelSensor=A0;            //Hall sensor is supplied with 5v and returns approx. 0-2V depending
int CancelValue;                //proximity of magnet in switch.  Highest voltage signifies CANCEL. 
// IS there a reliably detectabe CancelValue when the control is present?  As opposed to not installed
// Use to autodetect whether cancel switch is available.
boolean CancelState=false;
int Lin=2;                      //Define pins for left and right signal inputs
int Rin=3;
int Lout=6;                     //Define pins for left and right signal outputs 
int Rout=7;
int Lrun=9;                     //Define pins for left and right running light outputs.  Must be PWM pins
int Rrun=10;
int SignalWirePin=8;            //Pin to selecte 2-3wire operation. When pin is brought LOW (externally wired to GND), selects 2-wire.
boolean TwoWire;
int MomentaryPin=4;
boolean Momentary;
int AltPower=11;                //Define pin to signal whether AltPower should be supplied
int lb=0;
int rb=0;
int hb=0;
int HazPin=12;                  //Define pin for Hazard pushbutton
int PressType;

// Common button timing variables
int debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 250; // max ms between clicks for a double click event
int holdTime = 2000; // ms hold period: how long to wait for press+hold event
int longHoldTime = 5000; // ms long hold period: how long to wait for press+hold event

// Need a separate set of variables for each button otherwise they step on each other.
// Unfortunately, it also means separate button checking routines for each button.
// Left button variables
boolean LbuttonVal = HIGH; // value read from button
boolean LbuttonLast = HIGH; // buffered value of the button's previous state
boolean LDCwaiting = false; // whether we're waiting for a double click (down)
boolean LDConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean LsingleOK = true; // whether it's OK to do a single click
long LdownTime = -1; // time the button was pressed down
long LupTime = -1; // time the button was released
boolean LignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean LwaitForUp = false; // when held, whether to wait for the up event
boolean LholdEventPast = false; // whether or not the hold event happened already
boolean LlongHoldEventPast = false;// whether or not the long hold event happened already

// Right button variables
boolean RbuttonVal = HIGH; // value read from button
boolean RbuttonLast = HIGH; // buffered value of the button's previous state
boolean RDCwaiting = false; // whether we're waiting for a double click (down)
boolean RDConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean RsingleOK = true; // whether it's OK to do a single click
long RdownTime = -1; // time the button was pressed down
long RupTime = -1; // time the button was released
boolean RignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean RwaitForUp = false; // when held, whether to wait for the up event
boolean RholdEventPast = false; // whether or not the hold event happened already
boolean RlongHoldEventPast = false;// whether or not the long hold event happened already

// Hazard button variables
boolean HbuttonVal = HIGH; // value read from button
boolean HbuttonLast = HIGH; // buffered value of the button's previous state
boolean HDCwaiting = false; // whether we're waiting for a double click (down)
boolean HDConUp = false; // whether to register a double click on next release, or whether to wait and click
boolean HsingleOK = true; // whether it's OK to do a single click
long HdownTime = -1; // time the button was pressed down
long HupTime = -1; // time the button was released
boolean HignoreUp = false; // whether to ignore the button release because the click+hold was triggered
boolean HwaitForUp = false; // when held, whether to wait for the up event
boolean HholdEventPast = false; // whether or not the hold event happened already
boolean HlongHoldEventPast = false;// whether or not the long hold event happened already

Here is the code for the Setup and Loop. Other subroutines to follow as soon as I can get them undere the 9000 character postng limit...

void setup()
{
  //Serial.begin(9600);
  pinMode(DimPotInput,INPUT);
  pinMode(DelayPotInput,INPUT);
  pinMode(Lin,INPUT_PULLUP);
  pinMode(Rin,INPUT_PULLUP);
  pinMode(Lout,OUTPUT);
  pinMode(Rout,OUTPUT);
  pinMode(Lrun,OUTPUT);
  pinMode(Rrun,OUTPUT);
  pinMode(HazPin, INPUT_PULLUP);
  pinMode(SignalWirePin, INPUT_PULLUP);
  pinMode(MomentaryPin,INPUT_PULLUP);
  pinMode(AltPower,OUTPUT);
  digitalWrite(HazPin, HIGH );
  digitalWrite(Lin, HIGH);
  digitalWrite(Rin, HIGH);
  
    
}

void loop()
{
    //Read DelayPot and set MAX_SIGNAL_COUNT
    DelayPotValue=analogRead(DelayPotInput);          
    MAX_SIGNAL_COUNT=map(DelayPotValue,0,1023,0,200);

      //Allow user to turn off self-cancel by setting DelayPotValue to 0
      if (MAX_SIGNAL_COUNT==0)
        {
           MAX_SIGNAL_COUNT=15000;  //essentially, infinitely many cycles allowed
        }
    
    //Read DimPot and set PWMBrightness
    DimPotValue=analogRead(DimPotInput);
    PWMBrightness =map(DimPotValue,0,1023,0,255);

    //Read 2-3Wire sensor and set boolean value
    if (digitalRead(SignalWirePin)==LOW) TwoWire=true;
    else  TwoWire=false;
    
    //Read Momentary sensor and set boolean value
    if (digitalRead (MomentaryPin)==LOW) Momentary=true;
    else Momentary=false;  

    LOOPTIME = millis();               //record the current time
                //NOTE: millis() records time since the current program began, not since the loop began.
                //      It rolls over after about 50 days.  Query what happens then since this unit may be 
                //      connected to power for longer than that.

//Check to see if user has cancelled signals
  CancelValue=analogRead(CancelSensor);
  CancelValue=map(CancelValue,0,1023,1,100);  
  //In practice, the value ranges from 9 when not pressed to 45 when pressed.
  //but owing to improper positioning of the magnet, the value goes up to a maximum of 22 on a hard right signal and 36 on a hard left
  //Setting the threshhold anywhere above 40 should be safe. 
  
  //If the Cancel Sensor is not installed, then we may need code to skip over anything relating to the cancel sensor
  //On the other hand, it may be possible just to skip over anything related to the cancel button, because
  //with controlsets not so equipped, they also are not set for momentary operaton, and so the switches
  //are never in need of being "cancelled"
  //Here would be a good place to insert code detecting whether the sensor is installed and set a boolean.


 //Serial.print("Cancel value is: "); Serial.println(CancelValue);
 
   if (CancelValue >39)
  {
    L_SIGNAL_ON = false;
    R_SIGNAL_ON = false;
  }
 
 //Serial.print("Lin = "); Serial.println(digitalRead(Lin));
 //Serial.print("Rin = "); Serial.println(digitalRead(Rin));


//First, check to see if BOTH signals are on 
//this should happen only with controlsets that include a built-in Hazard switch
//that works by turning both signals on.
//Also, it can happen only with non-momentary controlsets

if (Momentary == false)
{
  if ((digitalRead(Rin) == LOW) && (digitalRead(Lin) == LOW))
  {
    MAX_HAZARD_COUNT = 1000000;
    digitalWrite(AltPower,HIGH);
    HAZ_S_BLINK();
    return;
  }
}
 

//Check Right button
if (Momentary == false)
{
  if (digitalRead(Rin) == LOW)
  {
      R_SIGNAL_ON=true;
      L_SIGNAL_ON=false; 
  }
  else
  {
    R_SIGNAL_ON=false;
  } 
}

if (Momentary == true)
{
    rb = checkRButton();          //Read the right button
    if (rb == 1)                  //Single push returns 1, double-push returns 2
    {
      R_SIGNAL_ON=true;
      L_SIGNAL_ON=false; 
      SIGNAL_COUNT=0;             // additional push restarts the counter
    }
    if (rb == 3) HAZARD_LONG();   //a long push  returns 3 and toggles HAZARD_L_STATE and cancels any HAZARD_S_STATE
                                  //A really long push registers as a 4, but 3 is reported first
}


//Check Left button
//Here, we have a difference between momentary and standard controls that cannot be overlooked.
//It does not make sense and would be misleading to check the push status of a standard button (other than digital on or off.)
//What about a momentary controlset NOT FITTED with a Cancel sensor?  We could forbid that combination.  
//We could provide a selector wire like the 2-3Wire selector.  
//We could perhaps use a DIP switch for the selectors, but then can we waterproof it?.

if (Momentary==true)
{
    lb = checkLButton();          //Read the left button
    if (lb == 1)                  //A double-push registers as 2
    {
      L_SIGNAL_ON=true;
      R_SIGNAL_ON=false; 
      SIGNAL_COUNT=0;             // additional push restarts the counter
    }
    if (lb == 3) HAZARD_SHORT();  //toggles HAZARD_S_STATE and cancels any HAZARD_L_STATE
                                  //A really long push registers as a 4, but 3 is reported first
}
if (Momentary == false)
{
  if (digitalRead(Lin) == LOW)  
  {
          L_SIGNAL_ON=true;
          R_SIGNAL_ON=false; 
  }
  else
  {
    L_SIGNAL_ON=false;
    //R_SIGNAL_ON=false;
  }
}


//Now check manual Hazard Button
hb=checkHButton();
  if (hb==1) HAZARD_SHORT();
  if (hb==3) HAZARD_LONG();



  
//Now act on the HAZARD request, if any
if (HAZARD_S_STATE == HIGH)
{
  digitalWrite(AltPower,HIGH);
  HAZ_S_BLINK();
  return;
}

if (HAZARD_L_STATE == HIGH)
{
  digitalWrite(AltPower,HIGH);
  HAZ_L_BLINK();
  return;
}

//Now act on requested signal functions
if (R_SIGNAL_ON == true)
{
  R_SIGNAL_BLINK();
  return;
}

if (L_SIGNAL_ON == true)
{
  L_SIGNAL_BLINK();
  return;
}

//If all preceding tests have failed (including HazBtn activity)then there is nothing going on.
//So, ensure that all lights are returned to normal operation state and then reset variables as needed.

  LIGHTS_NORMAL();
  RESET_VARIABLES();

} //END LOOP

Here is the last of the code. Sorry for the piecemeal nature of this. Is there some way around the 9000 character limit?

void HAZARD_SHORT()
{
 if (HAZARD_L_STATE == HIGH)  //turn HAZARD_L_STATE off if it is on
 {
  HAZARD_L_STATE = !HAZARD_L_STATE;
 }
 HAZARD_S_STATE = !HAZARD_S_STATE;
}

void HAZARD_LONG()
{
 if (HAZARD_S_STATE == HIGH) //turn HAZARD_S_STATE off if it is on
 {
  HAZARD_S_STATE = !HAZARD_S_STATE;
 }
 HAZARD_L_STATE = !HAZARD_L_STATE; 
}


void HAZ_S_BLINK()
{
  //HAZARD lights will be toggled only if more time has passed than the FLASH_INTERVAL_SHORT 
  //AND we have not exceeded the maximum allowed for the hazard function.
  if (((LOOPTIME) - (HAZARD_TIME) >= (FLASH_INTERVAL_SHORT)) && (HAZARD_COUNT <= MAX_HAZARD_COUNT))
  {
    SWITCH_HAZARD_S();
    if (TwoWire==false)
    {
    digitalWrite(Lrun,LOW);
    digitalWrite(Rrun,LOW);
    }
  }
  if (HAZARD_COUNT > MAX_HAZARD_COUNT)
  {
    LIGHTS_NORMAL();
  }
}

void SWITCH_HAZARD_S()
{
  //Routine toggles the signal lights on or off, increments the count of half-cycles, and records the time this is done
  HAZARD_TIME=millis();
  HAZARD_LIGHTS_STATE= !HAZARD_LIGHTS_STATE;
  HAZARD_COUNT=HAZARD_COUNT + 1;
  digitalWrite(Lout,HAZARD_LIGHTS_STATE);
  digitalWrite(Rout,HAZARD_LIGHTS_STATE);

  //Serial.print("We're here, and 2-wire is: "); Serial.println(TwoWire);
  //Serial.print("HAZARD_LIGHTS_STATE is: "); Serial.println(HAZARD_LIGHTS_STATE);
  
  if (TwoWire==true)
  {
    digitalWrite(Lrun,HAZARD_LIGHTS_STATE);
    digitalWrite(Rrun,HAZARD_LIGHTS_STATE);
  }
}

void HAZ_L_BLINK()
    //HAZARD lights will be toggled only if more time has passed than the FLASH_INTERVAL_LONG
    //It will flash the lights indefinitely and risks running down the battery.
{
  if (((LOOPTIME) - (HAZARD_TIME)) >= (FLASH_INTERVAL_LONG))
  {
    SWITCH_HAZARD_L();
    if(TwoWire==false)
    {
      digitalWrite(Lrun,LOW);
      digitalWrite(Rrun,LOW);
    }
  }
}

void SWITCH_HAZARD_L()
{
  HAZARD_TIME=millis();
  HAZARD_LIGHTS_STATE= !HAZARD_LIGHTS_STATE;
  digitalWrite(Lout,HAZARD_LIGHTS_STATE);
  digitalWrite(Rout,HAZARD_LIGHTS_STATE);
  if (TwoWire==true)
  {
    digitalWrite(Lrun,HAZARD_LIGHTS_STATE);
    digitalWrite(Rrun,HAZARD_LIGHTS_STATE);
  }
}

void L_SIGNAL_BLINK()
  //Blinks LEFT signal until MAX_SIGNAL_COUNT is reached.  SIGNAL_COUNT is in half-cycles.
{
  if ( ((LOOPTIME) - (SIGNAL_TIME)) >= (FLASH_INTERVAL)  && (SIGNAL_COUNT <= MAX_SIGNAL_COUNT))
  {
    digitalWrite(Lrun,LOW);
    digitalWrite(Rout,LOW);   //switching directly left to right
    if (TwoWire == true) analogWrite(Rrun,PWMBrightness);
    else digitalWrite(Rrun,HIGH);
    SWITCH_L_SIGNAL();
  }
  if ((SIGNAL_COUNT) > (MAX_SIGNAL_COUNT))
  {
    L_SIGNAL_ON = false;
    digitalWrite(Lout,LOW);
    //Serial.print("TwoWire="); Serial.println(TwoWire);
    if (TwoWire == true) analogWrite(Lrun,PWMBrightness);
    else     digitalWrite(Lrun,HIGH);
  }
  
}

void SWITCH_L_SIGNAL()
  //Actually toggles the LEFT signal on or off.
{
 SIGNAL_TIME = millis();
 SIGNAL_COUNT=SIGNAL_COUNT + 1 ;
  L_OUT_STATE= !L_OUT_STATE;
 digitalWrite(Lout,L_OUT_STATE);
 if (TwoWire == true) digitalWrite(Lrun,L_OUT_STATE);
}

void R_SIGNAL_BLINK()
  //Blinks RIGHT signal until MAX_SIGNAL_COUNT is reached.   SIGNAL_COUNT is in half-cycles.
{
  if ((((LOOPTIME) - (SIGNAL_TIME)) >= (FLASH_INTERVAL))  && (SIGNAL_COUNT <= MAX_SIGNAL_COUNT))
  {
    //Here we need to make provisions for 2-wire signals
    digitalWrite(Rrun,LOW);
    digitalWrite(Lout,LOW);   //switching directly right to left
    if (TwoWire == true) analogWrite(Lrun,PWMBrightness);
    else digitalWrite(Lrun,HIGH);
    SWITCH_R_SIGNAL();
  }
  if ((SIGNAL_COUNT) > (MAX_SIGNAL_COUNT))
  {
    R_SIGNAL_ON = false;
    digitalWrite(Rout,LOW);
    if (TwoWire == true) analogWrite(Rrun,PWMBrightness);
    else digitalWrite(Rrun,HIGH);
  }
}

void SWITCH_R_SIGNAL()
  //Actually toggles the RIGHT signal on or off.
{
 SIGNAL_TIME = millis();
 SIGNAL_COUNT=SIGNAL_COUNT + 1 ;
 R_OUT_STATE= !R_OUT_STATE;
 digitalWrite(Rout,R_OUT_STATE);
 if (TwoWire == true) digitalWrite(Rrun,R_OUT_STATE);
}

void LIGHTS_NORMAL()
{
 //Sets the lights to normal without modifying any variable used to test conditions.

  digitalWrite(AltPower,LOW);
  digitalWrite(Lout,LOW);
  digitalWrite(Rout,LOW);
  if (TwoWire == true)
  {
    analogWrite(Lrun,PWMBrightness);
    analogWrite(Rrun,PWMBrightness);
  }
  else
  {
    digitalWrite(Lrun,HIGH);
    digitalWrite(Rrun,HIGH);
  }
}

void RESET_VARIABLES()
  //take care of variables that need resetting when all functions have returned to normal status.
{
  SIGNAL_COUNT=0;
  HAZARD_COUNT=0;
  HAZARD_S_STATE=0;
}

Here is the circuit I am using:

Whatever viewer I use, the labels in the image are unreadable :frowning:

Hi,
It needs to be EXPORTED at a higher resolution.
Please attach it to your post.

Tom... :slight_smile:

Sorry for the red herring. Turns out I used an older board that had a not so good design on the reset circuitry.

Here is a video to show what mislead me. At the end I replug and you can see that it starts working. Oh well.

pgsmick:
Here is the last of the code. Sorry for the piecemeal nature of this. Is there some way around the 9000 character limit?

Yes. Just add your .ino file as an attachment.

I am not going to join parts together in case I introduce errors.

...R