原理:通过Linux客户端发送"w" “a” “s” "d"指令到树莓派实现控制垃圾桶的上、下、左、右移动
功能需求:
避障小车模式
. 避障移动
清洁桶模式
. 手伸过去,自动把盖子打开
. 屏幕显示状态
. 检测温湿度
. 远程控制,客户端发送控制命令
功能模块:
. 树莓派主控
. oled显示屏
. 超声波模块
. 温湿度传感器
. SG90舵机
. 马达及轮子
. 清洁桶
架构:
远程控制服务端
树莓派
远程控制客户端
linux虚拟机
模块对应的功能:
oled显示屏
. 温度
. 时间
. 树莓派IP
超声波模块
. 识别手扔垃圾的动作
. 识别障碍物
温度传感器
. 读取当前环境的温度
SG90舵机
. 打开清洁桶的盖子
马达及轮子
通过热熔胶黏在筒底
相关程序:
超声波模块:
#include
#include
#include
#include
#include"chaoshen.h"
#include"duoji.h"
float chaoshen()
{
// wiringPiSetup();
pinMode(16,INPUT);
pinMode(15,OUTPUT);
while(1){
digitalWrite(15,LOW);
digitalWrite(15,HIGH);
delayMicroseconds(10);
digitalWrite(15,LOW);
while(1){
if(digitalRead(16)==1){
break;
}
}
struct timeval t1;
gettimeofday(&t1,NULL);
while(1){
if(digitalRead(16)==0){
break;
}
}
struct timeval t2;
gettimeofday(&t2,NULL);
long start,stop;
start=t1.tv_sec*1000000+t1.tv_usec;
stop=t2.tv_sec*1000000+t2.tv_usec;
float dis;
dis=(float)(stop-start)/1000000*340/2*100;
printf("dis=%f\n",dis);
return dis;
delay(500);
}
pthread_exit(NULL);
}
电机模块:
#include
#include
#include
#include
#include
#include"dianji.h"
#include
#include
int Left_motor_go = 28;
int Left_motor_back = 29;
int Right_motor_go = 24;
int Right_motor_back = 25;
// int Left_motor_pwm = 27;
// int Right_motor_pwm = 23;
/*wiringPiSetup();
pinMode(Left_motor_go, OUTPUT);
pinMode(Left_motor_back, OUTPUT);
pinMode(Right_motor_go, OUTPUT);
pinMode(Right_motor_back, OUTPUT);
delay(2000);/
void dianji_shan() {
/ wiringPiSetup();
pinMode(Left_motor_go, OUTPUT);
pinMode(Left_motor_back, OUTPUT);
pinMode(Right_motor_go, OUTPUT);
pinMode(Right_motor_back, OUTPUT);
delay(500); */
digitalWrite(Left_motor_go,1);
digitalWrite(Left_motor_back,0);
// softPwmWrite(Left_motor_pwm, 150);
digitalWrite(Right_motor_go,1);
digitalWrite(Right_motor_back,0);
// softPwmWrite(Right_motor_pwm, 150);
delay(1000);
return;
}
void dianji_xia() {
/*/ wiringPiSetup();
pinMode(Left_motor_go, OUTPUT);
pinMode(Left_motor_back, OUTPUT);
pinMode(Right_motor_go, OUTPUT);
pinMode(Right_motor_back, OUTPUT);
delay(500);
*/
digitalWrite(Left_motor_go,0);
digitalWrite(Left_motor_back,1);
// softPwmWrite(Left_motor_pwm, 150);
digitalWrite(Right_motor_go,0);
digitalWrite(Right_motor_back,1);
// softPwmWrite(Right_motor_pwm, 150);
delay(1000);
return;
}
void dianji_zhuo() {
/* wiringPiSetup();
pinMode(Left_motor_go, OUTPUT);
pinMode(Left_motor_back, OUTPUT);
pinMode(Right_motor_go, OUTPUT);
pinMode(Right_motor_back, OUTPUT);
delay(500);
*/
digitalWrite(Left_motor_go,0);
digitalWrite(Left_motor_back,0);
// softPwmWrite(Left_motor_pwm, 150);
digitalWrite(Right_motor_go,1);
digitalWrite(Right_motor_back,0);
// softPwmWrite(Right_motor_pwm, 150);
delay(1000);
return;
}
void dianji_you() {
/*/ wiringPiSetup();
pinMode(Left_motor_go, OUTPUT);
pinMode(Left_motor_back, OUTPUT);
pinMode(Right_motor_go, OUTPUT);
pinMode(Right_motor_back, OUTPUT);
delay(500);
*/
digitalWrite(Left_motor_go,1);
digitalWrite(Left_motor_back,0);
// softPwmWrite(Left_motor_pwm, 150);
digitalWrite(Right_motor_go,0);
digitalWrite(Right_motor_back,0);
// softPwmWrite(Right_motor_pwm, 150);
delay(1000);
return;
}
void dianji_tinzhi() {
/*/ wiringPiSetup();
pinMode(Left_motor_go, OUTPUT);
pinMode(Left_motor_back, OUTPUT);
pinMode(Right_motor_go, OUTPUT);
pinMode(Right_motor_back, OUTPUT);
delay(500);
*/
digitalWrite(Left_motor_go,0);
digitalWrite(Left_motor_back,0);
// softPwmWrite(Left_motor_pwm, 150);
digitalWrite(Right_motor_go,0);
digitalWrite(Right_motor_back,0);
// softPwmWrite(Right_motor_pwm, 150);
delay(1000);
return;
}
void dianji(void*x) {
// wiringPiSetup();
pinMode(Left_motor_go, OUTPUT);
pinMode(Left_motor_back, OUTPUT);
pinMode(Right_motor_go, OUTPUT);
pinMode(Right_motor_back, OUTPUT);
delay(500);
int fd=*((int *)x);
char i;
while (1) {
recv(fd,&i,sizeof(i),0);
switch (i) {
case 'w':
dianji_shan();
break;
case 's':
dianji_xia();
break;
case 'a':
dianji_zhuo();
break;
case 'd':
dianji_you();
break;
case 'q':
dianji_tinzhi();
break;
default:
break;
}
// getchar();
}
pthread_exit(NULL);
return;
}
舵机模块:
#include
#include
#include
#include
#include"duoji.h"
void duoji() {
int pwmPin = 18;
wiringPiSetupGpio();
pinMode(pwmPin, PWM_OUTPUT);
pwmSetMode(PWM_MODE_MS);
pwmSetRange(2000);
pwmSetClock(192);
pwmWrite(pwmPin, 50);
delay(5000);
pwmWrite(pwmPin, 200);
}
日志模块:
#include
#include
#include “log.h”
FILE *g_log=NULL;
void log_creat() {
g_log = fopen("./servermylog", “a+”);
if (NULL == g_log) {
printf(“鎵撳紑澶辫触\n”);
}
}
void log_destroy() {
fclose(g_log);
g_log = NULL;
}
void log_write(const char *format, …) {
va_list args;
// char *para;
va_start(args, format);
vfprintf(g_log, format,args);
fflush(g_log);
va_end(args);//閿€姣?}
/int main() {
log_creat();
log_write("%s%s%s",“hello”,“xiaoyang”,“nigechun”);
log_destroy();
return 0;
}/
OLED模块部分程序:
#include
#include
#include
#include"wendu.h"
#include
#include
int fd;
unsigned char yi[4][16] = {" ", //绗竴琛? " “, //绗簩琛? " “, //绗笁琛? " 192.168.43.61 “, //绗洓琛?}; //鏄剧ず鍐呭
const unsigned char zi[];
void init(void) //鍒濆鍖?{
// wiringPiSetup();
fd = wiringPiI2CSetup(0x3c); // i2c鍒濆鍖?0x3c鏄痮led鐨勪粠鏈哄湴鍧€
wiringPiI2CWriteReg8(fd, 0x00, 0xa1); //鍥惧儚鍙嶄簡淇敼鎴?xa0
wiringPiI2CWriteReg8(fd, 0x00, 0xc8); //琛岃緭鍑哄弽浜嗕慨鏀规垚0xc0
wiringPiI2CWriteReg8(fd, 0x00, 0x8d); //鍏佽鐢佃嵎娉? wiringPiI2CWriteReg8(fd, 0x00, 0x14);
wiringPiI2CWriteReg8(fd, 0x00, 0xa6); //鎯冲弽鐩告樉绀烘敼鎴?xa7
wiringPiI2CWriteReg8(fd, 0x00, 0x21); //閲嶇疆鍒楀湴鍧€
wiringPiI2CWriteReg8(fd, 0x00, 0x00);
wiringPiI2CWriteReg8(fd, 0x00, 0x7f);
wiringPiI2CWriteReg8(fd, 0x00, 0xaf); //寮€鏄剧ず
}
void qingping(void) //娓呭睆
{
char zt1, zt2;
for (zt1 = 0; zt1 < 8; zt1++) {
wiringPiI2CWriteReg8(fd, 0x00, 0xb0 + zt1);
for (zt2 = 0; zt2 < 128; zt2++) wiringPiI2CWriteReg8(fd, 0x40, 0x00);
}
}
void ascii(void) //鏄剧ずASCII鐮?*16
{
int zt;
char zt3, zt4;
for (zt3 = 0; zt3 < 4; zt3++) {
wiringPiI2CWriteReg8(fd, 0x00, 0xb0 + (zt3 * 2));
for (zt4 = 0; zt4 < 16; zt4++)
for (zt = 0; zt < 8; zt++)
wiringPiI2CWriteReg8(fd, 0x40, zi[yi[zt3][zt4] * 16 + zt]);
wiringPiI2CWriteReg8(fd, 0x00, 0xb0 + (zt3 * 2) + 1);
for (zt4 = 0; zt4 < 16; zt4++)
for (zt = 0; zt < 8; zt++)
wiringPiI2CWriteReg8(fd, 0x40, zi[yi[zt3][zt4] * 16 + zt + 8]);
}
}
void shijian(void) //褰撳墠鏃堕棿
{
struct tm *ptr;
time_t lt;
lt = time(<);
ptr = localtime(<);
sprintf(yi[0],”%3.3f\n”,wendu());
strftime(yi[1], 16, “%m/%d %a”, ptr); //鏈?鏃?鍛ㄥ嚑
strftime(yi[2], 16, “%R %p”, ptr); //鏃?鍒?am鎴杙m
}
void oled(void) {
init();
qingping();
while (1) {
shijian();
ascii();
delay(1000);
}
pthread_exit(NULL);
}
温度模块:
#include
#include
#include
#include
#include
#include
#include
#include"wendu.h”
float wendu() {
char path[50] = “/sys/bus/w1/devices/”;
char rom[20];
char buf[100];
DIR *dirp;
struct dirent *direntp;
int fd = -1;
char *temp;
float value;
system("sudo modprobe w1-gpio");
system("sudo modprobe w1-therm");
if ((dirp = opendir(path)) == NULL) {
printf("opendir error\n");
return 1;
}
while ((direntp = readdir(dirp)) != NULL) {
if (strstr(direntp->d_name, "28-031697792d2c")) {
strcpy(rom, direntp->d_name);
printf(" rom: %s\n", rom);
}
}
closedir(dirp);
strcat(path, rom);
strcat(path, "/w1_slave");
if ((fd = open(path, O_RDONLY)) < 0) {
printf("open error\n");
return 1;
}
if (read(fd, buf, sizeof(buf)) < 0) {
printf("read error\n");
return 1;
}
temp = strchr(buf, 't');
sscanf(temp, "t=%s", temp);
value = atof(temp) / 1000;
printf(" temp : %3.3f\n", value);
sleep(1);
return value;
}
客户端:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include “log.h”
//#include"utils.h"
int main(){
int c_fd;
int ret;
char c_send;
// char *c_send;
// c_send=(char *)malloc(100);
log_creat();
c_fd = socket(AF_INET, SOCK_STREAM, 0); //濂楁帴瀛楀垱寤? if (c_fd < 0) {
perror(" 鍒涘缓濂楁帴瀛楀け璐?);
exit(-1);
}
struct sockaddr_in clientaddr; //閰嶇疆IP鍜岀鍙o紝涓庢湇鍔$涓€鑷?
memset(&clientaddr, 0, sizeof(struct sockaddr_in)); //娓呯┖
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons(8333);
clientaddr.sin_addr.s_addr = inet_addr("192.168.43.61");
ret = connect(c_fd, (struct sockaddr *)&clientaddr,sizeof(struct sockaddr_in));
if (ret < 0) {
perror("connect"); //閾炬帴鏈嶅姟绔? exit(-1);
}
log_write("閾炬帴鎴愬姛");
while(1){
printf("shu ru:\n");
scanf("%c",&c_send);
ret=send(c_fd,&c_send,sizeof(c_send),0);
log_write("%d\n",ret);
getchar();
}
return 0;
}
服务端:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include “oled.h”
#include “duoji.h”
#include “dianji.h”
#include “log.h”
#include"chaoshen.h"
#include"juli.h"
int main() {
wiringPiSetup();
int s_fd;
int ret;
int c_fd;
log_creat();
s_fd = socket(AF_INET, SOCK_STREAM, 0);
if (s_fd < 0) {
perror("socket");
exit(-1);
}
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;
memset(&serveraddr, 0, sizeof(struct sockaddr_in));
memset(&clientaddr, 0, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(8333); serveraddr.sin_addr.s_addr = inet_addr("192.168.43.61");
ret =
bind(s_fd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_in));
if (ret < 0) {
perror("bind");
exit(-1);
}
ret = listen(s_fd, 10);
if (ret < 0) {
perror("listen");
exit(-1);
}
c_fd = accept(s_fd, NULL, NULL);
if (c_fd < 0) {
perror(“accept”);
exit(-1);
}
log_write(“server%s\n”, “鎴愬姛閾炬帴”);
pthread_t t1;
pthread_t t2;
pthread_t t3;
ret = pthread_create(&t1, NULL,(void*)oled, NULL);
ret = pthread_create(&t2, NULL,(void*)juli, NULL);
ret = pthread_create(&t3, NULL,(void*)dianji,(void *)&c_fd);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
log_destroy();
return 0;
}
遇见的难题:
1、多次使用wiringPiSetup()造成程序段错误,只要在main函数一开始调用一次,不需要每个模块都调用,这会导致进程崩溃
2、在写OLED模块代码时在while中又使用了一次whie,导致进程一进oled,就出不去了,造成其他进程不能运行。显示IP地址时直接用fscanf函数直接把IP地址写入数组。
3、在写服务端代码时,创建线程时,传参的问题,传递套接字描述符c_fd,时需要用(void*)强转类型,调用这个形参时需要int fd=*((int *)x);,把这个形参转换成需要的参数类型再取值,注意括号。
4、注意树莓派与各个模块的接线。
5、注意.h文件的引用。
6、要使各个模块同时运行需要使用多线程,多线程的使用需要注意参数的传递与使用,线程中不能while中嵌套while,这会造成死循环。