Instructables

BIKEDUINO::: Stopping Point Predictor for bike riders

Featured
Picture of BIKEDUINO:::  Stopping Point Predictor for bike riders
DSC_0552.JPG
DSC_0553.JPG
The project consists in a Arduino that gets the speed of the bike from a dynamo and it controls a laser which points always to the point where the bike is gonna stop if it continues going at the same speed.

Used Hardware:

Arduino mini Atmega328
Laser
Servo
Dynamo
Battery pack 4 x 1,5 V
 
Remove these adsRemove these ads by Signing Up

Step 1: 1 Step: Build up an Mini Arduino Board

Picture of 1 Step: Build up an Mini Arduino Board
Build up an Mini Arduino Board or if you use it an Arduino Uno you can ignore this step.

http://http:/arduino/.cc/en/Main/StandaloneAssembly

Step 2: Step 2: Wire the dynamo in order to read the pulses it gives to the Arduino.

Picture of Step 2: Wire the dynamo in order to read the pulses it gives to the Arduino.
DSC_0524.JPG
Make a single wave rectificator for the dinamo and make it give positive pulses out. Then conect these pulses to an analog entry.
For assuring that the dynamo is giving pulses correctly use the osciloscope.

Step 3: Step 2: Process the reading from the Dynamo and get the SPEED , ACCELERATION and DISTANCE

Get the data on the Arduino, and process de pulses in order to get the Speed, Aceleration, and distance depending on the pulses.

You need to acurate very precisely in counting the pulses and then calbulate the SPEED, ACCELERATION and DISTANCE.

Here you get the code.


// Bikeduino version 1
// Lets your bicycle point a laser at the spot where it will stand still if the deceleration remains constant.

#include <Servo.h>

Servo servo;

// analog pin
#define DYNAMO_PIN 5
// pwm digital pin
#define SERVO_PIN 10
// digital pin
#define LASER_PIN 11

// time sample averaging window
#define WINDOW_SIZE 32
// acceleration averaging window
#define AWINDOW_SIZE 8

// the angle at which servo is pointing horizontally
#define SERVO_STRAIGHT_ANGLE 140
// the amount of milimeters the bike moves in one pulse from the dynamo (measured)
#define mm_per_pulse 16
// the amount of milimeters the laser is above the ground (on the bicycle)
#define bike_height 1030

void setup() {
  Serial.begin(19200);
  Serial.println("Bikeduino version 1.");
  servo.attach(SERVO_PIN);
  servo.write(SERVO_STRAIGHT_ANGLE); 
  pinMode(LASER_PIN, OUTPUT);
}

int q[WINDOW_SIZE];
int q_p = 0;

void queue(int x) {
  if (++q_p >= WINDOW_SIZE)
    q_p = 0;
  q[q_p] = x;
}

int average_pulsetime() {
  int i;
  long r=0;
  for (i=0; i<WINDOW_SIZE; i++) {
    r += q[i];
  }
  return (int) (r/WINDOW_SIZE);
}

int aq[AWINDOW_SIZE];
int aq_p = 0;

void aqueue(int x) {
  if (++aq_p >= AWINDOW_SIZE)
    aq_p = 0;
  aq[aq_p] = x;
}

int average_acceleration() {
  int i;
  long r=0;
  for (i=0; i<AWINDOW_SIZE; i++) {
    r += aq[i];
  }
  return (int) (r/AWINDOW_SIZE);
}

void wait_for_pulse() {
  /*
  while (digitalRead(DYNAMO_PIN)) {
  }
  while (!digitalRead(DYNAMO_PIN)) {
  }
  */
  while (analogRead(DYNAMO_PIN) < 300) {
  }
  while (analogRead(DYNAMO_PIN) > 300) {
  }
}

void laser_off() {
  digitalWrite(LASER_PIN, LOW);
}

void laser_on() {
    digitalWrite(LASER_PIN, HIGH);
}

int v_prev;
unsigned long prev_t;

void loop() {
  unsigned long t;
  int dt;
  wait_for_pulse();
  t = millis();
  dt = t - prev_t;
  queue(dt);
  prev_t = t;
 
  dt = average_pulsetime();
  int v = (1000*mm_per_pulse)/dt; // [v] = mm/s
 
  int dv = v - v_prev;
  v_prev = v;
 
  int a = (int) ((1000*(long)dv) / dt); // acceleration in mm/s^2
 
  aqueue(a);
//  Serial.println(); 
//  Serial.print("a: ");
//  Serial.println(a); 
  a = average_acceleration();

//  Serial.print("t: ");
//  Serial.println(t);
//  Serial.print("dt now:");
//  Serial.println(q[q_p]);
//  Serial.print("dt av: ");
//  Serial.println(dt);
//  Serial.print("v: ");
//  Serial.println(v);
//  Serial.print("a: ");
//  Serial.println(a);
  if (a == 0) {
    // don't change anything
  }
  else if (a < 0) {
    // we are slowing down, point the laser
    laser_on();
    int d = (int) (-sq((long) v)/a/2); // distance (mm) until standstill assuming deceleration remains constant
    double angle = (180.0/3.1416) * atan((double)bike_height / d); // angle between laser and forward horizontal
    servo.write(SERVO_STRAIGHT_ANGLE-angle); // change the minus to a plus if your servo is turned around
//    Serial.println();
//    Serial.print("d: ");

//    Serial.println(d);
//    Serial.print("angle: ");
//    Serial.println(angle);

  }
  else {
    // not slowing down
    laser_off();
    servo.write(SERVO_STRAIGHT_ANGLE); // point forward
  }
 
}

