admin 管理员组文章数量: 887017
目录
前言
一、HC-SR04超声波测距
0.超声波测距原理
✒️如何使HC-SR04发送超声波
✒️如何接收超声波返回
✒️如何通过时间算出距离
1.Linux的获取时间gettimeofday()
✒️timeval结构体
✒️gettimeofday()函数
2.利用gettimeofday()计算时间,实现超声波测距
二、SG90舵机
0.驱动SG90舵机原理
1.Linux的定时器
✒️itimerval结构体
✒️setitimer()函数
2.实现舵机全向转动
前言
在上篇已经刷好了Armbian系统,安装wiringPi完成基本的开发环境准备,接下来就是基于WiringPi配合常用模块来了解了解angePi的基本外设 — 通用输入输入设备GPIO、串口UART、IIC协议等。
一、HC-SR04超声波测距
0.超声波测距原理
《第二篇 树莓派基本外设基础》— 树莓派实现
《第三篇 SG90舵机和HC-SR04测距》— 51实现
(在上面的文章里,已经记录了HC-SR04的测距原理,这里简单略过)
具体体现在代码中,只需要知道以下关键信息:
✒️如何使HC-SR04发送超声波
向TRIG引脚发送一个10us 的脉冲信号(高电平),开始发送超声波
✒️如何接收超声波返回
开始发送波的同时,ECHO会被置为高电平直到波返回,置为低电平
(ECHO持续高电平的时间 = 超声波往返路程的花费的时间)
✒️如何通过时间算出距离
已知波在空气中传播速度为340 m/s。通过路程=速度×时间计算得出
1.Linux的获取时间gettimeofday()
✒️timeval结构体
✒️gettimeofday()函数
获取当前时间到新纪元时间Epoch的距离时间(可精确到微妙)
Epoch是指定为1970年1月1日0时0分0秒的格林威治时间
(也就是说该函数能获取当前时间距离1970年1月1日0时0分0秒那一刻xxxxxx秒xxxxxx微妙)
2.利用gettimeofday()计算时间,实现超声波测距
(模块坏了,没接上测试)
#include<wiringPi.h>
#include<unistd.h>
#include<sys/time.h>
#include<stdio.h>
#include<stdlib.h>
#define TRIG 23
#define ECHO 25
void init_hardware(){
int retn;
retn=wiringPiSetup();
if(retn < 0){
perror("init hardware");
exit(-1);
}
}
void init_pins(){
pinMode(ECHO,INPUT);
pinMode(TRIG,OUTPUT);
}
float measure_distance(){
long start_usec,stop_usec;
struct timeval rawtime1,rawtime2;
float distance;
digitalWrite(TRIG,LOW);
delayMicroseconds(2);
digitalWrite(TRIG,HIGH);
delayMicroseconds(10);
digitalWrite(TRIG,LOW);//start send ultrasonic
// printf("%d\n",digitalRead(ECHO));
while(!(digitalRead(ECHO) == 1));
gettimeofday(&rawtime1, NULL);
while(!(digitalRead(ECHO) == 0));//low
gettimeofday(&rawtime2,NULL);
start_usec =rawtime1.tv_sec*1000000+rawtime1.tv_usec;
stop_usec =rawtime2.tv_sec*1000000+rawtime2.tv_usec;
distance=(float)(stop_usec-start_usec)/1000000*17000;
return distance;
}
int main(){
float distance;
init_hardware();
init_pins();
while(1){
distance = measure_distance();
printf("%0.2f cm\n",distance);
delay(1000);
}
return 0;
}
二、SG90舵机
0.驱动SG90舵机原理
在前面的文章里,已经记录了SG90的相关信息,这里简单略过
体现在代码中,需要以下关键信息
1.Linux的定时器
✒️itimerval结构体
✒️setitimer()函数
设置定时器,可精确到us(微秒)级别,比alarm()函数精度更高
🔖参数①:which指定定时器的定时方式(传下面三个宏)
ITIMER_REAT | 根据实际时间倒计时,到达时间发送SIGALRM信号 |
ITIMER_VIRTUAL | 根据进程消耗的用户模式CPU时间进行倒计时,到达发送SIGVTALRM信号 |
ITIMER_PROF | 根据进程消耗的总CPU时间(即用户和系统)进行倒计时 |
🔖参数②:new_value
传入参数,表示定时的时长(传已初始化的itmerval结构体地址)
🔖参数③:old_value
传出参数,表示上一次定时剩余的时间(一般传NULL即可)
2.实现舵机全向转动
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <wiringPi.h>
#include <unistd.h>
#include <stdlib.h>
#define SG90 25
int angle = 0; //初始化角度为0度。0-0度 1-45度 2-90度 3-135度 4-180度
/* 初始化硬件 */
void init_hardware(){
if(wiringPiSetup() == -1){
perror("init");
exit(-1);
}else{
pinMode(SG90,OUTPUT);
}
}
/* 信号处理函数:主要实现控制SG90的转向 */
void signalHandler(int signum){
static int i = 0;
if(i > angle){ //angle=0时,i=0不满足条件,拉高电平得到0.5ms高电平转至0度
digitalWrite(SG90,LOW);
}else{ //angle=2,i=0 i=1均不满足条件,拉高电平得到1ms高电平转到40度
digitalWrite(SG90,HIGH);
} //angle=2,i=0 i=1 i=2均不满足条件,拉高电平得到1.5ms高电平转到90度
if(++i == 40){ //其他角度以此类推
i = 0;
}
}
/* 初始化定时器 */
void init_timer(){
struct itimerval timer;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 500; //每0.5ms定时到期一次
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0; //1s后启动定时器
if(setitimer(ITIMER_REAL,&timer,NULL) == -1){
perror("set timer");
exit(-1);
}
signal(SIGALRM,signalHandler); //捕获SIGALRM信号
}
int main(){
init_hardware();
digitalWrite(SG90,LOW);
init_timer();
while(1){
printf("input 1-0,2-45,3-90,4-135,5-180\n");
scanf("%d",&angle);
}
return 0;
}
版权声明:本文标题:第二篇 香橙派的外设开发基础(上)-GPIO篇 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1725890792h888146.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论