-
Notifications
You must be signed in to change notification settings - Fork 0
/
car-tracker2.ino
293 lines (239 loc) · 6.89 KB
/
car-tracker2.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
#include "Adafruit_FONA.h"
#include <SoftwareSerial.h>
#include "LowPower.h"
#define FONA_RX 3
#define FONA_TX 4
#define FONA_RST 5
#define FONA_PWR 6
#define FONA_PWR_STAT 9
// led
int redPin = 12;
int greenPin = 11;
int bluePin = 10;
int ledState = LOW;
unsigned long onMillis;
unsigned long offMillis;
const long led_interval = 2500;
int error_level = 0;
const int voltage_pin = A1;
float last_voltage;
bool startShutdown = false;
bool have_valid_location = false;
bool have_battery_pct = false;
bool message_sent = false;
/* Example
* char sendto[21] = "5552149854";
*/
char sendto[21] = "";
char message[80];
uint16_t vbat;
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
void setup() {
Serial.begin(9600);
// Status LED
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
// Pin reads the PSTAT pin on the FONA, and will be HIGH when the FONA is on
pinMode(FONA_PWR_STAT, INPUT);
// Pin controls the KEY pin on the FONA, driving HIGH for 2 seconds, then LOW for 2 seconds will toggle the power
pinMode(FONA_PWR, OUTPUT);
Serial.println(F("BOOT STATUS: Delaying 5 Seconds to Start"));
counter_delay(5000);
// Determine whether the FONA is ON, if it is, we need to turn it OFF
if (digitalRead(FONA_PWR_STAT)) {
Serial.println(F("VOID SETUP: FONA is ON, Turning FONA OFF.\n"));
fona_toggle_pwr(false);
}
else {
Serial.println(F("VOID SETUP: FONA is already OFF.\n"));
}
// Determine whether the 5v jack is supplying power. If it is, we should go into void_loop as normal
// If not, we should go to sleep and wait for the next plugin.
last_voltage = (float)(analogRead(voltage_pin) / 1024.0) * 3.3;
if (last_voltage >= .5) {
Serial.println(F("VOID SETUP: 5v jack is supplying power. Continue as normal.\n"));
}
else {
Serial.println(F("VOID SETUP: 5v jack is not supply power. Going into low power mode.\n"));
go_to_sleep();
}
}
void loop() {
if (digitalRead(FONA_PWR_STAT) && startShutdown == false) {
Serial.println(F("LOOP STATUS: FONA is ON, Turning FONA OFF."));
fona_toggle_pwr(false);
}
status_led(error_level);
// get_voltage() sets the global variable startShutdown
get_voltage();
if (startShutdown) {
// Turn the FONA On
fona_toggle_pwr(true);
// get_gps_location() sets global variable have_valid_location
get_battery(); // Will return a battery % even if 30x attempts fail.
get_gps_location();
if (have_valid_location) {
send_sms();
fona_toggle_pwr(false);
go_to_sleep();
}
else {
Serial.println(F("VOID LOOP: Unable to Fix GPS Location, Going to Sleep\n"));
fona_toggle_pwr(false);
go_to_sleep();
}
}
}
void get_battery() {
// Try to get the battery percentage
Serial.println(F("Attempting to get battery life from FONA"));
int tries = 0;
have_battery_pct = false;
do {
have_battery_pct = fona.getBattPercent(&vbat);
if (have_battery_pct) {
return have_battery_pct;
}
++tries;
delay(1000);
}
while (tries <= 30);
if (!have_battery_pct) {
vbat = 00;
have_battery_pct = true;
}
Serial.print(F("The battery has a value of "));
Serial.println(vbat);
Serial.print(" out of 100% \n");
}
void get_gps_location() {
Serial.println(F("Attempting to grab the most up to date GPS Fix on the location./n"));
int tries = 0;
do {
float latitude, longitude, speed_kph, heading, speed_mph, altitude;
have_valid_location = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);
char LAT[10];
char LONG[10];
if (have_valid_location) {
dtostrf(latitude, 8, 6, LAT);
dtostrf(longitude, 8, 6, LONG);
sprintf(message, "%s,%s,%u", LAT, LONG, vbat);
Serial.println(F("Sucessfully put together the URL string, including the GPS fix./n"));
Serial.println(message);
return have_valid_location;
} else {
Serial.println(F("Waiting for FONA GPS 3D fix..."));
}
delay(1000);
} while ( tries < 500 );
}
void send_sms() {
// Send SMS
Serial.println(F("Attempting to send the SMS Message: \n"));
Serial.print(message);
Serial.print(F("\n"));
bool message_sent = false;
int tries = 0;
do {
if (!fona.sendSMS(sendto, message)) {
Serial.println(F("SMS Failed"));
message_sent = false;
++tries;
} else {
Serial.println(F("SMS Sent!"));
message_sent = true;
break;
}
delay(100);
}
while (tries <= 4);
}
void fona_toggle_pwr(bool booting) {
digitalWrite(FONA_PWR, HIGH);
delay(2000);
digitalWrite(FONA_PWR, LOW);
delay(2000);
digitalWrite(FONA_PWR, HIGH);
if (booting) {
Serial.println(F("Booting - starting Serial FONA comms."));
fonaSerial->begin(4800);
if (! fona.begin(*fonaSerial)) {
Serial.println(F("Couldn't find FONA"));
error_level = 2;
while (1);
}
Serial.println(F("FONA is OK"));
Serial.println(F("Boot starting GPS"));
fona.enableGPS(true);
}
}
void get_voltage() {
float current_voltage = analogRead(voltage_pin);
current_voltage = (float)(current_voltage / 1024.0) * 3.3;
if ( current_voltage < .5 && last_voltage >= .5 ) {
startShutdown = true;
}
else {
startShutdown = false;
}
last_voltage = current_voltage;
}
void go_to_sleep() {
setColor(0, 0, 0);
attachInterrupt(0, wakeUp, RISING);
counter_delay(5000);
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
detachInterrupt(0);
Serial.println(F("Ignition Started - In standby until next shutdown of automobile."));
startShutdown = false;
error_level = 0;
// Car power when turning on goes high-low-high. Delay seeks toavoid putting FONA to sleep because of this.
delay(5000);
}
void wakeUp() {
// Just a handler for the pin interrupt.
}
void counter_delay(long delay_millis) {
unsigned long started = millis();
unsigned long last_print = 0;
do {
unsigned long time_till_continue = delay_millis - (millis() - started);
if (millis() - last_print > 1000) {
Serial.println(time_till_continue / 1000);
last_print = millis();
}
}
while (millis() - started < delay_millis);
}
void status_led(int error_status) {
unsigned long currentMillis = millis();
if (ledState == HIGH && ((currentMillis - onMillis) > 50)) {
setColor(0, 0, 0);
ledState = LOW;
offMillis = currentMillis;
}
else if (ledState == LOW && ((currentMillis - offMillis) >= led_interval)) {
onMillis = currentMillis;
if (error_status == 0) {
setColor(0, 100, 0);
}
else if (error_status == 1) {
setColor(200, 200, 0);
}
else if (error_status == 2) {
setColor(200, 0, 0);
}
else {
setColor(80, 0, 80);
}
ledState = HIGH;
}
}
void setColor(int red, int green, int blue) {
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}