No response from automotive light module on UNO

Hi everybody,

This is my first time posting here, so I hope that everything is placed correct.
For a school project I am working on a Porsche that is being built to racing spec. To accomodate for easy use of flash to pass and patterns in hazard lights, I thought it would be nice to use an Arduino for all of this.

The Arduino should be able to switch the low and high beams on, flash the high beams several times when a specific button is pressed, activate the turn signals and switch the rainlight on the back of the vehicle.

For this, I wanted to use an Arduino Uno, combined with a MOSFET shield from Sparkfun (6 predefined MOSFET outputs). To show what is activated, I wanted to use an 16x2 LCD which I had at home, this isn't implemented in the code yet. The switches are connected to GND with the internal pull-up resistors enabled.

This is just the first part of the code, the things I have until now. When I wanted to test the code, halfway through programming the functions, I got no response at all when pushing the buttons.
What should be happening is when the LowBeamSwitch is pushed, the low beams should turn on, when the HighBeamSwitch button is pressed, the high beams should turn on and when the FlashToPassSwitch button is pressed, the high beams (and if not active already, the low beams as well) should flash 3 times. In order to not let this interfere with the regular highbeam and lowbeam functions, I set flags so they couldn't interfere.

I ran over my code several times now, but I still am unable to find the error in my code. I guess it will be in my switch debounce part, but to me it looks alright.

I would greatly appreciate any help!

Yours Sincerely,

Joël

// For programming pins 0 and 1 should be disconnected

// Pin definitions for switches
const byte LowBeamSwitch = 0;
const byte HighBeamSwitch = 1;
const byte FlashToPassSwitch = 2;


// Pin definitions for MOSFET's
const byte LowBeam = 3;
const byte HighBeam = 5;


// Constants


const int ShortFlash = 125; // Indicates the time [ms] needed for a short flash, as used in Hazard mode
const int LongFlash = 250;  // Indicates the time [ms] needed for a long flash, as used in hazard mode and turn signals
const byte FlashToPassFlashes = 3; // Indicates how many flashes are done when the flash to pass button is pressed.

const int DebounceDelay = 50; // The debounce time when a switch is activated

// Variables for debouncing
byte LowBeamSwitchState;  // The current state of the switch
byte HighBeamSwitchState;
byte FlashToPassSwitchState;


byte LastLowBeamSwitchState = 1;  // The previous state of the switch (HIGH/LOW)
byte LastHighBeamSwitchState = 1;
byte LastFlashToPassSwitchState = 1;


unsigned long LastDebounceTimeLowBeam = 0;  //Reference for measuring debounce, initialised at 0
unsigned long LastDebounceTimeHighBeam = 0;
unsigned long LastDebounceTimeFlashToPass = 0;


// Variables for millis delay
unsigned long PreviousMillisLowBeam = 0;  // Will store last time MOSFET was updated
unsigned long PreviousMillisHighBeam = 0;
unsigned long PreviousMillisFlashToPass = 0;


// Variables for toggling outputs
byte LowBeamState = 0;
byte HighBeamState = 0;


byte FlashToPassFlag = LOW; // When this flag is toggled, the flash to pass loop is active and the high beam loop is interrupted
byte LowBeamFlag = LOW; // When this flag is toggled, the LowBeam loop is active and LowBeam isn't included in flash to pass
int FlashToPassCounter = 0;

// Include the lcd library code

#include <LiquidCrystal.h>


// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(14, 15, 16, 17, 18, 19);

void setup() {
  // Initialise switches as inputs with internal pull-up resistors enabled
  pinMode (LowBeamSwitch, INPUT_PULLUP);
  pinMode (HighBeamSwitch, INPUT_PULLUP);
  pinMode (FlashToPassSwitch, INPUT_PULLUP);
 

  // Initialise MOSFET's as outputs
  pinMode (LowBeam, OUTPUT);
  pinMode (HighBeam, OUTPUT);
  
}

void loop() {
  // put your main code here, to run repeatedly:

  LowBeamLoop();
  FlashToPassLoop();
  HighBeamLoop();
}

//-----------------------------------------------------------------------------------------

