当前位置: 首页 > news >正文

【回眸】香橙派Zero2 超声波模块测距控制SG90舵机转动

前言

知识准备

超声波模块时序图

gettimeofday()函数作用

gettimeofday()函数原型

 tv结构体

获取当前系统时间与格林威治时间的时间差

获取香橙派数10万秒花费的时间

使用超声波模块获取到障碍物距离

SG90舵机模块

舵机模块的作用

舵机模块方波时序图

 舵机模块工作原理

 知识准备

setitimer时间函数原型

使用setitimer函数实现1秒钟打印一次hello

连接舵机和香橙派 

舵机控制与PWM方波关系

后记

前言

这个系列的上一篇文章介绍了香橙派的基础功能和作用,还用通过代码让蜂鸣器响起来。

本篇博文介绍如何使用香橙派使超声波模块完成测距功能。

知识准备

超声波模块时序图

通过 距离 = 速度 * 时间这个公式能够得到与障碍物的距离,注意障碍物不能太小,也最好比较平整,避免有误差。 

在写测距代码之前,先了解一下Linux下获取时间的函数 gettimeofday()

gettimeofday()函数作用

作用:获取当前系统时间与格林威治(GTM/UTC)的时间差

优点:可以精确到微秒级别且系统调用小

gettimeofday()函数原型

#include<sys/time.h>
int gettimeofday(struct timeval* tv, struct timezone* tz);

 tv结构体

struct timeval 
{time_t tv_sec;suseconds_t tv_usec;
}

tz在早期是用来获取时区,目前已经废弃,设置为NULL即可。

获取当前系统时间与格林威治时间的时间差

新建一个c文件命名为time,使用该函数获取当前系统时间与格林威治时间的时间差,用秒和微妙分别表示。 

time.c

#include <stdio.h>
#include <sys/time.h>
int main(){struct timeval tv;gettimeofday(&tv,NULL);printf("sec = %ld,usec = %ld\n",tv.tv_sec,tv.tv_usec);return 0;
}

获取香橙派数10万秒花费的时间

 再新建一个c文件命名为timeCnt10.c,预期效果是返回香橙派数10万秒花费的时间,单位是微秒

#include <stdio.h>
#include <sys/time.h>
void cntTest(){int i ,j;for(i=0;i<100;i++){for(j=0;j<1000;j++);}
}int main(){struct timeval timestop;struct timeval timestart;long diffTime;gettimeofday(&timestart,NULL);cntTest();gettimeofday(&timestop,NULL);diffTime = 1000000*(timestop.tv_sec - timestart.tv_sec) + (timestop.tv_usec - timestart.tv_usec);printf("H616 count 10w S use time =  %ld us\n",diffTime);return 0;
}

可以看到每次运行的结果都不一样,基本上稳定在1460左右,说明香橙派的资源每次需要1460毫秒左右 。

使用超声波模块获取到障碍物距离

 echo.c

注意这里的diffTime 单位是微秒

dis的单位是厘米

#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <unistd.h>
#include <stdlib.h>#define Trig 0
#define Echo 1double getDistance()
{struct timeval start;struct timeval stop;long diffTime;double dis;pinMode(Trig, OUTPUT);pinMode(Echo, INPUT);digitalWrite(Trig, LOW);usleep(5);digitalWrite(Trig, HIGH);usleep(10);digitalWrite(Trig, LOW);while (!(digitalRead(Echo)));gettimeofday(&start, NULL);while (digitalRead(Echo));gettimeofday(&stop, NULL);diffTime = 1000000 * (stop.tv_sec - start.tv_sec) + (stop.tv_usec - start.tv_usec);dis = ((double)diffTime / 1000000 * 34000 / 2);return dis;
}int main()
{double dis;if (wiringPiSetup() == -1){fprintf(stderr, "error:%s", "initWiringPi error");exit(-1);}while (1){dis = getDistance();printf("dis = %lf\n", dis);usleep(500000);}return 0;
}

触发的引脚从超声波模块连接到物理3PIN脚(靠左一列的第二行针脚) 

echo的引脚从超声波模块连接到物理5PIN脚(靠左一列的第三行针脚) 

VCC的线需要连接到5V的物理口,如果接到3.3V的物理口则无法正常驱动。

GND的线需要接到任意GND的物理口。

SG90舵机模块

舵机模块的作用

舵机模块的作用是通过编程可以将塑料齿轮转不同的角度,用于精确控制角度位置。

舵机模块方波时序图

 舵机模块工作原理

向SG90舵机模块的黄色线输入PWM方波,不同占空比对应着不同角度。

SG90 黄色线输入频率是50HZ,周期是20ms的方波。

0.5ms-------------0度; 2.5% 对应函数中CCRx为5

1.0ms------------45度; 5.0% 对应函数中CCRx为10

1.5ms------------90度; 7.5% 对应函数中CCRx为15

2.0ms-----------135度; 10.0% 对应函数中CCRx为20

2.5ms-----------180度; 12.5% 对应函数中CCRx为25

这里舵机是否能够转动180度还是要具体看硬件是否支持。

 知识准备

在实现SG90功能开发之前,还需要了解一个时间函数。

setitimer时间函数原型

int setitimer(int which,const struct itimerval *new_value,struct itimerval *old_value);

 new_value和old_value的数据结构为:

