前言:
雖然一路坎坷,但經(jīng)過(guò)近半年的不懈努力,我終于完成了本人在上海大學(xué)申報(bào)的創(chuàng)新項(xiàng)目——智能手機(jī)遙控電燈研究,在此感謝那些給予過(guò)我?guī)椭娜,特別感謝老爸給予的技術(shù)上的幫助。
好東西自然不能獨(dú)享,為了讓大家也能體驗(yàn)一下集物聯(lián)網(wǎng)、智能家居和一大堆現(xiàn)代科技名詞為一體的現(xiàn)代化居家生活,所以決定發(fā)一篇教程,幫助大家用手機(jī)來(lái)遙控電燈(高手請(qǐng)繞道)。
吐槽一下:上海大學(xué)校級(jí)創(chuàng)新項(xiàng)目經(jīng)費(fèi)3000元,武漢大學(xué)1000
廢話不多說(shuō)了,正文開始:
開發(fā)環(huán)境:
采用AVR128單片機(jī),C語(yǔ)言編寫程序,avrstudio4setup.exe4.19 + WinAVR-20100110-install.exe + vr-toolchain編輯、編譯、仿真。
所需器材:
1.USB接口JTAG仿真器+AVR128單片機(jī)(用jtag連接電腦后將后文中的C程序代碼通過(guò)avrstudio4這個(gè)軟件燒寫進(jìn)單片機(jī)的CPU中,至于avrstudio4的使用說(shuō)明網(wǎng)上有很多,這里不再說(shuō)明):

2.SRD-5VDC-SL-C 1路 5V繼電器驅(qū)動(dòng)模塊 :

3.TCP232-T 串口轉(zhuǎn)以太網(wǎng)雙向以太網(wǎng)轉(zhuǎn)串口TCP,IP轉(zhuǎn)串口、RJ45轉(zhuǎn)TTL。

4.智能手機(jī)一部