void LowBeamLoop() {
  if (digitalRead(LowBeamSwitch) != LastLowBeamSwitchState) { //  If the switch changed, due to noise of switching
    LastDebounceTimeLowBeam = millis();  // reset the debouncing timer
  }
  if ((millis() - LastDebounceTimeLowBeam) > DebounceDelay) {

    //  The debounce time has passed, so it is valid switching
    if (digitalRead(LowBeamSwitch) != LowBeamSwitchState) {
      LowBeamSwitchState = digitalRead(LowBeamSwitch);// reset the debouncing timer

      if (LowBeamSwitchState != LastLowBeamSwitchState) { // If the switch has been switched
        LowBeamState = !LowBeamState; // Toggle the Low Beam
        digitalWrite(LowBeam, LowBeamState);  // Output to MOSFET
        LowBeamFlag = !LowBeamFlag; // Flip the LowBeam Flag
      }
    }
  }
  LastLowBeamSwitchState = digitalRead(LowBeamSwitch);  // Set the last value to detect changes next time
}

//-----------------------------------------------------------------------------------------

void FlashToPassLoop() {
  if (FlashToPassFlag == LOW) {
    if (digitalRead(FlashToPassSwitch) != LastFlashToPassSwitchState) { //  If the switch changed, due to noise of switching
      LastDebounceTimeFlashToPass = millis();  // reset the debouncing timer
    }
    if ((millis() - LastDebounceTimeFlashToPass) > DebounceDelay) {

      //  The debounce time has passed, so it is valid switching
      if (digitalRead(FlashToPassSwitch) != FlashToPassSwitchState) {
        FlashToPassSwitchState = digitalRead(FlashToPassSwitch);// reset the debouncing timer
        if (FlashToPassSwitchState != LastFlashToPassSwitchState) { // If the switch has been switched
          FlashToPassFlag = !FlashToPassFlag; // Flip the Flash to pass Flag
        }
      }
    }
    LastFlashToPassSwitchState = digitalRead(FlashToPassSwitch);  // Set the last value to detect changes next time
  }
  else {
    if ((millis() - PreviousMillisFlashToPass) >= LongFlash) {
      PreviousMillisFlashToPass = millis();

      if (FlashToPassCounter >= 0 && FlashToPassCounter <= ((FlashToPassFlashes * 2) - 1)) {
        FlashToPassCounter++; // Increment the flash to pass counter
        HighBeamState = !HighBeamState; // Toggle the High Beam
        digitalWrite(HighBeam, HighBeamState);  // Output to MOSFET

        if (LowBeamFlag == LOW) {
          LowBeamState = !LowBeamState; // Toggle the Low Beam if it is not activated regular
          digitalWrite(LowBeam, LowBeamState);  // Output to MOSFET
        }
      }
      else {
        FlashToPassFlag = LOW;  //Reset the flash to pass flag
      }
    }
  }
}

//-----------------------------------------------------------------------------------------

void HighBeamLoop() {
  if (FlashToPassFlag == LOW) {
    if (digitalRead(HighBeamSwitch) != LastHighBeamSwitchState) { //  If the switch changed, due to noise of switching
      LastDebounceTimeHighBeam = millis();  // reset the debouncing timer
    }
    if ((millis() - LastDebounceTimeHighBeam) > DebounceDelay) {

      //  The debounce time has passed, so it is valid switching
      if (digitalRead(HighBeamSwitch) != HighBeamSwitchState) {
        HighBeamSwitchState = digitalRead(HighBeamSwitch);// reset the debouncing timer

        if (HighBeamSwitchState != LastHighBeamSwitchState) { // If the switch has been switched
          HighBeamState = !HighBeamState; // Toggle the High Beam
          digitalWrite(HighBeam, HighBeamState);  // Output to MOSFET
        }
      }
    }
  }
}

//-----------------------------------------------------------------------------------------

Porsche_944_Turbo_Light_Module.ino (7 KB)

// For programming pins 0 and 1 should be disconnectedWhy use them in the first place ?

I was going to suggest that you put some Serial.print()s in your code at strategic points but if you use pins 0 and 1 that will not be possible.

I have 6 pns for the lcd, 6 for outputs and 7 for switches. These aren't in my code right now because the post would be too long, but I need 19 out of 20 Arduino UNO pins..

but I need 19 out of 20 Arduino UNO pins..

