LoRa IoT-knoop

De onderstaande story beschrijft de constructie van een eenvoudige LoRa-IoT-knoop, voor gebruik met het TTN-netwerk:

Dit is een IoT-knoop op basis van het Arduino pro mini-bordje (3.3V), met een Hope RFM95-module als LoRa-radio. Als software wordt de LMIC-library gebruikt.

De Arduino pro mini heeft geen eigen USB-aansluiting: hiervoor gebruik je een USB-naar-serieel (FTDI FT232) adapter.

De onderdelen voor dit bordje, inclusief de USB-naar-serieel-adapter, kun je bestellen via TinyTronics:

De kosten van de onderdelen voor het bordje zijn ca. 25 Euro; een USB-kabel en een USB-naar-serieel omzetter kosten ca. 7,50 Euro. Deze laatste heb je alleen nodig voor het programmeren van het bordje, niet voor het eigenlijke gebruik. (Je kunt het bordje ook voorgesoldeerd krijgen, voor 10 Euro extra.)

De genoemde “story” omvat een uitgebreide handleiding voor het solderen van het bordje, en voor het programmeren en configureren daarvan.

Notitie

Het Arduino-bordje werkt op 3.3V. Dit betekent dat de onderdelen (sensoren e.d.) die je hierop aansluit, ook op 3.3V moeten werken. Bovendien werkt dit bordje op 8 MHz. Je moet in de Arduino IDE de juiste versie van de Arduino pro mini selecteren, anders werkt de seriële monitor (e.d.) niet goed.

Voor het programmeren gebruik je de Arduino IDE, met de volgende libraries:

(Wat is de structuur van de toepassing?)

De toepassing is te vinden op GitHub:

void do_send(osjob_t* j) {
  byte buffer[2];

  float temperature,pascal;
    uint16_t t_value, p_value, s_value;
    bmp280.awaitMeasurement();
    bmp280.getTemperature(temperature);
    bmp280.getPressure(pascal);
    bmp280.triggerMeasurement();
    pascal=pascal/100;
    Serial.print(" Pressure: ");
    Serial.print(pascal);
    Serial.print(" Pa; T: ");
    Serial.print(temperature);
    Serial.println(" C");

    // getting sensor values

    temperature = constrain(temperature,-24,40);  //temp in range -24 to 40 (64 steps)
    pascal=constrain(pascal,970,1034);    //pressure in range 970 to 1034 (64 steps)*/
        t_value=int16_t((temperature*(100/6.25)+2400/6.25)); //0.0625 degree steps with offset
                                                      // no negative values
        Serial.print(F("decoded TEMP: "));
        Serial.print(t_value,HEX);
        p_value=int16_t((pascal-970)/1); //1 mbar steps, offset 970.
        Serial.print(F(" decoded Pascal: "));
        Serial.print(p_value,HEX);
        s_value=(p_value<<10) + t_value;  // putting the bits in the right place
        Serial.print(F(" decoded sent: "));
        Serial.println(s_value,HEX);
        buffer[0]=s_value&0xFF; //lower byte
        buffer[1]=s_value>>8;   //higher byte
    // 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, (uint8_t*) buffer, 2 , 0);
    Serial.println(F("Sending: "));
  }
}

De sensoren worden uitgelezen, en de waarden worden gecodeerd in 2 bytes. Vervolgens wordt de buffer aangemerkt voor verzending: het eigenlijke zenden vindt plaats op een moment dat bepaald wordt door de LMIC-library (os); hierbij wordt rekening gehouden met de beperkigen van de 868 MHz-band (maar niet met de beperkingen van TTN “fair use”).

NB: er is hier geen enkele reden om “float”s te gebruiken: de library geeft de resultaten in 32-bits integer waarden.

void loop() {
    if (joined==false) { // start OTAA JOIN
      os_runloop_once();
    } else {
      do_send(&sendjob);    // Send sensor values
      while (sleeping == false) {
        os_runloop_once();
      }
      sleeping = false;
      for (int i=0;i<sleepcycles;i++) {
          LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);    //sleep 8 seconds
      }
    }

    digitalWrite(LedPin,((millis()/100) % 2) && (joined==false)); // only blinking when joining and not sleeping
}

Te doen

  • Herschrijven van de basisopzet van de toepassing…
  • Nagaan: wat is de rol van sendjob?

Pin-mapping

// Pin mapping is hardware specific.
// Pin mapping Doug Larue PCB
const lmic_pinmap lmic_pins = {
.nss = 10,
.rxtx = 0, //LMIC_UNUSED_PIN,
.rst = 0,
.dio = {4, 5, 7},
};

Configureren voor TTN

(Zie: Getting things started on The Things Network, in de story.)

Opmerking: de TTN-story is erg uitgebreid, en voorzien van foto’s. Deze is goed te volgen; een klein bezwaar is dat deze in het Engels is.

  • de batterij sluit je aan op de pinnen “3.3V” (rood) en “GND” (zwart).
  • gebruik de batterij niet tegelijk met de FTDI USB-naar-serieel adapter. Je kunt de batterij-aansluiting laten zitten: zorg er dan voor dat de schakelaar “off” is.
  • gebruik het bordje nooit zonder LoRa-antenne; sommige bordjes gebruiken hiervoor een draad (van 82.2 mm), andere bordjes hebben een antenne-connector: sluit daarop altijd een antenne aan voor het gebruik.

NB: omdat je de programmatekst voor elke IoT-knoop moet aanpassen, is het handig elke aangepaste versie te bewaren met de naam van de knoop, bijvoorbeeld: ttn_mini_node_0.ino. (Je kunt eventueel ook de naam van de toepassing hierin gebruiken.)

Te doen

  • configuratie-gegevens in EEPROM: dan kun je configuratie splitsen van gebruik.