RPI向小车迈进01:结合web服务的GPIO实验
本帖最后由 wing 于 2014-2-18 11:20 编辑本次实验的目前是通过web服务用网页方式控制RPI的GPIO,点亮LED或者关掉它.
包括web服务在内全部用c来写.写个web服务不是一件很难的事情,像Apache,nginx之类的现成架构太过臃肿和RPI纤细的身材不太相衬,
控制GPIO方面使用了wiringPi库,下文会介绍如何安装这个库,如想深入了解可以访问http://wiringpi.com/
开发工具使用qtcreator,为了和vi党划清界线这个是首选(不要跟我提月食,这里不是暮光之城).
第一步,我们来安装qtcreator,
步骤很简单只要执行命令
sudo apt-get install qtcreator
这个过程可能需要点时间,总共会下载过百兆的内容,请保证RPI的网络通畅和有充足的电能(如果你是用电池的话)
安装完成后,用root身份运行qtcreator,
初次启用需要设置下 toolchain
Tools > Options > build & run >tool chain >add 选择 GCC
本次实验是通过wiringPi来控制GPIO,为了安装方便首先准备GIT,如果你已经安装了GIT这一步可以跳过.
sudo apt-get install git-core
如果安装过程中出现问题,可以用以下命令修复
sudo apt-get update
sudo apt-get upgrade
安装完GIT后我们来克隆wiringPi
git clone git://git.drogon.net/wiringPi
cd wiringPi
git pull origin
cd wiringPi
./build
完成之后可以使用下面的命令来测试下
gpio -v
gpio readall
正常情况下可以获取到软件版本和所有GPIO当前的状态
好了,到目前为止已经万事具备,那么我们来写程序.
在qtcreator建立一个非qt项目,选择一个用qmake的纯c工程
代码
#include<sys/socket.h>
#include<errno.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include <wiringPi.h>
#define BUF_LEN 1028
#define SERVER_PORT 8001
#define pinNumber 7
//404找不到指定资源的头部信息
const static char http_head_error[] = "HTTP/1.1 404 Not Found\r\nContent-type: text/html\r\n\r\n";
//200成功的头部信息
const static char http_head_ok[] = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
//LED关灯页面
const static char http_body_off[] =
"<html><head><title>RPI_led</title></head>"
"<body><h1>LED 7 is off</h1>"
"<div/><input type='button' value=led_ON onclick=\"location.href='ledon.act';\" />"
"<p><input type='button' value=led_OFF onclick=\"location.href='ledoff.act';\" />"
"</body></html>";
//LED开灯页面
const static char http_body_on[] =
"<html><head><title>RPI_led</title></head>"
"<body><h1>LED 7 is on</h1>"
"<div/><input type='button' value=led_ON onclick=\"location.href='ledon.act';\" />"
"<p><input type='button' value=led_OFF onclick=\"location.href='ledoff.act';\" />"
"</body></html>";
//解析到HTTP请求的文件后,发送相应的网页信息
int http_send_file(char *filename, int sockfd)
{
if((strcmp(filename, "/ledon.act")==0)||(strcmp(filename, "/ledoff.act")==0)){
//通过write函数发送http响应报文;报文包括HTTP响应头和响应内容--HTML内容
write(sockfd, http_head_ok, strlen(http_head_ok));
if (strcmp(filename, "/ledon.act")==0){
write(sockfd, http_body_on, strlen(http_body_on));
//点亮LED...
digitalWrite(pinNumber, 1);
}
if (strcmp(filename, "/ledoff.act")==0){
write(sockfd, http_body_off, strlen(http_body_off));
//关闭LED...
digitalWrite(pinNumber, 0);
}
}
else{
//未找到情况下发送404error响应
write(sockfd, http_head_error, strlen(http_head_error));
}
return 0;
}
//HTTP请求解析
void serve(int sockfd){
char buf;
read(sockfd, buf, BUF_LEN);
if(!strncmp(buf, "GET", 3)){
char *file = buf + 4;
char *space = strchr(file, ' ');
*space = '\0';
http_send_file(file, sockfd);
}
}
void main(){
//初始化wiringPi
if (-1 == wiringPiSetup()) {
return;
}
//设置为输出端口
pinMode(pinNumber, OUTPUT);
int sockfd,err,newfd;
struct sockaddr_in addr;
//建立TCP套接字
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
return;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
//这里要注意,端口号一定要使用htons先转化为网络字节序,否则绑定的实际端口
addr.sin_port = htons(SERVER_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in))){
return;
}
listen(sockfd, 128);
while(1){
//不间断接收HTTP请求并处理,这里使用单线程
newfd = accept(sockfd, NULL, NULL);
serve(newfd);
close(newfd);
}
}
.pro
如果想在qtcreator上顺利编译还要添加 -lwiringPi编译连接
最后来Build下工程,现在已经完成了一个完整的程序了,是完全用IDE写程序的,至此终于可以和vi党划清界限了
什么你也是vi党!!那我就假装是用vi写的程序,然后用下面命令编译
gcc main.c -o http_gpio_test -lwiringpi
注意GPIO定义图,接上LED,
用下面的命令查下RPI的IP地址
ifconfig
root身份运行程序,访问 http://192.168.1.21:8001/ledoff.act 测试下吧
下面视频是在手机上测试的效果
http://player.youku.com/player.php/sid/XNjY4NzgzODky/v.swf 用python做服务器吧。。。这样太折腾了— —。。。树莓派的能力还是挺强的。。。 就是因为没人用qt手写web服务所以我才敢发出来的 我认真看了,楼主写的非常详细非常认真,在下佩服佩服。
楼主的程序熟练应用了 SOCKET,处理了GET方法,然后根据 GET方法之后的URI载入ledoff或者ledon等静态界面。可以说楼主对WEB网页和底层的结合还是有很深的见解的。
但是也给楼主提点意见
第一:虽然是LED动态控制,但是还是静态网页,每次按钮总是重新载入页面。这样就不能有效利用ajax这些异步技术了。
第二:我也建议使用python,充分利用python flask框架。当然安装apache服务器的话,树莓派的网页开发就是LAMP开发没什么两样了。
两点意见,仅供参考。再次佩服楼主的认真精神。 xukai871105 发表于 2014-2-6 20:41 static/image/common/back.gif
我认真看了,楼主写的非常详细非常认真,在下佩服佩服。
楼主的程序熟练应用了 SOCKET,处理了GET方法, ...
感谢你的认真阅读和意见 ,
关于第一点: 我的下一个实验是关于PWM的 , 有望用上ajax和html5 .
关于第二点: 我也相信python是RPI的首选开发语言 ,
不过"RPI向小车迈进"这一系列的开发环境已经确定了qtcreator+c+web的开发环境 ,
后续的内容也不打算改变了 . 楼主你可以把你硬件清单放出来吗,我也想搞 qykings 发表于 2014-2-20 12:45 static/image/common/back.gif
楼主你可以把你硬件清单放出来吗,我也想搞
这个实验硬件很少的,
一个LED和一个470欧电阻,
接线方式是 : RPI 的GPIO 7 -> 电阻 -> LED 正极
RPI的GND ->LED 负极 wing 发表于 2014-2-7 11:58 static/image/common/back.gif
感谢你的认真阅读和意见 ,
关于第一点: 我的下一个实验是关于PWM的 , 有望用上ajax和html5 .
关于你的第二点,我很赞同这样做。
这样做更贴近TCP IP协议本身,以后再弄ajax,RESTFul,CoAP的话,会理解的深刻的多! wing 发表于 2014-2-20 16:06 static/image/common/back.gif
这个实验硬件很少的,
一个LED和一个470欧电阻,
接线方式是 : RPI 的GPIO 7 -> 电阻 -> LED 正极
谢楼主,我搞用c写几行代码实现了电机 驱动http://pan.baidu.com/s/1jGt7Pbg
页:
[1]