IR activated light switch - residual bugs

Ford Mustangs really aren't bad, for what they are.

It's in the end really down to what kind of philosophy you want with a car.

Mustangs are a statement of raw power, the kind of car that's going to push you into the back of your seat with screaming tyres if you even so much as give the accelerator a dirty look. :slight_smile: And let's not forget the mesmerising sound of eight cylinders...

The MG F followed the tradition of post-war, small and sometimes slightly underpowered British "everyman" sports cars. Which stemmed from the idea that you shouldn't have to have a large bank account to be able to have a bit of fun on the road.

The steering on the F is a bit light-footed though, especially at the kind of speeds that are still legal here in Germany on the Autobahn... :slight_smile: It will do 190 kph (120 mph), but you will find yourself soon wanting to go back down to something like 80 to 90 mph. This car was engineered for British roads and their national speed limit of 70 mph, and it shows... There are aftermarket solutions to that like an air splitter that gets mounted to the underside of the front bumper, which actually does eliminate some of the lift, but I'd prefer to not have my car looking like it was used in "Fast & Furious"... :confused:

Back to the topic, maybe a good next step is going to be to just hook my breadboard up to the car and see how my circuit actually behaves under realistic conditions, especially when cranking the engine. And then make improvements from there.

maybe a good next step is going to be to just hook my breadboard up to the car and see how my circuit actually behaves under realistic conditions, especially when cranking the engine. And then make improvements from there.

Hey, now, there's a good idea.

Hehe, muscle cars aren't bad. Only don't try to break or accelerate while cornering. But he, don't get me wrong! That makes a muscle car what it is! If it doesn't misbehave it's not a muscle car :smiley:

carguy:
Back to the topic, maybe a good next step is going to be to just hook my breadboard up to the car and see how my circuit actually behaves under realistic conditions, especially when cranking the engine. And then make improvements from there.

Great idea except I would straighten the circuit first a bit. Sprinkle some decoupling caps, remove some unnecessarily caps and diodes. Just a single diode and cap for the uC, switch and pot will do. And to extend the efficiency of the cap by a factor 10, increase all resistors by a factor 10 :smiley:

Just because it works doesn't mean it always works nor makes it a good design :slight_smile:

septillion:
Great idea except I would straighten the circuit first a bit. Sprinkle some decoupling caps, remove some unnecessarily caps and diodes. Just a single diode and cap for the uC, switch and pot will do. And to extend the efficiency of the cap by a factor 10, increase all resistors by a factor 10 :smiley:

Just because it works doesn't mean it always works nor makes it a good design :slight_smile:

