Making gear shift lights flash at a certain RPM?

Hi,

I'm making some gear shift lights for a car.
I've got a sketch working where 4 lights sequentially come on at certain RPM, which I have working. However, I'd like them all to flash above a certain threshold, which I'm struggling with....

I'm currently using lines like:-

if ((frequency30) > LED0_On_At)
{
digitalWrite(LED0, HIGH);
}
if ((frequency
30) < LED0_On_At)
{
digitalWrite(LED0, LOW);

where (frequency*30), is my current RPM, and "LED0_On_At" is the integer containing the rpm at which I'd like the first light to come on at.
I have three other LED's being LED1,LED2,LED3, and I have another integer "LED_Blick_RPM" at which I'd like all four outputs to blink.

I've tried something like the following into my routine, but the lights simply stay on above my threshold:-
If ((frequency*30) > LED_Blick_RPM)
delay (100);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay (100);

How can I do this ?

Blink without Delay

I've tried something like the following into my routine

"Flashing" an LED means turning it off and on on a regular basis. That snippet of something like code only turns the LED pins off.

PaulS:
"Flashing" an LED means turning it off and on on a regular basis. That snippet of something like code only turns the LED pins off.

Hi,
Thanks for your reply. "only turns the LED pins off.", but it does not turn them off....
I'd hoped that the "delay(100)" would wait 100ms before switching them off, and then the second "delay(100)" would wait a further 100ms before returning to the previous lines that turn them on again.

Hutkikz:
Blink without Delay

Won't this make the LED's blink all the time?
I'd like the LED's to sequentially come (not flashing) on with increasing RPM, but then all flash when my RPM exceed the value of my integer "LED_Blick_RPM".

Or can I nest the code to "blink without delay"?

Or can I nest the code to "blink without delay"?

In a way, yes. You set a flag that indicates whether the LEDs should be blinking, or not.

Independently, you see if it is time (and necessary) to toggle the state of the LED pins.

I'd hoped that

you'd post ALL of your code. Seems we are both going to be disappointed.

PaulS:
In a way, yes. You set a flag that indicates whether the LEDs should be blinking, or not.

Independently, you see if it is time (and necessary) to toggle the state of the LED pins.
you'd post ALL of your code. Seems we are both going to be disappointed.

Hi Paul,

My full code:-

#include <FreqMeasure.h>
#include <LiquidCrystal.h>
const int LED0 = 9;
const int LED1 = 10;
const int LED2 = 11;
const int LED3 = 12;

int LED0_On_At = 2000;
int LED1_On_At = 2200;
int LED2_On_At = 2400;
int LED3_On_At = 2600;

int LED_Blick_RPM = 2800;

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

void setup() {
lcd.begin(16,2);
lcd.print("Freq:");
lcd.setCursor(0, 1);
lcd.print("RPM:");
FreqMeasure.begin();
pinMode(LED0,OUTPUT);
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);

}
double sum=0;
int count=0;

void loop(){
if (FreqMeasure.available()) {
// average several reading together
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 5) {
float frequency = FreqMeasure.countToFrequency(sum / count);
lcd.setCursor(10, 0);
lcd.print(frequency);
lcd.setCursor(10, 1);
lcd.print(frequency30);
sum = 0;
count = 0;
if ((frequency
30) > LED0_On_At)
{
digitalWrite(LED0, HIGH);
}
if ((frequency30) < LED0_On_At)
{
digitalWrite(LED0, LOW);
}
if ((frequency
30) > LED1_On_At)
{
digitalWrite(LED1, HIGH);
}
if ((frequency30) < LED1_On_At)
{
digitalWrite(LED1, LOW);
}
if ((frequency
30) > LED2_On_At)
{
digitalWrite(LED2, HIGH);
}
if ((frequency30) < LED2_On_At)
{
digitalWrite(LED2, LOW);
}
if ((frequency
30) > LED3_On_At)
{
digitalWrite(LED3, HIGH);
}
if ((frequency*30) < LED3_On_At)
{
digitalWrite(LED3, LOW);

}
}
}
}

Where do I need to put what to achieve my goal?

int LED_Blick_RPM = 2800;

Blick?

Multiplying frequency by 30 so many times seems pointless. Do it once, and store in an intermediate variable.