5.電燈....
1、系統(tǒng)設(shè)計(jì):
智能家居物聯(lián)網(wǎng)控制器
1.AVR128 PORTD, 操作繼電器模塊(后文有開發(fā)板和繼電器的原理圖,及連接方式)
2.AVR128 Usart0 與TCP232-T通訊,接收指令轉(zhuǎn)換PORTD電平
3.繼電器模塊, 實(shí)現(xiàn)火線通斷控制,進(jìn)一部控制電器設(shè)備,本例控制電燈
4.TCP232-T模塊,實(shí)現(xiàn)串行通訊與TCP通訊的通明傳輸。工作模式為Client,TCP協(xié)議,主動(dòng)連接遠(yuǎn)程服務(wù)器。接收AVR128的指令,
遙控端
智能手機(jī),通過(guò)WEB網(wǎng)頁(yè)或者應(yīng)用軟件控制遠(yuǎn)程電燈
2、指令協(xié)議(由遙控端發(fā)送到服務(wù)器,再由服務(wù)器廣播到TCP232-T模塊,再由單片機(jī)進(jìn)行接下來(lái)的控制繼電器部分,最后達(dá)到控制電燈的目的)
1.開燈指令:1212140400DBBF PORTD輸出低電平,繼電器模塊獲得低電位,常開狀態(tài)轉(zhuǎn)換為閉合狀態(tài)
2.關(guān)燈指令:12121404FF9BFF PORTD輸出低電平,繼電器模塊獲得低電位,常開狀態(tài)轉(zhuǎn)換為閉合狀態(tài)
3.查詢燈狀態(tài)指令:12121404AAxxxx 獲取PORTD狀態(tài)并返回。
其中12121404為本例標(biāo)識(shí)。TCP232-T模塊成功連接服務(wù)端后,發(fā)送設(shè)備設(shè)備標(biāo)識(shí)。 本例為12121404,控制指令以12121404起頭。
十六進(jìn)制
實(shí)例
發(fā)送1212140400DBBF
其中12121404為標(biāo)識(shí),00為開燈指令,DBBF為CRC檢驗(yàn)碼(用來(lái)檢驗(yàn)控制端發(fā)送的16進(jìn)制代碼和服務(wù)器端收到的16進(jìn)制代碼是否相同,詳見后文的C程序代碼)
控制器返回[123.4.244.144:20108] 45
其中123.4.244.144為控制器IP地址,20108為控制器TCP端口,45表示指令格式正確,并被正確執(zhí)行
控制器返回[123.4.244.144:20108] 4BDBBF
4BDBBF表示指令標(biāo)識(shí)正確,但是CRC不正確,正確的CRC為DBBF
控制器返回[123.4.244.144:20108] 4B
非指令或者其他錯(cuò)誤。
3、智能家居物聯(lián)網(wǎng)控制器功能設(shè)計(jì)
電源,采用220轉(zhuǎn)5V/200mA統(tǒng)一供電,其他部件由單片機(jī)提供VDD5V和VCC3.3V,單片機(jī)工作在5V狀態(tài)(注意跳線)。
其中TCP232-T 需要50mA才能穩(wěn)定工作,SRD-5VDC-SL-C也需要50mA才能正確動(dòng)作。所以采用獨(dú)立電源。
共地設(shè)計(jì)。
花絮:實(shí)驗(yàn)過(guò)程中,使用計(jì)算機(jī)USB(2.0)供電,單獨(dú)編程實(shí)驗(yàn)繼電器能能正常動(dòng)作,單獨(dú)使用TCP232-T也能正常連接網(wǎng)絡(luò)。聯(lián)合調(diào)試的時(shí)候,繼電器不動(dòng)作。分析原因,起初以為單片機(jī)提供電流有限,負(fù)載能力差,后來(lái)考慮到單片機(jī)本身需要100mA左右電流,隨采用獨(dú)立電源供電,以提供更大電流。實(shí)驗(yàn)成功。
AVR單片機(jī)開發(fā)板
有兩供電方,USB和獨(dú)立電源,并有5V和3.3跳線。本例單片機(jī)工作在5V狀態(tài)。
繼電器模塊電源設(shè)計(jì)
使用5V供電,3個(gè)接線柱,分別為電源正,控制線(低電位有效),電源地。分別連接到電源正,AVR的PORTD口,電源地。
繼電器模塊輸出(連接被控制設(shè)備,本例為電燈電源線中的火線),有3個(gè)接口,中間為公共地,一端為常開狀態(tài),另一端為常閉狀態(tài)。本例使用常開狀態(tài),接收用戶指令,實(shí)現(xiàn)常開和閉和動(dòng)作。
TCP232-T模塊電源設(shè)計(jì)
電源使用5V供電,串行通訊為TTL電平(<3.3V為0,3.5-5V為1。串口為-9V - +9V電平,〈0V為0,〉1V為1。兩種接口不能接錯(cuò)),TTL電平可以直接接單片機(jī)端口。
如果是TTL電平,直接POARTE0和POARTE1,如果是串口模塊,接單片機(jī)開發(fā)板串口。串口只使用2,3,5三根線。
4、原理圖
AVR開發(fā)板
PORTD接繼電器模塊,為簡(jiǎn)單,寫端口0x00或者0xFF,以控制端口電平,實(shí)現(xiàn)控制繼電器動(dòng)作。
PORTE接8個(gè)LED,一般用來(lái)在開發(fā)過(guò)程中指示工作狀態(tài),本例最終版本無(wú)用。
POARTE0和POARTE1接TTL電平的TCP232-T模塊的TXD和RXD
POARTE0和POARTE1另外設(shè)計(jì)連接MAX232轉(zhuǎn)換芯片和接口,供串口設(shè)備通訊。
USART1接485轉(zhuǎn)換口
另有電源總開關(guān)、復(fù)位鍵和4個(gè)鍵盤。
繼電器模塊
輸入端,分別接電源正,PORTD任意一個(gè),和電源地
輸出端,使用常開接口,只能控制1條線路。其他空置懸空。
電源,電源正接VDD,電源地接GND。
TCP232-T模塊
? RJ45接口,標(biāo)準(zhǔn)的網(wǎng)口,使用1、2、3、6四根線
? 串口端,TTL電平,RXD接POARTE0,POARTE1接TXD
? 電源,電源正接VDD,電源地接GND。
? CFG空置,如果被拉底,比如接GND,則模塊工作于串口設(shè)置模式,不響應(yīng)網(wǎng)絡(luò)連接。
5、使用說(shuō)明
服務(wù)器:
本軟件使用VB編寫
Modbus協(xié)議規(guī)定的傳輸媒介有串行總線和以太網(wǎng)兩種,其中串行總線規(guī)定了ASCII模式和RTU模式兩種傳輸方式。本軟件以GB/T19582-2008為藍(lán)本,實(shí)現(xiàn)Modbus協(xié)議的TCP模式、ASCII模式和RTU模式之間相互轉(zhuǎn)換;并將UDP協(xié)議納入TCP模式,實(shí)現(xiàn)廣播通訊;模擬應(yīng)答,沒有物理設(shè)備也可以調(diào)試系統(tǒng)。擴(kuò)展了TCP模式,開發(fā)出微型Webserver,實(shí)現(xiàn)了3種模式與HTTP協(xié)議之間的轉(zhuǎn)換,使通用瀏覽器(比如Window 的IE或者Andriod 的瀏覽器)成為控制器。

