Main Content

Esta página se ha traducido mediante traducción automática. Haga clic aquí para ver la versión original en inglés.

Recopile datos agrícolas a través de The Things Network

Este ejemplo muestra cómo configurar la recopilación de datos de tres sensores conectados a una placa de microprocesador con una radio LoRa®. Esta configuración permite la creación de una red de sensores distribuidos en un área grande. Los sensores envían datos a The Things Network, que luego se envían a ThingSpeak para su análisis y visualización. En el ejemplo, crea un dispositivo prototipo, se conecta a The Things Network e integra la recopilación de datos con ThingSpeak. El dispositivo que se muestra aquí recopila datos de temperatura, humedad del suelo y GPS.

Visión general

El ejemplo consta de tres pasos principales. La integración de Things Network se divide a su vez en varios subpasos. El paso más complicado es la construcción del dispositivo. Para completar el ejemplo, necesita una cuenta de ThingSpeak y una cuenta en The Things Network. En ThingSpeak, crea un nuevo canal. En Things Network, crea una aplicación y registra un dispositivo. Luego, crea un decodificador de carga útil y agrega la integración que reenvía los datos a ThingSpeak.

1) Configure un canal ThingSpeak para recopilar datos

2) Configurar la Red de Cosas

  • Crear aplicación

  • Registrar dispositivo

  • Crear formato de carga útil

  • Añadir Integración

3) Crear dispositivo

  • Hardware utilizado para crear el nodo del sensor

  • Esquema y Conexiones

4) Dispositivo de programa

  • Configuración de programación

  • Código

Configurar un canal de ThingSpeak para recopilar datos

1) Cree un canal ThingSpeak, como se muestra en Recopilar datos en un nuevo canal. Registre la clave API de escritura y la ID del canal para su nuevo canal.

2) Navegar a la Configuración de canales página. Establezca las etiquetas de campo de la siguiente manera.

  • Campo 1— Counter

  • Campo 2— Soil Moisture

  • Campo 3— Temperature F

3) Haga clic Guardar canal en la parte inferior para guardar la configuración.

Configurar la aplicación de red Things

Crea una cuenta en la red de cosas , y luego inicie sesión en La consola de red Things.

Crear aplicación

1) Seleccionar Aplicaciones.

2) Seleccionar Agregar aplicación.

3) Crea un ID de aplicación , luego agrega un Descripción. Selecciona el Registro del controlador basado en su ubicación.

Registrar un dispositivo

1) Haga clic en el Dispositivos pestaña y registrar un dispositivo. Para más información, ver Registro de dispositivos.

2) Cree una identificación de dispositivo. Ingrese el dispositivo EUI si su dispositivo tiene uno. Si no, seleccione el botón a la izquierda de la Dispositivo EUI campo para generar el EUI automáticamente.

3) Haga clic Registro. El navegador le devuelve a la Visión general pestaña.

4) Seleccione el Ajustes pestaña.

5) En la configuración, seleccione ABP para el método de activación. Para facilitar la depuración, puede deshabilitar opcionalmente el Comprobaciones del contador de fotogramas al final de la página.

6) Registrar el Dirección del dispositivo , Clave de sesión de red , y Clave de sesión de la aplicación. Esta información es necesaria en el código de su dispositivo.

Crear formateador de carga útil

El formateador de carga utiliza los bytes enviados a la aplicación desde la puerta de enlace para ensamblar un mensaje. En este ejemplo, el mensaje de carga deseado es un objeto codificado en JSON que se envía a ThingSpeak.

1) Regrese a la vista de la aplicación usando el menú de navegación en la parte superior. Luego haga clic en el Formatos de carga útil pestaña.

2) En el decoder interfaz, cree el código para convertir los bytes enviados desde su dispositivo en un objeto JSON para escribir en ThingSpeak. El código condicional para lat y lon maneja la posibilidad de valores positivos o negativos.

function Decoder(b, port) {
  
 var counter = b[0] << 8) | b[1];
 var moisture = b[2] | b[3] << 8;
 var temp= ( b[4] | b[5] << 8 )/100;
 var lat = ( b[6] | b[7] << 8 | b[8] << 16 | (b[8] & 0x80 ? 0xFF << 24 : 0)) / 10000;
 var lon = ( b[9] | b[10] << 8 | b[11] << 16 | (b[11] & 0x80 ? 0xFF << 24 : 0)) / 10000;

  return {
    field1: counter,
    field2: moisture,
    field3: temp,
    latitude: lat,
    longitude: lon
  }
}

Añadir Integración

Para reenviar datos a ThingSpeak, debe tener una aplicación en Things Network con un dispositivo registrado y un formateador de carga útil. Cree una integración de ThingSpeak para reenviar los datos.

1) Inicie sesión en su La consola de red Things.

2) Seleccionar Aplicaciones y seleccione la aplicación desde la que desea reenviar datos a ThingSpeak.

3) Haga clic en el integraciones pestaña.

4) Seleccione ThingSpeak.

5) En el campo ID de proceso, asigne un nombre a su integración.

