commit
a2b2d3411d
@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <lmic.h>
|
#include <lmic.h>
|
||||||
|
|
||||||
void ttn_register(void (*callback)(uint8_t message));
|
void ttn_register(void (*callback)(uint8_t message));
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -40,10 +39,11 @@ void ttn_register(void (*callback)(uint8_t message));
|
|||||||
// Configuration
|
// Configuration
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define USE_CAYENNE
|
||||||
#define DEBUG_PORT Serial // Serial debug port
|
#define DEBUG_PORT Serial // Serial debug port
|
||||||
#define SERIAL_BAUD 115200 // Serial debug baud rate
|
#define SERIAL_BAUD 115200 // Serial debug baud rate
|
||||||
#define SLEEP_BETWEEN_MESSAGES 0 // Do sleep between messages
|
#define SLEEP_BETWEEN_MESSAGES 0 // Do sleep between messages
|
||||||
#define SEND_INTERVAL 30000 // Sleep for these many millis
|
#define SEND_INTERVAL 10000 // Sleep for these many millis
|
||||||
#define MESSAGE_TO_SLEEP_DELAY 5000 // Time after message before going to sleep
|
#define MESSAGE_TO_SLEEP_DELAY 5000 // Time after message before going to sleep
|
||||||
#define LOGO_DELAY 5000 // Time to show logo on first boot
|
#define LOGO_DELAY 5000 // Time to show logo on first boot
|
||||||
#define LORAWAN_PORT 10 // Port the messages will be sent to
|
#define LORAWAN_PORT 10 // Port the messages will be sent to
|
||||||
@ -94,6 +94,7 @@ void ttn_register(void (*callback)(uint8_t message));
|
|||||||
#define GPS_RX_PIN 12
|
#define GPS_RX_PIN 12
|
||||||
#define GPS_TX_PIN 15
|
#define GPS_TX_PIN 15
|
||||||
#define GPS_BAUDRATE 9600
|
#define GPS_BAUDRATE 9600
|
||||||
|
#define USE_GPS 1
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// LoRa SPI
|
// LoRa SPI
|
||||||
|
40
main/gps.ino
40
main/gps.ino
@ -62,6 +62,44 @@ static void gps_loop() {
|
|||||||
_gps.encode(_serial_gps.read());
|
_gps.encode(_serial_gps.read());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef USE_CAYENNE
|
||||||
|
// CAYENNE DF
|
||||||
|
void buildPacket(uint8_t txBuffer[11])
|
||||||
|
{
|
||||||
|
sprintf(t, "Lat: %f", _gps.location.lat());
|
||||||
|
Serial.println(t);
|
||||||
|
sprintf(t, "Lng: %f", _gps.location.lng());
|
||||||
|
Serial.println(t);
|
||||||
|
sprintf(t, "Alt: %f", _gps.altitude.meters());
|
||||||
|
Serial.println(t);
|
||||||
|
int32_t lat = _gps.location.lat() * 10000;
|
||||||
|
int32_t lon = _gps.location.lng() * 10000;
|
||||||
|
int32_t alt = _gps.altitude.meters() * 100;
|
||||||
|
|
||||||
|
txBuffer[2] = lat >> 16;
|
||||||
|
txBuffer[3] = lat >> 8;
|
||||||
|
txBuffer[4] = lat;
|
||||||
|
txBuffer[5] = lon >> 16;
|
||||||
|
txBuffer[6] = lon >> 8;
|
||||||
|
txBuffer[7] = lon;
|
||||||
|
txBuffer[8] = alt >> 16;
|
||||||
|
txBuffer[9] = alt >> 8;
|
||||||
|
txBuffer[10] = alt;
|
||||||
|
/*
|
||||||
|
txBuffer[2] = ( LatitudeBinary >> 16 );// & 0xFF;
|
||||||
|
txBuffer[3] = ( LatitudeBinary >> 8 );// & 0xFF;
|
||||||
|
txBuffer[4] = LatitudeBinary;// & 0xFF;
|
||||||
|
|
||||||
|
txBuffer[5] = ( LongitudeBinary >> 16 ) & 0xFF;
|
||||||
|
txBuffer[6] = ( LongitudeBinary >> 8 ) & 0xFF;
|
||||||
|
txBuffer[7] = LongitudeBinary & 0xFF;
|
||||||
|
|
||||||
|
txBuffer[8] = Height >> 16;
|
||||||
|
txBuffer[9] = Height >> 8;
|
||||||
|
txBuffer[10] = Height;*/
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint8_t txBuffer[9];
|
||||||
|
|
||||||
void buildPacket(uint8_t txBuffer[9])
|
void buildPacket(uint8_t txBuffer[9])
|
||||||
{
|
{
|
||||||
@ -89,3 +127,5 @@ void buildPacket(uint8_t txBuffer[9])
|
|||||||
hdopGps = _gps.hdop.value()/10;
|
hdopGps = _gps.hdop.value()/10;
|
||||||
txBuffer[8] = hdopGps & 0xFF;
|
txBuffer[8] = hdopGps & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
// inside the project_config folder.
|
// inside the project_config folder.
|
||||||
|
|
||||||
// Make sure only one of the following is defined (CFG_us915 or CFG_eu868)
|
// Make sure only one of the following is defined (CFG_us915 or CFG_eu868)
|
||||||
#define CFG_us915 1
|
#define CFG_au915 1
|
||||||
|
//#define CFG_au923 1
|
||||||
//#define CFG_eu868 1
|
//#define CFG_eu868 1
|
||||||
|
|
||||||
#define CFG_sx1276_radio 1
|
#define CFG_sx1276_radio 1
|
||||||
|
265
main/main.ino
265
main/main.ino
@ -1,185 +1,196 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Main module
|
Main module
|
||||||
|
|
||||||
# Modified by Kyle T. Gabriel to fix issue with incorrect GPS data for TTNMapper
|
# Modified by Kyle T. Gabriel to fix issue with incorrect GPS data for TTNMapper
|
||||||
|
|
||||||
Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
|
Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <rom/rtc.h>
|
#include "rom/rtc.h"
|
||||||
|
|
||||||
uint8_t txBuffer[9];
|
|
||||||
|
|
||||||
// Message counter, stored in RTC memory, survives deep sleep
|
// Message counter, stored in RTC memory, survives deep sleep
|
||||||
RTC_DATA_ATTR uint32_t count = 0;
|
RTC_DATA_ATTR uint32_t count = 0;
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Submodules
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
#include <TinyGPS++.h>
|
||||||
|
|
||||||
|
#ifdef USE_CAYENNE
|
||||||
|
// CAYENNE DF
|
||||||
|
static uint8_t txBuffer[11] = {0x03, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
#else
|
||||||
|
uint8_t txBuffer[9];
|
||||||
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Application
|
// Application
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void send() {
|
void send() {
|
||||||
char buffer[40];
|
char buffer[40];
|
||||||
snprintf(buffer, sizeof(buffer), "Latitude: %10.6f\n", gps_latitude());
|
snprintf(buffer, sizeof(buffer), "Latitude: %10.6f\n", gps_latitude());
|
||||||
screen_print(buffer);
|
screen_print(buffer);
|
||||||
snprintf(buffer, sizeof(buffer), "Longitude: %10.6f\n", gps_longitude());
|
snprintf(buffer, sizeof(buffer), "Longitude: %10.6f\n", gps_longitude());
|
||||||
screen_print(buffer);
|
screen_print(buffer);
|
||||||
snprintf(buffer, sizeof(buffer), "Error: %4.2fm\n", gps_hdop());
|
snprintf(buffer, sizeof(buffer), "Error: %4.2fm\n", gps_hdop());
|
||||||
screen_print(buffer);
|
screen_print(buffer);
|
||||||
|
|
||||||
buildPacket(txBuffer);
|
buildPacket(txBuffer);
|
||||||
|
|
||||||
#if LORAWAN_CONFIRMED_EVERY > 0
|
#if LORAWAN_CONFIRMED_EVERY > 0
|
||||||
bool confirmed = (count % LORAWAN_CONFIRMED_EVERY == 0);
|
bool confirmed = (count % LORAWAN_CONFIRMED_EVERY == 0);
|
||||||
#else
|
#else
|
||||||
bool confirmed = false;
|
bool confirmed = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ttn_cnt(count);
|
ttn_cnt(count);
|
||||||
ttn_send(txBuffer, sizeof(txBuffer), LORAWAN_PORT, confirmed);
|
ttn_send(txBuffer, sizeof(txBuffer), LORAWAN_PORT, confirmed);
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sleep() {
|
void sleep() {
|
||||||
#if SLEEP_BETWEEN_MESSAGES
|
#if SLEEP_BETWEEN_MESSAGES
|
||||||
|
|
||||||
// Show the going to sleep message on the screen
|
// Show the going to sleep message on the screen
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
snprintf(buffer, sizeof(buffer), "Sleeping in %3.1fs\n", (MESSAGE_TO_SLEEP_DELAY / 1000.0));
|
snprintf(buffer, sizeof(buffer), "Sleeping in %3.1fs\n", (MESSAGE_TO_SLEEP_DELAY / 1000.0));
|
||||||
screen_print(buffer);
|
screen_print(buffer);
|
||||||
|
|
||||||
// Wait for MESSAGE_TO_SLEEP_DELAY millis to sleep
|
// Wait for MESSAGE_TO_SLEEP_DELAY millis to sleep
|
||||||
delay(MESSAGE_TO_SLEEP_DELAY);
|
delay(MESSAGE_TO_SLEEP_DELAY);
|
||||||
|
|
||||||
// Turn off screen
|
// Turn off screen
|
||||||
screen_off();
|
screen_off();
|
||||||
|
|
||||||
// Set the user button to wake the board
|
// Set the user button to wake the board
|
||||||
sleep_interrupt(BUTTON_PIN, LOW);
|
sleep_interrupt(BUTTON_PIN, LOW);
|
||||||
|
|
||||||
// We sleep for the interval between messages minus the current millis
|
// We sleep for the interval between messages minus the current millis
|
||||||
// this way we distribute the messages evenly every SEND_INTERVAL millis
|
// this way we distribute the messages evenly every SEND_INTERVAL millis
|
||||||
uint32_t sleep_for = (millis() < SEND_INTERVAL) ? SEND_INTERVAL - millis() : SEND_INTERVAL;
|
uint32_t sleep_for = (millis() < SEND_INTERVAL) ? SEND_INTERVAL - millis() : SEND_INTERVAL;
|
||||||
sleep_millis(sleep_for);
|
sleep_millis(sleep_for);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void callback(uint8_t message) {
|
void callback(uint8_t message) {
|
||||||
if (EV_JOINING == message) screen_print("Joining TTN...\n");
|
if (EV_JOINING == message) screen_print("Joining TTN...\n");
|
||||||
if (EV_JOINED == message) screen_print("TTN joined!\n");
|
if (EV_JOINED == message) screen_print("TTN joined!\n");
|
||||||
if (EV_JOIN_FAILED == message) screen_print("TTN join failed\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_REJOIN_FAILED == message) screen_print("TTN rejoin failed\n");
|
||||||
if (EV_RESET == message) screen_print("Reset TTN connection\n");
|
if (EV_RESET == message) screen_print("Reset TTN connection\n");
|
||||||
if (EV_LINK_DEAD == message) screen_print("TTN link dead\n");
|
if (EV_LINK_DEAD == message) screen_print("TTN link dead\n");
|
||||||
if (EV_ACK == message) screen_print("ACK received\n");
|
if (EV_ACK == message) screen_print("ACK received\n");
|
||||||
if (EV_PENDING == message) screen_print("Message discarded\n");
|
if (EV_PENDING == message) screen_print("Message discarded\n");
|
||||||
if (EV_QUEUED == message) screen_print("Message queued\n");
|
if (EV_QUEUED == message) screen_print("Message queued\n");
|
||||||
|
|
||||||
if (EV_TXCOMPLETE == message) {
|
if (EV_TXCOMPLETE == message) {
|
||||||
screen_print("Message sent\n");
|
screen_print("Message sent\n");
|
||||||
sleep();
|
sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EV_RESPONSE == message) {
|
if (EV_RESPONSE == message) {
|
||||||
|
|
||||||
screen_print("[TTN] Response: ");
|
screen_print("[TTN] Response: ");
|
||||||
|
|
||||||
size_t len = ttn_response_len();
|
size_t len = ttn_response_len();
|
||||||
uint8_t data[len];
|
uint8_t data[len];
|
||||||
ttn_response(data, len);
|
ttn_response(data, len);
|
||||||
|
|
||||||
char buffer[6];
|
char buffer[6];
|
||||||
for (uint8_t i=0; i<len; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
snprintf(buffer, sizeof(buffer), "%02X", data[i]);
|
snprintf(buffer, sizeof(buffer), "%02X", data[i]);
|
||||||
screen_print(buffer);
|
screen_print(buffer);
|
||||||
}
|
|
||||||
screen_print("\n");
|
|
||||||
}
|
}
|
||||||
|
screen_print("\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_count() {
|
uint32_t get_count() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
// Debug
|
// Debug
|
||||||
#ifdef DEBUG_PORT
|
#ifdef DEBUG_PORT
|
||||||
DEBUG_PORT.begin(SERIAL_BAUD);
|
DEBUG_PORT.begin(SERIAL_BAUD);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Buttons & LED
|
// Buttons & LED
|
||||||
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
pinMode(BUTTON_PIN, INPUT_PULLUP);
|
||||||
pinMode(LED_PIN, OUTPUT);
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
|
||||||
// Hello
|
// Hello
|
||||||
DEBUG_MSG(APP_NAME " " APP_VERSION "\n");
|
DEBUG_MSG(APP_NAME " " APP_VERSION "\n");
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
screen_setup();
|
screen_setup();
|
||||||
|
|
||||||
// Init GPS
|
// Init GPS
|
||||||
gps_setup();
|
gps_setup();
|
||||||
|
|
||||||
// Show logo on first boot
|
// Show logo on first boot
|
||||||
if (0 == count) {
|
if (0 == count) {
|
||||||
screen_print(APP_NAME " " APP_VERSION, 0, 0);
|
screen_print(APP_NAME " " APP_VERSION, 0, 0);
|
||||||
screen_show_logo();
|
screen_show_logo();
|
||||||
screen_update();
|
screen_update();
|
||||||
delay(LOGO_DELAY);
|
delay(LOGO_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TTN setup
|
// TTN setup
|
||||||
if (!ttn_setup()) {
|
if (!ttn_setup()) {
|
||||||
screen_print("[ERR] Radio module not found!\n");
|
screen_print("[ERR] Radio module not found!\n");
|
||||||
delay(MESSAGE_TO_SLEEP_DELAY);
|
delay(MESSAGE_TO_SLEEP_DELAY);
|
||||||
screen_off();
|
screen_off();
|
||||||
sleep_forever();
|
sleep_forever();
|
||||||
}
|
}
|
||||||
|
|
||||||
ttn_register(callback);
|
ttn_register(callback);
|
||||||
ttn_join();
|
ttn_join();
|
||||||
ttn_sf(LORAWAN_SF);
|
ttn_sf(LORAWAN_SF);
|
||||||
ttn_adr(LORAWAN_ADR);
|
ttn_adr(LORAWAN_ADR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
gps_loop();
|
gps_loop();
|
||||||
ttn_loop();
|
ttn_loop();
|
||||||
screen_loop();
|
screen_loop();
|
||||||
|
|
||||||
// Send every SEND_INTERVAL millis
|
// Send every SEND_INTERVAL millis
|
||||||
static uint32_t last = 0;
|
static uint32_t last = 0;
|
||||||
static bool first = true;
|
static bool first = true;
|
||||||
if (0 == last || millis() - last > SEND_INTERVAL) {
|
if (0 == last || millis() - last > SEND_INTERVAL) {
|
||||||
if (0 < gps_hdop() && gps_hdop() < 50 && gps_latitude() != 0 && gps_longitude() != 0) {
|
if (0 < gps_hdop() && gps_hdop() < 50 && gps_latitude() != 0 && gps_longitude() != 0) {
|
||||||
last = millis();
|
last = millis();
|
||||||
first = false;
|
first = false;
|
||||||
send();
|
Serial.println("TRANSMITTING");
|
||||||
} else {
|
send();
|
||||||
if (first) {
|
} else {
|
||||||
screen_print("Waiting GPS lock\n");
|
if (first) {
|
||||||
first = false;
|
screen_print("Waiting GPS lock\n");
|
||||||
}
|
first = false;
|
||||||
if (millis() > GPS_WAIT_FOR_LOCK) {
|
}
|
||||||
sleep();
|
if (millis() > GPS_WAIT_FOR_LOCK) {
|
||||||
}
|
sleep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,6 +155,14 @@ void ttn_join() {
|
|||||||
// https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
|
// https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
|
||||||
LMIC_selectSubBand(1);
|
LMIC_selectSubBand(1);
|
||||||
|
|
||||||
|
#elif defined(CFG_au915)
|
||||||
|
Serial.println("AU_915");
|
||||||
|
// NA-US channels 0-71 are configured automatically
|
||||||
|
// but only one group of 8 should (a subband) should be active
|
||||||
|
// TTN recommends the second sub band, 1 in a zero based count.
|
||||||
|
// https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json
|
||||||
|
LMIC_selectSubBand(1);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If using a mono-channel gateway disable all channels
|
// If using a mono-channel gateway disable all channels
|
||||||
@ -210,6 +218,7 @@ void ttn_send(uint8_t * data, uint8_t data_size, uint8_t port, bool confirmed){
|
|||||||
|
|
||||||
// Prepare upstream data transmission at the next possible time.
|
// Prepare upstream data transmission at the next possible time.
|
||||||
// Parameters are port, data, length, confirmed
|
// Parameters are port, data, length, confirmed
|
||||||
|
|
||||||
LMIC_setTxData2(port, data, data_size, confirmed ? 1 : 0);
|
LMIC_setTxData2(port, data, data_size, confirmed ? 1 : 0);
|
||||||
|
|
||||||
_ttn_callback(EV_QUEUED);
|
_ttn_callback(EV_QUEUED);
|
||||||
|
Loading…
Reference in New Issue
Block a user