-
Notifications
You must be signed in to change notification settings - Fork 0
/
toy_truck_odometer.ino
129 lines (94 loc) · 3.27 KB
/
toy_truck_odometer.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Low-Power - Version: Latest
#include <LowPower.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <avr/interrupt.h>
#include <avr/power.h>
#include <avr/sleep.h>
#include <avr/io.h>
const int REV_COUNTER_PIN = 2;
const int REV_HALFWAY_PIN = 3;
const int LED_BACKLIGHT_PIN = 10;
const int WHEEL_CIRCUM = 17;
const int EE_ADDRESS = 0; // EEPROM memory location where odometer storage begins
unsigned long distance_odometer; // (inches)
volatile unsigned long time_last_active;
volatile bool rev_happened = false;
volatile bool halfway_point_passed = false;
String message;
// See the .PNG file for the wiring diagram
const int RS = 9, EN = 8, D4 = 4, D5 = 5, D6 = 6, D7 = 7;
LiquidCrystal lcd(RS, EN, D4, D5, D6, D7);
void setup()
{
Serial.begin(9600);
pinMode(LED_BACKLIGHT_PIN, OUTPUT);
pinMode(REV_COUNTER_PIN, INPUT);
pinMode(REV_HALFWAY_PIN, INPUT);
digitalWrite(LED_BACKLIGHT_PIN, HIGH);
attachInterrupt(digitalPinToInterrupt(REV_COUNTER_PIN), processRev, FALLING);
attachInterrupt(digitalPinToInterrupt(REV_HALFWAY_PIN), processHalfwayPoint, FALLING);
// Get the stored distance
EEPROM.get(EE_ADDRESS, distance_odometer);
// Set up the LCD's number of columns and rows
lcd.begin(16, 2);
update_lcd(String( String(distance_odometer / 12) + " feet"));
// So that we don't go to sleep right away
time_last_active = millis();
}
long time_now;
void loop()
{
// Go to sleep if not active within past 5 seconds
if ((millis() - time_last_active) > 5000) {
/*
Serial.println("About to go to sleep");
time_now = millis();
Serial.print("time_now - time_last_active(ms): ");
Serial.println(time_now - time_last_active);
delay(250); // Give serial time to print
*/
go_to_sleep();
}
if (rev_happened) {
rev_happened = false; // Reset for next wheel revolution
distance_odometer += WHEEL_CIRCUM;
// Serial.print("rev_happened: ");
// Serial.print(distance_odometer);
// Serial.println(" inches");
update_lcd(String( String(distance_odometer / 12) + " feet"));
}
}
// ************************************************
// SUBROUTINES
// ************************************************
void processRev() {
if (halfway_point_passed) {
rev_happened = true;
halfway_point_passed = false; // prep for next rotation
}
// Refresh time till sleep since the wheel is moving
time_last_active = millis();
}
void processHalfwayPoint() {
halfway_point_passed = true;
// Refresh time till sleep since the wheel is moving
time_last_active = millis();
}
void update_lcd(String message) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Odometer");
lcd.setCursor(0, 1);
lcd.print(message);
}
void go_to_sleep() {
lcd.noDisplay(); // turn off text display
digitalWrite(LED_BACKLIGHT_PIN, LOW);
EEPROM.put(EE_ADDRESS, distance_odometer); // Write out current distance to memory in case of power loss
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
// Upon waking up, sketch continues from this point AFTER
// servicing whatever ISR triggered the wakeup
digitalWrite(LED_BACKLIGHT_PIN, HIGH);
lcd.display();
}