Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #14437
    bpmcgee
    Participant

    Hi,

    I hope you can point out what I’m doing wrong. I’m using the ultra v3 with the LMIC library (MCCI LoraWAN LMIC Library) and ArduinoLowPower. I’ve scanned and rescanned every example I can find, but I can’t get the unit to go below 830 uA while in LowPower.sleep ().

    What I need to do is to remain asleep until one of two switches is triggered, then wait to see if the other is also triggered, then send a message and go back to sleep.

    Below is my code.

    #include <ArduinoJson.h>
    
    /*******************************************************************************
       Copyright (c) 2020 Brian McGee
       Driveway sensor monitor.
       Do not forget to define the radio type correctly in config.h.
     *******************************************************************************/
    
    #include <CayenneLPP.h> 
    #include <ArduinoLowPower.h>
    #include <lmic.h>
    #include <hal/hal.h>
    #include <SerialFlash.h>
    #include <SPI.h>
    #include <Wire.h>
    #define EUI64_CHIP_ADDRESS 0x50
    #define EUI64_MAC_ADDRESS 0xF8
    #define EUI64_MAC_LENGTH 0x08
    #define MAX_DATA_SIZE 51
    #define Serial SerialUSB
    /*
       Local data.
    */
    const float version = 1.3;
    const int SENSOR1_PIN = 7;
    const int SENSOR2_PIN = 8;
    volatile uint32_t trigger1 = 0;
    volatile uint32_t trigger2 = 0;
    volatile int programmingMode = 0;
    const int SFLASH_PIN  = 4;
    int VEHICLE_DELAY = 2000;
    volatile int vehicle_detection = 1;
    
    #define VEHICLE_DETECTED    1
    #define VEHICLE_ARRIVING    2
    #define VEHICLE_LEAVING     3
    
    const int LED_PIN     = 13;
    
    // This EUI must be in little-endian format, so least-significant-byte
    // first. When copying an EUI from ttnctl output, this means to reverse
    // the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
    // 0x70.
    static const u1_t PROGMEM APPEUI[8] = {  0xFF, 0xFF, 0xFF, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
    void os_getArtEui (u1_t* buf) {
      memcpy_P(buf, APPEUI, 8);
    }
    
    // This should also be in little endian format, see above.
    static  u1_t PROGMEM DEVEUI[8];
    void os_getDevEui (u1_t* buf) {
      memcpy_P(buf, DEVEUI, 8);
    }
    
    // This key should be in big endian format (or, since it is not really a
    // number but a block of memory, endianness does not really apply). In
    // practice, a key taken from ttnctl can be copied as-is.
    static const u1_t PROGMEM APPKEY[16] = { 0xFF, 0xFF, 0xFF, 0x50, 0x67, 0x14, 0xC7, 0x16, 0xD6, 0x5B, 0x45, 0xD3, 0xFD, 0xC2, 0xAD, 0x8E };
    void os_getDevKey (u1_t* buf) {
      memcpy_P(buf, APPKEY, 16);
    }
    
    //static uint8_t mydata[] = "Hello, world!";
    //static uint8_t data[MAX_DATA_SIZE];
    CayenneLPP lpp (MAX_DATA_SIZE);
    static osjob_t sendjob;
    
    // Schedule TX every this many seconds (might become longer due to duty
    // cycle limitations).
    const unsigned TX_INTERVAL = 60;
    
    // Pin mapping
    const lmic_pinmap lmic_pins = {
      .nss = 5,
      .rxtx = LMIC_UNUSED_PIN,
      .rst = 3,
      .dio = {2, 6, LMIC_UNUSED_PIN},
    };
    
    void printHex2(unsigned v) {
      v &= 0xff;
      if (v < 16)
        Serial.print('0');
      Serial.print(v, HEX);
    }
    
    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"));
          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("AppSKey: ");
            for (size_t i = 0; i < sizeof(artKey); ++i) {
              if (i != 0)
                Serial.print("-");
              printHex2(artKey[i]);
            }
            Serial.println("");
            Serial.print("NwkSKey: ");
            for (size_t i = 0; i < sizeof(nwkKey); ++i) {
              if (i != 0)
                Serial.print("-");
              printHex2(nwkKey[i]);
            }
            Serial.println();
          }
          // Disable link check validation (automatically enabled
          // during join, but because slow data rates change max TX
          // size, we don't use it in this example.
          //os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(5), sendMessage);
          break;
        /*
          || This event is defined but not used in the code. No
          || point in wasting codespace on it.
          ||
          || 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;
        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.print(F("Received "));
            Serial.print(LMIC.dataLen);
            Serial.println(F(" bytes of payload"));
          }
          // Schedule next transmission
          //os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), sendMessage);
          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;
        /*
          || This event is defined but not used in the code. No
          || point in wasting codespace on it.
          ||
          || 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_TXCANCELED"));
          break;
        case EV_RXSTART:
          /* do not print anything -- it wrecks timing */
          break;
        case EV_JOIN_TXCOMPLETE:
          Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
          break;
        default:
          Serial.print(F("Unknown event: "));
          Serial.println((unsigned) ev);
          break;
      }
    }
    
    void sendMessage (osjob_t *j)
    {
      int x;
      SerialUSB.print ("Vehicle Detected: ");
      SerialUSB.println (vehicle_detection);
    
      if (vehicle_detection != 0)
      {
        if (LMIC.opmode & OP_TXRXPEND) {
          Serial.println(F("OP_TXRXPEND, not sending"));
        }
        else
        {
          lpp.reset ();
          lpp.addDigitalOutput (1, vehicle_detection);
          LMIC_sendWithCallback(1, lpp.getBuffer(), lpp.getSize(), 0, txCompletionCallback, 0);
          Serial.println(F("Packet queued"));
          vehicle_detection = 0;
        }
    
      }
    }
    
    void txCompletionCallback(void *pUserData, int fSuccess)
    {
      Serial.print ("TX Completion Status:");
      Serial.println (fSuccess);
    
    }
    
    void setup() {
     int count;
      unsigned char pinNumber;
    
      // ***** Put unused pins into known state *****
      pinMode(0, INPUT_PULLUP);
      pinMode(1, INPUT_PULLUP);
    
      // D7-D13, A0(D14)-A5(D19), SDA(D20), SCL(D21), MISO(D22)
      for (pinNumber = 7; pinNumber <= 22; pinNumber++)
      {
        pinMode(pinNumber, INPUT_PULLUP);
      }
      // RX_LED (D25) & TX_LED (D26) (both LED not mounted on Mini Ultra Pro)
      pinMode(25, INPUT_PULLUP);
      pinMode(26, INPUT_PULLUP);
      // D30 (RX) & D31 (TX) of Serial
      pinMode(30, INPUT_PULLUP);
      pinMode(31, INPUT_PULLUP);
      // D34-D38 (EBDG Interface)
      for (pinNumber = 34; pinNumber <= 38; pinNumber++)
      {
        pinMode(pinNumber, INPUT_PULLUP);
      }
      // ***** End of unused pins state initialization *****
    
      pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite (LED_PIN, LOW);
    
      /*
         Enable the vehicle detector pins.
      */
      pinMode(SENSOR1_PIN, INPUT_PULLUP);
      pinMode(SENSOR2_PIN, INPUT_PULLUP);
      LowPower.attachInterruptWakeup(digitalPinToInterrupt(SENSOR1_PIN), sensorChanged1, FALLING);
      LowPower.attachInterruptWakeup(digitalPinToInterrupt(SENSOR2_PIN), sensorChanged2, FALLING);
    
      // Initialize serial flash
      SerialFlash.begin(4);
      // Put serial flash in sleep
      SerialFlash.sleep();
      setDevEui(&DEVEUI[EUI64_MAC_LENGTH - 1]);
    
      if (programmingMode)
      {
        while (!Serial && millis() < 10000);
        Serial.begin(115200);
        Serial.print("Starting Driveway v");
        Serial.println(version, 1);
        
        Serial.print(F("DEVEUI: "));
    
        for (count = EUI64_MAC_LENGTH; count > 0; count--)
        {
          Serial.print("0x");
          if (DEVEUI[count - 1] <= 0x0F) Serial.print("0");
          Serial.print(DEVEUI[count - 1], HEX);
          Serial.print(" ");
        }
        Serial.println();
    
      }
      else
      {
        int count;
        SerialUSB.println("Entering standby mode in:");
        for (count = 30; count > 0; count--)
        {
          SerialUSB.print(count);
          SerialUSB.println(" s");
          programmingModeDelay (1000);
          USBDevice.detach ();
        }
    
      }
      
      // LMIC init
      os_init();
      // Reset the MAC state. Session and pending data transfers will be discarded.
      LMIC_reset();
      LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
      LMIC_setAdrMode (true);
    
      // Test if I'm not set up for TTN correctly.
      LMIC_setLinkCheckMode(0);
      LMIC_setDrTxpow(DR_SF7, 14);
      LMIC_selectSubBand(1);
      // End test
      // Start job (sending automatically starts OTAA too)
      sendMessage (&sendjob);
    
    }
    
    void loop() {
      os_runloop_once();
    
      /*
       * If we're still trying to send a message, we don't want to sleep here.  If we're NOT sending
       * a message, but one of the sensors has been triggered, we're going to delay.  Otherwise we're
       * going to go into power saving mode.
       */
        if (LMIC.opmode & OP_TXRXPEND) {
          // No sleep/delay.
        }
        else
        {
          if ((trigger1 !=0) || (trigger2 != 0) || (programmingMode))
          {
            // No power saving.  Flash the LED if we're waiting for a second trigger.
            if ((trigger1 !=0) || (trigger2 != 0)) 
              programmingModeDelay (500);
            else
            {
              Serial.println ("Going to sleep.");
            }
          }
          else
          {
            // Go to sleep.
            programmingModeDelay (1000);
            programmingModeDelay (1000);
            LowPower.deepSleep ();
          }
        } /* endif */
       
      /* If trigger1 is nonzero it means we haven't sent a notification yet. */
      if ((trigger1 != 0) || (trigger2 != 0))
      {
        int32_t now = millis ();
        int32_t offset1 = 0;
        int32_t offset2 = 0;
    
        if (trigger1)
          offset1 = abs(now  - trigger1);
    
        if (trigger2)
          offset2 = abs(now - trigger2);
    
        /*
           We want to allow at least VEHICLE_DELAY milliseconds for the vehicle
           to travel from one sensor to the other.
        */
        if (((offset1 > VEHICLE_DELAY) || (offset2 > VEHICLE_DELAY)) || ((trigger1 != 0) && (trigger2 != 0)))
        {
          SerialUSB.print (offset1);
          SerialUSB.print (" - ");
          SerialUSB.println (offset2);
          /*
             Okay, so we've waited.  If we only have one sensor triggered, just send a "VEHICLE".
             If we have both triggered, send VEHICLE-UP or VEHICLE-DOWN as appropriate.
          */
          if ((trigger1 == 0) || (trigger2 == 0))
          {
            // VEHICLE
            //sendMessage (VEHICLE_DETECTED);
            vehicle_detection = VEHICLE_DETECTED;
            sendMessage (&sendjob);
          }
          else
          {
            if (trigger2 > trigger1)
            {
              vehicle_detection = VEHICLE_ARRIVING;
              sendMessage (&sendjob);
            }
            else
            {
              vehicle_detection = VEHICLE_LEAVING;
              sendMessage (&sendjob);
            }
          }
          trigger1 = trigger2 = 0;
        }
      }
    }
    
    void sensorChanged1()
    {
      trigger1 = millis();
    
    }
    
    void sensorChanged2()
    {
      trigger2 = millis();
    
    }
    
    void setDevEui(unsigned char* buf)
    {
      Wire.begin();
      Wire.beginTransmission(EUI64_CHIP_ADDRESS);
      Wire.write(EUI64_MAC_ADDRESS);
      Wire.endTransmission();
      Wire.requestFrom(EUI64_CHIP_ADDRESS, EUI64_MAC_LENGTH);
    
      // Format needs to be little endian (LSB...MSB)
      while (Wire.available())
      {
        *buf-- = Wire.read();
      }
    }
    
     void programmingModeDelay (int duration)
      {
        digitalWrite (LED_PIN, HIGH);
        delay (duration / 2);
        digitalWrite (LED_PIN, LOW);
        delay (duration / 2);
      }
    #14445
    LIM PHANG MOH
    Keymaster

    It’s most probably one of the pins are floating or contradicting with the state you have set them up with. Use a meter and check the pins for floating voltages.

    And what sensor are you using? In most of the cases, the sensors are not low power enough.

Viewing 2 posts - 1 through 2 (of 2 total)
  • You must be logged in to reply to this topic.