树莓派Python/C语言超声波测距以及利用超声波模块小车避障

使用Python进行超声距离测量 – 第1部分

树莓派Python/C语言超声波测距以及利用超声波模块小车避障

  • 超声波传感器

    树莓派Python/C语言超声波测距以及利用超声波模块小车避障

LED,蜂鸣器和开关是人们尝试与Raspberry Pi相连接的最常见的项目。在某宝中发现的有点不同的是超声波测量模块。这允许您测量距离最近的墙壁或固体物体的距离。这些模块很容易买到,便宜而且比较直接的连接到GPIO头。

所以这里有一些关于我的超声测量模块和Python的实验的信息。在未来的项目中,我可以看到这些模块是向Pi动力机器人或汽车添加一些智能的好方法。

树莓派Python/C语言超声波测距以及利用超声波模块小车避障

HC-SR04模块的成本约为3-4yuan,是一个匹配的大小。其设计由5V供电,具有1个输入引脚和1个输出引脚。该模块通过向空中发送超声波脉冲并测量反弹所需的时间来工作。该值可以用于计算脉冲行进的距离。

连接到Pi

为模块供电很简单。只需将+ 5V和Ground引脚连接到Pi的GPIO接头上的引脚2和引脚6。

模块上的输入引脚称为“触发”,用于触发发送超声波脉冲。理想情况下,它需要一个5V信号,但它与GPIO的3.3V信号工作正常。所以我将触发器直接连接到GPIO头上的引脚16(GPIO23)。

您可以在RPI上使用任何您喜欢的GPIO引脚,但您需要注意引用并相应地修改您的Python脚本。

树莓派Python/C语言超声波测距以及利用超声波模块小车避障

模块的输出称为“回波”,需要更多思考。输出引脚为低电平(0V),直到模块进行距离测量。然后将此引脚设置为高电平(+ 5V),使脉冲返回相同的时间。所以我们的脚本需要衡量这个引脚保持高电平的时间。该模块对“高”使用+ 5V电平,但是对于仅适用于3.3V的GPIO头上的输入,该模块太高。为了确保Pi只能用3.3V命中,我们可以使用基本的分压器。这是由两个电阻组成。

如果R1和R2相同,则电压被分成两半。这将给我们2.5V。如果R2是R1的两倍,那么我们得到3.33V,这是很好的。所以理想情况下,您希望R2位于R1和R1 x2之间。在我的示例电路中,我使用了330和470欧姆的电阻。一个替代方案是使用1K和1K5值。如果不用也可以 ,但不保证不bug

这是我的最后一个电路图。我选择了GPIO23和GPIO24,但您可以使用GPIO头上的17个可用GPIO引脚中的任何一个。只要记住更新脚本。

树莓派Python/C语言超声波测距以及利用超声波模块小车避障

超声波模块电路

这是我的电路照片。我用了一小块面包板和一些男对女跳线。

树莓派Python/C语言超声波测距以及利用超声波模块小车避障

超声波传感器电路

Python脚本

现在脚本实际上要做一些测量。在这个例子中,我使用的是Python。为什么Python?这是Pi最喜欢的语言,所以我倾向于将它用于所有的实验,但是这里的技术很容易应用于C.

您可以直接使用此链接 或通过Pi上的命令行下载脚本:

wget https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/ultrasonic_1.py

然后可以使用以下命令运行:

sudo python ultrasonic_1.py

声音的速度

用于找到距离的计算依赖于声音的速度。这随温度而变化。脚本根据预定义的温度计算要使用的正确值。如果需要,您可以更改此值,或者使用温度传感器动态测量该值。

相片

以下是我通过GPIO头连接到Raspberry Pi的超声波传感器的一些照片:

准确性

这里有一些关于准确性的一些观点:

  • 距离测量的精度取决于时间。Linux下的Python不适合精确的时序,但是对于一般的操作,它可以正常工作。为了提高准确性,您需要开始使用C代替。

  • 当配置GPIO时,模块需要一段时间才能完成第一次读取,所以我在脚本开始时添加了0.5秒的延迟。

  • 传感器具有广泛的灵敏度。在杂乱的环境中,由于对象在模块的侧面,您可能会读取更短的读数。

  • 测量时间可达2厘米左右。低于这个限度,结果可以给出奇怪的结果。

  • 如果超声波传感器接触任何东西,结果是不可预知的。

感谢这项技术,我现在知道从我的桌子到天花板的距离是155厘米。

如果不用上面的代码 可以复制如下代码进行测试。我是在树莓派3B上运行

|

#! /usr/bin/python

# -*- coding:utf-8 -*-

#本代码实现的是树莓派利用超声波模块测距

#使用超声波测距模块时,VCC接树莓派的5V,GND接树莓派GND。trig接树莓派38,echo接树莓派40.

#GPIO编码方式为BOARD!!!

import RPi.GPIO as GPIO

import time

def checkdist():

#发出触发信号

GPIO.output(38,GPIO.HIGH)

#保持10us以上(我选择15us)

time.sleep(0.000015)

GPIO.output(38,GPIO.LOW)

while not GPIO.input(40):

pass

#发现高电平时开时计时

t1 = time.time()

while GPIO.input(40):

pass

#高电平结束停止计时

t2 = time.time()

#返回距离,单位为厘米

return (t2-t1)*34000/2

GPIO.setmode(GPIO.BOARD)

GPIO.setup(38,GPIO.OUT,initial=GPIO.LOW)

GPIO.setup(40,GPIO.IN)

time.sleep(2)

try:

while True:

print 'Distance: %0.2f cm' %checkdist()

time.sleep(0.5)

except KeyboardInterrupt:

GPIO.cleanup()

|

