Mike Kushnerik
Published © CC BY-SA

Upgrading cheap bicycle lights

Have you ever been annoyed with overly complicated bike lights? This project is for you!

AdvancedFull instructions provided2 hours143

Things used in this project

Hardware components

Microchip ATtiny202
×1
Adafruit - High Voltage UPDI Friend
×1
Power Profiler Kit II
Nordic Semiconductor Power Profiler Kit II
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Final Schematic

Code

bike_light_sequential_v1

Arduino
// sequential bike light
// by: miekush
// 2026/04/20

#include <avr/sleep.h>

#define LED1_PIN            1   //PA7
#define LED2_PIN            0   //PA6
#define LED3_PIN            4   //PA3
#define LED4_PIN            2   //PA1
#define LED5_PIN            3   //PA2
#define SW_PIN              5   //PA0

#define MILLIS_POLL_DELAY   10
#define LED_SEQ_DELAY       250
#define SW_BOUNCE_DELAY     50

bool ledState=false;
uint8_t ledPos=0;
uint16_t ledSeqDelayCount=0;

bool swBounceDelay=false;
uint16_t swBounceDelayCount=0;

unsigned long currentMillis=0;
unsigned long previousMillis=0;

void setup()
{
  //make sure LEDs are all off on boot
  digitalWrite(LED1_PIN, HIGH);
  digitalWrite(LED2_PIN, HIGH);
  digitalWrite(LED3_PIN, HIGH);
  digitalWrite(LED4_PIN, HIGH);
  digitalWrite(LED5_PIN, HIGH);

  //LED outputs
  pinMode(LED1_PIN, OUTPUT);
  pinMode(LED2_PIN, OUTPUT);
  pinMode(LED3_PIN, OUTPUT);
  pinMode(LED4_PIN, OUTPUT);
  pinMode(LED5_PIN, OUTPUT);

  //switch input
  pinMode(SW_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(SW_PIN), switchISR, FALLING);
}

void loop()
{
  currentMillis = millis();
  if((currentMillis-previousMillis) >= MILLIS_POLL_DELAY)
  {
    if(ledState)
    {
      ledSeqDelayCount++;
      if(ledSeqDelayCount>(LED_SEQ_DELAY / MILLIS_POLL_DELAY))
      {
        ledPos++;
        if(ledPos>4)
        {
          ledPos=0;
        }
        ledSeqDelayCount=0;
      }
    }

    if(swBounceDelay)
    {
      swBounceDelayCount++;
      if(swBounceDelayCount>SW_BOUNCE_DELAY)
      {
        swBounceDelay=false;
        swBounceDelayCount=0;
      }
    }

    previousMillis=currentMillis;
  }

  if(ledState)
  {
    ledSequence(ledPos);
  }
  else
  {
    ledSequence(0);
    if(!swBounceDelay)
    {
      goToSleep();
    }
  }
}

void switchISR(void)
{
  if(!swBounceDelay)
  {
    ledState=!ledState;
    ledPos=0;
    swBounceDelayCount=0;
    swBounceDelay=true;
  }
}

void goToSleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_cpu();
}

void ledSequence(uint8_t pos)
{
  switch(pos)
  {
    case 0:
      digitalWrite(LED1_PIN, HIGH);
      digitalWrite(LED2_PIN, HIGH);
      digitalWrite(LED3_PIN, HIGH);
      digitalWrite(LED4_PIN, HIGH);
      digitalWrite(LED5_PIN, HIGH);
      break;
    case 1:
      digitalWrite(LED1_PIN, LOW);
      digitalWrite(LED2_PIN, HIGH);
      digitalWrite(LED3_PIN, HIGH);
      digitalWrite(LED4_PIN, HIGH);
      digitalWrite(LED5_PIN, LOW);
      break;
    case 2:
      digitalWrite(LED1_PIN, LOW);
      digitalWrite(LED2_PIN, LOW);
      digitalWrite(LED3_PIN, HIGH);
      digitalWrite(LED4_PIN, LOW);
      digitalWrite(LED5_PIN, LOW);
      break;
    case 3:
      digitalWrite(LED1_PIN, LOW);
      digitalWrite(LED2_PIN, LOW);
      digitalWrite(LED3_PIN, LOW);
      digitalWrite(LED4_PIN, LOW);
      digitalWrite(LED5_PIN, LOW);
      break;
    case 4:
      digitalWrite(LED1_PIN, LOW);
      digitalWrite(LED2_PIN, LOW);
      digitalWrite(LED3_PIN, LOW);
      digitalWrite(LED4_PIN, LOW);
      digitalWrite(LED5_PIN, LOW);
      break;
    default:
      break;
  }
}

Credits

Mike Kushnerik
7 projects • 8 followers
Electrical Engineer

Comments