6) En el campo Autorización, ingrese la clave API de escritura para el canal en el que desea almacenar sus datos. La clave API está disponible en el claves API pestaña de su canal ThingSpeak.

7) En el campo Id. de canal, ingrese la Id. de canal para el canal de ThingSpeak al que desea reenviar datos. El ID del canal está disponible en la página de su canal de ThingSpeak.

Crear dispositivo

Hardware utilizado para crear el nodo del sensor

Puede usar varios dispositivos LoRa compatibles con los protocolos LoRaWan para conectarse a The Things Network. Este ejemplo demuestra el procedimiento utilizando la siguiente configuración de hardware.

Esquema y Conexiones

Conecte los sensores como se muestra en el esquema. La fotografía muestra una posible configuración de los sensores en una caja de proyecto. En esta configuración, es posible que el sensor de temperatura dentro de la caja no refleje exactamente la temperatura exterior. Necesitas agregar una antena a la radio LoRa.

1) Conecte las conexiones de alimentación y tierra para el GPS y los sensores de temperatura. No conecte la alimentación al sensor de humedad.

2) Conecte la salida del sensor de humedad del suelo a la entrada analógica en A0.

3) Configure el sistema para que el sensor de humedad se apague cuando no esté en uso. El pin de alimentación del sensor de humedad está conectado al pin GPIO 11 en la pluma M0. Apagar la alimentación cuando no está en uso prolonga la vida útil del sensor.

4) Conecte el pin de datos del sensor DH-22 a PA-15 en el Feather M0, que es el pin 5 en el boceto de Arduino.

5) Para la placa GPS, conecte TX a RX en el Feather M0 y RX a TX.

6) Habilite la radio LoRa conectando PA20 (pin 29, GPIO 6) en el Feather M0 a tierra.

7) Cree un interruptor de alimentación conectando un interruptor desde el pin En a tierra.

Dispositivo de programa

Configuración de programación

1) Descargue el último IDE de Arduino.

2) Descarga el Biblioteca de GPS de Adafruit o agregar el Adafruit_GPS biblioteca en el administrador de la biblioteca. Seleccione Sketch > Include Library > Manage Libraries. Búsqueda Adafruit_GPS para agregarlo a sus bibliotecas instaladas.

3) Descarga el Biblioteca LoraWan-in-C para el entorno Arduino o añadir el lmic y hal/hal bibliotecas en el administrador de bibliotecas. Seleccione Sketch > Include Library > Manage Libraries. Búsqueda lmic y seleccione MCCI LoRaWAN LMIC library para agregarlo a sus bibliotecas instaladas. También agregue el MCCI Arduino LoRaWan Library to the library manager.

4) Crear la aplicación. Abra una nueva ventana en el IDE de Arduino y guarde el archivo. Agregue el código proporcionado en la sección Código.

Código

1) Comience por incluir las bibliotecas apropiadas e inicialice las variables.

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include "DHT.h"
#include <Adafruit_GPS.h>

#define DHTPIN 5
#define GPSSerial Serial1
#define SOIL_PIN 14
#define SOIL_POWER_PIN 11
#define GPSECHO false   // Set to 'true' if you want to debug and listen to the raw GPS sentences
#define PAYLOAD_SIZE 13 // Number of bytes sent plus 2


// LoRaWAN NwkSKey, network session key
static const PROGMEM u1_t NWKSKEY[16] = {0x98, 0xEB, 0x1A, 0xC5, 0xF9, 0x20, 0x15, 0xCD, 0x12, 0xE5, 0x72, 0xFF, 0xCD, 0xE2, 0x94, 0x46};
// LoRaWAN AppSKey, application session key
static const u1_t PROGMEM APPSKEY[16] = {0x50, 0x28, 0x4D, 0xAE, 0xEA, 0x41, 0x53, 0x7E, 0xCA, 0x70, 0xD2, 0x26, 0xCC, 0x14, 0x66, 0x19};
// LoRaWAN end-device address (DevAddr)
static const u4_t DEVADDR = 0x26021115;

// Callbacks are only used in over-the-air activation. Leave these variables empty unless you use over the air activation.
void os_getArtEui(u1_t *buf) {}
void os_getDevEui(u1_t *buf) {}
void os_getDevKey(u1_t *buf) {}

// Payload to send to TTN gateway
static uint8_t payload[PAYLOAD_SIZE];
static osjob_t sendjob;

// Schedule TX at least this many seconds
const unsigned TX_INTERVAL = 60; //was 30

// Pin mapping for Adafruit Feather M0 LoRa
const lmic_pinmap lmic_pins = {
    .nss = 8,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 4,
    .dio = {3, 6, LMIC_UNUSED_PIN},
    .rxtx_rx_active = 0,
    .rssi_cal = 8, // LBT cal for the Adafruit Feather M0 LoRa, in dB.
    .spi_freq = 8000000,
};

Adafruit_GPS GPS(&GPSSerial); // Connect to the GPS on the hardware port.

DHT dht(DHTPIN, DHT22);  // Connect to the temperature sensor.
uint16_t counter = 0;
int32_t myLatitude = -12345; // Initialize for testing before GPS finds a lock.
int32_t myLongitude = 54321; // Initialize for testing.
int myMoisture = 0; // 10 bit ADC value.
float temperatureF = 1111; 

