Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
1 result

main.cpp

Blame
  • 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();
    }