歡迎下載研華科技主題白皮書:
【AIoT】研華AIoT邊緣智能及網關解決方案
[摘要] 物聯網、大數據、云服務與人工智能,是產業(yè)數位轉型的關鍵科技趨勢,透過創(chuàng)新應用,將替各產業(yè)帶來巨大商機與全新 局面。研華以堅強的硬件實力為基礎,開發(fā)出多元軟件服務。
http://m.xujingxiang.cn/resource/advantech/index.php?act=detail&item=1496
這篇開始,我們就真正做《網關》升級版教程了,采用arduino+zigbee哦。
arduino簡單易學,zigbee自組網(如果不懂c語言,直接用就好,我們已經刷好自組網代碼)!
這次我們的教程是通過以下配件實現《網關》功能,并在手機端點擊按鈕,使zigbee模塊上的燈閃亮(實現是發(fā)送真正的命令了{ckxxxxxxxxx}的格式)!
通過不同的格式命令就可以操作開、關、接收、發(fā)送數據!之后《溫濕傳感器》《zigbee插座》等就可以直接連上了!
上面就是arduino開源網關的配件。
1、SMARTRF04EB(ZIGBEE下載器)
2、CP2102(arduino下載器)
3、電源供電
4、arduino板(含w5100、zigbee插槽、SD卡座)
5、zigbee開發(fā)板 (如果只想學zigbee只需要兩塊開發(fā)板和zigbee模塊,自組網學習哦)
6、zigbee模塊
實現自己的arduino開源網關吧(自己有arduino和w5100是可以代替我們的arduino板的)。
第一部份:arduino板刷上代碼。
一、安裝CP2102驅動(USB驅動)
https://pan.baidu.com/s/1o6iDLcm(下載后直接安裝或發(fā)現有新硬件就更新驅動)。
二、將CP2102連上arduino板底下的插槽的一定要一一對應哦。DTR->DTR
GND->GND
TX->RXI
RX->TXO
VDD3.3->VCC
三、刷arduino代碼
大家可以直接在這里下載源代碼:
https://pan.baidu.com/s/1i386zPV(包含arduino軟件和所有的庫)
下面我們就貼上代碼(都有注釋哦)
#include <iBoardRF24Network.h>
#include <iBoardRF24.h>
#include <digitalWriteFast.h>
#include <SPI.h>
#include <Ethernet.h>
//請到m.znck007.com申請登陸-》家中環(huán)境-》網關,里可以看到!
#define APIKEY "xxxxxxxxxxxxxxxx" //設置apikey
uint16_t sid=001;//設置sid(設備號)
//NRF24l01發(fā)送接收節(jié)點
const uint16_t this_node = 0;
const uint16_t other_node = 1;
//NRF24l01收發(fā)數據
struct payload_t
{
uint32_t ms;
uint32_t data;
char sendchar[20];
};
//NRF24l01腳針設置
iBoardRF24 radioSend(3,8,5,6,7,2);
iBoardRF24Network networkSend(radioSend);
bool ispayload=false;//NRF24l01收發(fā)判斷
uint16_t sendChannel=1;//NRF24l01發(fā)送頻道
uint32_t sendCount=0;//NRF24l01發(fā)送次數
char incomingData[20]={0};//NRF24l01接收到的字符(其它設置發(fā)過來)
//設置MAC地址,如果有二個請改為不同(隨意)
static byte mymac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetClient client;//聲明網關類
char server[] = "api.znck007.com";//聲明API網址
//char urlBuf[] = "/index.php";
static long timer;//用于規(guī)定時間間隔
unsigned long last_http;//記錄http時間,用于http超時判斷,目前20秒無響應則重新GET。
bool ishttpget=false;//標示http是否已經結束
bool isUpdate=false;//成功則更新服務器數據為正常
char updateData[20]={0};//更新的字符(服務器通過字符分析指定某個設備)
//串口通信處理(主要用于zigbee通信)
unsigned long serialnowlast;
char serialbuff[80]={0};
char serialData;
int seriali=0;
void setup(void)
{
//設置串口波特率
Serial.begin(115200);
Serial.println("IBOARD_GATEWAY_ZIGBEE/RF24Network");
//NRF24l01初始化
SPI.begin();
radioSend.begin();
//獲取IP DNS等
Serial.println("n[getDHCPandDNS]");
if (Ethernet.begin(mymac) == 0)
{
Serial.print(F("Failed to configure Ethernet using DHCPn"));
while(1);
}
else
{
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print("."); }
Serial.println("Ethernet configuration OK");
}
//連接web服務器
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected");
client.println("GET /index.php HTTP/1.1");
client.println("Host: api.znck007.com");
client.println("Connection: close");
client.println();
}
else {
// kf you didn't get a connection to the server:
Serial.println("connection failed");
client.stop();
}
//判斷web服務器是否正常
timer=millis();
while ((!client.available()) && (millis()-timer)<2000);
if (client.available()) {
char c = client.read();
Serial.print(c);
client.stop();
}
timer = millis();
//完成setup
Serial.println("setup success");
}
void loop(void)
{
// //NRF24l01檢測接收數處理
// //如果使用NRF24l01,請啟動這里(并刪除ZIGBEE檢測接收數據處理)
// networkSend.begin(/*channel*/ sid, /*node address*/ this_node);
// // Pump the network regularly
// networkSend.update();
//
// // Is there anything ready for us?
// timer=millis();
// //while ((!networkSend.available()) && (millis()-timer)<2000);
// while(networkSend.available())
// {
// // If so, grab it and print it out
// RF24NetworkHeader header;
// payload_t payload;
// memset(payload.sendchar, 0, 20);
// networkSend.read(header,&payload,sizeof(payload));
// Serial.print("Received packet #");
// Serial.print(payload.data);
// Serial.print(" at ");
// Serial.print(payload.ms);
// Serial.print(" getchar ");
// Serial.println(payload.sendchar);
//
// ispayload = true;
//
// get_html_body(payload.sendchar,incomingData);
// Serial.println(incomingData);
// }
//
// if(!ishttpget)
// {
// if(ispayload)
// {
// ispayload = false;
//
// if(strstr(incomingData,"{ck") && strstr(incomingData,"}") )
// {
// last_http = millis();
// ishttpget=true;
//
// Serial.println("n>>> POST");
// static char buf[20]={0};
// sprintf(buf,"%s",incomingData);
//
// client_post(server,APIKEY,buf);
// my_result_cb();
//
// return;
// }
//
// }
//
//
// }
//ZIGBEE檢測接收數據處理
if(!ishttpget)
{
unsigned long serialnow = millis();//獲取現在的時間
if(serialnow - serialnowlast >= 5000)//如果數據間隔超過5秒而清空字符(為了防止數據錯亂)
{
serialnowlast = millis();
memset(serialbuff, 0, 80);
seriali=0;
}
bool isSerial=false;
while( Serial.available() )//如果串口有數據(ZIGBEE或電腦發(fā)過來的)
{
if(seriali==0)
{
Serial.println("Serial->");//打印出來方便調試
}
serialData=(char)Serial.read();//讀取串口數據
//Serial.print(serialData);////這里不打印,否則ZIGBEE檢測到{ckxxxx}就認為是命令
serialbuff[seriali]=serialData;////保存到數組
seriali++;////數組長度+1
if(serialData=='}' || seriali>=80)//如果發(fā)現}而說明命令結束(并少于80個字符,太長會出錯)
{
isSerial=true;
break;
}
}
//開始處理{ckxxxxx}字符,如POST上傳到web服務器
if(isSerial)
{
serialnowlast = millis(); //更新當前時間,不然5秒就超時了
//Serial.println(serialbuff);
char body[81]={0};
get_html_body(serialbuff,body);//獲取只是{ckxxxxxx}的字符,因為這是我們的命令格式
//Serial.println(body);
Serial.println("-------------------");
//如果命令格式真確則POST到web服務器了
if(strstr(body,"{ck") && strstr(body,"}") )
{
last_http = millis();
ishttpget=true;
timer = millis();
Serial.println("n>>> POST");
//static char buf[81]={0};
//sprintf(buf,"%s",body);
client_post(server,APIKEY,body);//POST到網址,APIKEY,字符
my_result_cb();//接收web服務器返回的字符
}
memset(serialbuff, 0, 80);//清空字符
seriali=0;//字符長度為0
return;
}
}
//delay(200);
//更新web服務器命令的狀態(tài)(比如發(fā)送成功還是失敗還是異常等,NRF24l01用到,ZIGBEE不用這里而是直接發(fā)送{ck00xxxxxxupdate}命令就行)
if( isUpdate )
{
isUpdate=false;
last_http = millis();
ishttpget=true;
Serial.println("n>>> UPDATE");
static char buf[20]={0};
sprintf(buf,"%s",updateData);
//Serial.println(buf);
client_post(server,APIKEY,buf);//POST到網址,APIKEY,字符
my_result_cb();//接收web服務器返回的字符
isUpdate=false;
return;
}
//每2秒鐘查看web服務器是有命令數據
unsigned long now = millis();
if(now - last_http >= 2000)
{
if(!ishttpget || (now - last_http) >= 20000)//20秒超時會執(zhí)行,為了防卡死問題
{
last_http = millis();
ishttpget=true;
Serial.println("n>>> REQ");
static char buf[20]={0};
sprintf(buf,"{ck001000000000}"); //這個字符串代表獲取新命令數據
client_post(server,APIKEY,buf);//POST到網址,APIKEY,字符
my_result_cb();//接收web服務器返回的字符
timer = millis();
}
}
}
//接收web服務器返回的字符
static void my_result_cb(){
char eth_buffer[350];
timer=millis();
while ((!client.available()) && (millis()-timer)<1000);
if (client.available()) {
for(int j=0;client.available()>0;j++)
{
char c = client.read();
eth_buffer[j]=c;
Serial.print(c);
}
client.stop();
}
Serial.println();
char body[81]={0};
get_html_body(eth_buffer,body);//獲取只是{ckxxxxxx}的字符,因為這是我們的命令格式
//Serial.println(body);
sendChannel=get_channel(body);//獲取是哪個sid,這是m.znck007.com手機客服端里的sid
// //如果使用NRF24l01,請啟動這里
// if( sendChannel>0 )
// {
// networkSend.begin(/*channel*/ sendChannel, /*node address*/ other_node);
//
// networkSend.update();
// Serial.println("");
// Serial.print("Sending...");
// if(sendCount>1000000) sendCount=0;
// payload_t payload = { sendChannel, sendCount++, "{ck000000000000}" };//millis()
// sprintf(payload.sendchar,"%s",body);
// RF24NetworkHeader header(/*to node*/ this_node);
// bool ok = networkSend.write(header,&payload,sizeof(payload));
// if (ok)
// {
// Serial.println("ok.");
//
// isUpdate=true;
// char front[10]={0};
// memcpy(front,body,9);
// sprintf(updateData,"%supdate}",front);
// Serial.println(updateData);
//
// }
// else
// {
// Serial.println("failed.");
// }
// }
ishttpget=false;
last_http = millis();
networkSend.begin(/*channel*/ sid, /*node address*/ this_node);
networkSend.update();
}
//獲取只是{ckxxxxxx}的字符,因為這是我們的命令格式
void get_html_body(char *p,char *s){
char rechar[81]={0};
int bufi=0;
bool isend=false;
int charnum=0;
for(bufi=0;bufi<strlen(p);bufi++){
//Serial.print(p[bufi]);
if(p[bufi]=='{'){
isend=true;
}
if(p[bufi]=='}' && isend==true){
isend=false;
rechar[charnum]=p[bufi];
break;
}
if(isend){
if(charnum<80)
{
rechar[charnum]=p[bufi];//Serial.print(rechar[charnum]);
charnum++;
}
}
}
Serial.println("");
//memcpy(s,rechar,17);
sprintf(s,"%s",rechar);
}
//獲取是哪個sid,這是m.znck007.com手機客服端里的sid
int get_channel(char *buff){
if( strstr(buff,"{ck") && strstr(buff,"}") && strlen(buff)>10)
{
char charChannel[4]={0};
memcpy(charChannel,buff+3,3);
Serial.println(charChannel);
int intChannel=atoi(charChannel);
Serial.println(intChannel);
return intChannel;
}
else
{
return 0;
}
}
//W5100芯片POST字符數據到web服務器
int client_post(char *server, char *apikey, char *buf){
if (client.connect(server, 80))
{
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("POST /index.php");
client.println(" HTTP/1.1");
client.println("Host: api.znck007.com");
client.print("apikey: ");
client.println(APIKEY);
client.print("Accept: *");
client.print("/");
client.println("*");
client.print("Content-Length: ");
// calculate the length of the sensor reading in bytes:
// 8 bytes for {"value":} + number of digits of the data:
size_t thisLength = strlen(buf);
client.println(thisLength);
client.println("Content-Type: application/x-www-form-urlencoded");
client.println("Connection: close");
client.println();
client.println(buf);
client.println();
}
else
{
// kf you didn't get a connection to the server:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
}
四、插上網線,打開串口就可以測試聯網是否成功了!
第二部份:刷zigbee模塊代碼
一、將zigbee模塊插到zigbee開發(fā)板上
二、連上SMARTRF04EB下載器。
將一邊有凸出來的一端與(VDD、RES、NC、DC、GND的NC對應就正確了!
三、安裝SMARTRF04EB驅動
https://pan.baidu.com/s/1dDH1ZX3(安裝SmartRFStudio后里面包含有驅動)
提示:如果刷不成功,點擊一下SMARTRF04EB上的RESET(凹進去就用筆撮)。
四、安裝IAR 8.1,軟件比較大,安裝后看說明破解就好。
https://pan.baidu.com/s/1c0b69Ra(下載解壓里面有安裝說明)
五、下載zigbee自組網代碼。
https://pan.baidu.com/s/1COxT8(最新ZStack-CC2530-2.5.1自組網代碼,已經寫好了按鍵、LED燈功能)
六、點擊編譯并下載。
七、插個LED到zigbee開發(fā)板的P1.0和-。
八、安到arduino板上。
第三步:使用手機測試
一、手機打開m.znck007.com手機控制端。
二、新建一個開關。
三、點擊開關,如果發(fā)現LED燈閃,說明《網關工作正常了》!
OK,《網關》部份已經搞定了,下期我們就來上《溫濕傳感器》《Zigbee插座》《紅外控制》!
因為我們還未使用Wifi,所以都需要與《網關》交互數據哦!
等我們Wifi產品出來就可以單獨使用了!