2) Usa el setup función para iniciar el sensor de temperatura, el GPS y la radio LoRa.

void setup()
{
    Serial.begin(115200);
    dht.begin();
    Serial.println("Start");
    // Set the power pin for the moisture sensor
    pinMode(SOIL_POWER_PIN,OUTPUT);
    digitalWrite(SOIL_POWER_PIN, LOW);

    GPS.begin(9600); // 9600 NMEA is the default baud rate.
    GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
    GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // Set a 1 Hz update rate.

    delay(1000); // Wait for GPS to initialize.

    // Ask for firmware version
    GPSSerial.println(PMTK_Q_RELEASE);
    // Initialize the LMIC.
    os_init();
    // Reset the MAC state. Resetting discards the session and pending data transfers. 
    LMIC_reset();

    // Set static session parameters. 
    uint8_t appskey[sizeof(APPSKEY)];
    uint8_t nwkskey[sizeof(NWKSKEY)];
    memcpy_P(appskey, APPSKEY, sizeof(APPSKEY));
    memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY));
    LMIC_setSession(0x13, DEVADDR, nwkskey, appskey);

    LMIC_selectSubBand(1);
    // Only use the correct The Things Network channels, disable the others.
    for (int c = 0; c < 72; c++)
    {
        if ((c < 8) || (c > 15))
        {
            LMIC_disableChannel(c);
        }
    }
    
    LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);

    // Disable link check validation
    LMIC_setLinkCheckMode(0);

    // TTN uses SF9 for its RX2 window.
    LMIC.dn2Dr = DR_SF9;

    // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library)
    LMIC_setDrTxpow(DR_SF7, 14);

    // Start job.
    processJob(&sendjob);
}

3) Usa el loop función para iniciar el proceso LoRa y analizar los datos del GPS.

void loop() // Run over and over again
{
    os_runloop_once();

    char c = GPS.read();
    if (GPSECHO)
     {
        if (c){
            Serial.print(c);
              }
     }
    // If a sentence is received, parse it
    if (GPS.newNMEAreceived())
    {
        if (!GPS.parse(GPS.lastNMEA())) // Also sets the newNMEAreceived() flag to false
            return;                   
    }
}

4) El GetSensorData La función enciende el sensor de humedad y lee sus datos, luego lo apaga. También lee el sensor de temperatura y verifica la información del dispositivo GPS. Si hay una posición de GPS, esta función actualiza la información de posición.

void GetSensorData()
{
    digitalWrite(SOIL_POWER_PIN, HIGH);
    delay(1000);
    myMoisture = analogRead(SOIL_PIN);
    digitalWrite(SOIL_POWER_PIN, LOW);
    temperatureF = dht.readTemperature( true );
    Serial.println("moisture " + String( myMoisture ) + " temp " + String( temperatureF ));
     
    if (GPS.fix)
    {
        Serial.print( "Location: " );
        Serial.print( GPS.latitudeDegrees * 100, 4 );
        Serial.print( " break " );
        Serial.print( GPS.lat );
        Serial.print( ", " );
        Serial.print( GPS.longitudeDegrees * 100 , 4 );
        Serial.println( GPS.lon );
        myLatitude = GPS.latitudeDegrees * 10000;
        myLongitude = GPS.longitudeDegrees * 10000;
    }
}

5) Usa el onEvent función para procesar eventos de la radio LoRa. La función actualiza el monitor serie, programa la próxima transmisión y recibe mensajes.

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"));
        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.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_TXSTART:
        Serial.println(F("EV_TXSTART"));
        break;
    default:
        Serial.print(F("Unknown event: "));
        Serial.println((unsigned)ev);
        break;
    }
}

6) El processJob La función convierte los datos del sensor en bits para ser enviados a través de la radio LoRa.

void processJob(osjob_t *j)
{
    getSensorData();
    
    if (LMIC.opmode & OP_TXRXPEND) // Check if there is a current TX/RX job running.
    {
        Serial.println(F("OP_TXRXPEND, not sending"));
    }
    else
    {
        payload[0] = byte(counter);
        payload[1] = counter >>8;

        payload[2] = byte(myMoisture);
        payload[3] = myMoisture >> 8;

        int shiftTemp = int(temperatureF * 100); // Convet temperature float to integer for sending and save two places.
        payload[4] = byte(shiftTemp);
        payload[5] = shiftTemp >> 8;

        payload[6] = byte(myLatitude);
        payload[7] = myLatitude >> 8;
        payload[8] = myLatitude >> 16;

        payload[9] = byte(myLongitude);
        payload[10] = myLongitude >> 8;
        payload[11] = myLongitude >> 16;

        LMIC_setTxData2(1, payload, sizeof(payload) - 1, 0); // Prepare upstream data transmission at the next possible time.

        counter++;
        Serial.println(String(counter));
    }
    // Next TX is scheduled after TX_COMPLETE event.

Para obtener información sobre cómo crear un panel de visualización detallado en su canal de ThingSpeak, consulte Crear una vista de canal de ThingSpeak personalizada.