极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 15100|回复: 9

RPI向小车迈进01:结合web服务的GPIO实验

[复制链接]
发表于 2014-2-4 17:32:57 | 显示全部楼层 |阅读模式
本帖最后由 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工程



代码
[pre lang="c" line="1"]#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[BUF_LEN];
    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);
    }
}
[/code]

.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 测试下吧





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2014-2-4 17:37:09 | 显示全部楼层
下面视频是在手机上测试的效果
回复 支持 反对

使用道具 举报

发表于 2014-2-5 22:17:24 | 显示全部楼层
用python做服务器吧。。。这样太折腾了— —。。。树莓派的能力还是挺强的。。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-6 09:07:10 | 显示全部楼层
就是因为没人用qt手写web服务所以我才敢发出来的
回复 支持 反对

使用道具 举报

发表于 2014-2-6 20:41:53 | 显示全部楼层
我认真看了,楼主写的非常详细非常认真,在下佩服佩服。

楼主的程序熟练应用了 SOCKET,处理了GET方法,然后根据 GET方法之后的URI载入ledoff或者ledon等静态界面。可以说楼主对WEB网页和底层的结合还是有很深的见解的。

但是也给楼主提点意见
第一:虽然是LED动态控制,但是还是静态网页,每次按钮总是重新载入页面。这样就不能有效利用ajax这些异步技术了。
第二:我也建议使用python,充分利用python flask框架。当然安装apache服务器的话,树莓派的网页开发就是LAMP开发没什么两样了。

两点意见,仅供参考。再次佩服楼主的认真精神。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-7 11:58:58 | 显示全部楼层
xukai871105 发表于 2014-2-6 20:41
我认真看了,楼主写的非常详细非常认真,在下佩服佩服。

楼主的程序熟练应用了 SOCKET,处理了GET方法, ...

感谢你的认真阅读和意见 ,

关于第一点: 我的下一个实验是关于PWM的 , 有望用上ajax和html5 .

关于第二点: 我也相信python是RPI的首选开发语言 ,
                   不过"RPI向小车迈进"这一系列的开发环境已经确定了qtcreator+c+web的开发环境 ,
                   后续的内容也不打算改变了 .
回复 支持 反对

使用道具 举报

发表于 2014-2-20 12:45:11 | 显示全部楼层
楼主你可以把你硬件清单放出来吗,我也想搞
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-20 16:06:26 | 显示全部楼层
qykings 发表于 2014-2-20 12:45
楼主你可以把你硬件清单放出来吗,我也想搞

这个实验硬件很少的,
一个LED和一个470欧电阻,
接线方式是 : RPI 的GPIO 7 -> 电阻 -> LED 正极
                  RPI的GND ->LED 负极
回复 支持 反对

使用道具 举报

发表于 2014-2-21 09:17:01 | 显示全部楼层
wing 发表于 2014-2-7 11:58
感谢你的认真阅读和意见 ,

关于第一点: 我的下一个实验是关于PWM的 , 有望用上ajax和html5 .

关于你的第二点,我很赞同这样做。

这样做更贴近TCP IP协议本身,以后再弄ajax,RESTFul,CoAP的话,会理解的深刻的多!
回复 支持 反对

使用道具 举报

发表于 2014-4-3 20:02:11 | 显示全部楼层
wing 发表于 2014-2-20 16:06
这个实验硬件很少的,
一个LED和一个470欧电阻,
接线方式是 : RPI 的GPIO 7 -> 电阻 -> LED 正极

谢楼主,我搞用c写几行代码实现了电机 驱动http://pan.baidu.com/s/1jGt7Pbg
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-28 22:38 , Processed in 0.043659 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表