OutoSoft

Odd Software for Odd Jobs

Bike Sonar, Arduino code

Here's the Arduino code of the prototype I've got running on my bike after a bit of cleanup.


// Simple "bike sonar" ... aka rear parking sensor for a bicyle Winking
// Version 1.1, Brett Hallen, 2016
// Uses: HR-SC04 ultrasonic sensor,
// MAX7219 LED driver,
// four-digit LED display,
// and a piezo buzzer (Jaycar AB-3459)
// Implemented on my bike using a Freetronics LeoStick - requires 5V
// so powered with a "USB battery bank"

// http://playground.arduino.cc/Main/LedControl
#include "LedControl.h"

// http://playground.arduino.cc/Code/NewPing
#include "NewPing.h"

/* ---------------> Sonar Stuff <--------------- */
#define triggerPin 7
#define echoPin 6
#define maxDistance 400 // the HR-SC04 has a max range of about 450cm
#define triggerDistance 100 // when to trigger buzzer, in cm
#define pingDelay 50 // pause between sonar pings
NewPing sonar(triggerPin,echoPin,maxDistance);

/* ---------------> LED/MAX7219 Stuff <--------------- */
#define Din 8
#define CS 9
#define CLK 10
LedControl lc = LedControl(Din,CLK,CS,1);

/* ---------------> Speaker Stuff <--------------- */
#define speakerPin 12

void setup()
{
int i = 0;

// for verification of ping result to serial monitor
Serial.begin(115200);

// initialise the LEDs
lc.shutdown(0,false);
// Intensity between 0 (lowest) and 16 (highest)
lc.setIntensity(0,10);
lc.clearDisplay(0);

// Bit of fancy "I'm powering on, running setup()" indication
// print 0123 on LED
for (i=0;i<=3;i++)
{
lc.setChar(0,i,i,false);
delay(100);
lc.setChar(0,i,' ',false);
}
// print 3210 on LED
for (i=3;i>=0;i--)
{
lc.setChar(0,i,i,false);
delay(100);
lc.setChar(0,i,' ',false);
}

// initialise speaker output
pinMode(speakerPin, OUTPUT);

// setup done
playTone(500,700);
}

void loop()
{
// pause between sonar pings
delay(pingDelay);

// send a ping
int uS = sonar.ping();

// calculate distance in cm
int distance = uS / US_ROUNDTRIP_CM;

// print distance on the LED
printDistanceOnLED(distance);

// object closer than minimum distance?
if (triggerDistance > distance)
{
// closer the object, the faster the 'beeps'
int toneDelay = distance * 5;
// turn on LEDs
lc.shutdown(0,false);
playTone(toneDelay,500); // beep
delay(toneDelay); // pause
playTone(toneDelay,500); // beep
}
else if (250 < distance)
{
lc.shutdown(0,true);
}
}

void printDistanceOnLED(int distance)
{
int metres = distance / 100;
distance = distance - metres * 100;
int cms_tens = distance / 10;
int cms_ones = distance % 10;

// only display digits if non-zero
// no need for thousands digit
lc.setChar(0,0,' ',false);

// display hundreds digit?
// yes if it is non-zero
if (metres)
{
lc.setDigit(0,1,(byte)metres,false);
}
else
{
lc.setChar(0,1,' ',false);
}

// display tens digit?
// yes if it is non-zero or we already have displayed the hundreds digit
if ((cms_tens) || (metres))
{
lc.setDigit(0,2,(byte)cms_tens,false);
}
else
{
lc.setChar(0,2,' ',false);
}

// display ones digit?
// yes if it is non-zero, or we already have displayed the hundreds or tens digit
if ((cms_ones) || (cms_tens) || (metres))
{
lc.setDigit(0,3,(byte)cms_ones,false);
}
else
{
lc.setChar(0,3,' ',false);
}

// for verification to serial monitor
Serial.print(metres); Serial.print("."); Serial.print(cms_tens); Serial.print(cms_ones); Serial.println("m");
}

// duration in milliseconds, frequency in Hertz
// http://michael.thegrebs.com/2009/03/23/playing-a-tone-through-an-arduino-connected-piezo/
void playTone(long duration, int freq)
{
duration *= 1000;
int period = (1.0 / freq) * 1000000;
long elapsed_time = 0;
while (elapsed_time < duration) {
digitalWrite(speakerPin,HIGH);
delayMicroseconds(period / 2);
digitalWrite(speakerPin, LOW);
delayMicroseconds(period / 2);
elapsed_time += (period);
}
}