if ((frequency*30) > LED0_On_At)
{
  digitalWrite(LED0, HIGH);
}
if ((frequency*30) < LED0_On_At)     
{
  digitalWrite(LED0, LOW);
}

Just ignore the LED if frequency*30 == LED0_On_At?

If that is not the intent, then learn to use else blocks.

You could shorten that code:

digitalWrite(LED0, (frequency*30) > LED0_On_At);

(assuming that you meant to turn the LED off when the frequency * 30 is less than or equal to LED0_On_At.

Where do I need to put what to achieve my goal?

You need a global variable, of type boolean, called overRev. You need to set overRev to frequency*30) > LED_Blick_RPM, when count is greater than 5.

You need a global variable, of type unsigned long, called toggleTime. You need to set toggleTime to the value returned by millis() if frequency*30) > LED_Blick_RPM, when count is greater than 5.

At the end of loop(), you need some code like so:

   if(overRev)
   {
      unsigned long now = millis();
      if(now - toggleTime > interval)
      {
         ledState = !ledState;
         digitalWrite(LED0, ledState);
         digitalWrite(LED1, ledState);
         digitalWrite(LED2, ledState);
         digitalWrite(LED3, ledState);

         toggleTime = now;
      }
   }

You'll need to define a global variable, interval, of type unsigned long, with whatever length of time you want the LEDs on and off when blinking.

You'll need to define a global variable, ledState, of type byte. The initial value doesn't matter, since it is going to change all the time.

Thanks for your replies so far :-)

I've been playing with this. Having got the frequency measurement part working on the car, I've taken that out whilst I try to develop the rest a little on the bench. I've replaced the frequency measurement with a potentiometer into analog A0 for test purposes.

I've added a start up test routine to illuminate individual LED's the flash all four before it runs the loop.