下面为小车避障的代码 ,先定义小车前后左右的动作。然后进行距离判断进行相应的动作。

|

#!/home/pi/server

# coding=utf-8

#使用超声波测距模块时,VCC接树莓派的5V,GND接树莓派GND。trig接树莓派38,echo接树莓派40.

#GPIO编码方式为BOARD!!

import RPi.GPIO as GPIO

import time

def t_stop():

GPIO.output(11,False)

GPIO.output(12,False)

GPIO.output(15,False)

GPIO.output(16,False)

def t_up():

GPIO.output(11,True)

GPIO.output(12,False)

GPIO.output(15,True)

GPIO.output(16,False)

def t_down():

GPIO.output(11,False)

GPIO.output(12,True)

GPIO.output(15,False)

GPIO.output(16,True)

def t_left():

GPIO.output(11,False)

GPIO.output(12,True)

GPIO.output(15,True)

GPIO.output(16,False)

def t_right():

GPIO.output(11,True)

GPIO.output(12,False)

GPIO.output(15,False)

GPIO.output(16,True)

def bee():

GPIO.output(12,True)

time.sleep(0.5)

GPIO.output(12,False)

GPIO.output(15,True)

time.sleep(5)

GPIO.output(12,True)

GPIO.output(15,False)

def checkdist():

#发出触发信号

GPIO.output(38,GPIO.HIGH)

#保持10us以上(我选择15us)

time.sleep(0.000015)

GPIO.output(38,GPIO.LOW)

while not GPIO.input(40):

pass

#发现高电平时开时计时

t1 = time.time()

while GPIO.input(40):

pass

#高电平结束停止计时

t2 = time.time()

#返回距离,单位为厘米

return (t2-t1)*34000/2

GPIO.setwarnings(False)

GPIO.setmode(GPIO.BOARD)

GPIO.setup(38,GPIO.OUT,initial=GPIO.LOW)

GPIO.setup(40,GPIO.IN)

GPIO.setup(11,GPIO.OUT)

GPIO.setup(12,GPIO.OUT)

GPIO.setup(15,GPIO.OUT)

GPIO.setup(16,GPIO.OUT)

##time.sleep(2)

try:

while True:

dis = int(checkdistance())

print(dis)

if dis <= 30:

print"distance less than 0.30m and back"

t_stop()

time.sleep(0.1)

t_down()

time.sleep(0.5)

t_left()

elif dis >30:

print"forward"

time.sleep(0.1)

t_up()

except KeyboardInterrupt:

GPIO.cleanup()

|

树莓派Python/C语言超声波测距以及利用超声波模块小车避障

此图与代码中定义是C语言的代码

如下为小车超声波避障的C代码

|

#include <stdio.h>

#include <stdlib.h>

#include <softPwm.h>

#include <unistd.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <time.h>

#include <wiringPi.h>

#define Trig28

#define Echo29

#define BUFSIZE 512

#define MOTOR_GO_FORWARD digitalWrite(1,HIGH); digitalWrite(4,LOW); digitalWrite(5,HIGH); digitalWrite(6,LOW)

#define MOTOR_GO_BACK digitalWrite(1,LOW); digitalWrite(4,HIGH); digitalWrite(5,LOW); digitalWrite(6,HIGH)

#define MOTOR_GO_RIGHT digitalWrite(1,HIGH); digitalWrite(4,LOW); digitalWrite(5,LOW); digitalWrite(6,LOW)

#define MOTOR_GO_LEFT digitalWrite(1,LOW); digitalWrite(4,LOW); digitalWrite(5,HIGH); digitalWrite(6,LOW)

#define MOTOR_GO_STOP digitalWrite(1, LOW); digitalWrite(4,LOW); digitalWrite(5, LOW); digitalWrite(6,LOW)

void ultraInit(void)

{

pinMode(Echo, INPUT);

pinMode(Trig, OUTPUT);

}

float disMeasure(void)

{

struct timeval tv1;

struct timeval tv2;

long start, stop;

float dis;

digitalWrite(Trig, LOW);

delayMicroseconds(2);

digitalWrite(Trig, HIGH);

delayMicroseconds(10); //发出超声波脉冲

digitalWrite(Trig, LOW);

while(!(digitalRead(Echo) == 1));

gettimeofday(& tv1, NULL); //获取当前时间

while(!(digitalRead(Echo) == 0));

gettimeofday(& tv2, NULL); //获取当前时间

start = tv1.tv_sec * 1000000 + tv1.tv_usec; //微秒级的时间

stop = tv2.tv_sec * 1000000 + tv2.tv_usec;

dis = (float)(stop - start) / 1000000 * 34990 / 2; //求出距离

return dis;

}

int main(int argc, char *argv[])

{

float dis;

// char buf[BUFSIZE]={0xff,0x00,0x00,0x00,0xff };

int time=1;

/*RPI*/

wiringPiSetup();

/*WiringPi GPIO*/

pinMode (1, OUTPUT); //IN1

pinMode (4, OUTPUT); //IN2

pinMode (5, OUTPUT); //IN3

pinMode (6, OUTPUT); //IN4

printf("ok"); //

while(1){

dis = disMeasure();

printf("distance = %0.2f cmn",dis); //输出当前超声波测得的距离

if(dis<30){ //测得前方障碍的距离小于30cm时做出如下响应

MOTOR_GO_BACK;

delay(time * 300);

MOTOR_GO_LEFT;

delay(time * 300);

}

else{

MOTOR_GO_FORWARD; //无障碍时前进

delay(time * 10);

MOTOR_GO_STOP;

}

}

return 0;

}

|

树莓派Python/C语言超声波测距以及利用超声波模块小车避障

原文始发于:树莓派Python/C语言超声波测距以及利用超声波模块小车避障

|

发表评论