-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathATT_LoRaWAN_TRACKTRACE.cpp
214 lines (178 loc) · 5.1 KB
/
ATT_LoRaWAN_TRACKTRACE.cpp
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
/*
Copyright 2016 AllThingsTalk
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/
#include "ATT_LoRaWAN_TRACKTRACE.h"
#include <Wire.h>
#define BATTERY_REPORT_SEC 59 //determins how frequently the interrupt clock wakes up to send battery stats.
#define BATTERY_REPORT_MIN 59
#define BATTERY_REPORT_HOUR 23
#define BATTERY_REPORT_EVERY RTCZero::MATCH_MMSS //MATCH_HHMMSS
//These constants are used for reading the battery voltage
#define ADC_AREF 3.3
#define BATVOLT_PIN BAT_VOLT
#define BATVOLT_R1 4.7
#define BATVOLT_R2 10
#define SENDBATTERYEVERY 86400000 //send battery every 24 hours, used to check time if we missed a hartbeat from the interrupt clock.
/**
* Turns the led on according to the given color. Makes no assumptions about the status of the pins
* i.e. it sets them every time,
*/
void setLedColor(LedColor color)
{
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, HIGH);
switch (color)
{
case NONE:
break;
case RED:
digitalWrite(LED_RED, LOW);
break;
case GREEN:
digitalWrite(LED_GREEN, LOW);
break;
case BLUE:
digitalWrite(LED_BLUE, LOW);
break;
case YELLOW:
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, LOW);
break;
case MAGENTA:
digitalWrite(LED_BLUE, LOW);
digitalWrite(LED_RED, LOW);
break;
case CYAN:
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_BLUE, LOW);
break;
case WHITE:
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_BLUE, LOW);
break;
default:
break;
}
}
//power
void initPower()
{
pinMode(ENABLE_PIN_IO, OUTPUT);
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; //prepare the board for deep sleep mode.
}
void setGPSPower(int8_t value)
{
digitalWrite(GPS_ENABLE, value);
}
void setPower(int8_t value)
{
digitalWrite(ENABLE_PIN_IO, value);
}
// wire communication
#define ACCEL_ADR 0b0011110
uint8_t writeReg(uint8_t reg, uint8_t val)
{
Wire.beginTransmission(ACCEL_ADR);
Wire.write(reg);
Wire.write(val);
Wire.endTransmission();
delayMicroseconds(10000);
}
uint8_t readReg(uint8_t reg)
{
Wire.beginTransmission(ACCEL_ADR);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(ACCEL_ADR, 0x01);
uint8_t val = Wire.read();
Wire.endTransmission();
return val;
}
//board
volatile bool _reportMovement = false;
volatile bool _reportMagneto = false;
void onAccelInterrupt()
{
_reportMovement = true;
}
void onMagnetoInterrupt()
{
_reportMagneto = true;
}
void initAcceleroInterrupts()
{
pinMode(ACCEL_INT1, INPUT_PULLUP);
pinMode(ACCEL_INT2, INPUT_PULLUP);
attach(ACCEL_INT1, onAccelInterrupt, FALLING);
attach(ACCEL_INT2, onAccelInterrupt, FALLING);
}
void attach(int pin, voidFuncPtr callback, int mode)
{
attachInterrupt(pin, callback, mode);
//has to be set after first call to attachinterrupt
SYSCTRL->XOSC32K.bit.RUNSTDBY = 1; // Set the XOSC32K to run in standby
//possibly that we have to do |= in the next statement, to keep the settings done by the rtczero timer.
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_EIC) | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_CLKEN;// Configure EIC to use GCLK1 which uses XOSC32K
}
//returns true if the accelerometer reported movement
//resets the switch so that new movement can be detected on the next run.
bool hasMoved()
{
if (_reportMovement) {
_reportMovement = false;
return true;
}
return false;
}
//returns true if the accelerometer reported a change in the magnetic field
//resets the switch so that a new change can be detected on the next run.
bool magnetoChanged()
{
if (_reportMagneto) {
_reportMagneto = false;
return true;
}
return false;
}
void disableUSB()
{
USB->DEVICE.CTRLA.reg &= ~USB_CTRLA_ENABLE;
}
void enableUSB()
{
USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE;
}
//put the device is a deep sleep mode.
void sleep()
{
delay(180);
//disableUSB();
__WFI(); //Enter sleep mode
//...Sleep forever or until interupt has arrived.
//enableUSB();
delay(180); //after waking up, give the device a little bit of time to wake up, if we don't do this, the serial will block and the first call to SerialUSB will make the app fail.
}
//battery
int batteryStatus()
{
SerialUSB.println("reporting battery status");
uint16_t batteryVoltage = analogRead(BATVOLT_PIN);
uint16_t battery = (ADC_AREF / 1.023) * (BATVOLT_R1 + BATVOLT_R2) / BATVOLT_R2 * (float)batteryVoltage;
battery = (uint16_t)((100.0/ 1200.) * (float) (battery-3000));
if (battery > 100)
battery = 100;
SerialUSB.print("level: "); SerialUSB.println(battery);
return battery;
}