I'd like to add another pot. into another analog input to adjust the brightness of my LED's (yes, I know pin 12 is not PWM, I'll swap that later).
I currently have the following statements to control my LED's

digitalWrite(LED0, rpm > LED0_On_At);
digitalWrite(LED1, rpm > LED1_On_At);
digitalWrite(LED2, rpm > LED2_On_At);
digitalWrite(LED3, rpm > LED3_On_At);

I've tried replacing the digitalWrite with analogWrite instructions, but keep getting "too many arguments" messages. I've tried changing the parenthesis, but I'm obviously missing something......

If my "rpm" is greater than the value of "LED0_On_At" etc, how can I write the value of my analog input to an analog output (or more accurately analog input/4 to analog output)??

My full code:-

#include <LiquidCrystal.h>
const int LED0 = 9;
const int LED1 = 10;
const int LED2 = 11;
const int LED3 = 12;

unsigned long interval = 0;
unsigned long toggleTime = 0;
byte ledState = 1;
int first_light = 7200; //FIRST USER VARIABLE (first lights at)
int LED_Blick_RPM = 7500; //SECOND USER VARIABLE (Blink at)
int interval_between_lights = ((LED_Blick_RPM - first_light)/4);
int LED0_On_At = (first_light) ; //first light On at rpm?
int LED1_On_At = (first_light + (interval_between_lights)); //second light on at rpm?
int LED2_On_At = (first_light + (interval_between_lights2)); //third light on at rpm?
int LED3_On_At = (first_light + (interval_between_lights
3)); //fourth light on at rpm?

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

void setup() {
lcd.begin(16,2);
pinMode(LED0,OUTPUT);
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
lcd.print ("analog_read_to_");
lcd.setCursor(0,1);
lcd.print ("LCD_With_Lights8");
delay (2000);
analogWrite(LED0, 10);
delay(500);
digitalWrite(LED1, HIGH);
delay(500);
digitalWrite(LED2, HIGH);
delay(500);
digitalWrite(LED3, HIGH);
delay(500);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(50);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(50);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(50);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(50);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(50);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(50);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(50);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(50);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(50);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(50);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(50);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(50);
digitalWrite(LED0, LOW);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
delay(50);
digitalWrite(LED0, HIGH);
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
delay(50);
}

void loop(){

int rpm = (analogRead(0)*8);

lcd.print(LED0_On_At);
lcd.setCursor(6,0);
lcd.print(LED1_On_At);
lcd.setCursor(12,0);
lcd.print(LED2_On_At);
lcd.setCursor(0,1);
lcd.print(LED3_On_At);
lcd.setCursor(6,1);
lcd.print(LED_Blick_RPM);

lcd.setCursor(12,1);
lcd.print(rpm);
delay(20);
lcd.clear();

digitalWrite(LED0, rpm > LED0_On_At);
digitalWrite(LED1, rpm > LED1_On_At);
digitalWrite(LED2, rpm > LED2_On_At);
digitalWrite(LED3, rpm > LED3_On_At);

if(rpm > LED_Blick_RPM )
{
unsigned long now = millis();
if(now - toggleTime > interval)
{
ledState = !ledState;
digitalWrite(LED0, ledState);
digitalWrite(LED1, ledState);
digitalWrite(LED2, ledState);
digitalWrite(LED3, ledState);

toggleTime = now;
delay (5);
}
}
}

digitalWrite(LED0, rpm > LED0_On_At);

Try some parentheses:

digitalWrite(LED0, (rpm > LED0_On_At));

Hi Paul,

Try some parentheses:

digitalWrite(LED0, (rpm > LED0_On_At));

[/quote]

I'd like to exchange the digitalWrite with analogWrite at a variable value.

the previous code worked well with ON and OFF, but now I'd like an analog output....

I'd like to exchange the digitalWrite with analogWrite at a variable value.

What variable value? You have a current rpm and a threshold for each pin. What value do you want to compute based on those two known values?

Paul,

The logic of when the lights illuminate is fine, but I'd like to be able to manually adjust the brightness of the LED's depending on the ambient lighting conditions.

I want them full brightness when driving in bright sunshine, but significantly dimmer if driving at night or poor conditions.

I want them full brightness when driving in bright sunshine, but significantly dimmer if driving at night or poor conditions.

So, you want the value to use in the analogWrite() call to be a function of some unknown data. Hmmm. I'll have to think about that for a while.

"Hmmm. I'll have to think about that for a while."

I initially thought it should be fairly straightforward, as the conditions for the previous "digitalWrite" are simple enough. I hoped changing the "digital" to "analog" but adding a variable as a brightness would have done it.......

As you'll have guessed, I'm new to Arduino. I've been programming industrial PLC's for years, so struggling with basics is even more frustrating.......

I hoped changing the "digital" to "analog" but adding a variable as a brightness would have done it.......

It would. The issue is what value to use. For testing purposes, you could add a potentiometer, and reads its value, to use as the second argument.

In the final product, you need some way of measuring ambient light levels AND to get user input.

I've been programming industrial PLC's for years

How would you manufacture the needed data to drive a PLC?

Paul,

No. I don't want to measure ambient light. I'd simply like to use a knob on a potentiometer, and put it into an analog input.

for the time being, I'd be happy to simply put a fixed value into some conditions of an analog output instruction, simply downloading a modified sketch to prove the function...

I'd simply like to use a knob on a potentiometer, and put it into an analog input.

I presume you meant output there. So, what is the problem?

for the time being, I'd be happy to simply put a fixed value into some conditions of an analog output instruction

I don't understand what you mean by "some conditions of an analog output instruction. Have you tried:

   analogWrite(LED0, 180);

?

(Assuming, of course, that LED0 contains a PWM pin number)

PaulS:
I presume you meant output there. So, what is the problem?

No. a potentiometer into an analog input, which I'd use to create a variable to use to control the brightness of my four LEDs.

Quote

❝for the time being, I'd be happy to simply put a fixed value into some conditions of an analog output instruction

I don't understand what you mean by "some conditions of an analog output instruction.

I've currently got the line:-
digitalWrite(LED0, rpm > LED0_On_At);
where "LED0" is written high if the value of "rpm" is greater than the value of "LED0_On_At".

If I were to create a variable "brightness", if the value or "rpm" were greater that the value of "LED0_On_At", I'd like the analog output "LED0" to have the value of "brightness" written to it.

Should I be returning to something like my original sketch where I'd got something like:-

if (rpm> LED0_On_At)
{
analogWrite(LED0,brightness);
}
if (rpm < LED0_On_At)
{
analogWrite(LED0, LOW);
}

but then, would my "ledState" blink part still work?

Should I be returning to something like my original sketch where I'd got something like

Yes.

but then, would my "ledState" blink part still work?

Yes. You can use analogWrite() and digitalWrite() on the same pins. You can blink the LED at reduced brightness, using analogWrite(), too.