Select Git revision
main.cpp 8.22 KiB
#include <config.h>
#include <axp20x.h>
#include <Arduino_LoRaWAN_ttn.h>
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <TinyGPS++.h>
#include <OneButton.h>
class cLoRaWAN : public Arduino_LoRaWAN_ttn
{
public:
cLoRaWAN(){};
protected:
virtual bool GetOtaaProvisioningInfo(Arduino_LoRaWAN::OtaaProvisioningInfo *) override;
virtual void NetSaveFCntUp(uint32_t uFCntUp) override;
virtual void NetSaveFCntDown(uint32_t uFCntDown) override;
virtual void NetSaveSessionInfo(const SessionInfo &Info, const uint8_t *pExtraInfo, size_t nExtraInfo) override;
};
bool cLoRaWAN::GetOtaaProvisioningInfo(
OtaaProvisioningInfo *pInfo)
{
static const uint8_t DEVEUI[8] = TTN_DEVEUI;
static const uint8_t APPEUI[8] = TTN_APPEUI;
static const uint8_t APPKEY[16] = TTN_APPKEY;
if (pInfo)
{
memcpy(pInfo->AppKey, APPKEY, sizeof(APPKEY));
memcpy(pInfo->DevEUI, DEVEUI, sizeof(DEVEUI));
memcpy(pInfo->AppEUI, APPEUI, sizeof(APPEUI));
}
return true;
}
void cLoRaWAN::NetSaveFCntDown(uint32_t uFCntDown)
{
// save uFcntDown somwwhere
}
void cLoRaWAN::NetSaveFCntUp(uint32_t uFCntUp)
{
// save uFCntUp somewhere
}
void cLoRaWAN::NetSaveSessionInfo(
const SessionInfo &Info,
const uint8_t *pExtraInfo,
size_t nExtraInfo)
{
// save Info somewhere.
}
const cLoRaWAN::lmic_pinmap pinMap = {
.nss = 18,
.rxtx = cLoRaWAN::lmic_pinmap::LMIC_UNUSED_PIN,
.rst = 23,
.dio = {26, 33, cLoRaWAN::lmic_pinmap::LMIC_UNUSED_PIN},
};
AXP20X_Class axp;
HardwareSerial GPS(1);
TinyGPSPlus gps;
cLoRaWAN LoRaWAN{};
OneButton btn = OneButton(BUTTON_PIN, true, true);
static uint8_t mydata[] = "Hello, world!";
static osjob_t sendjob;
const unsigned TX_INTERVAL = 60;
void setupPower()
{
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS))
{
Serial.println("AXP192 Begin PASS");
}
else
{
Serial.println("AXP192 Begin FAIL");
}
axp.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); // OLED : off
axp.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); // N/C : off
axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON); // ESP32 : on
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LORA : on
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // GPS : on
axp.setDCDC3Voltage(3300); // ESP32 : 3.3V
axp.setLDO2Voltage(3300); // LORA : 3.3V
axp.setLDO3Voltage(3300); // GPS : 3.3V
axp.setChgLEDMode(AXP20X_LED_OFF);
}
void setupGps()
{
GPS.begin(9600, SERIAL_8N1, 34, 12); // IO34: RX, IO12: TX
}
void printStatus()
{
axp.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
while (GPS.available())
{
gps.encode(GPS.read());
}
Serial.println("##############################");
Serial.println("--- Power ---");
Serial.printf("DCDC1/OLED Status : %s\n", axp.isDCDC1Enable() ? "enabled" : "disabled");
Serial.printf("DCDC1/OLED Voltage : %g V\n", (float)axp.getDCDC1Voltage() / 1000);
Serial.printf("DCDC2/N/C Status : %s\n", axp.isDCDC2Enable() ? "enabled" : "disabled");
Serial.printf("DCDC2/N/C Voltage : %g V\n", (float)axp.getDCDC2Voltage() / 1000);
Serial.printf("DCDC3/ESP32 Status : %s\n", axp.isDCDC3Enable() ? "enabled" : "disabled");
Serial.printf("DCDC3/ESP32 Voltage : %g V\n", (float)axp.getDCDC3Voltage() / 1000);
Serial.printf("LDO2/LoRa Status : %s\n", axp.isLDO2Enable() ? "enabled" : "disabled");
Serial.printf("LDO2/LoRa Voltage : %g V\n", (float)axp.getLDO2Voltage() / 1000);
Serial.printf("LDO3/GPS Status : %s\n", axp.isLDO3Enable() ? "enabled" : "disabled");
Serial.printf("LDO3/GPS Voltage : %g V\n", (float)axp.getLDO3Voltage() / 1000);
Serial.println("--- Battery ---");
Serial.printf("Battery Connected: %s\n", axp.isBatteryConnect() ? "true" : "false");
if (axp.isBatteryConnect())
{
Serial.printf("Battery Percentage : %d %%\n", axp.getBattPercentage());
Serial.printf("Battery Voltage : %g V\n", axp.getBattVoltage() / 1000);
Serial.printf("Charging Enabled : %s\n", axp.isChargeingEnable() ? "true" : "false");
Serial.printf("Battery Charging : %s\n", axp.isChargeing() ? "true" : "false");
Serial.printf("Set Charge Current : %g mA\n", axp.getSettingChargeCurrent());
}
Serial.println("--- Chip ---");
Serial.printf("Chip Temp : %.1f C°\n", axp.getTemp() / 10);
Serial.println("--- GPS ---");
Serial.print("Latitude : ");
Serial.println(gps.location.lat(), 5);
Serial.print("Longitude : ");
Serial.println(gps.location.lng(), 4);
Serial.print("Satellites : ");
Serial.println(gps.satellites.value());
Serial.print("Altitude : ");
Serial.print(gps.altitude.feet() / 3.2808);
Serial.println("M");
Serial.print("Time : ");
Serial.print(gps.time.hour());
Serial.print(":");
Serial.print(gps.time.minute());
Serial.print(":");
Serial.println(gps.time.second());
Serial.print("Speed : ");
Serial.println(gps.speed.kmph());
Serial.println("##############################");
axp.setChgLEDMode(AXP20X_LED_OFF);
}
static void handleClick() {
printStatus();
}
void do_send(osjob_t *j)
{
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND)
{
Serial.println(F("OP_TXRXPEND, not sending"));
}
else
{
// Prepare upstream data transmission at the next possible time.
LMIC_setTxData2(1, mydata, sizeof(mydata) - 1, 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
void onEvent(ev_t ev)
{
Serial.print(os_getTime());
Serial.print(": ");
switch (ev)
{
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
// TTN uses SF9 for its RX2 window.
LMIC.dn2Dr = EU868_DR_SF9;
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
{
u4_t netid = 0;
devaddr_t devaddr = 0;
u1_t nwkKey[16];
u1_t artKey[16];
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
Serial.print("netid: ");
Serial.println(netid, DEC);
Serial.print("devaddr: ");
Serial.println(devaddr, HEX);
Serial.print("artKey: ");
for (int i = 0; i < sizeof(artKey); ++i)
{
Serial.print(artKey[i], HEX);
}
Serial.println("");
Serial.print("nwkKey: ");
for (int i = 0; i < sizeof(nwkKey); ++i)
{
Serial.print(nwkKey[i], HEX);
}
Serial.println("");
LMIC_setSeqnoUp(140);
}
break;
case EV_RFU1:
Serial.println(F("EV_RFU1"));
break;
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen)
{
Serial.println(F("Received "));
Serial.println(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
case EV_SCAN_FOUND:
Serial.println(F("EV_SCAN_FOUND"));
break;
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println(F("EV_TXCANCELLED"));
break;
case EV_JOIN_TXCOMPLETE:
Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
break;
default:
Serial.println(F("Unknown event " + (unsigned)ev));
break;
}
}
void setup()
{
Serial.begin(115200);
Wire.begin(21, 22);
setupPower();
setupGps();
LoRaWAN.begin(pinMap);
btn.attachClick(handleClick);
printStatus();
do_send(&sendjob);
}
void loop()
{
LoRaWAN.loop();
btn.tick();
}