外部接口:
RJ45 ,網(wǎng)口
J1,控制線,23公共,1為常開,4為常閉?梢钥刂250V以下電壓,2A電流。
電源,5V
開關(guān),總電源開關(guān)
網(wǎng)絡(luò)接口設(shè)置:
本例使用RJ45口網(wǎng)絡(luò)配置,專用軟件。工作于Client模式,通過(guò)有線內(nèi)部網(wǎng)絡(luò),連接公網(wǎng)SERVER。根據(jù)網(wǎng)絡(luò)環(huán)境,設(shè)置靜態(tài)IP,不支持DHCP。
可設(shè)置本機(jī)IP,網(wǎng)關(guān),端口20108,和遠(yuǎn)程SERVER地址和端口8234。心跳設(shè)計(jì),斷網(wǎng)自動(dòng)連接。
智能手機(jī)TCP應(yīng)用軟件模式:
用于局域網(wǎng)和廣域網(wǎng),本例為安卓應(yīng)用軟件
網(wǎng)上找到有個(gè)叫easytcp的軟件比較好使,可以配合SERVER使用
智能手機(jī)WEB模式(不太穩(wěn)定):
用于廣域網(wǎng),本例為通用瀏覽器,支持HTML即可。HTTP協(xié)議,端口9000。
6、程序設(shè)計(jì)
控制器采用C設(shè)計(jì)
這里給出核心代碼
//*************************************************************************
// 繼電器模塊編程設(shè)計(jì)
//*************************************************************************
#define Lamp_IO PORTD //繼電器模塊所在數(shù)據(jù)口
#define Lamp_DDR DDRD //方向寄存器
Lamp_IO=0xFF; //數(shù)據(jù)口為輸出
Lamp_DDR=0xFF;
if((data_buf[RX_length-1]==0xFF) ||(data_buf[RX_length-1]==0x00))
{
usart_send(0x45); //將接收到的數(shù)據(jù)再發(fā)出去
Lamp_Display(data_buf[RX_length-1]); //寫PORTD,控制繼電器模塊,繼電器低電平有效,0xFF為關(guān)燈,0x00為開燈
}
//*************************************************************************
// USART通訊設(shè)計(jì)
//*************************************************************************
//由于采用通明傳輸,因此本例只涉及USART通訊編程,使用USART0,也就是PORTE0和PORTE1。
//初始化
#define baud 9600 //設(shè)置波特率的大小
#define baud_setting (uint)((ulong)F_CPU/(16*(ulong)baud)-1) //波特率計(jì)算公式
#define baud_h (uchar)(baud_setting>>8) //提取高位
#define baud_l (uchar)(baud_setting) //低位
void usart_init()
{
UCSR0A=0x00; //單倍速模式
UCSR0B=0xF8; //接收中斷和發(fā)送中斷允許
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00); //寫UCSRC寄存器,異步通信無(wú)校驗(yàn),8位數(shù)據(jù)1位停止位
UBRR0H=baud_h; //寫波特率的值
UBRR0L=baud_l;
}
//發(fā)送數(shù)據(jù)
void usart_send(uchar data)
{
while( !( UCSR0A & (1<<UDRE0)) ); //等待發(fā)送緩沖器為空
UDR0 = data; //接收到的數(shù)據(jù)再發(fā)回電腦
delay_ms(2);
}
//數(shù)據(jù)接收結(jié)束中斷向量
SIGNAL(SIG_USART0_RECV) //中斷服務(wù)程序
{
uchar RxTemp;
RxTemp=UDR0; //將接收到的數(shù)據(jù)取出
usart_rx_data[RxReadIndex]=RxTemp;
if(++RxReadIndex> Rx_Buf_Size) //如果寫接收緩沖區(qū)索引大于接收緩沖區(qū)的長(zhǎng)度
RxReadIndex=0; //則索引重新清0
rx_flag=1;
}
//*************************************************************************
// CRC檢驗(yàn)和判斷
//*************************************************************************
uint get_crc(uint n)
{
uchar i,j;
CRC_word=0xffff;//賦值:0xffff
for(i=0;i<n;i++)
{
CRC_word^=(uint)data_buf[i];//計(jì)算CRC_word
for(j=0;j<8;j++)
{
if(CRC_word&0x0001)
{
CRC_word=CRC_word>>1;
CRC_word^=0xa001;
}
else
{
CRC_word>>=1;
}
}
}
return CRC_word;
}
判斷
RX_length=RxReadIndex-2;//*256+data_buf[3];//取數(shù)據(jù)長(zhǎng)度數(shù)據(jù)
RX_CRC_word=data_buf[RX_length+1]*256+data_buf[RX_length];//取CRC校驗(yàn)碼
CRC_word=get_crc(RX_length);//計(jì)算接收數(shù)據(jù)校驗(yàn)碼
if(CRC_word==RX_CRC_word)//校驗(yàn)數(shù)據(jù)比較
{}
兩位CRC碼提取
(CRC_word%256);
(CRC_word/256);
//*************************************************************************
// 主程序
//*************************************************************************
int main(void)
{
system_init(); //系統(tǒng)初始化
usart_init(); //usart串口初始化配置
SREG|=0x80; //開啟全局中斷
while(1)
{
_delay_ms(50); //為串口中斷方式延遲,這個(gè)很重要,本例通訊數(shù)據(jù)少,因此設(shè)置50
if((RxReadIndex>0) && (rx_flag==1))
{
cli(); //全局中斷無(wú)效,同SREG=0x00;
RX_data=&usart_rx_data[0];//指針接收數(shù)組首地址
for(read_count=0;read_count<RxReadIndex;read_count++)//copy
{
data_buf[read_count]=*RX_data++;
usart_send(data_buf[read_count]);
}
receive_code_fun();
_delay_us(5);
RxReadIndex=0;//接收中斷次數(shù)清零
rx_flag=0;
sei();//開全局中斷,同SREG|=0x80;
}
}
}
server采用VB設(shè)計(jì)
使用控件,創(chuàng)建微WEB服務(wù)器,接受并解析HTTP協(xié)議,執(zhí)行指令后返回HTML數(shù)據(jù)流。
指令只轉(zhuǎn)發(fā)給受控制端。
主頁(yè)源代碼如下:
===========================
<html>
<head>
<title>MODBUS調(diào)試 --- 上海大學(xué) 陳歌</title>
</head>
<body>
<imgsrc="/img/shu.gif">MODBUS協(xié)議轉(zhuǎn)換助手
<form name="f"action="modbus.html" method=post>
ID<input type="text"name="ID" maxlength="30" >
地址<input type="text" name="AD"maxlength="30" ><br>
數(shù)據(jù)<input type="text" name="DATA_LEN"maxlength="50" >
<select name="FUNC">
<option value ="01">讀開關(guān)量</option>
<option value ="02">02</option>
<option value="03">讀寄存器</option>
<option value="04">04</option>
</select>
<input type="submit"value="執(zhí)行" ></form>
<textarea rows="10"cols="50">
這里顯示的是,返回?cái)?shù)據(jù)
</textarea>
<form name="N"action="modbus.html" method=post>
普通數(shù)據(jù)發(fā)送<input type="text" name="post_send_str"maxlength="80" >
<select name="hexstr">
<option value ="16">16進(jìn)制</option>
<option value ="01">字符串</option>
</select>
<input type="submit"value="發(fā)送" ></form>
</form>
</body>
</html>
==================================