I am actually going to the electronics store tonight (I've got a Conrad just five minutes from where I live :slight_smile: ) to get the parts you suggested.

So, in summary, is this what I should be getting?

resistors:

  • 47 k
  • 2x 100K
  • 220K

(for the voltage dividers)

  • 100k pot

  • 100nF decoupling cap

  • ...

(here's my latest schematic again:)

septillion:
Note, a delay() prevents anything else from happening so might bite you in the future :wink:

Yeah, but on the other hand, 25 ms isn't much for this application. How would you write code to eliminate a false signal that lasts somewhere around 25 ms?

That's a luxury :slight_smile: But I guess so. Didn't recheck the divider values.

Schematic is getting smaller and smaller. Hard to read it atm...

Still two things:

  • Just 1 cap + 1 diode for the uC, pot and switch.
  • The sprinkling of 100nF's

And extra:
-Fuse on light switch is indeed save. But I'll find the inductor overkill. Same for second diode in front of the divider. The 10uF is more useful for the transistor then t is for the uC anyway.

  • I would add a pull down to both transistors so a small leak current doesn't turn them on.
  • Why not place the led's in series?
  • Why still keep the 3300uF?
  • Maybe use a constant current for the leds. That way the voltage dip doesn't effect the brightness and so doesn't the difference in voltage between a running and not running engine. (It will be very noticeable now!)

septillion:
And extra:
-Fuse on light switch is indeed save. But I'll find the inductor overkill. Same for second diode in front of the divider. The 10uF is more useful for the transistor then t is for the uC anyway.

I wanted to make sure the 10 uF will only bridge voltage decrease on the light switch sense pin, and not drain into the transistor that powers the IR module.

septillion:

  • Why not place the led's in series?

To make it more likely that when one fails, the other one still works... remember back in the old days when electrical Christmas tree lights for your backyard were in series, and you could play a joke on your neighbours by disconnecting one light bulb and the whole tree would go dark, and they would have to check all 50 light bulbs for the one that was loose? :slight_smile:

septillion:

  • Why still keep the 3300uF?

I will probably eliminate it with the next revision.

septillion:

  • Maybe use a constant current for the leds. That way the voltage dip doesn't effect the brightness and so doesn't the difference in voltage between a running and not running engine. (It will be very noticeable now!)

On the other hand, the power regulator delivers the same 5V regardless of what the input voltage from the battery is, doesn't it?

But I will check all that when I connect the breadboard to my car.

carguy:
I wanted to make sure the 10 uF will only bridge voltage decrease on the light switch sense pin, and not drain into the transistor that powers the IR module.

But I think it's more useful for the IR module then for the sense pin. You can debounce/filter that while a resetting/brown out-ing IR module might give you more trouble.

carguy:
To make it more likely that when one fails, the other one still works... remember back in the old days when electrical Christmas tree lights for your backyard were in series, and you could play a joke on your neighbours by disconnecting one light bulb and the whole tree would go dark, and they would have to check all 50 light bulbs for the one that was loose? :slight_smile:

Do you also remember the power consumption of those old Christmas lights? :wink: A led is very unlikely to fail IF operated within spec. Even at it's end of life it will not just go out, it will fade. White leds do burn up, unlike led bulb manufacturers what us to believe... Yes, after 30.000 hours a led bulb will probably still light (if the electronics did not say bang...) but the light output will be peanuts compared to new...

carguy:
On the other hand, the power regulator delivers the same 5V regardless of what the input voltage from the battery is, doesn't it?

Ahh, yes, forgot you power the leds from the 5V. Schematic is so small now :zipper_mouth_face: Then you don't have to worry about that and then you can't connect 2 white leds in series indeed :slight_smile:

septillion:
But I think it's more useful for the IR module then for the sense pin. You can debounce/filter that while a resetting/brown out-ing IR module might give you more trouble.

I'll think about it. I'm not sure what the IR breakout draws, I've tried to find information online but haven't really had much luck. It contains a Texas Instruments IC of some kind, two status LEDs and one infrared emitter LED as well as an infrared sensor. Also, it has a small pot on board with which you can adjust the IR sensor's distance sensitivity.

septillion:
Do you also remember the power consumption of those old Christmas lights? :wink:

We never had any because my parents thought they were just a silly thing to put in your backyard. But even low-level light bulb-based lights must have drawn a good few amps...

septillion:
Ahh, yes, forgot you power the leds from the 5V. Schematic is so small now :zipper_mouth_face: Then you don't have to worry about that and then you can't connect 2 white leds in series indeed :slight_smile:

I will try to re-simplify the whole schematic again with my next revision, I promise :wink:

But now, I have to get going to Conrad... before I will get bad looks again from them for showing up right before closing, and expecting them to locate all the parts on my long list from their drawers in five minutes flat... :smiley:

EDIT: Not sure I am understanding your complaint correctly about the schematic getting smaller, but it just gets displayed at a smaller size by the forum's software. If you are using Firefox, you can just right click on the image and then click "viev image". Then you'll see the image in its full size.

Alternatively, here's a direct link to the schematic:

Ahhh, yeah. Didn't notice it's the forum doing that. The schematic indeed became bigger so everything on the scaled imaged now is very small. Didn't notice it's the forum because I'm used to a forum making the image clickable when it does that... :confused:

I’ve been thinking about how to solve the problem in software of a possible bad connection on the light sensing pin, which checks if the car’s light switch is on… You know, like I said, to make sure the lights won’t dim up again if there’s just a few milliseconds of voltage drop to logical low on that pin.

Here’s what I’ve got so far. It does the trick, but it does have a delay() in it:

byte getMode() {                          // This function checks which mode the circuit is supposed to be in

  int switchPinState = analogRead(switchPin);
  boolean lightSense = digitalRead(lightSensePin);

  if (lightSense) {                       // IR and always-on modes only when the light switch is on

    if (switchPinState > 800) return 1;   // IR activated mode
    if (switchPinState < 100) return 0;   // always-off mode
    else return 2;                        // always-on mode
  }
  
  else {

    delay(100);                                // check again
    if (!digitalRead(lightSensePin)) return 0;  // always-off mode
  }
}

Mehhh, that's blocking code... That WILL bite you some day. Or it does already if you try to do something else at "the same time" like adjusting the led brightness. And why do you read it analog? There is voltage (aka switch on) or there is not (aka switch off). So a digital read would make more sens :smiley:

Did I ever talk about Bounce2? Does it all for you :slight_smile:

septillion:
And why do you read it analog? There is voltage (aka switch on) or there is not (aka switch off). So a digital read would make more sens :smiley:

Well, the “light sense pin” checks if the car’s light switch is on. So that one is digitalRead, as you can see in my code snippet.

The mode switch is analogRead, because as you can see in my schematic, it’s connected to a voltage divider, so the point is that mode switch position 1 will produce a different analog reading than mode switch position 2. Which is then used to determine what mode of operation the code is supposed to go into.

What is Bounce2?

Ahh, sorry again. Was to quick, one hand typing while eating a sandwich :stuck_out_tongue:

For the digital pin I would just grab a library like Bounc2 clickerty-click

For the analog I would do kind of the same (but don’t know a library for it…). I would read it periodically, let’s say 50 times a second, and only change state when you saw a value in the same range (aka switch position) for let’s say 4 times in a row.

const byte ModeSwitchPin = A0;
const byte ModeSwitchInterval = 20;
const byte ModeSwitchRanges[] = {25, 200};
const byte ModeSwitchCountThreshold = 4;

byte modeSwitchLastMillis;  //last time the modeSwitch was checked
byte modeSwitchLastMode;   //last state it was in
byte modeSwitchCount;       //how many times was it in that state?

byte mode;  //real stable state of the modeSwitch

byte currentMillis = millis();
if(currentMillis - modeSwitchLastMillis >= ModeSwitchInterval){
  //save for next time
  modeSwitchLastMillis = currentMillis;
  
  byte modeNow;
  unsigned int value = analogRead(ModeSwitchPin);
  for(modeNow = 0; modeNow <= sizeof(ModeSwitchRanges); modeNow++){
    if(value < ModeSwitchRanges[modeNow]){
      break;
    }
  }
  
  //The same as last
  if(modeNow == modeSwitchLastMode){
    //increase count
    if(modeSwitchCount < ModeSwitchCountThreshold){
      modeSwitchCount++;
    }
    //or set mode if we saw it enough
    else{
      mode = modeNow;
    }
  }
  //not the same, reset
  else{
    modeSwitchLastMode = modeNow;
    modeSwitchCount = 0;
  }
}

Mm, this s actually bagging for a nice library :stuck_out_tongue:

hm... right now, I simply check the mode by calling the above posted getMode() function at the beginning of every run of the loop() section.

getMode() returns either 0, 1 or 2, and I then use that to either go into IR sensor mode, or always-off or always-on mode. If it isn't already in that mode, of course.

Another question - we were talking about whether or not a sleep mode on the Attiny85 is useful. How much power will the Attiny85 use at 16 MHz internal, running a sketch like mine? I've found that the dimming up and dimming down looks the smoothest at 16 MHz.

I've just re-read the Recom power regulator's data sheet, it does say that its quiescent current is 7 mA.

How you wrap it is up to you. But now, there is a big fat delay() in there :wink:

Your sketch is irrelevant, even a sketch with only delay() will draw the same. It's what peripherals are running. But have a look at the datasheet I would say.

Mm, that's weird. The 16Mhz is wayyyyyyy to fast to give you, as human, noticeable difference compared to 4Mhz. 4Mhz should be just fine if you do all the timing correct. 1ms is still 1ms but if you leave the same divider for the PWM you end up with a very low pwm frequency which you can notice. But that's easy to fix. I would try to make it around 1kHz

100 ms is a big fat delay for a microcontroller; but from a user's perspective, it's still twice as fast as the blink of an eye. :wink:

About the MHz speed... I am currently developing the code on an Atmega328P-PU with 16 MHz external. I've migrated it from the Attiny85 to the 328 because it's just easier to debug that way (not having any free pins for SoftwareSerial). But in the end, the final sketch will run on the Attiny85 again.

I tried early versions of my sketch on the Attiny85 at 8 MHz internal, and the dimming just wasn't that smooth. Maybe now with a good number of refinements of my code since then, that problem will no longer exist.

As far as overall project progress, my code is nearly finished. One more thing I am going to do is simplify the circuit and hook it up to my car, and then when the last improvements are implemented, it will be migrated back onto the Attiny85, and then I will connect that breadboard to my car one more time and if everything works, I will start soldering everything neatly onto a perfboard and put it inside a module case so I can install it in my car. :wink:

For a micro it’s the world! But even for a human, if you don’t blink, 100ms is very very noticeable. In that time you can’t adjust the brightness because it will stick in that 100ms and for fading not changing the brightness for 100ms will be visible… And because you want it to react “instant” on you changing the switch it has to check the switch multiple times a second so multiple delay()'s a second. And why? There are very easy ways around it.

8Mhz is moooooore then fast enough to fade smoothly so it must have been your code :wink: For example, if you use blocking code :wink: Heck, even 1Mhz can give you smooth fading and all, no problem.

On the other hand, are you going to be able to crank the engine and adjust the brightness all at the same time during those 100 ms? Or is that even a typical use of such a center console light? :wink:

Also, I’ve already installed an “ambiente” light in the MG. You know, the kind that modern cars have, where the center console is faintly illuminated in a slight glow that is produced by an LED or two in the front part of the roof. Not having a solid roof on my convertible, I put the LEDs in the bottom of the rear view mirror. Anyway, they are not powered by an IC, but simply by a cap that fades them out and a diode, and they are connected to the light switch wire. A completely analog circuit. I’ve given them a brightness pot as well. The thing is, that circuit has been doing its work for three years now in that car, and except for when I first installed it, I have never (re)adjusted the brightness pot. You see where I am going with this… :wink:

And when you’re not cranking, during normal operation, this 100 ms delay only kicks in if there is a shaky connection on the light switch sensing wire or if you are actually turning off the car’s lights:

  if (lightSense) {                       // IR and always-on modes only when the light switch is on

    if (switchPinState > 800) return 1;   // IR activated mode
    if (switchPinState < 100) return 0;   // always-off mode
    else return 2;                        // always-on mode
  }
 
  else {

    delay(100);                                // check again
    if (!digitalRead(lightSensePin)) return 0;  // always-off mode
  }

The only major problem I see with that is that when the car battery is at 10 volts, with a 22(0)K/10(0)K voltage divider, you are going to be just barely above the logic threshold, so the circuit might behave erratically. On the other hand, if your battery voltage is that low, you’ve got much bigger problems than whether or not your center console LEDs are working :wink:

Maybe it’s not a bad idea after all to do an analogRead on the light sensing pin, and then put the value threshold in the if-statement somewhere around 300 or something…

(quick question on that voltage divider - when there’s no voltage on it, i.e. when the lights are off, will the 100K resistor be adequate as a pull down for that pin? In most Arduino documentations, it says to use 5K to 10K as pull downs)

Also, I will probably be operating my center console light in moving traffic most of the time. My attention will be focused on what’s going on around me in traffic, not on whether or not there will be a 0.1-second delay in the fading down of the LEDs if there’s a bad connection or if I turn off the lights :wink:

But I promise I will look into the Bounce2 library. :wink:

But if a small break happens during fading, and that may be at a random moment with a bad connection, it gives you a hick up.

More general what I meant to say is way build a ugly piece of code into your nice project while it's easy to overcome?

And besides that, I see a loophole in that code. The rereading of the code does nothing but introduce a bug into your code :wink: What if you indeed read a LOW on the switchPin, you wait 100ms, but then you read a HIGH? What do you expect the function to return now?

If your answer is 0, then why bother checking the pin again?

If your answer is any other number then you are kind of right. Because exiting a function with a return type without specifying the return value will give you undefined behavior :smiley:

At 10V you indeed have more problems :stuck_out_tongue: (Trickle charge :wink: ) but you can fix this by using a lower value resistor in the top leg and a zener below (4v7 or so). And I think I would add a 100nF ceramic (the sprinkle of decoupling caps) to clamp fast transitions (but I would drop the inductor on the light switch). I at least would not bother with analogReadings for that...

100k should do that just fine but it can pick up more noise but a cap will make it pretty stable. You can leave the 10k there (and 22k) to make it a bit more sturdy. They don't load any cap to keep the micro running during cranking. But you might be a bit out of spec when fuse in the permanent power fails and you phantom power it via the light switch...

Alternative would be to use a opto coupler....