Button Debounce & states (overly complicated bicycle light system)

Hi all!
Im about to do a re-write (yet again) for my current electronics-project, to control a number of different lights (including detatchable trailer), using arduino as controller.

I know, its a waste of processing power, i could have solved the project much simpler, faster and cheaper had i gone with the motorcycle-approach with turn indicator relays and standard handlebar buttons and switches.

But that had´nt felt "right".. :slight_smile:

Instead, i wish to prepare for the future, to be able to integrate my light system with other future bike upgrades, like a e-bike conversion or dedicated mp3-player (with separate, permanently attatched speakers).

But since im getting tired of re-writing the code, i figured i should ask the internet for the best approach given the current set of "problems" to solve..

There are a number of different inputs on the project, about 7 digital (on/off) pins are used for buttons and switches, aditional 2 analog pins are used for brake detection.
The brake detectors will be utilizing hall effect sensors and tiny magnets, fixed in the brakehandle pivot point (to detect when the brake lever is moved, and roughly how much).

The output channels will be turn indicator left/right, positional lights front/rear, side lights left/right, extra light (front), brakelight (rear), along with 4 aditional digital channels (3 for power control, 1 for extra light mode selector)

The power control mentioned above will be a 4 digital pin output, to 3 mosfets, that allows the system to disconnect currently un-used external components (like the extra light(front) and power output thru the trailer socket (when trailer is not present)).

A number of buttons will offer 2 separate clicks, long and short, to activate different sets of states for the coresponding function.
For instance, when the right indicator button is pressed, depending if its a short or long click, the system responds with ether a fast 3 blink right signal that then selfterminates, or activates right indicator lights, to blink until next time the button is pressed (and released).

The same goes for the extra light (front) button, short click turns on/off the extra light, long click changes to the next mode, to increase the light output.

The extra light (front) function will be a dual high power LED bicycle front light, that offers 4 different modes, you select the next mode by clicking the single button on the housing, off>lights low>lights mid > lights HIGH! > off.

I aim to disconnect the led light with a mosFET when i turn off the extra lights from the handlebar button, and when i re-connect it electronically, it will also activate the transistor connected over the mode-select button inside the extra light housing.
This way i can both turn off/on the extra light, and also keep the current led modes.

So as you can see, there is a lot that will be happening in software, and i need a neat way to store all this info..

And since i dont want to be addressing each pin, each button, debounce each instance and so on, i figured i try to use for-loops instead, in functions that are called each x program loops, to avoid a timer per input to debounce.

I havent decided if i will be using arrays or bitWrite/bitRead int´s, but the idea is to copy currentRead to lastRead, set currentRead to digitalRead(thisPin), and then compare currentRead[thisPin] with lastRead[thisPin], if both entries are same, set buttonState[thisPin] = 1, else 0.
if buttonState[thisPin] = 1, buttonCount[thisPin]++
to count number of program loops while the button is pressed
if buttonState[thisPin] == 0 && buttonCount[thisPin] >longpressLimit, execute longPress[thisPin] and set buttonCount[thisPin] = 0;

And from what i understand of programming (witch is not much), i have then read and debounced each button and got a array of each buttons corresponding function, and i can then read if the last buttonpress is long, short or "currently pressed".

I do apologize for the above mess of a attempt to explain what i mean, i face two challenges, not my main language and im no programmer, just a average joe with learning difficulties.. :slight_smile:

But what im asking here is primarily, does that last part of the above piece sound reasonable or is this a uneccisarily complicated way of doing things?

Im not asking anyone to write the code for me, im just asking for hints, suggestions and constructive chriticism.. :slight_smile: (and yes, im missing a spelling checker.. sorry.. :slight_smile:

That code may work, with the right debounce scan interval. Do you have an idea how long your buttons bounce?

For the button press long/short I would use millis() instead. Set a variable to the current millis() the moment you detect the button is pressed; then check how long it's been pressed to determine short or long press (e.g. <500 ms is short press, 500 ms and up long press). Start checking for off state after 5-10 ms or so to allow for bounce.

For added complexity: why don't you add an accelerometer to sense whether you're making a turn (by measuring the angle of your bike, as you're leaning while turning this should be quite easy to detect), and then automatically turn off the turn signals when you're going straight again (or press the button, of course)?

i havent the faintest idea of how long my buttons bounce, i only have a arduino-based osciloscope and that does not show a timescale..
Also, the arduiscope is limited to serial baudrate, so i kind of doubt its sensitive enough to measure bounce..

But i guess its somewhat the same as other momentary push-buttons, so less than 20mS?

And regarding the added complexity, you (probably) failed to realize one fundamental thing; frame of reference. :slight_smile:

The accelerometer would read straight up ALL the time (until i crash), since i must lean into each curve.
And since the g-force is pulling me outward, i must counter-lean in the other direction, making my sensed gravity being in an angle relating to the g-force sensed by a stationary observer.

It might detect a acceleration in a given direction, but that might just as well be the road surface or sidewind im detecting.

I also had these ideas, some also revolved around measuring the front fork angle relating to the bike frame, but i have yet to find a dependable end-turn-detector.. :slight_smile:

I think it would be easier with a digital compass, to detect when im no longer changing heading.
But on the other hand, this would be somewhat dangerous as it might turn off the turn indicator too soon, when i havent exited the roundabout or intersection and so on..

So i´ll suffice with 3 turn indicator modes, blink while button is pressed (off when released), blink 3 times (and then off) when button is short-licked and toggle indicator on/off with a longclick.

I did have some ideas about stacking buttons on top of each other, the lower buttons with increasingly strong springs.
This would then allow me to gently press the button for function 1, press a bit harder for function 2, and press it to the bottom for function 3.

Somewhat like the feature on some digital cameras, focus with a half-press, take the picture with a full-press.

A gyroscope output may be more helpful than acceleration. You can measure the inclination and curve angle, so that you can determine from the inclination when the curve is finished.