目录
上篇补充:仅通过ssh登录树莓派
①一条这样的线,一端连树莓派网口,一端连电脑
②电脑连接wifi(手机热点也可),右键网络图标 ,打开“网络和Internet”设置,点击高级网络设置里的“更改适配器选项”,,选择正在使用的那个适配器(这里是WLAN)
③树莓派开机,等待网口灯亮后。打开Advanced IP Scanner(可以扫描本机网段下所有设备IP的工具) ,或win+R,输入cmd,打开命令提示符,输入arp -a命令。找到MAC(物理地址)为B8:27:EB开头的设备
④复制获得的IP,打开Xshell或putty等工具,登录到树莓派
进入本篇主题:浅学树莓派基本外设(自动开盖垃圾桶)
模块:HC-SR04超声波模块 SG90舵机
-
树莓派的接口:
I/O:Input Ouput 对于主控芯片来说
Input:人体红外传感器,烟雾传感器,火焰传感器,震动传感器
Output: 继电器,蜂鸣器
PWM:电机调速,调整灯光明亮度
串口uart、SPI、IIS、其他特定硬件接口:flash
其他芯片: Nanopi、S3c2410、2440、6410、Tiny210 、tiny4412(Linux)
海思方案,瑞芯微方案,移远方案
C51,STM32,Arduino,WemosD1(没有OS(Linux)纯裸机开发)
一、HC-SR04超声波测距原理和代码实现
原理:(常见于中学物理题,霍霍了多少孩纸)
GPIO4向 Trig 引脚发送一个 10us 的脉冲信号,开始发送超声波,并把 Echo置为高电平,发射超声波之后,与接收到传回的超声波之前,Echo这个响应引脚会一直呈现高电平,然后准备接收返回的超声波。等到超声波撞到障碍物弹回来并被模块接收,Echo引脚置为低电平。
(有用的话:Echo持续高电平的时间就是超声波往返路程的花费的时间,通过记录时间,再利用路程=速度X时间 可算出路程(注意是往返路程),已知:超声波速度340m/s)
PS:实际编写代码时,需注意时间是微秒级别,转换单位时避免精度丢失 。
超声波测距demo:
#include<wiringPi.h>
#include<softPwm.h>
#include<unistd.h>
#include<sys/time.h>
#include<stdio.h>
#include<stdlib.h>
#include<error.h>
#define TRIG 4
#define ECHO 5
#define BEE 6
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 * 34000 / 2;
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舵机原理
原理:不同于HC-SR04超声波模块,SG90舵机的控制信号是PWM信号,利用其占空比的变化,改变舵机转动的角度。如下图(来源于百度)
通过控制线发送一个PWM信号可以控制舵机转动到一个角度,这个PWM信号必须周期性发送,否则舵机就会转到一个任意的角度。通常,控制舵电机的PWM信号周期为20ms(50HZ),宽度在0.5ms-2.5ms之间(对应最小角度和最大角度)。
以0-180度的舵机为例,,我已经知道了舵机的pwm周期为20ms,然后是这样的
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
这里舵机的实现与wemos D1有所不同,通过查询众多文章(大部分用Python实现)
C写的主要了解到的方式有三种:①硬件PWM;②软件PWM;③高低电平模拟。
什么是PWM:(来源于百度)
树莓派或者是其他单片机一个引脚只能输出两个特定的电平——高电平和低电平。在树莓派上大多的GPIO都是高电平3.3V,低电平0V。但如果想要输出3.3~0V之间的电压怎么办呢?比如输出一个2V?树莓派(以及stm32,C51之类的)是没有办法直接设置引脚的电平来达到输出2V的电平值。那么就要使用PWM来输出介于低电平和高电平之间的电压。
那么PWM是怎么做到的呢?很简单:我们不能直接输出2V,那我们换一种方式——通过给引脚一个周期脉冲,然后看这个脉冲的高电平部分占整个脉冲的比例,从而计算这个输出的电平。举个栗子?:比如我给出一个周期为20s的周期脉冲,然后让其中的高电平为12s,这样的话输出的电平就是(12/20)*3.3V≈2V,那么2V就输出了?。
也就是说,PWM是根据周期脉冲中高电平所占的比例来确定GPIO输出的电压的。这里,高电平所占周期脉冲的周期的比例称为占空比。
在wiringPi中提供的关于硬件PWM的通用GPIO函数有:
- 函数①: void pinMode (int pin, int mode)
参数解释:pin:配置的引脚 mode:指定引脚的IO模式(PWM_OUTPUT为PWM输出模式)
注意:只有wiringPi 引脚编号下的1脚(BCM下的18脚) 支持PWM输出
- 函数②: void pwmWrite (int pin, int value)
参数解释:pin:引脚 value:写入到PWM寄存器的值,范围在0~1024之间。
注意:pin只能是wiringPi 引脚编号下的1脚(BCM下的18脚)
(可以利用PWM做LED的呼吸灯实验)
在wiringPi中提供的关于软件PWM的通用GPIO函数有:
PWM驱动舵机的demo:
#include<stdio.h>
#include<wiringPi.h>
#include<softPwm.h>
#define SERVO 7
void init_(){
wiringPiSetup();
pinMode(SERVO,PWM_OUTPUT);
}
int main(){
init_();
while(1){
softPwmCreate(SERVO,20,200);
softPwmWrite(SERVO,10);
delay(1000);
softPwmWrite(SERVO,25);
delay(1000);
}
return 0;
}
在做开盖垃圾桶过程中的问题:
①供电不足可以会导致程序运行时死机,或者模块工作不正常,建议使用稳定电源供电(充电宝、符合规格的充电适配器等),树莓派供电正常时,红灯常亮。
②查找资料时,有说法树莓派PWM不稳定,会导致舵机抖动的问题(其中有建议使用pigpio库可解决,附网址:pigpio libraryhttp://abyz.me.uk/rpi/pigpio/cif.html#gpioInitialise
最后编辑于:2022年2月20日
说明:由于笔者水平有限,文中不可避免有所错漏,敬请广大读者斧正。