Or a different kind of LCD. A serial LCD would need one pin (since you don't need to read from it). An I2C LCD would need two (specific) pins.

At the very least, put the LCD away until you get everything debugged, and then add it, using the hardware serial pins to drive it.

Thank you for your response.

I will shift the 0 and 1 pin to one of the analogue pins and leave the LCD for the moment.
I'll start the serial debugging tonight or tomorrow, if I can't find the problem, I'll be in touch again.
So far no obvious errors in the code?

So far no obvious errors in the code?

Well, there are obvious areas for improvement.

First, you should use structs to collect related data. For instance, you have a low beam light switch pin, a low beam state, a low beam flag, a low beam debounce time, etc. Create a struct to hold all the data for each of the three switches (one struct/three instances).

Second, do SOME of the processing in loop(). Calling three functions, when only one of them will accomplish anything, is not how I would do it.

But, either you did not explain what the code actually does, or my eyes glazed over before I read that far.

Hi all,

I've been quite busy on the car, apart from the electronics, that's why this response comes after such a long time.
Everything is working and connected, apart from the LCD.
The error in the code seemed to be somewhere in the debouncing part, so this was deleted. Because of it's insignificance and a seriously tight schedule this is left out for now, I might look into this in the future. I will attach the working script to this post.

The LCD is not working though. Display looks fine until a relay is activated, then the trouble starts as can be seen in this youtube video:

Without relays everything is fine, so this is where the problem is. There are flyback diodes in place for every relay, but the cable length between flyback diodes and relays is about 1.5m (they are placed on the sparkfun board, which is about 1.5m apart from the switches, relays and the LCD), could this be an issue? placing a 47uF capacitor over the LCD power also didn't work.
The arduino gets its power directly on the 5V pin through an TSR 1-2450 - 5V/1A SWITCHING REGULATOR.

To be clear:
The arduino uno has an sparkfun mosfet power shield on top (https://www.sparkfun.com/products/10618). The LCD is connected through 1.5m cables to the arduino. The switches are connected through 1.5m cables to the arduino and the other side to a common ground. The relays have a common +12v from the car battery, the other side is connected through 1.5m cables to the sparkfun mosfet shield, which switches these to the arduino ground, which goes through a 1.5m cable to the common ground of the vehicle. It should be noted that the LCD, switches, arduino and mosfets all use the same common ground in the end.

I hope that some of you can help me with fixing this LCD, because if the 1.5m distance is not the problem, I am absolutely clueless.

Thank you for your time!

Joël

Porsche_944_Turbo_Light_Module.ino (10.5 KB)

Hi,
Welcome to the forum.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
This so we can see how your input and output devices are connected, please include power supplies.

How long is the cable from the UNO to the LCD?
It looks like the UNO is resetting when you activate a relay, if the relay coils are disconnected the problem is not present?
Can you measure the coil current of the relays please?

I have used those DC to DC units before and they should be fine, but place a 0.1uF cap between the input and gnd and another 0.1uF cap between output and gnd.

Thanks.. Tom.. :slight_smile:

I hope that some of you can help me with fixing this LCD, because if the 1.5m distance is not the problem, I am absolutely clueless.

In an nasty automotive environment, 1.5 meters is a VERY long way to be sending data to an LCD.

PaulS:
In an nasty automotive environment, 1.5 meters is a VERY long way to be sending data to an LCD.

Indeed - a shielded cable would be the minimum precaution, grounded only at one end.

Hi,
As this is in a racing competition environment, the small LCD will not be that visible to the driver, with vibration and speed of observations needed.

You would be better to have indicator lights for each function, or each output, showing the light operation flashing, just like on a normal vehicle.

Tom... :slight_smile:

TomGeorge:
Hi,
As this is in a racing competition environment, the small LCD will not be that visible to the driver, with vibration and speed of observations needed.

You would be better to have indicator lights for each function, or each output, showing the light operation flashing, just like on a normal vehicle.

Tom... :slight_smile:

This is indeed the case, but this will probably just be a checking screen (so no frequent looking needed).

MarkT:
Indeed - a shielded cable would be the minimum precaution, grounded only at one end.

Would shielding just the LCD cables be enough, or would each bundle have to be shielded (LCD bundle, mosfet to relay bundle, switches to arduino bundle)? Because all the connectors have been soldered on, this would be a real pain I think.

TomGeorge:
Hi,
Welcome to the forum.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
This so we can see how your input and output devices are connected, please include power supplies.

How long is the cable from the UNO to the LCD?
It looks like the UNO is resetting when you activate a relay, if the relay coils are disconnected the problem is not present?
Can you measure the coil current of the relays please?

I have used those DC to DC units before and they should be fine, but place a 0.1uF cap between the input and gnd and another 0.1uF cap between output and gnd.

Thanks.. Tom.. :slight_smile:

I will place the capacitors tomorrow. Cable from uno to lcd is about 1.5m. When the coils are disconnected the problem is not present, so the coils are definitely the cause. I can't measure the coil current right now, but according to calculations I once made, it should be around 100mA per coil.

I've attached a picture of how the power lines go. The lcd is not included completely, only the power lines, rest is connected as in the hello world tutorial and working. Switches are also not drawn because 20 arduino pins to draw are a lot. They are connected to the arduino pins on one side and ground on the other side. I have drawn one relay as an example, the rest is connected in the same way.

I hope this is enough information for the moment.

Joël