struct itimerval {struct timeval it_interval; /* Interval for periodic timer */struct timeval it_value;    /* Time until next expiration */
};struct timeval {time_t      tv_sec;         /* seconds */suseconds_t tv_usec;        /* microseconds */
};

使用setitimer函数实现1秒钟打印一次hello

设置的时间单位是500微秒,需要2000个500微秒才是1秒

clock.c

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>static int i;void signal_handler(int signum)
{i++;if (i == 2000){printf("hello\n");i = 0;}
}int main()
{int res = 0;struct itimerval itv;// 设定定时时间itv.it_interval.tv_sec = 0;itv.it_interval.tv_usec = 500;// 设定开始生效,启动定时器的时间itv.it_value.tv_sec = 1;itv.it_value.tv_usec = 0;// 设定定时方式res = setitimer(ITIMER_REAL, &itv, NULL);if (res == -1){perror("error\n");exit(-1);}// 信号处理signal(SIGALRM, signal_handler);while (1);return 0;
}

连接舵机和香橙派 

 按照上图连接舵机和香橙派

注意SG90模块也和超声波模块一样,需要一个5V的电压,所以VCC需要连接5V的IO

GND也要选GND的IO

SG90Pin在代码里是5,对应物理PIN口是11

像上图示例这样连接舵机和树莓派,注意接地和VCC如果接反了会烧掉舵机。另外舵机的线是连在一起的,可以剪开杜邦线嫁接一下再用电工胶带绑一下连接处。

或者使用公对母杜邦线衔接一下也可以。

舵机控制与PWM方波关系

舵机的控制一般需要一个20ms 左右的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms 范围内的角度控制脉冲部分。以180 度角度伺服为例,那么对应的控制关系是这样的:

      0.5ms ---------- 0 °;

      1.0ms ---------- 45 °;

      1.5ms ---------- 90 °;

      2.0ms ---------- 135 °;

      2.5ms ---------- 180 °;

方波的总周期是20ms,设置的时间单位是500微秒,就是40个单位为20ms,所以当i等于1时,舵机角度为0°,当i等于2时,舵机角度为45°,当i等于3时,舵机角度为90°,当i等于4时,舵机角度为135°,当i等于5时,舵机角度为180°。

SG90.c

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>#define SG90Pin 5static int i = 0;
static int angle = 0;void signal_handler(int signum)
{if (i <= angle){digitalWrite(SG90Pin, HIGH);}else{digitalWrite(SG90Pin, LOW);}if (i == 40){i = 0;}i++;
}int main()
{int res;struct itimerval itv;wiringPiSetup();pinMode(SG90Pin, OUTPUT);// 设定定时时间itv.it_interval.tv_sec = 0;itv.it_interval.tv_usec = 500;// 设定开始生效,启动定时器的时间itv.it_value.tv_sec = 1;itv.it_value.tv_usec = 0;// 设定定时方式res = setitimer(ITIMER_REAL, &itv, NULL);if (res == -1){perror("error\n");exit(-1);}// 信号处理signal(SIGALRM, signal_handler);while (1){printf("Please input angle: 1-0   2-45  3-90  4-135  5-180\n");scanf("%d", &angle);}return 0;
}

预期看到的效果是输入1---5,可以让舵机转向不同的方向,最终结果也是符合预期的。

后记

要是在上大学的时候搞这个还有点小困难,工作几年以后发现简单不少,时间是最好的老师?? 

相关文章:

  • 2025年北京市职工职业技能大赛第六届信息通信行业网络安全技能大赛初赛-wp
  • 某团小程序mtgsig,_token 生成逻辑分析
  • AWS WebRTC如何实现拉流?内部是这样实现的
  • QuecPython+Aws:快速连接亚马逊 IoT 平台
  • STM32--GPIO
  • ffmpeg录音测试
  • k8s node soft lockup (内核软死锁) 优化方案
  • <论文>(字节跳动)使用大语言模型进行时间序列理解和推理
  • Nginx 安全防护与HTTPS部署
  • 2025 RSAC|大语言模型应用风险与厂商攻防新策略
  • 【coze】故事卡片(图片、音频、文字)
  • 游戏引擎学习第261天:切换到静态帧数组
  • 瑞克的CTF
  • MySQL中的约束
  • 赛灵思 XCZU11EG-2FFVC1760I XilinxFPGAZynq UltraScale+ MPSoC EG
  • 第一章-语言基础\3.STL
  • https://juejin.cn/editor/drafts/7262346366541070395
  • 高性能网络优化:深入解析忙轮询(Busy Polling)技术
  • HTTP 与 HTTPS 的深度剖析:差异、原理与应用场景
  • 第11次:用户注册(简要版)
  • 李云泽:支持设立新的金融资产投资公司,今天即将批复一家
  • 上海乐高乐园度假区将于7月5日开园
  • 南京明孝陵石兽遭涂鸦“到此一游”,景区:已恢复原貌,警方在排查
  • 人民日报头版:让青春之花绽放在祖国和人民最需要的地方
  • 校方就退60件演出服道歉:承诺回收服装承担相关费用,已达成和解
  • 政府效率部效果不佳?马斯克有意寻求支持,含糊表态部门未来