13
本帖最后由 brantsun 于 2016-8-21 17:52 编辑
一,项目概述
智能产品未来的发展,首先就需要致力于改变消费者“不必要”的消费习惯,通过威廉希尔官方网站
的进步从而让产品的价格也开始有竞争力,良好的市场推广和简单易上手的APP支持,才能让产品更好地与市场融入。而智能家居的发展在未来也是非常火的,未来家装智能家居是不可缺少的产品,我们的作品,智能家庭中央控制系统,意在用一块小的嵌入式板子就能作为整个家庭控制网络的核心,当然是可以实现的。
材料:香蕉派,路由器,温湿度传感器,一氧化碳传感器,STM32f103,24L01无线通讯模块,八通路继电器,风扇,有刷电机。
二 ,项目实现过程
1.首先我们需要给香蕉派刷好Debian系统。(具体点击链接查看)
2我们需要配置好我们的香蕉派上的服务器环境以及设置好静态IP。
3.将自己写好的网站部署到自己的香蕉派服务器上。
4.建立起与部署好的网站所需要的数据---数据库的搭建。
5.配置好所有需要的gpio口,写好相关模块的驱动程序,并且加入到开机自启动。
6.配置好开机权限的自动给予,并且先用php座位后台进行测试。
7.后台全新升级,使用jsp。
好了,我们来说说我们最终的作品吧!我们最终的作品采用了jsp作为后台。
首先,登录页面,没有账号的话可以注册,用户名相同无法注册,当输入完用户名后会触发数去焦点事件,然后,通过AJAX和后台通讯,查询数据库。
打开的首页:
用户登录平台:
用户注册界面:
登陆成功后会到我们的传感器信息显示页面:
(这里显示的都是我们的所有传感器的测量的信息)
然后大家可以点击添加设备,会有下面这些设备:
添加完设备后点击我的设备:
(这就是我们刚才添加的设备)
同时我们还可以添加和修改自己的信息:
那么一以上就是我们整个电脑端的介绍
8.客户端的实现
这是我们最初做的一款app,只实现了开关量的控制:
网页的附件:用压缩软件解压zip后得到war格式的文件再用解压软件解压就好了:
后来我们加上了生活信息的显示,连接上香蕉派服务器后就能显示了,如果有燃气泄漏则客户单会报警,发出声音:
apk附件:
9.这是stm32和温湿度传感器,一氧化碳传感器2.4g无线通讯模块,二通路驱动模块,风扇和窗帘。
(
香蕉派部分:
为了极大的利用香蕉派,风扇和窗帘我们使用了香蕉派控制的。
窗帘:使用了一个有刷减速电机和三个红外距离传感器,减速电机主要控制窗帘的卷起和放下,红外距离传感器主要是用来检测窗帘当前所在的位置。
风扇:我们是使用了香蕉派产生的一路pwm来控制的。( link:用香蕉派产生硬件pwm。)
24L01无线模块:和stm32 单片机通讯。
stm32部分:
24L01无线模块:和香蕉派通讯。
温湿度传感器:测量当前室内的温湿度。
一氧化碳传感器:检测是否有燃气泄漏。
led:检测是否和香蕉派连接成功,如果成功会规律的闪烁。
)
我们的香蕉派会每3秒去读取数据库,将读取的数据发送给单片机;
- #include
- #include
- #include "/usr/include/mysql/mysql.h"
- extern int d1,d2,d3,d4;
- void mysqlupdate(void) {
- MYSQL my_connection;
- int res;
- char txt[70];
- sprintf(txt,"update ths set tem=%d,hum=%d,smok=%d,watertemp=%d",d1,d2,d3,d4);
- printf("%s",txt);
- mysql_init(&my_connection);
- if (mysql_real_connect(&my_connection, "localhost","root", "root","users", 0, NULL, CLIENT_FOUND_ROWS))
- {
- printf("Connection successn");
- res = mysql_query(&my_connection, txt);
- if(!res)
- {
- printf("inserted %lu rowsn",(unsigned long)mysql_affected_rows(&my_connection));
- }
- else
- {
- fprintf(stderr, "Insert error %d: %sn",mysql_errno(&my_connection),mysql_error(&my_connection));
- }
- mysql_close(&my_connection);
- }
- else
- {
- fprintf(stderr, "Connection failedn");
- if (mysql_errno(&my_connection))
- {
- fprintf(stderr, "Connection error %d: %sn",mysql_errno(&my_connection),mysql_error(&my_connection));
- }
- }
- }
- int readmysql(char *a){
- MYSQL mysql;//mysql connection
- MYSQL_RES *res;
- MYSQL_ROW row;
- char *query;
- char *string;
- int t,r,b;
- char text[70];
- sprintf(text,"select * from equstate where equname='%s'",a);
- //printf("%s",text);
- mysql_init(&mysql);
- if(mysql_real_connect(&mysql, "localhost","root", "root","users", 0, NULL, CLIENT_FOUND_ROWS)){
- // query="select * from equstate where equname='' ";
- t=mysql_query(&mysql,text);
- if(t)
- {
- printf("err:%s",mysql_error(&mysql));
- }
- res=mysql_store_result(&mysql);
- while(row=mysql_fetch_row(res))
- {
- // for(t=0;t
- // {
- // printf("%st",row[2]);
- // }
- // printf("n");
- b=atoi(row[2]);
- // printf("%dn",b);
- }
- mysql_free_result(res);
- mysql_close(&mysql);
- }
- else{
- fprintf(stderr, "Connection failedn");
- if (mysql_errno(&mysql))
- {
- fprintf(stderr, "Connection error %d: %sn",mysql_errno(&mysql),mysql_error(&mysql));
- }
- }
- return b;
- }
复制代码
这里大家可能会遇到一个问题,就是装完mysql后,在编译程序时并不能找到mysql的c库;
例如: #include "/usr/include/mysql/mysql.h"会出错。
怎样解决?
这样:
- apt-get install libmysqlclient-dev
复制代码
安装完库后就可以使用了。
24L01的驱动,通过C语言gpio库写的:
- #include "pyinclude.h"
- #include "NRF24L01.h"
- /***************************************************************
- //模块名称:NRF24L01无线模块
- //功 能:数据收发
- // -----------------
- // | |
- // | PD6|--->CE
- // | PD7|--->CSN
- // | PD8|--->SCK
- // | PD9|-->MOSI
- // | PD10|<--MISO
- // | PD11|<--IRQ
- // | |
- // -----------------
- ****************************************************************/
- uchar TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x11,0x11,0x11}; //本地地址
- uchar RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
- /*******************************************************************
- //函数名称:void NRF24L01_IO_set(void)
- //函数功能:NRF24L01引脚初始化
- //参 数:无
- //返 回 值:无
- ********************************************************************/
- void NRF24L01_IO_set(void)
- {
- RF24L01_CE;
- RF24L01_CSN;
- RF24L01_SCK;
- RF24L01_MOSI;
- RF24L01_MISO;
- RF24L01_IRQ;
- }
- /*******************************************************************
- //函数名称:SPI_RW()
- //函数功能:完成GPIO模拟SPI的功能,将输出字节(MOSI)从MSB循环输出
- // 同时将输入字节(MISO)从LSB循环移入,上升沿读入,下降沿
- // 输出。(从SCK被初始化为低电平可以判出)
- //参 数:byte(字节)
- //返 回 值:byte
- ********************************************************************/
- uchar SPI_RW(uchar data)
- {
- uchar i,temp=0;
- for(i=0;i<8;i++) // output 8-bit
- {
- if((data & 0x80)==0x80)
- {
- RF24L01_MOSI_1; // output 'uchar', MSB to MOSI
- }
- else
- {
- RF24L01_MOSI_0;
- }
- data = (data << 1); // shift next bit into MSB..
- temp<<=1;
- RF24L01_SCK_1; // Set SCK high..
- if((RF24L01_MISO_PIN)==1)temp++; // capture current MISO bit
- RF24L01_SCK_0; // ..then set SCK low again
- }
- return(temp); // return read uchar
- }
- /*******************************************************************
- //函数名称:void inerDelay_us(uchar n)
- //函数功能:n 延时数
- //参 数:无
- //返 回 值:无
- ********************************************************************/
- void inerDelay_us(uchar n)
- {
- for(;n>0;n--);
- }
- /****************************
- //函数名称:SPI_Read()
- //函数功能:读取寄存器的值
- //参 数:reg(寄存器)
- //返 回 值:reg_val(寄存器值)
- *****************************/
- uchar SPI_Read(uchar reg)
- {
- uchar reg_val;
- RF24L01_CSN_0; // CSN low, initialize SPI communication...
- SPI_RW(reg); // Select register to read from..
- reg_val = SPI_RW(0); // ..then read registervalue
- RF24L01_CSN_1; // CSN high, terminate SPI communication
- return(reg_val); // return register value
- }
- /******************************************************************
- //函数名称:SPI_RW_Reg()
- //函数功能:寄存器访问函数,把设定的值写进相应的寄存器,并读取返回值
- //参 数:reg(寄存器选择),value(设定值)
- //返 回 值:status
- ********************************************************************/
- uchar SPI_RW_Reg(uchar reg, uchar value)
- {
- uchar status1;
- RF24L01_CSN_0; // CSN low, init SPI transaction
- status1 = SPI_RW(reg); // select register
- SPI_RW(value); // ..and write value to it..
- RF24L01_CSN_1; // CSN high again
- return(status1); // return nRF24L01 status uchar
- }
- /********************************************************
- //函数名称:uchar SPI_Read_Buf()
- //函数功能:接收时读取FIFO缓冲区的值
- //参 数:reg(寄存器),*pBuf(数据存储),bytes(字节数)
- //返 回 值:status
- *********************************************************/
- uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar chars)
- {
- uchar status2,uchar_ctr;
- RF24L01_CSN_0; // Set CSN low, init SPI tranaction
- status2 = SPI_RW(reg); // Select register to write to and read status uchar
- for(uchar_ctr=0;uchar_ctr
- {
- pBuf[uchar_ctr] = SPI_RW(0);
- }
- RF24L01_CSN_1;
- return(status2); // return nRF24L01 status uchar
- }
- /***********************************************************
- //函数名称:SPI_Write_Buf()
- //函数功能:发射缓冲区访问,把数组里的数放到FIFO缓冲区中
- //参 数:reg(寄存器选择),*pBuf(待写数据,bytes(字节数))
- //返 回 值:status NRF24L01状态位
- ************************************************************/
- uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar chars)
- {
- uchar status1,uchar_ctr;
- RF24L01_CSN_0; //SPI使能
- status1 = SPI_RW(reg);
- for(uchar_ctr=0; uchar_ctr
- {
- SPI_RW(*pBuf++);
- }
- RF24L01_CSN_1; //关闭SPI
- return(status1); //
- }
- /**************************
- //函数名称:RX_Mode()
- //函数功能:设定为接收模式
- //参 数:无
- //返 回 值:无
- ***************************/
- void RX_Mode(void)
- {
- RF24L01_CE_0;
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH);
-
- SPI_RW_Reg(WRITE_REG + EN_AA,0X01); //Enable Auto.ACK:Pipe0
- SPI_RW_Reg(WRITE_REG + EN_RXADDR,0X01); //Enable Pipe0
- SPI_RW_Reg(WRITE_REG + RF_CH,40); //Selsct RF channl 40
- SPI_RW_Reg(WRITE_REG + RX_PW_P0,TX_PLOAD_WIDTH);
- SPI_RW_Reg(WRITE_REG + RF_SETUP,0X0f);
- SPI_RW_Reg(WRITE_REG + CONFIG,0X0f); //Set PWR_UP bit ,enable CRC(2bytes)&Prim:RX.RX_DR enabled
- RF24L01_CE_1; //Set CE pin high to enable RX device
- }
- /*****************************
- //函数名称:TX_Mode()
- //函数功能:设定24L01发送方式
- //参 数:无
- //返 回 值:无
- ******************************/
- void TX_Mode(void)
- {
- RF24L01_CE_0;
- SPI_Write_Buf(WRITE_REG + TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0,TX_ADDRESS,TX_ADR_WIDTH);
-
- SPI_RW_Reg(WRITE_REG + EN_AA,0X01); //Enable Auto.Ack:Pipe0
- SPI_RW_Reg(WRITE_REG + EN_RXADDR,0X01); //Enable Pipe0
- SPI_RW_Reg(WRITE_REG + SETUP_RETR,0X1a); //500us + 80us,10 retrans
- SPI_RW_Reg(WRITE_REG + RF_CH,40); //Select RF channal 40
- SPI_RW_Reg(WRITE_REG + RF_SETUP,0X0f); //TX_PWR:0dBm,Datarate:2Mbps,LNA:HCURR
- SPI_RW_Reg(WRITE_REG +CONFIG,0X0e); //Set PWR_UP bit,enable CRC(2bytes)&Prim:TX.MAX_RT&TX_DS enabled
- RF24L01_CE_1;
- inerDelay_us(130); //注意不能太小
- }
- //****************************************************************************************************/
- //函数:void SetRX_Mode(void)
- //功能:数据接收配置
- //****************************************************************************************************/
- void SetRX_Mode(void)
- {
- RF24L01_CE_0 ;
- SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // IRQ收发完成中断响应,16位CRC ,主接收
- RF24L01_CE_1;
- inerDelay_us(130); //注意不能太小
- }
- /*******************************************************************
- //函数名称:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
- //函数功能:数据读取后放入rx_buf接收缓冲区中
- //参 数:*rx_buf(待收数据)
- //返 回 值:revale (完成标志)
- ********************************************************************/
- uchar nRF24L01_RxPacket(uchar* rx_buf)
- {
- uchar revale=0;
- uchar sta;
- sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况
- if(sta&0x40) // 判断是否接收到数据
- {
- RF24L01_CE_0 ; //SPI使能
- SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH); // read receive payload from RX_FIFO buffer
- SPI_RW_Reg(FLUSH_RX,0xff);
- revale =1; //读取数据完成标志
- }
- SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
- return revale;
- }
- /*************************************************
- //函数名称:void nRF24L01_TxPacket(char * tx_buf)
- //函数功能:发送 tx_buf中数据
- //参 数:*tx_buf(待发数据)
- //返 回 值:无
- ***************************************************/
- uchar nRF24L01_TxPacket(uchar * tx_buf)
- {
- uchar revale=0;
- uchar sta;
- RF24L01_CE_0 ; //StandBy I模式
- // SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址
- SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据
- //SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送
- RF24L01_CE_1; //置高CE,激发数据发送
- while ((RF24L01_IRQ_PIN)!=0);
- sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况
- SPI_RW_Reg(WRITE_REG+STATUS,sta);//通过写1来清楚中断标志
- SPI_RW_Reg(FLUSH_TX,0xff);
- if(sta&MAX_RT)
- return MAX_RT; //达到最大重发次数
- else if(sta&TX_DS) //发送完成
- return TX_DS;
- else
- return revale; //其他原因发送失败
- //inerDelay_us(10);
- }
- /********************************
- //函数名称:init_NRF24L01()
- //函数功能:NRF24L01初始化
- //参 数:无
- //返 回 值:无
- *********************************/
- void init_NRF24L01(void)
- {
- //inerDelay_us(100);
- NRF24L01_IO_set();
- RF24L01_CE_0 ; // chip enable
- RF24L01_CSN_1; // Spi disable
- RF24L01_SCK_0; // Spi clock line init high
- SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址
- SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动 ACK应答允许
- SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21
- SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 设置信道工作为2.4GHZ,收发必须一致
- SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
- SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0f); //设置发射速率为1MHZ,发射功率为最大值0dB
- SPI_RW_Reg(WRITE_REG + CONFIG, 0x0E); // IRQ收发完成中断响应,16位CRC ,主接收
- }
- /********************************
- //函数名称:uchar NRF24L01_Check(void)
- //函数功能:检查NRF24L01是否连接
- //参 数:无
- //返 回 值:0连接成功;1连接失败
- *********************************/
- uchar NRF24L01_Check(void)
- {
- uchar buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
- uchar i;
- SPI_Write_Buf(WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.
- SPI_Read_Buf(TX_ADDR,buf,5); //读出写入的地址
- for(i=0;i<5;i++)if(buf[i]!=0XA5)break;
- if(i!=5)return 1; //检测24L01错误
- return 0; //检测到24L01
- }
复制代码
在linux下编译的时候要这样:
- objects = test24L01.o pyinclude.o NRF24L01.o gpio_lib.o testmysql.o
- start : $(objects)
- gcc -lmysqlclient -o start $(objects)
- test24L01.o : NRF24L01.h pyinclude.h gpio_lib.h testmysql.h
- NRF24L01.o : NRF24L01.h pyinclude.h gpio_lib.h
- pyinclude.o : pyinclude.h gpio_lib.h
- gpio_lib.o : gpio_lib.h
- testmysql.o: /usr/include/mysql/mysql.h
- .PHONY : clean
- clean :
- -rm start $(objects)
复制代码
同时需要注意有些地方的缩进,不然会报错。makefile是非常严格的。
两个部分的 电路:
单片机的代码:
很遗憾我们现在没有能将香蕉派连接到外网,我们做好了单片机端的微信控制,我们后续有更新我们会及时发帖分享的。
整个系统的控制就涉及到了HTTP协议,喜欢的朋友们可以去了解了解GET 和POST请求,我们就是通过get和post请求来控制的,只需自己定制一套通讯协议就可实现。由于快到结贴时间了,现在也比较忙,我先结贴,之后的帖子我会给大家详细介绍如何去实现控制,当然后台是最重要的,一定要掌握一门后台语言!同时也非常感谢 电子发烧友 论坛的活动,从这次活动中我学到了很多东西,收获很大,后续我会陆续将我的收获分享给大家。
|
评分
-
查看全部评分
|