Skip to content

Instantly share code, notes, and snippets.

@rupl
Last active May 30, 2022 17:56
Show Gist options
  • Save rupl/bf05d1ad40131a21f16fb24fbef9c0e3 to your computer and use it in GitHub Desktop.
Save rupl/bf05d1ad40131a21f16fb24fbef9c0e3 to your computer and use it in GitHub Desktop.
Code to power an Arduino biking jacket. Build details here: https://chrisruppel.com/blog/lilypad-arduino-biking-jacket/
/*!
* LilyPad Arduino Biking Jacket
*
* Each sleeve has a button and indicator light near the cuff.
* - Pressing the a button turns the blinker on for a few cycles.
* - Hold the same button to stop it sooner.
* - Pressing both buttons turns on hazard mode.
* - Hold one button to disable hazard mode.
*
* Made with <3 for Karin :)
*
* @license GPL 2.0
* @see https://chrisruppel.com/blog/lilypad-arduino-biking-jacket/
*/
const int left = 9;
const int minus = 10;
const int right = 11;
const int leftHand = 2;
const int leftButton = 3;
const int rightHand = A3;
const int rightButton = A2;
const int RESET = 5;
int leftCounter = RESET;
int rightCounter = RESET;
int hazardMode = 0;
int hazardModeJustDisabled = 0;
///////////////////////////
// Setup
///////////////////////////
void setup() {
pinMode(left, OUTPUT);
pinMode(right, OUTPUT);
pinMode(leftHand, OUTPUT);
pinMode(rightHand, OUTPUT);
pinMode(minus, OUTPUT);
digitalWrite(minus, LOW);
pinMode(leftButton, INPUT_PULLUP);
pinMode(rightButton, INPUT_PULLUP);
}
///////////////////////////
// Main Loop
///////////////////////////
void loop() {
// IF hazardMode is enabled,
// AND no buttons are being pressed,
// THEN do another cycle of hazardMode
if (hazardMode == 1) {
hazard();
}
// IF left button is pressed,
// THEN listen and respond.
if (digitalRead(leftButton) == LOW) {
// Listen for additional input until button is released.
while(digitalRead(leftButton) == LOW) {
// IF other signal is detected,
// THEN toggle hazard mode.
if (digitalRead(rightButton) == LOW) {
hazardMode = 1 - hazardMode;
if (hazardMode == 0) {
hazardModeJustDisabled = 1;
}
return;
}
}
// IF blink cycle is active
// THEN reset and end it prematurely
if (leftCounter < RESET) {
leftCounter = RESET;
return;
} else {
// Trigger blinker once button is released
// with no other input detected.
blink(left, leftHand);
}
}
// IF right button is pressed,
// THEN listen and respond.
if (digitalRead(rightButton) == LOW) {
// Listen for additional input until button is released.
while(digitalRead(rightButton) == LOW) {
// IF other signal is detected,
// THEN toggle hazard mode.
if (digitalRead(leftButton) == LOW) {
hazardMode = 1 - hazardMode;
if (hazardMode == 0) {
hazardModeJustDisabled = 1;
}
return;
}
}
// IF blink cycle is active
// THEN reset and end it prematurely
if (rightCounter < RESET) {
rightCounter = RESET;
return;
} else {
// Trigger blinker once button is released
// with no other input detected.
blink(right, rightHand);
}
}
// IF leftCounter is not at default
// THEN trigger a blink cycle.
if (leftCounter != RESET) {
blink(left, leftHand);
}
// IF rightCounter is not at default
// THEN trigger a blink cycle.
if (rightCounter != RESET) {
blink(right, rightHand);
}
}
///////////////////////////
// Blink
//
// Runs one full cycle of the blinking pattern on the specified side.
// Requires a blinker side and hand signal as input.
///////////////////////////
void blink(int blinker, int hand) {
int x;
// IF hazard mode is enabled,
// OR hazardMode was disabled last cycle,
// THEN do nothing.
if (hazardMode == 1 || hazardModeJustDisabled == 1) {
hazardModeJustDisabled = 0;
return;
}
// State management
if (blinker == left) {
// Don't allow both blinkers to cycle down at the same time.
rightCounter = RESET;
// Continue with blink cycle.
leftCounter--;
// When cycle is finished, reset to default.
if (leftCounter <= 0) {
leftCounter = RESET;
}
}
// State management
if (blinker == right) {
// Don't allow both blinkers to cycle down at the same time.
leftCounter = RESET;
// Continue with blink cycle.
rightCounter--;
// When cycle is finished, reset to default.
if (rightCounter <= 0) {
rightCounter = RESET;
}
}
// Enable indicator light for driver.
digitalWrite(hand, HIGH);
// Fade in blinker.
for (x = 0; x <= 255; x += 6) {
analogWrite(blinker, x);
delay(2);
}
// Blink rapidly a few times
digitalWrite(blinker, HIGH);
delay(100);
digitalWrite(blinker, LOW);
delay(75);
digitalWrite(blinker, HIGH);
delay(100);
digitalWrite(blinker, LOW);
delay(75);
digitalWrite(blinker, HIGH);
delay(100);
digitalWrite(blinker, LOW);
delay(75);
digitalWrite(blinker, HIGH);
delay(100);
digitalWrite(blinker, LOW);
delay(75);
digitalWrite(blinker, HIGH);
delay(100);
// Fade out blinker.
for (x = 255; x >= 0; x--) {
analogWrite(blinker, x);
delay(3);
}
// Blinker off completely.
digitalWrite(blinker, LOW);
// Disable indicator light for driver.
digitalWrite(hand, LOW);
// Pause before continuing.
delay(250);
}
///////////////////////////
// Hazard
//
// Runs one cycle of the hazard blinking pattern on both sides of the jacket.
///////////////////////////
void hazard() {
hazardMode = 1;
leftCounter = RESET;
rightCounter = RESET;
digitalWrite(left, HIGH);
digitalWrite(right, HIGH);
digitalWrite(leftHand, HIGH);
digitalWrite(rightHand, HIGH);
// Check for interrupt while lights are on
delay(300);
if (digitalRead(leftButton) == LOW || digitalRead(rightButton) == LOW) {
hazardMode = 0;
hazardModeJustDisabled = 1;
}
delay(300);
digitalWrite(left, LOW);
digitalWrite(right, LOW);
digitalWrite(leftHand, LOW);
digitalWrite(rightHand, LOW);
delay(400);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment