CAT LoRa Starter Kit ตอนที่ 5 เพิ่มฟังชันก์การวัดอุณหภูมิให้กับ CAT Lora Library

Choonewza
7 min readJan 5, 2020

สวัสดีครับ ในตอนที่แล้วผมได้อธิบายการสร้างไลบรารี CAT LoRaไว้ใช้เองแบบง่าย ๆ ในบทความนี้เราจะมาทำการเพิ่มการอ่านอุณหภูมิ (Temperature) และความชื้นในอากาศ (Humidity) เนื่องจากในบอร์ด CAT LoRa Starter Kit ได้มีการใส่เซนเซอร์ HTS221 ไว้ให้แล้ว โดยเราจะนำไลบรารี่ที่ชื่อ SmartEverything HTS221 มาใช้ใน CAT LoRa Library ที่เราได้สร้างไว้

ติดตั้งไลบรารี่ SmartEverything HTS221

โดยไปที่ Manage Libraries แล้วคนหาไลบรารี่ชื่อ SmartEverything HTS221 จากนั้นทำการติดตั้งจนเสร็จ

เขียนโปรแกรม

ที่ไฟล์ CatLoRaS76S.h แก้ไขดังนี้

  1. include ไลบรารี่ SmartEverything HTS221 เข้ามาใช้งาน
  2. เพิ่ม getTemp() — เพื่อดึงค่าอุณหภูมิ
  3. เพิ่ม getHumi() — เพื่อดีงค่าความชื้น
//ไฟล์ CatLoRaS76S.h....
#include <HTS221.h>
....
class catLoRaS76S
{
...
public:
...
String getTemp();
String getHumi();
}

ที่ไฟล์ CatLoRaS76S.cpp แก้ดังนี้

//ไฟล์ CatLoRaS76S.cpp....void catLoRaS76S::begin(uint32_t bundRate){
...
smeHumidity.begin();
}
double catLoRaS76S:: getTemp(){
return smeHumidity.readTemperature();
}
double catLoRaS76S:: getHumi(){
return smeHumidity.readHumidity();
}

เมื่อแก้ไขแล้วจะได้ดังนี้

CatLoRaS76S.h

//ไฟล์ CatLoRaS76S.h#ifndef catLoRaS76S_h
#define catLoRaS76S_h
#include "Arduino.h"
#include <Wire.h>
#include <HTS221.h>
#include "wiring_private.h" // pinPeripheral() function
class catLoRaS76S
{
private:
void SERCOM1_Handler(void);
void macCommand(String comm);
void freqLoraConfig(void);
public:
~catLoRaS76S();
catLoRaS76S();
void begin(uint32_t bundRate);
void joinABP(String loraClass, String devEui, String devAddr, String nwksKey, String appsKey);
void transmit(uint8_t port, String payLoad);
String receive(void);
unsigned int getPortReceive(String dataFromReceive);
String getPayloadReceive(String dataFromReceive);
String getTemp();
String getHumi();
};
#endif

CatLoRaS76S.cpp

//ไฟล์ CatLoRaS76S.cpp#include "catLoRaS76S.h"#define _DEBUG 1#define _PIN_RX 11
#define _PIN_TX 10
#define _LED_BUIDIN 13
#define _MAC_SIP_RESET "sip reset"#define _MAC_SET_CH_FREQ "mac set_ch_freq"
#define _MAC_SET_RX2 "mac set_rx2"
#define _MAC_SAVE "mac save"
#define _MAC_SET_CLASS "mac set_class"
#define _MAC_SET_DEVEUI "mac set_deveui"
#define _MAC_SET_DEVADDR "mac set_devaddr"
#define _MAC_SET_NWKSKEY "mac set_nwkskey"
#define _MAC_SET_APPSKEY "mac set_appskey"
#define _MAC_JOIN_ABP "mac join abp"
#define _MAC_TX_UCNF "mac tx ucnf"
#define _MAC_SET_appEUI "mac set_appeui"
#define _MAC_SET_APPKEY "mac set_appkey"
#define _MAC_JOIN_OTAA "mac join otaa"
Uart Serial2(&sercom1, _PIN_RX, _PIN_TX, SERCOM_RX_PAD_0, UART_TX_PAD_2);catLoRaS76S::~catLoRaS76S() {}catLoRaS76S::catLoRaS76S()
{
pinMode(_LED_BUIDIN, OUTPUT);
}
void SERCOM1_Handler(void)
{
Serial2.IrqHandler();
}
void catLoRaS76S::macCommand(String comm)
{
Serial2.print(comm);
delay(250);
String msg = Serial2.readString();#ifdef _DEBUG
Serial.print("_DEBUG: ");
Serial.print(comm);
Serial.println(msg);
#endif
delay(100);
}
void catLoRaS76S::begin(uint32_t bundRate)
{
Wire.begin();
Serial2.begin(bundRate);
pinPeripheral(_PIN_TX, PIO_SERCOM);
pinPeripheral(_PIN_RX, PIO_SERCOM);
delay(500);
freqLoraConfig();smeHumidity.begin();
}
void catLoRaS76S::freqLoraConfig(void)
{
int freq[] = {923200000, 923400000, 922000000, 922200000, 922400000, 922600000, 922800000, 923000000};
macCommand(String(_MAC_SIP_RESET));
delay(1000);
//chanel 0 to 7
for (int i = 0; i < sizeof freq / sizeof freq[0]; i++)
{
macCommand(String(_MAC_SET_CH_FREQ) + " " + i + " " + freq[i]);
}
macCommand(String(_MAC_SET_RX2) + " 2 923200000");
macCommand(String(_MAC_SAVE));
}
void catLoRaS76S::joinABP(String loraClass, String devEui, String devAddr, String nwksKey, String appsKey)
{
macCommand(String(_MAC_SET_CLASS) + " " + loraClass);
macCommand(String(_MAC_SET_DEVEUI) + " " + devEui);
macCommand(String(_MAC_SET_DEVADDR) + " " + devAddr);
macCommand(String(_MAC_SET_NWKSKEY) + " " + nwksKey);
macCommand(String(_MAC_SET_APPSKEY) + " " + appsKey);
macCommand(String(_MAC_JOIN_ABP));
macCommand(String(_MAC_SAVE));
}
void catLoRaS76S::transmit(uint8_t port, String payLoad)
{
String comm = String(_MAC_TX_UCNF) + String(" ") + String(port) + String(" ") + payLoad;
Serial2.print(comm);
#ifdef _DEBUG
Serial.print("_DEBUG_TX: ");
Serial.println(comm);
#endif
delay(250);
}
String catLoRaS76S::receive(void)
{
String msg = Serial2.readString();
if (msg == "")
{
return "";
}
#ifdef _DEBUG
Serial.print("_DEBUG_RX: ");
Serial.println(msg);
#endif
String rawData = "";String checkDL = ">> mac rx ";
int checkStart = msg.indexOf(checkDL);
if (checkStart != -1)
{
int checkEND = msg.indexOf("\n", checkStart + 1);
rawData = msg.substring(checkStart + 10, checkEND);
}
return rawData;
}
unsigned int catLoRaS76S::getPortReceive(String dataFromReceive)
{
String macComm = "";if (dataFromReceive != "")
{
int checkStart = dataFromReceive.indexOf(' ');
if (checkStart > -1)
{
macComm = dataFromReceive.substring(0, checkStart);
}
}
return (unsigned int) macComm.toInt();
}
String catLoRaS76S::getPayloadReceive(String dataFromReceive)
{
String macComm = "";
if (dataFromReceive != "")
{
int checkStart = dataFromReceive.indexOf(' ');
if (checkStart > -1)
{
int checkEND = dataFromReceive.indexOf("\n", checkStart + 1);
macComm = dataFromReceive.substring(checkStart + 1, checkEND);
}
}
return macComm;
}
double catLoRaS76S:: getTemp(){
return smeHumidity.readTemperature();
}
double catLoRaS76S:: getHumi(){
return smeHumidity.readHumidity();
}

ทดสอบ

โดยเราจะเขียนโปรแกรมส่งค่าอุณหภูมิกับความชื้นขึ้นไปยัง Network Server โดยใช้รูปแบบดังนี้

รูปแบบ Payload → 01XXYY02XXYY

โดยที่
อุณหภูมิ → 01XXYY
ความชื้น → 02XXYY
XX = ค่า อุณหภูมิ/ความชื้น ในตำแหน่งจำนวนเต็ม
YY = ค่า อุณหภูมิ/ความชื้นในตำแหน่งทศนิยม

ตัวอย่าง
อุณหภูมิ 33.49 องศา จะได้เป็น 013349
ความชื้น 73.43 จะได้เป็น 027343
payload → 013349027343

ไฟล์ catLoraTest.ino ที่ทำการแก้ไขแล้ว

#include "catLoRaS76S.h"#define _ABP_CLASS "C"
#define _DEV_EUI "????????????????"
#define _DEV_ADDR "????????"
#define _NWKS_KEY "????????????????????????????????"
#define _APPS_KEY "????????????????????????????????"
catLoRaS76S lora;unsigned long startMillisTX;
unsigned long currentMillisTX;
const unsigned long periodTX = 20000;
unsigned long startMillisRX;
unsigned long currentMillisRX;
const unsigned long periodRX = 250;
uint8_t _port = 5;
String _payload = "010203";
void setup() {
Serial.begin(115200);
delay(1000);
lora.begin(115200);
lora.joinABP(_ABP_CLASS, _DEV_EUI, _DEV_ADDR, _NWKS_KEY, _APPS_KEY);
startMillisTX = millis();
}
void loop() {//-----TX START-----
currentMillisTX = millis();
if (currentMillisTX - startMillisTX >= periodTX) {
double temp = lora.getTemp();
double humi = lora.getHumi();
Serial.print("Temp=");
Serial.print(temp);
Serial.print(", ");
Serial.print("Humi=");
Serial.println(humi);
String tempFormat = String("01") + String(uint16_t(temp*100));
String humiFormat = String("02") + String(uint16_t(humi*100));
_payload = tempFormat + humiFormat;
lora.transmit(_port, _payload);

startMillisTX = currentMillisTX;
}
//-----TX END-----
//-----RX START-----
currentMillisRX = millis();
if (currentMillisRX - startMillisRX >= periodRX) {
String rawDL = lora.receive();
if (rawDL != "") {
uint16_t rPort = (uint16_t) lora.getPortReceive(rawDL);
String rPayload = lora.getPayloadReceive(rawDL);
Serial.print("Port = ");
Serial.println(rPort);
Serial.print("Payload = ");
Serial.println(rPayload);
}
startMillisRX = currentMillisRX;
}
//-----RX END-----
}

รันโปรแกรมแล้วจะได้ผลลับดังนี้

เมื่อเราทำการรันดูข้อมูลอุณหภูมิที่วัดได้ จะสังเกตุได้ว่าเซนเซอร์ HTS221 มันวัดอุณหภูมิได้ประมาณ 32 องศาเซลเซียสนั้น พบว่าค่าที่ได้น่าจะผิดจากความเป็นจริง เพราะผมทดสอบในห้องแอร์โดยตั้งอุณหภูมิไว้ที่ 25 องศา ดังนั้นค่าอุณหภูมิที่ได้น่าจะเป็นอุณหภูมิของตัวบอร์ดมากกว่าที่จะเป็นของสภาพอากาศรอบข้าง ผมจึงใช้เครื่องวัดอุณหภูมิตัวบอร์ดปรากฏว่าได้ค่าอุณหภูมิใกล้เคียงกับที่เซนเซอร์วัดได้

จากโปรแกรมที่เราเขียนขึ้นข้างต้น จะพบว่าการจะนำข้อมูลจากเซนเซอร์ส่งผ่านเครือข่าย lora ได้นั้นต้องทำการแปลงข้อมูลให้อยู่ในรูปแบบของเลขฐาน 16 ก่อน ดังเช่นในที่นี้เราได้กำหนดรูปแบบ Payload เป็น 01XXYY02XXYY ดังนั้นเพื่อให้ง่ายต่อการนำไปใช้งานเราสามารถสร้าง method เพิ่มเพื่อกำหนดรูปแบบของ Payload ที่เราต้องการไว้ใน Library ได้เลย เช่น รูปแบบของ CayenneLPP ดังนี้

String catLoRaS76S:: getTempHumiCayenneLPPformat(){
String temp = "";
String humi = "";
String cayenneLPPformat = "";

String cayenTemp = "0067"; //3digi (2byte) *0.1(10)
String cayenHumi = "0168"; //2digi (1byte) *0.5(2)

temp = uint16_t(this->getTemp()*10);
humi = uint16_t(this->getHumi()*2);

char tempHex[5];
char humiHex[3];
sprintf(tempHex, "%04x", temp.toInt());
sprintf(humiHex, "%02x", humi.toInt());

cayenneLPPformat = cayenTemp + tempHex + cayenHumi + humiHex;

return cayenneLPPformat;
}

“สำหรับรูปแบบ CayenneLPP Format ดูได้ที่ https://www.thethingsnetwork.org/docs/devices/arduino/api/cayennelpp.html

Last updated on CAT LoRa Library

CatLoRaS76S.h (last updated)

//ไฟล์ CatLoRaS76S.h#ifndef catLoRaS76S_h
#define catLoRaS76S_h
#include "Arduino.h"
#include <Wire.h>
#include <HTS221.h>
#include "wiring_private.h" // pinPeripheral() function
class catLoRaS76S
{
private:
void SERCOM1_Handler(void);
void macCommand(String comm);
void freqLoraConfig(void);
public:
~catLoRaS76S();
catLoRaS76S();
void begin(uint32_t bundRate);
void joinABP(String loraClass, String devEui, String devAddr, String nwksKey, String appsKey);
void joinOTAA(String loraClass, String devEui, String appEui, String appKey);
void transmit(uint8_t port, String payLoad);
String receive(void);
unsigned int getPortReceive(String dataFromReceive);
String getPayloadReceive(String dataFromReceive);
double getTemp();
double getHumi();
String getTempHumiCayenneLPPformat();
};
#endif

CatLoRaS76S.cpp (last updated)

//ไฟล์ CatLoRaS76S.cpp#include "catLoRaS76S.h"#define _DEBUG 1#define _PIN_RX 11
#define _PIN_TX 10
#define _LED_BUIDIN 13
#define _MAC_SIP_RESET "sip reset"#define _MAC_SET_CH_FREQ "mac set_ch_freq"
#define _MAC_SET_RX2 "mac set_rx2"
#define _MAC_SAVE "mac save"
#define _MAC_SET_CLASS "mac set_class"
#define _MAC_SET_DEVEUI "mac set_deveui"
#define _MAC_SET_DEVADDR "mac set_devaddr"
#define _MAC_SET_NWKSKEY "mac set_nwkskey"
#define _MAC_SET_APPSKEY "mac set_appskey"
#define _MAC_JOIN_ABP "mac join abp"
#define _MAC_TX_UCNF "mac tx ucnf"
#define _MAC_SET_APPEUI "mac set_appeui"
#define _MAC_SET_APPKEY "mac set_appkey"
#define _MAC_JOIN_OTAA "mac join otaa"
Uart Serial2(&sercom1, _PIN_RX, _PIN_TX, SERCOM_RX_PAD_0, UART_TX_PAD_2);catLoRaS76S::~catLoRaS76S() {}catLoRaS76S::catLoRaS76S()
{
pinMode(_LED_BUIDIN, OUTPUT);
}
void SERCOM1_Handler(void)
{
Serial2.IrqHandler();
}
void catLoRaS76S::macCommand(String comm)
{
Serial2.print(comm);
delay(250);
String msg = Serial2.readString();#ifdef _DEBUG
Serial.print("_DEBUG: ");
Serial.print(comm);
Serial.println(msg);
#endif
delay(100);
}
void catLoRaS76S::begin(uint32_t bundRate)
{
Wire.begin();
Serial2.begin(bundRate);
pinPeripheral(_PIN_TX, PIO_SERCOM);
pinPeripheral(_PIN_RX, PIO_SERCOM);
delay(500);
freqLoraConfig();smeHumidity.begin();
}
void catLoRaS76S::freqLoraConfig(void)
{
int freq[] = {923200000, 923400000, 922000000, 922200000, 922400000, 922600000, 922800000, 923000000};
macCommand(String(_MAC_SIP_RESET));
delay(1000);
//chanel 0 to 7
for (int i = 0; i < sizeof freq / sizeof freq[0]; i++)
{
macCommand(String(_MAC_SET_CH_FREQ) + " " + i + " " + freq[i]);
}
macCommand(String(_MAC_SET_RX2) + " 2 923200000");
macCommand(String(_MAC_SAVE));
}
void catLoRaS76S::joinABP(String loraClass, String devEui, String devAddr, String nwksKey, String appsKey)
{
macCommand(String(_MAC_SET_CLASS) + " " + loraClass);
macCommand(String(_MAC_SET_DEVEUI) + " " + devEui);
macCommand(String(_MAC_SET_DEVADDR) + " " + devAddr);
macCommand(String(_MAC_SET_NWKSKEY) + " " + nwksKey);
macCommand(String(_MAC_SET_APPSKEY) + " " + appsKey);
macCommand(String(_MAC_JOIN_ABP));
macCommand(String(_MAC_SAVE));
}
void catLoRaS76S::joinOTAA(String loraClass, String devEui, String appEui, String appKey)
{
macCommand(String(_MAC_SET_CLASS) + " " + loraClass);
macCommand(String(_MAC_SET_DEVEUI) + " " + devEui);
macCommand(String(_MAC_SET_APPEUI) + " " + appEui);
macCommand(String(_MAC_SET_APPKEY) + " " + appKey);
macCommand(String(_MAC_JOIN_OTAA));
macCommand(String(_MAC_SAVE));
}
void catLoRaS76S::transmit(uint8_t port, String payLoad)
{
String comm = String(_MAC_TX_UCNF) + String(" ") + String(port) + String(" ") + payLoad;
Serial2.print(comm);
#ifdef _DEBUG
Serial.print("_DEBUG_TX: ");
Serial.println(comm);
#endif
delay(250);
}
String catLoRaS76S::receive(void)
{
String msg = Serial2.readString();
if (msg == "")
{
return "";
}
#ifdef _DEBUG
Serial.print("_DEBUG_RX: ");
Serial.println(msg);
#endif
String rawData = "";String checkDL = ">> mac rx ";
int checkStart = msg.indexOf(checkDL);
if (checkStart != -1)
{
int checkEND = msg.indexOf("\n", checkStart + 1);
rawData = msg.substring(checkStart + 10, checkEND);
}
return rawData;
}
unsigned int catLoRaS76S::getPortReceive(String dataFromReceive)
{
String macComm = "";if (dataFromReceive != "")
{
int checkStart = dataFromReceive.indexOf(' ');
if (checkStart > -1)
{
macComm = dataFromReceive.substring(0, checkStart);
}
}
return (unsigned int)macComm.toInt();
}
String catLoRaS76S::getPayloadReceive(String dataFromReceive)
{
String macComm = "";
if (dataFromReceive != "")
{
int checkStart = dataFromReceive.indexOf(' ');
if (checkStart > -1)
{
int checkEND = dataFromReceive.indexOf("\n", checkStart + 1);
macComm = dataFromReceive.substring(checkStart + 1, checkEND);
}
}
return macComm;
}
double catLoRaS76S::getTemp()
{
return smeHumidity.readTemperature();
}
double catLoRaS76S::getHumi()
{
return smeHumidity.readHumidity();
}
String catLoRaS76S::getTempHumiCayenneLPPformat()
{
String temp = "";
String humi = "";
String cayenneLPPformat = "";
String cayenTemp = "0067"; //3digi (2byte) *0.1(10)
String cayenHumi = "0168"; //2digi (1byte) *0.5(2)
temp = uint16_t(this->getTemp() * 10);
humi = uint16_t(this->getHumi() * 2);
char tempHex[5];
char humiHex[3];
sprintf(tempHex, "%04x", temp.toInt());
sprintf(humiHex, "%02x", humi.toInt());
cayenneLPPformat = cayenTemp + tempHex + cayenHumi + humiHex;return cayenneLPPformat;
}

บทความนี้ก็ขอจบเพียงเท่านี้นะครับ

--

--