主要内容

通过物联网收集农业数据

这个例子展示了如何从连接到带有LoRa®无线电的微处理器板上的三个传感器设置数据收集。这种配置允许在大范围内创建分布式传感器网络。传感器将数据发送到物联网,然后转发到ThingSpeak进行分析和可视化。在本例中,您构建了一个原型设备,连接到Things Network,并将数据收集与ThingSpeak集成。这里展示的装置收集温度、土壤湿度和GPS数据。

概述

该示例包含三个主要步骤。物联网集成进一步分为几个子步骤。最复杂的步骤是构建设备。要完成这个例子,你需要一个ThingSpeak账户和一个Things Network账户。在ThingSpeak上,你创建了一个新频道。在Things Network上,您创建一个应用程序并注册一个设备。然后创建一个有效负载解码器,并添加将数据转发到ThingSpeak的集成。

1)建立ThingSpeak频道来收集数据

2)建立物品网络

  • 创建应用程序

  • 注册设备

  • 创建有效载荷格式

  • 添加集成

3)创建设备

  • 创建传感器节点的硬件

  • 原理图与连接

4)程序装置

  • 编程设置

  • 代码

建立一个ThingSpeak频道来收集数据

1)创建ThingSpeak频道,如图所示在新的渠道收集数据.记录写API键和新通道的通道ID。

2)导航到频道设置页面。各字段的标签设置如下。

  • 场1 -计数器

  • 场2 -土壤水分

  • 场3 -温度F

3)点击节省通道在底部保存您的设置。

配置Things网络应用程序

创建帐户在The Things Network然后登录Things网络控制台

创建应用程序

1)选择应用程序。

2)选择添加应用程序

3)创建应用程序ID,然后添加描述.选择处理程序注册根据你的位置。

注册设备

1)点击设备选项卡,注册设备。有关更多信息,请参见设备注册

2)创建设备ID。如果您的设备有设备EUI,请输入设备EUI。如果没有,则选择控件左侧的按钮设备行字段自动生成EUI。

3) Cick注册.浏览器返回到概述选项卡。

4)选择设置选项卡。

5)在设置中,激活方式选择ABP。要帮助进行调试,可以选择禁用帧计数器检查在这一页的底部。

6)记录设备地址网络会话密钥,App会话密钥.这些信息在设备代码中是必需的。

创建有效载荷格式化程序

有效负载格式化器使用从网关发送到应用程序的字节来组装消息。在本例中,所需的有效负载消息是发送到ThingSpeak的json编码对象。

1)通过顶部的导航菜单返回到应用程序视图。然后单击负载格式选项卡。

2)在……译码器接口,创建代码将从您的设备发送的字节转换为JSON对象写入ThingSpeak。的条件代码纬度而且处理正或负值的可能性。

函数解码器(b,端口){var计数器= b[0] << 8) | b[1];Var moisture = b[2] | b[3] << 8;Var temp= (b[4] | b[5] << 8)/100;var lat = (b [6] [7] | b < < 8 | b [8] < < 16 | (b [8] & 0 x80吗?0xFF << 24: 0)) / 10000;var朗= (b [9] | b [10] < < 8 | b [11] < < 16 | (b [11] & 0 x80吗?0xFF << 24: 0)) / 10000;返回{field1: counter, field2: moisture, field3: temp, latitude: lat, longitude: lon}}

添加集成

要将数据转发到ThingSpeak,您必须在Things Network上有一个带有注册设备和有效载荷格式化器的应用程序。创建ThingSpeak集成来转发数据。

1)登录你的Things网络控制台

2)选择应用程序然后选择你想要向ThingSpeak转发数据的应用程序。

3)点击集成选项卡。

4)选择ThingSpeak。

5)在Process ID字段中,命名您的集成。

6)在授权字段中,输入你想要存储数据的通道的写API密钥。API键可从API密钥标签的ThingSpeak频道。

7)在“通道ID”字段中,输入您想要转发数据的ThingSpeak通道的通道ID。频道ID可以在ThingSpeak频道的页面上找到。

创建设备

创建传感器节点的硬件

您可以使用支持LoRaWan协议的各种LoRa设备连接到Things Net金宝appwork。本示例演示使用以下硬件设置的过程。

原理图与连接

按示意图所示连接传感器。照片显示了工程箱中传感器的可能配置。在这种配置中,盒子内部的温度传感器可能不能准确地反映外部温度。你需要增加天线到LoRa电台。

1)连接GPS和温度传感器的电源和接地。请不要连接湿度传感器的电源。

2)将土壤湿度传感器输出连接到模拟输入A0处。

3)设置系统,使水分传感器不使用时电源关闭。水浸传感器的电源引脚连接在羽毛M0的GPIO引脚11上。在不使用时关闭电源可以延长传感器的寿命。

4)将DH- 22传感器数据引脚连接到Feather M0上的PA-15上,即Arduino草图中的引脚5。

5)对于GPS板,将羽毛M0的TX与RX连接,RX与TX连接。

6)将Feather M0的PA20(引脚29,GPIO 6)连接到地面,开启LoRa收音机。