Step 4: STEP 4: Attach a laser on the top of a Servo

Picture of STEP 4: Attach a laser on the top of a Servo
DSC_0551.JPG
Connect a Laser to a servo. A laser doesn´t consume much so it can be connected directly to the Arduino. Otherwise use a transistor.

Step 5: Step 5: Make the laser move closer the more we are brake.

This need a bit of data processing plus a bit of triangulating.

// Bikeduino version 1
// Lets your bicycle point a laser at the spot where it will stand still if the deceleration remains constant.

#include <Servo.h>

Servo servo;

// analog pin
#define DYNAMO_PIN 5
// pwm digital pin
#define SERVO_PIN 10
// digital pin
#define LASER_PIN 11

// time sample averaging window
#define WINDOW_SIZE 32
// acceleration averaging window
#define AWINDOW_SIZE 8

// the angle at which servo is pointing horizontally
#define SERVO_STRAIGHT_ANGLE 140
// the amount of milimeters the bike moves in one pulse from the dynamo (measured)
#define mm_per_pulse 16
// the amount of milimeters the laser is above the ground (on the bicycle)
#define bike_height 1030

void setup() {
  Serial.begin(19200);
  Serial.println("Bikeduino version 1.");
  servo.attach(SERVO_PIN);
  servo.write(SERVO_STRAIGHT_ANGLE); 
  pinMode(LASER_PIN, OUTPUT);
}

int q[WINDOW_SIZE];
int q_p = 0;

void queue(int x) {
  if (++q_p >= WINDOW_SIZE)
    q_p = 0;
  q[q_p] = x;
}

int average_pulsetime() {
  int i;
  long r=0;
  for (i=0; i<WINDOW_SIZE; i++) {
    r += q[i];
  }
  return (int) (r/WINDOW_SIZE);
}

int aq[AWINDOW_SIZE];
int aq_p = 0;

void aqueue(int x) {
  if (++aq_p >= AWINDOW_SIZE)
    aq_p = 0;
  aq[aq_p] = x;
}

int average_acceleration() {
  int i;
  long r=0;
  for (i=0; i<AWINDOW_SIZE; i++) {
    r += aq[i];
  }
  return (int) (r/AWINDOW_SIZE);
}

void wait_for_pulse() {
  /*
  while (digitalRead(DYNAMO_PIN)) {
  }
  while (!digitalRead(DYNAMO_PIN)) {
  }
  */
  while (analogRead(DYNAMO_PIN) < 300) {
  }
  while (analogRead(DYNAMO_PIN) > 300) {
  }
}

void laser_off() {
  digitalWrite(LASER_PIN, LOW);
}

void laser_on() {
    digitalWrite(LASER_PIN, HIGH);
}

int v_prev;
unsigned long prev_t;

void loop() {
  unsigned long t;
  int dt;
  wait_for_pulse();
  t = millis();
  dt = t - prev_t;
  queue(dt);
  prev_t = t;
 
  dt = average_pulsetime();
  int v = (1000*mm_per_pulse)/dt; // [v] = mm/s
 
  int dv = v - v_prev;
  v_prev = v;
 
  int a = (int) ((1000*(long)dv) / dt); // acceleration in mm/s^2
 
  aqueue(a);
//  Serial.println(); 
//  Serial.print("a: ");
//  Serial.println(a); 
  a = average_acceleration();

//  Serial.print("t: ");
//  Serial.println(t);
//  Serial.print("dt now:");
//  Serial.println(q[q_p]);
//  Serial.print("dt av: ");
//  Serial.println(dt);
//  Serial.print("v: ");
//  Serial.println(v);
//  Serial.print("a: ");
//  Serial.println(a);
  if (a == 0) {
    // don't change anything
  }
  else if (a < 0) {
    // we are slowing down, point the laser
    laser_on();
    int d = (int) (-sq((long) v)/a/2); // distance (mm) until standstill assuming deceleration remains constant
    double angle = (180.0/3.1416) * atan((double)bike_height / d); // angle between laser and forward horizontal
    servo.write(SERVO_STRAIGHT_ANGLE-angle); // change the minus to a plus if your servo is turned around
//    Serial.println();
//    Serial.print("d: ");

//    Serial.println(d);
//    Serial.print("angle: ");
//    Serial.println(angle);

  }
  else {
    // not slowing down
    laser_off();
    servo.write(SERVO_STRAIGHT_ANGLE); // point forward
  }
 
}

Step 6: 6 Make a box, get some batteries and put everything together

Picture of 6 Make a box, get some batteries and put everything together
DSC_0533.JPG
DSC_0551.JPG
DSC_0534.JPG
DSC_0526.JPG
Hi,

I had the chance to pay visit you guys a short vizit on September 22.

I'm glad to see it worked out great.

Keep up the good work!
cool, do you have a video of this in action? how did you calculate the distance to break?
They calculated the speed of the wheel by reading out the dynamo. If you know the by which rate your speed is decreasing and you know the distance you advance between each pulse. you can easily calculate the distance where the time between the next pulse will be infinite.
This is interesting,
Some may over look it being that its on a bike, but I would suggest that its just as useful on a motorcycle / scooter, or even in a car. A simple crash avoidance detector maybe, anyway you are young and seem to have good ideas keep it up!
Hankenstien
Rduino.com
Pro

Get More Out of Instructables

Already have an Account?

close

PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!