主要内容

通过物联网收集农业数据

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

概述

该示例包含三个主要步骤。物联网集成进一步分为几个子步骤。最复杂的步骤是构建设备。要完成这个例子,你需要一个ThingSpeak账号和一个the 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:计数器,field2:湿度,field3:温度,纬度:纬度,经度:lon}}

添加集成

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

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

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

3)点击集成选项卡。

4)选择ThingSpeak。

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

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

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

创建设备

创建传感器节点的硬件

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

原理图及连接

按原理图所示连接传感器。这张照片显示了一个项目箱中传感器的可能配置。在这种配置中,盒内的温度传感器可能不能准确地反映外部温度。你需要增加天线到LoRa收音机。

1)连接GPS和温度传感器的电源和接地。禁止将电源接在湿度传感器上。

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

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

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

5)对于GPS板,在Feather 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  #include  #include  #include "DHT.h" #include  #define DHTPIN 5 #define GPSSerial Serial1 #define SOIL_PIN 14 #define SOIL_POWER_PIN 11 #define GPSECHO false //如果你想调试和监听原始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,应用程序会话密钥静态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 [PAYLOAD_SIZE];静态osjob_t sendjob;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 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)使用设置功能启动温度传感器,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 = analoggread (SOIL_PIN);digitalWrite (SOIL_POWER_PIN、低);temperatureF = dht。readTemperature(true);系列。println("moisture " +字符串(myMoisture) + " temp " +字符串(温度值));if (GPS.fix){串行。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)使用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(温度f * 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频道中创建详细的可视化仪表板,请参见创建自定义ThingSpeak通道视图