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

2.SRD-5VDC-SL-C 1路 5V繼電器驅動模塊 :

3.TCP232-T 串口轉以太網雙向以太網轉串口TCP,IP轉串口、RJ45轉TTL。

4.智能手機一部

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

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