歡迎下載研華科技主題白皮書(shū):
【AIoT】研華AIoT邊緣智能及網(wǎng)關(guān)解決方案
[摘要] 物聯(lián)網(wǎng)、大數(shù)據(jù)、云服務(wù)與人工智能,是產(chǎn)業(yè)數(shù)位轉(zhuǎn)型的關(guān)鍵科技趨勢(shì),透過(guò)創(chuàng)新應(yīng)用,將替各產(chǎn)業(yè)帶來(lái)巨大商機(jī)與全新 局面。研華以堅(jiān)強(qiáng)的硬件實(shí)力為基礎(chǔ),開(kāi)發(fā)出多元軟件服務(wù)。
http://fundaciorobertgraves.com/resource/advantech/index.php?act=detail&item=1496
這篇開(kāi)始,我們就真正做《網(wǎng)關(guān)》升級(jí)版教程了,采用arduino+zigbee哦。
arduino簡(jiǎn)單易學(xué),zigbee自組網(wǎng)(如果不懂c語(yǔ)言,直接用就好,我們已經(jīng)刷好自組網(wǎng)代碼)!
這次我們的教程是通過(guò)以下配件實(shí)現(xiàn)《網(wǎng)關(guān)》功能,并在手機(jī)端點(diǎn)擊按鈕,使zigbee模塊上的燈閃亮(實(shí)現(xiàn)是發(fā)送真正的命令了{(lán)ckxxxxxxxxx}的格式)!
通過(guò)不同的格式命令就可以操作開(kāi)、關(guān)、接收、發(fā)送數(shù)據(jù)!之后《溫濕傳感器》《zigbee插座》等就可以直接連上了!
上面就是arduino開(kāi)源網(wǎng)關(guān)的配件。
1、SMARTRF04EB(ZIGBEE下載器)
2、CP2102(arduino下載器)
3、電源供電
4、arduino板(含w5100、zigbee插槽、SD卡座)
5、zigbee開(kāi)發(fā)板 (如果只想學(xué)zigbee只需要兩塊開(kāi)發(fā)板和zigbee模塊,自組網(wǎng)學(xué)習(xí)哦)
6、zigbee模塊
實(shí)現(xiàn)自己的arduino開(kāi)源網(wǎng)關(guān)吧(自己有arduino和w5100是可以代替我們的arduino板的)。
第一部份:arduino板刷上代碼。
一、安裝CP2102驅(qū)動(dòng)(USB驅(qū)動(dòng))
https://pan.baidu.com/s/1o6iDLcm(下載后直接安裝或發(fā)現(xiàn)有新硬件就更新驅(qū)動(dòng))。
二、將CP2102連上arduino板底下的插槽的一定要一一對(duì)應(yīng)哦。DTR->DTR
GND->GND
TX->RXI
RX->TXO
VDD3.3->VCC
三、刷arduino代碼
大家可以直接在這里下載源代碼:
https://pan.baidu.com/s/1i386zPV(包含arduino軟件和所有的庫(kù))
下面我們就貼上代碼(都有注釋哦)
#include <iBoardRF24Network.h>
#include <iBoardRF24.h>
#include <digitalWriteFast.h>
#include <SPI.h>
#include <Ethernet.h>
//請(qǐng)到m.znck007.com申請(qǐng)登陸-》家中環(huán)境-》網(wǎng)關(guān),里可以看到!
#define APIKEY "xxxxxxxxxxxxxxxx" //設(shè)置apikey
uint16_t sid=001;//設(shè)置sid(設(shè)備號(hào))
//NRF24l01發(fā)送接收節(jié)點(diǎn)
const uint16_t this_node = 0;
const uint16_t other_node = 1;
//NRF24l01收發(fā)數(shù)據(jù)
struct payload_t
{
uint32_t ms;
uint32_t data;
char sendchar[20];
};
//NRF24l01腳針設(shè)置
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ā)送次數(shù)
char incomingData[20]={0};//NRF24l01接收到的字符(其它設(shè)置發(fā)過(guò)來(lái))
//設(shè)置MAC地址,如果有二個(gè)請(qǐng)改為不同(隨意)
static byte mymac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetClient client;//聲明網(wǎng)關(guān)類(lèi)
char server[] = "api.znck007.com";//聲明API網(wǎng)址
//char urlBuf[] = "/index.php";
static long timer;//用于規(guī)定時(shí)間間隔
unsigned long last_http;//記錄http時(shí)間,用于http超時(shí)判斷,目前20秒無(wú)響應(yīng)則重新GET。
bool ishttpget=false;//標(biāo)示http是否已經(jīng)結(jié)束
bool isUpdate=false;//成功則更新服務(wù)器數(shù)據(jù)為正常
char updateData[20]={0};//更新的字符(服務(wù)器通過(guò)字符分析指定某個(gè)設(shè)備)
//串口通信處理(主要用于zigbee通信)
unsigned long serialnowlast;
char serialbuff[80]={0};
char serialData;
int seriali=0;
void setup(void)
{
//設(shè)置串口波特率
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服務(wù)器
// 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服務(wù)器是否正常
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檢測(cè)接收數(shù)處理
// //如果使用NRF24l01,請(qǐng)啟動(dòng)這里(并刪除ZIGBEE檢測(cè)接收數(shù)據(jù)處理)
// 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檢測(cè)接收數(shù)據(jù)處理
if(!ishttpget)
{
unsigned long serialnow = millis();//獲取現(xiàn)在的時(shí)間
if(serialnow - serialnowlast >= 5000)//如果數(shù)據(jù)間隔超過(guò)5秒而清空字符(為了防止數(shù)據(jù)錯(cuò)亂)
{
serialnowlast = millis();
memset(serialbuff, 0, 80);
seriali=0;
}
bool isSerial=false;
while( Serial.available() )//如果串口有數(shù)據(jù)(ZIGBEE或電腦發(fā)過(guò)來(lái)的)
{
if(seriali==0)
{
Serial.println("Serial->");//打印出來(lái)方便調(diào)試
}
serialData=(char)Serial.read();//讀取串口數(shù)據(jù)
//Serial.print(serialData);////這里不打印,否則ZIGBEE檢測(cè)到{ckxxxx}就認(rèn)為是命令
serialbuff[seriali]=serialData;////保存到數(shù)組
seriali++;////數(shù)組長(zhǎng)度+1
if(serialData=='}' || seriali>=80)//如果發(fā)現(xiàn)}而說(shuō)明命令結(jié)束(并少于80個(gè)字符,太長(zhǎng)會(huì)出錯(cuò))
{
isSerial=true;
break;
}
}
//開(kāi)始處理{ckxxxxx}字符,如POST上傳到web服務(wù)器
if(isSerial)
{
serialnowlast = millis(); //更新當(dāng)前時(shí)間,不然5秒就超時(shí)了
//Serial.println(serialbuff);
char body[81]={0};
get_html_body(serialbuff,body);//獲取只是{ckxxxxxx}的字符,因?yàn)檫@是我們的命令格式
//Serial.println(body);
Serial.println("-------------------");
//如果命令格式真確則POST到web服務(wù)器了
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到網(wǎng)址,APIKEY,字符
my_result_cb();//接收web服務(wù)器返回的字符
}
memset(serialbuff, 0, 80);//清空字符
seriali=0;//字符長(zhǎng)度為0
return;
}
}
//delay(200);
//更新web服務(wù)器命令的狀態(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到網(wǎng)址,APIKEY,字符
my_result_cb();//接收web服務(wù)器返回的字符
isUpdate=false;
return;
}
//每2秒鐘查看web服務(wù)器是有命令數(shù)據(jù)
unsigned long now = millis();
if(now - last_http >= 2000)
{
if(!ishttpget || (now - last_http) >= 20000)//20秒超時(shí)會(huì)執(zhí)行,為了防卡死問(wèn)題
{
last_http = millis();
ishttpget=true;
Serial.println("n>>> REQ");
static char buf[20]={0};
sprintf(buf,"{ck001000000000}"); //這個(gè)字符串代表獲取新命令數(shù)據(jù)
client_post(server,APIKEY,buf);//POST到網(wǎng)址,APIKEY,字符
my_result_cb();//接收web服務(wù)器返回的字符
timer = millis();
}
}
}
//接收web服務(wù)器返回的字符
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}的字符,因?yàn)檫@是我們的命令格式
//Serial.println(body);
sendChannel=get_channel(body);//獲取是哪個(gè)sid,這是m.znck007.com手機(jī)客服端里的sid
// //如果使用NRF24l01,請(qǐng)啟動(dòng)這里
// 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}的字符,因?yàn)檫@是我們的命令格式
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);
}
//獲取是哪個(gè)sid,這是m.znck007.com手機(jī)客服端里的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字符數(shù)據(jù)到web服務(wù)器
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();
}
}
四、插上網(wǎng)線,打開(kāi)串口就可以測(cè)試聯(lián)網(wǎng)是否成功了!
第二部份:刷zigbee模塊代碼
一、將zigbee模塊插到zigbee開(kāi)發(fā)板上
二、連上SMARTRF04EB下載器。
將一邊有凸出來(lái)的一端與(VDD、RES、NC、DC、GND的NC對(duì)應(yīng)就正確了!
三、安裝SMARTRF04EB驅(qū)動(dòng)
https://pan.baidu.com/s/1dDH1ZX3(安裝SmartRFStudio后里面包含有驅(qū)動(dòng))
提示:如果刷不成功,點(diǎn)擊一下SMARTRF04EB上的RESET(凹進(jìn)去就用筆撮)。
四、安裝IAR 8.1,軟件比較大,安裝后看說(shuō)明破解就好。
https://pan.baidu.com/s/1c0b69Ra(下載解壓里面有安裝說(shuō)明)
五、下載zigbee自組網(wǎng)代碼。
https://pan.baidu.com/s/1COxT8(最新ZStack-CC2530-2.5.1自組網(wǎng)代碼,已經(jīng)寫(xiě)好了按鍵、LED燈功能)
六、點(diǎn)擊編譯并下載。
七、插個(gè)LED到zigbee開(kāi)發(fā)板的P1.0和-。
八、安到arduino板上。
第三步:使用手機(jī)測(cè)試
一、手機(jī)打開(kāi)m.znck007.com手機(jī)控制端。
二、新建一個(gè)開(kāi)關(guān)。
三、點(diǎn)擊開(kāi)關(guān),如果發(fā)現(xiàn)LED燈閃,說(shuō)明《網(wǎng)關(guān)工作正常了》!
OK,《網(wǎng)關(guān)》部份已經(jīng)搞定了,下期我們就來(lái)上《溫濕傳感器》《Zigbee插座》《紅外控制》!
因?yàn)槲覀冞€未使用Wifi,所以都需要與《網(wǎng)關(guān)》交互數(shù)據(jù)哦!
等我們Wifi產(chǎn)品出來(lái)就可以單獨(dú)使用了!