/*
* ATTENTION: run the memorysetter code first.
* If you do not you will get random numbers for
* your odometer and tripmeter.
* The memorysetter code will sweep the used
* memory positions and set the required
* odometer and tripmeter value.
*/
//include the display library
#include <LiquidCrystal.h>
//include the EEPROM library for the memory functions
#include <EEPROM.h>
//initiate the display library
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
//declaring variables
int hallpin=1; //hall sensor interrupt pin (digital pin 3)
int hallstate=0;
int hallcounter=0;
long odometer=0;
int tripmeter=0;
int servicemeter=0;
int rotationcounter=0;
int vspeed=0; //vehicle speed
int dvspeed=0; //vehicle display speed
int tyrec=1935; //tyre circumference in mm ADD TYRE CIRCUMFERENCE HERE
long deltat=0; //time between hall inputs
long timea=0; //variable to count time
long timec=0; //variable to count time
//button variables
int b1pin=6;
int b1prevstate=HIGH;
int b1state=HIGH;
long b1timepressed=0;
long b1timereleased=0;
long b1holdtime=0;
int b1waspressed=0;
//speed array values
int speedrr=500; //speed refresh rate
const int speedarraysize=5; //arraysize
int speedarray[speedarraysize];
int arrayposition=0;
//memory variables
int odoaddress=1;
int tripaddress=odoaddress+8;
int serviceaddress=odoaddress+15;
/*
* Here follows some code to create the big
* characters for the speed
*/
byte bar1[8] =
{
B11100,
B11110,
B11110,
B11110,
B11110,
B11110,
B11110,
B11100
};
byte bar2[8] =
{
B00111,
B01111,
B01111,
B01111,
B01111,
B01111,
B01111,
B00111
};
byte bar3[8] =
{
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111
};
byte bar4[8] =
{
B11110,
B11100,
B00000,
B00000,
B00000,
B00000,
B11000,
B11100
};
byte bar5[8] =
{
B01111,
B00111,
B00000,
B00000,
B00000,
B00000,
B00011,
B00111
};
byte bar6[8] =
{
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B11111,
B11111
};
byte bar7[8] =
{
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B00111,
B01111
};
byte bar8[8] =
{
B11111,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000
};
//////////END OF BIG FONT STUFF
void setup() {
//declare LCD size
lcd.begin(16, 2);
//attach the interrupt for the hall sensor
attachInterrupt(hallpin, hallfunction, RISING);
//define the button pinmode. INPUT_PULLUP to avoid the need of a resistor (normally open switch)
pinMode(b1pin, INPUT_PULLUP);
//search the memory for odometer and tripmeter values
addressselector();
///////bigfont stuff
// assignes each segment a write number
lcd.createChar(1,bar1);
lcd.createChar(2,bar2);
lcd.createChar(3,bar3);
lcd.createChar(4,bar4);
lcd.createChar(5,bar5);
lcd.createChar(6,bar6);
lcd.createChar(7,bar7);
lcd.createChar(8,bar8);
/////////end of bigfont stuff
}
void loop() {
//check the speed
speedcheck();
//check if something is going on with the button
buttoncheck();
//display mileage values
lcd.setCursor(10,0);
lcd.print(odometer); //Display the odometer value in km
/*
* If you want the odometer value in miles,
* change the line into this:
* lcd.print(odometer*0.621371192,0);
*/
lcd.setCursor(10,1);
lcd.print(tripmeter); //Display the tripmeter value in km
/*
* If you want the tripmeter value in miles,
* change the line into this:
* lcd.print(tripmeter*0.621371192,0);
*/
//display the speed
printlargespeed();
}
//hall sensor interrupt function
void hallfunction(){
vspeed=tyrec*3.6/(millis()-deltat);
timea=millis(); //start to count since last signal
deltat=millis(); //reset last input
rotationcounter=rotationcounter+1; //count the rotations
}
//This function calculates the speed every time the magnet will pass the hall sensor.
//If there is too much time between two passes the vehicle is not moving apparently
//and the speed will be set 0.
void speedcheck(){
//set speed to zero if there is no signal for too long
if (millis()-timea > 1000){
vspeed=0;
timea=millis();
}
//start filling the array with speed values then calculate the average
//this ensures a smooth display of speed
if (millis()-timec >= speedrr/speedarraysize){
speedarray[arrayposition]=vspeed;
arrayposition=arrayposition+1;
if (arrayposition == speedarraysize){
arrayposition=0;
dvspeed=0;
for (int x=0; x<speedarraysize; x++)
{
dvspeed=dvspeed+speedarray[x];
}
/*
* The following line calculates the speed in km/h.
* If you want the speed in MPH change it into this:
* dvspeed=(dvspeed/speedarraysize)*0.621371192;
*/
dvspeed=dvspeed/speedarraysize;
}
timec=millis();
}
//actions after driving 1km
if (rotationcounter >= 1000000/tyrec){
odometer=odometer+1;
memorywrite(odoaddress, odometer); //save new odometer value in memory
tripmeter=tripmeter+1;
if (tripmeter > 999){
tripmeter=0;
}
memorywrite(tripaddress, tripmeter); //save new tripmeter value in memory
//call the wearleveller to reduce EEPROM wear
wearleveller();
rotationcounter=0;
}
}
void buttoncheck(){
b1state=digitalRead(b1pin);
if (b1state != b1prevstate){
if (b1state == LOW){ //button was pressed
b1timepressed=millis();
b1waspressed=1;
}
if (b1state == HIGH){
b1timereleased=millis();
b1waspressed=0;
b1holdtime=b1timereleased-b1timepressed;
lcd.clear();
}
}
b1prevstate=b1state;
if (b1waspressed==1){
if (millis()-b1timepressed > 3000){
tripmeter=0;
memorywrite(tripaddress, tripmeter); //save new tripmeter value in memory
b1waspressed=0;
}
}
}
/*
*
* In this section you find the memory read/write functions
*
*/
//select the addresses where values are stored
void addressselector(){
odometer=memoryread(odoaddress);
tripmeter=memoryread(odoaddress+8);
servicemeter=memoryread(odoaddress+15);
for (int pos=1; pos<252; pos=pos+25){
if (memoryread(pos)> odometer){
odoaddress=pos;
odometer=memoryread(pos);
tripaddress=pos+8;
tripmeter=memoryread(tripaddress);
serviceaddress=pos+15;
servicemeter=memoryread(serviceaddress);
}
}
}
//change memory position after every write
void wearleveller(){
odoaddress=odoaddress+25;
tripaddress=tripaddress+25;
serviceaddress=serviceaddress+25;
if (odoaddress >= 250){
odoaddress=1;
tripaddress=odoaddress+8;
serviceaddress=odoaddress+15;
}
}
//write to memory
void memorywrite(int address, long value){
long val1=value/100000;
value=value-val1*100000;
long val2=value/10000;
value=value-val2*10000;
int val3=value/1000;
value=value-val3*1000;
int val4=value/100;
value=value-val4*100;
int val5=value/10;
int val6=value-val5*10;
EEPROM.write(address, val1);
EEPROM.write(address+1, val2);
EEPROM.write(address+2, val3);
EEPROM.write(address+3, val4);
EEPROM.write(address+4, val5);
EEPROM.write(address+5, val6);
}
//read from memory
long memoryread(int address){
long val1=EEPROM.read(address);
long val2=EEPROM.read(address+1);
int val3=EEPROM.read(address+2);
int val4=EEPROM.read(address+3);
int val5=EEPROM.read(address+4);
int val6=EEPROM.read(address+5);
long result=val1*100000+val2*10000+val3*1000+val4*100+val5*10+val6;
return result;
}
/*
* Here follows more code for the custom
* characters to display the speed with
* a large font
*/
void custom0(int col)
{ // uses segments to build the number 0
lcd.setCursor(col, 0);
lcd.write(2);
lcd.write(8);
lcd.write(1);
lcd.setCursor(col, 1);
lcd.write(2);
lcd.write(6);
lcd.write(1);
}
void custom1(int col)
{
lcd.setCursor(col,0);
lcd.write(32);
lcd.write(32);
lcd.write(1);
lcd.setCursor(col,1);
lcd.write(32);
lcd.write(32);
lcd.write(1);
}
void custom2(int col)
{
lcd.setCursor(col,0);
lcd.write(5);
lcd.write(3);
lcd.write(1);
lcd.setCursor(col, 1);
lcd.write(2);
lcd.write(6);
lcd.write(6);
}
void custom3(int col)
{
lcd.setCursor(col,0);
lcd.write(5);
lcd.write(3);
lcd.write(1);
lcd.setCursor(col, 1);
lcd.write(7);
lcd.write(6);
lcd.write(1);
}
void custom4(int col)
{
lcd.setCursor(col,0);
lcd.write(2);
lcd.write(6);
lcd.write(1);
lcd.setCursor(col, 1);
lcd.write(32);
lcd.write(32);
lcd.write(1);
}
void custom5(int col)
{
lcd.setCursor(col,0);
lcd.write(2);
lcd.write(3);
lcd.write(4);
lcd.setCursor(col, 1);
lcd.write(7);
lcd.write(6);
lcd.write(1);
}
void custom6(int col)
{
lcd.setCursor(col,0);
lcd.write(2);
lcd.write(3);
lcd.write(4);
lcd.setCursor(col, 1);
lcd.write(2);
lcd.write(6);
lcd.write(1);
}
void custom7(int col)
{
lcd.setCursor(col,0);
lcd.write(2);
lcd.write(8);
lcd.write(1);
lcd.setCursor(col, 1);
lcd.write(32);
lcd.write(32);
lcd.write(1);
}
void custom8(int col)
{
lcd.setCursor(col, 0);
lcd.write(2);
lcd.write(3);
lcd.write(1);
lcd.setCursor(col, 1);
lcd.write(2);
lcd.write(6);
lcd.write(1);
}
void custom9(int col)
{
lcd.setCursor(col, 0);
lcd.write(2);
lcd.write(3);
lcd.write(1);
lcd.setCursor(col, 1);
lcd.write(7);
lcd.write(6);
lcd.write(1);
}
void printNumber(int value, int col) {
if (value == 0) {
custom0(col);
} if (value == 1) {
custom1(col);
} if (value == 2) {
custom2(col);
} if (value == 3) {
custom3(col);
} if (value == 4) {
custom4(col);
} if (value == 5) {
custom5(col);
} if (value == 6) {
custom6(col);
} if (value == 7) {
custom7(col);
} if (value == 8) {
custom8(col);
} if (value == 9) {
custom9(col);
}
}
void printlargespeed(){
int c, d, u, number;
number = dvspeed;
if (number > 99) {
c = (number - (number % 100)) / 100;
number = number % 100;
} else {
c = 0;
}
if (number > 9) {
d = (number - (number % 10)) / 10;
number = number % 10;
} else {
d = 0;
}
u = number;
if (dvspeed <10){
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
printNumber(u, 6);
}
if (dvspeed >= 10 && dvspeed < 100){
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
printNumber(d, 3);
printNumber(u, 6);
}
if (dvspeed >= 100){
lcd.setCursor(0,0);
printNumber(c, 0);
printNumber(d, 3);
printNumber(u, 6);
}
}