7)通过连接En引脚到地的开关来创建一个电源开关。

项目设备

编程设置

1)下载最新的Arduino IDE。

2)下载Adafruit GPS库或添加Adafruit_GPS库管理器中的库。选择草图>包括图书馆>管理库.搜索Adafruit_GPS将其添加到已安装的库中。

3)下载LoraWan-in-C图书馆为Arduino环境或添加lmic而且哈尔/哈尔库管理器中的库。选择草图>包括图书馆>管理库.搜索lmic并选择MCCI LoRaWAN LMIC库将其添加到已安装的库中。还要添加MCCI Arduino LoRaWan库交给库经理。

4)创建应用程序。在Arduino IDE中打开一个新窗口并保存文件。添加代码部分中提供的代码。

代码

1)从包含适当的库和初始化变量开始。

#include < lmc .h> #include  #include  #include "DHT.h" #include  #define DHTPIN 5 #define gppsserial Serial1 #define SOIL_PIN 14 #define SOIL_POWER_PIN 11 #define GPSECHO false //设置为'true'如果你想调试和监听原始的GPS句子#define PAYLOAD_SIZE 13 //发送的字节数加2 // LoRaWAN NwkSKey,网络会话密钥静态const PROGMEM u1_t NwkSKey [16] = {0x98, 0xEB, 0x1A, 0xC5, 0xF9, 0x20, 0x15, 0xCD, 0x12, 0xE5, 0x72, 0xFF, 0xCD,0xE2, 0x94, 0x46};// LoRaWAN AppSKey,应用程序会话密钥static const u1_t PROGMEM AppSKey [16] = {0x50, 0x28, 0x4D, 0xAE, 0xEA, 0x41, 0x53, 0x7E, 0xCA, 0x70, 0xD2, 0x26, 0xCC, 0x14, 0x66, 0x19};// LoRaWAN端设备地址(DevAddr) static const u4_t DevAddr = 0x26021115;//回调只在无线激活中使用。保持这些变量为空,除非你使用空气激活。void os_getArtEui(u1_t *buf) {} void os_getDevEui(u1_t *buf) {} void os_getDevKey(u1_t *buf){} //载荷发送到TTN网关静态uint8_t载荷[PAYLOAD_SIZE];静态osjob_t;//调度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, // Adafruit Feather M0 LoRa LBT cal, 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)使用设置功能启动温度传感器、GPS和LoRa无线电。

void setup() {Serial.begin(115200);dht.begin ();以“开始”);//设置湿度传感器pinMode的电源引脚(SOIL_POWER_PIN,OUTPUT);digitalWrite (SOIL_POWER_PIN、低);GPS.begin (9600);//默认波特率为9600 NMEA。GPS.sendCommand (PMTK_SET_NMEA_OUTPUT_RMCGGA);GPS.sendCommand (PMTK_SET_NMEA_UPDATE_1HZ);//设置1hz的更新速率。 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)使用循环函数启动LoRa进程并解析GPS数据。

void loop() //反复运行{os_runloop_once();char c = GPS.read();if (GPSECHO) {if (c){Serial.print(c);}} //如果接收到一个句子,解析它If (GPS.newNMEAreceived()) {If (!GPS.parse(GPS.lastNMEA())) //也设置newNMEAreceived()标志为false返回;}}

4)GetSensorData功能打开湿度传感器的电源并读取其数据,然后关闭电源。它还读取温度传感器,并检查来自GPS设备的信息。如果有一个GPS修复,这个函数更新位置信息。

void GetSensorData() {digitalWrite(SOIL_POWER_PIN, HIGH);延迟(1000);myMoisture = analogue (SOIL_PIN);digitalWrite (SOIL_POWER_PIN、低);温度f = dht。readTemperature(true);系列。println("moisture " + String(myMoisture) + " temp " + String(温控温度));if (GPS.fix){串行。打印(“位置:”); 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)使用onEvent功能处理来自LoRa无线电的事件。该功能更新串行监视器,安排下一个传输,并接收消息。

void onEvent(ev_t ev) {Serial.print(os_getTime());系列。打印(“:”);switch (ev) {case EV_SCAN_TIMEOUT: Serial.println(F("EV_SCAN_TIMEOUT"));打破;case EV_BEACON_FOUND: Serial.println(F("EV_BEACON_FOUND"));打破;case EV_BEACON_MISSED: Serial.println(F("EV_BEACON_MISSED"));打破;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)processJob函数将传感器数据转换为通过LoRa无线电发送的位。

void processJob(osjob_t *j) {getSensorData();如果(LMIC。opmode & OP_TXRXPEND) //检查当前是否有TX/RX作业在运行。{系列。println(F("OP_TXRXPEND,未发送"));} else{有效载荷[0]=字节(计数器);有效载荷[1]=计数器>>8;负载[2]=字节(myMoisture);有效载荷[3]= myMoisture >> 8;int shiftTemp = int(温度* 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.

要了解如何在ThingSpeak cannel中创建详细的可视化仪表板,请参见创建自定义ThingSpeak通道视图