主要内容

通过物联网收集农业数据

这个例子展示了如何设置数据收集从三个传感器连接到微处理器板与LoRa®收音机。这种配置允许在大范围内创建分布式传感器网络。传感器将数据发送到Things Network,然后转发到ThingSpeak进行分析和可视化。在本例中,您构建了一个原型设备,连接到the 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网络控制台

创建应用程序

1)选择应用程序。

2)选择添加应用程序

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

注册一个设备

1)点击设备制表符并注册设备。有关更多信息,请参见设备注册

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

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

4)选择设置选项卡。

5)在设置中选择激活方式为“ABP”。为了辅助调试,可以选择禁用帧计数器检查在这一页的底部。

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

创建负载格式化程序

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

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

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

function Decoder(b, port) {var counter = b[0] << 8) | b[1];Var湿度= b[2] | [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万博1manbetxwork。这个示例演示了使用以下硬件设置的过程。

示意图和联系

按照原理图连接传感器。照片显示了一个项目框中传感器的可能配置。在这种配置中,盒内的温度传感器可能不能准确反映外部温度。你需要添加一个天线到劳拉电台。

1)连接GPS和温度传感器的电源和接地。请勿为湿度传感器接通电源。

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

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

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

5)对于GPS板,连接TX到RX的羽毛M0和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并选择mci LoRaWAN LMIC库将其添加到已安装的库中。还添加了MCCI Arduino LoRaWan Library给图书馆管理员。

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

代码

1)首先包含适当的库并初始化变量。

# include < lmic.h > # include <哈尔/ 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假/ /设置为“真正的”如果你想调试和听原始GPS句子# define PAYLOAD_SIZE 13 / /发送的字节数+ 2 / / LoRaWANNwkSKey,网络会话密钥static const PROGMEM u1_t NwkSKey [16] = {0x98, 0xEB, 0x1A, 0xC5, 0xF9, 0x20, 0x15, 0xCD, 0x12, 0xE5, 0x72, 0xFF, 0xCD, 0x2, 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};//终端地址(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) {} // Payload to send to TTN gateway static uint8_t Payload [PAYLOAD_SIZE];静态osjob_t sendjob;//将TX调度为最少这么多秒const unsigned TX_INTERVAL = 60;/ / 30 / /销映射Adafruit羽毛M0罗拉const lmic_pinmap lmic_pins = {.nss = 8, .rxtx = LMIC_UNUSED_PIN首要= 4,.dio = {3 6 LMIC_UNUSED_PIN}, .rxtx_rx_active = 0, .rssi_cal = 8, / / LBT Adafruit羽毛M0罗拉卡尔,在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 return;} }

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

void GetSensorData() {digitalWrite(SOIL_POWER_PIN, HIGH);延迟(1000);myMoisture = analogRead (SOIL_PIN);digitalWrite (SOIL_POWER_PIN、低);双氢睾酮temperatureF =。readTemperature(真正的);系列。println("湿气" + String(myMoisture) + " temp " + String(temperatureF)); / /输入温度if (GPS.fix) {Serial. fix (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"));打破;案例EV_BEACON_FOUND:以(F(“EV_BEACON_FOUND”));打破;案例EV_BEACON_MISSED:以(F(“EV_BEACON_MISSED”));打破;案例EV_BEACON_TRACKED:以(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频道视图