ttgo-t-beam-gps-ttn-tracker/main/main.ino

293 lines
8.3 KiB
Arduino
Raw Normal View History

2019-02-10 18:35:12 +00:00
/*
Main module
2019-02-10 18:35:12 +00:00
# Modified by Kyle T. Gabriel to fix issue with incorrect GPS data for TTNMapper
2019-02-10 18:35:12 +00:00
Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
2019-02-10 18:35:12 +00:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
2019-02-10 18:35:12 +00:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
2019-02-10 18:35:12 +00:00
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
2019-02-10 18:35:12 +00:00
*/
#include "configuration.h"
#include "rom/rtc.h"
2019-08-26 00:44:56 +00:00
#include <TinyGPS++.h>
#include <Wire.h>
2019-02-10 18:35:12 +00:00
2019-08-25 17:46:03 +00:00
#ifdef T_BEAM_V10
#include "axp20x.h"
2019-08-25 17:56:43 +00:00
AXP20X_Class axp;
bool pmu_irq = false;
String baChStatus = "No charging";
2019-08-25 17:46:03 +00:00
#endif
2019-08-26 00:58:12 +00:00
bool ssd1306_found = false;
bool axp192_found = false;
2019-02-10 18:35:12 +00:00
// Message counter, stored in RTC memory, survives deep sleep
RTC_DATA_ATTR uint32_t count = 0;
2019-07-11 08:07:14 +00:00
2019-08-23 22:05:07 +00:00
#if defined(PAYLOAD_USE_FULL)
// includes number of satellites and accuracy
uint8_t txBuffer[10];
#elif defined(PAYLOAD_USE_CAYENNE)
2019-08-23 14:22:03 +00:00
// CAYENNE DF
static uint8_t txBuffer[11] = {0x03, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#endif
2019-02-10 18:35:12 +00:00
// -----------------------------------------------------------------------------
// Application
// -----------------------------------------------------------------------------
void send() {
char buffer[40];
snprintf(buffer, sizeof(buffer), "Latitude: %10.6f\n", gps_latitude());
screen_print(buffer);
snprintf(buffer, sizeof(buffer), "Longitude: %10.6f\n", gps_longitude());
screen_print(buffer);
snprintf(buffer, sizeof(buffer), "Error: %4.2fm\n", gps_hdop());
screen_print(buffer);
buildPacket(txBuffer);
#if LORAWAN_CONFIRMED_EVERY > 0
bool confirmed = (count % LORAWAN_CONFIRMED_EVERY == 0);
#else
bool confirmed = false;
#endif
ttn_cnt(count);
ttn_send(txBuffer, sizeof(txBuffer), LORAWAN_PORT, confirmed);
count++;
2019-02-10 18:35:12 +00:00
}
void sleep() {
#if SLEEP_BETWEEN_MESSAGES
2019-02-10 18:35:12 +00:00
// Show the going to sleep message on the screen
char buffer[20];
snprintf(buffer, sizeof(buffer), "Sleeping in %3.1fs\n", (MESSAGE_TO_SLEEP_DELAY / 1000.0));
screen_print(buffer);
2019-02-10 18:35:12 +00:00
// Wait for MESSAGE_TO_SLEEP_DELAY millis to sleep
delay(MESSAGE_TO_SLEEP_DELAY);
2019-02-10 18:35:12 +00:00
// Turn off screen
screen_off();
2019-02-10 18:35:12 +00:00
// Set the user button to wake the board
sleep_interrupt(BUTTON_PIN, LOW);
2019-02-10 18:35:12 +00:00
// We sleep for the interval between messages minus the current millis
// this way we distribute the messages evenly every SEND_INTERVAL millis
uint32_t sleep_for = (millis() < SEND_INTERVAL) ? SEND_INTERVAL - millis() : SEND_INTERVAL;
sleep_millis(sleep_for);
2019-02-10 18:35:12 +00:00
#endif
2019-02-10 18:35:12 +00:00
}
void callback(uint8_t message) {
if (EV_JOINING == message) screen_print("Joining TTN...\n");
if (EV_JOINED == message) screen_print("TTN joined!\n");
if (EV_JOIN_FAILED == message) screen_print("TTN join failed\n");
if (EV_REJOIN_FAILED == message) screen_print("TTN rejoin failed\n");
if (EV_RESET == message) screen_print("Reset TTN connection\n");
if (EV_LINK_DEAD == message) screen_print("TTN link dead\n");
if (EV_ACK == message) screen_print("ACK received\n");
if (EV_PENDING == message) screen_print("Message discarded\n");
if (EV_QUEUED == message) screen_print("Message queued\n");
if (EV_TXCOMPLETE == message) {
screen_print("Message sent\n");
sleep();
}
if (EV_RESPONSE == message) {
screen_print("[TTN] Response: ");
size_t len = ttn_response_len();
uint8_t data[len];
ttn_response(data, len);
char buffer[6];
for (uint8_t i = 0; i < len; i++) {
snprintf(buffer, sizeof(buffer), "%02X", data[i]);
screen_print(buffer);
2019-02-10 18:35:12 +00:00
}
screen_print("\n");
}
2019-02-10 18:35:12 +00:00
}
uint32_t get_count() {
return count;
2019-02-10 18:35:12 +00:00
}
2019-08-26 00:55:00 +00:00
void scanI2Cdevice(void)
{
byte err, addr;
int nDevices = 0;
for (addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
err = Wire.endTransmission();
if (err == 0) {
Serial.print("I2C device found at address 0x");
if (addr < 16)
Serial.print("0");
Serial.print(addr, HEX);
Serial.println(" !");
nDevices++;
if (addr == SSD1306_ADDRESS) {
ssd1306_found = true;
Serial.println("ssd1306 display found");
}
if (addr == AXP192_SLAVE_ADDRESS) {
axp192_found = true;
Serial.println("axp192 PMU found");
}
} else if (err == 4) {
Serial.print("Unknow error at address 0x");
if (addr < 16)
Serial.print("0");
Serial.println(addr, HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
}
2019-02-10 18:35:12 +00:00
void setup() {
// Debug
2019-08-25 16:57:37 +00:00
#ifdef DEBUG_PORT
DEBUG_PORT.begin(SERIAL_BAUD);
2019-08-25 16:57:37 +00:00
#endif
2019-08-26 00:55:00 +00:00
delay(1000);
2019-08-25 16:57:37 +00:00
#ifdef T_BEAM_V10
2019-08-26 00:44:56 +00:00
Wire.begin(I2C_SDA, I2C_SCL);
2019-08-26 00:55:00 +00:00
scanI2Cdevice();
2019-08-26 00:44:56 +00:00
axp192_found = true;
2019-08-25 16:57:37 +00:00
if (axp192_found) {
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
Serial.println("AXP192 Begin PASS");
} else {
Serial.println("AXP192 Begin FAIL");
}
// axp.setChgLEDMode(LED_BLINK_4HZ);
2019-08-25 17:29:56 +00:00
Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
Serial.println("----------------------------------------");
2019-08-25 16:57:37 +00:00
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON);
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON);
axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON);
axp.setDCDC1Voltage(3300);
2019-08-25 17:29:56 +00:00
Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
2019-08-25 16:57:37 +00:00
pinMode(PMU_IRQ, INPUT_PULLUP);
attachInterrupt(PMU_IRQ, [] {
pmu_irq = true;
}, FALLING);
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1);
axp.clearIRQ();
if (axp.isChargeing()) {
baChStatus = "Charging";
}
} else {
2019-08-25 17:29:56 +00:00
Serial.println("AXP192 not found");
2019-08-25 16:57:37 +00:00
}
#endif
2019-02-10 18:35:12 +00:00
// Buttons & LED
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
// Hello
DEBUG_MSG(APP_NAME " " APP_VERSION "\n");
// Display
screen_setup();
// Init GPS
gps_setup();
// Show logo on first boot
if (0 == count) {
screen_print(APP_NAME " " APP_VERSION, 0, 0);
screen_show_logo();
screen_update();
delay(LOGO_DELAY);
}
// TTN setup
if (!ttn_setup()) {
screen_print("[ERR] Radio module not found!\n");
delay(MESSAGE_TO_SLEEP_DELAY);
screen_off();
sleep_forever();
}
ttn_register(callback);
ttn_join();
ttn_sf(LORAWAN_SF);
ttn_adr(LORAWAN_ADR);
2019-02-10 18:35:12 +00:00
}
void loop() {
gps_loop();
ttn_loop();
screen_loop();
// Send every SEND_INTERVAL millis
static uint32_t last = 0;
static bool first = true;
if (0 == last || millis() - last > SEND_INTERVAL) {
if (0 < gps_hdop() && gps_hdop() < 50 && gps_latitude() != 0 && gps_longitude() != 0) {
last = millis();
first = false;
Serial.println("TRANSMITTING");
send();
} else {
if (first) {
screen_print("Waiting GPS lock\n");
first = false;
}
if (millis() > GPS_WAIT_FOR_LOCK) {
sleep();
}
2019-02-10 18:35:12 +00:00
}
}
2019-02-10 18:35:12 +00:00
}