【问题标题】:How to use Python to measure speed of bike like a digital speedometer, using a Raspberry Pi?如何使用 Python 来测量自行车的速度,比如使用 Raspberry Pi 的数字速度计?
【发布时间】:2017-02-09 11:48:57
【问题描述】:

我正在使用 Raspberry Pi 开展一个项目,并在 Python 中完成了代码。我的项目是测量从自行车四周的距离和自行车的速度。我可以使用超声波传感器测量距离,但尝试使用霍尔效应传感器测量速度,但速度读数异常。

例如,我得到 10 公里/小时,而另一个实例是 99 公里/小时,依此类推。我想像原始速度计一样读取,它可以提供逐渐递增或递减的读数。我在同一个文件中使用多个函数并在多个 GPIO 引脚上工作的另一件事是让我的程序变慢。

如何提高速度,以免错过任何 GPIO 的任何脉冲?这是我的代码和输出文件。

测距代码

import RPi.GPIO as GPIO
import time
import sys
import csv
from time import sleep
import math
GPIO.setmode(GPIO.BOARD)

TRIG1=7    #front ultrasonic sensor configuration
ECHO1=12

TRIG2=11  #back ultrasonic sensor configuration
ECHO2=15

TRIG3=13  #left ultrasonic sensor configuration
ECHO3=16

TRIG4=18    #right ultrasonic sensor configuration
ECHO4=22

j=10000    # maximum number of readings
data=[]


GPIO.setup(7,GPIO.OUT)
GPIO.output(TRIG1,0)        #front us sensor setup
GPIO.setup(12,GPIO.IN)
time.sleep(0.0001)

GPIO.setup(11,GPIO.OUT)
GPIO.output(TRIG2,0)   #back us sensor setup
GPIO.setup(15,GPIO.IN)
time.sleep(0.0001)

GPIO.setup(13,GPIO.OUT)
GPIO.output(TRIG1,0)   #left us sensor setup
GPIO.setup(16,GPIO.IN)
time.sleep(0.0001)

GPIO.setup(18,GPIO.OUT)
GPIO.output(TRIG2,0)  #right us sensor setup
GPIO.setup(22,GPIO.IN)
time.sleep(0.0001)

print ("starting measurements...........")

def front():
      GPIO.output(TRIG1,1)
      time.sleep(0.0001)#distance from front sensor
      GPIO.output(TRIG1,0)
      start1=time.time()
      stop1=time.time()
      while GPIO.input(ECHO1) == 0:
            start1=time.time()
      while GPIO.input(ECHO1) == 1:
            stop1=time.time()
      time1=stop1-start1
      distance1=time1 * 17000
      return distance1

def back():
      GPIO.output(TRIG2,1)
      time.sleep(0.0001) 
      GPIO.output(TRIG2,0)    #distance from back sensor
      start2=time.time()
      stop2=time.time()
      while GPIO.input(ECHO2) == 0:
            start2=time.time()
      while GPIO.input(ECHO2) == 1:
            stop2=time.time()
      time2=stop2-start2
      distance2=time2 * 17000
      return distance2
def left():
      GPIO.output(TRIG3,1)
      time.sleep(0.0001)
      GPIO.output(TRIG3,0)#distance from left sensor
      start3=time.time()
      stop3=time.time()
      while GPIO.input(ECHO3) == 0:
            start3=time.time()
      while GPIO.input(ECHO3) == 1:
            stop3=time.time()
      time3=stop3-start3
      distance3=time3 * 17000
      return distance3

def right():
      GPIO.output(TRIG4,1)
      time.sleep(0.0001)
      GPIO.output(TRIG4,0)  #distance from right sensor
      start4=time.time()
      stop4=time.time()
      while GPIO.input(ECHO4) == 0:
            start4=time.time()
      while GPIO.input(ECHO4) == 1:
            stop4=time.time()
      time4=stop4-start4
      distance4=time4 * 17000
      return distance4

with open('test.csv','w') as testfile:
      csv_writer = csv.writer(testfile)
      while j:
            distance1=front()
            distance2=back()
            distance3=left()
            distance4=right()
            data.append([distance1,distance2,distance3,distance4,time.ctime()])
            csv_writer.writerow([distance1,distance2,distance3,distance4,time.ctime()])
            time.sleep(0.5)
            j=j-1

lenth=len(data)
print (data) 
GPIO.cleanup ()

对于速度测量:

#!/usr/bin/python3
import RPi.GPIO as GPIO
from time import sleep
import time, math

dist_meas = 0.00
km_per_hour = 0
rpm = 0
elapse = 0
sensor = 29
pulse = 0
start_timer = time.time()

def init_GPIO():               # initialize GPIO
   GPIO.setmode(GPIO.BOARD)
   GPIO.setwarnings(False)
   GPIO.setup(sensor,GPIO.IN,GPIO.PUD_UP)

def calculate_elapse(channel):            # callback function
   global pulse, start_timer, elapse
   pulse+=1                        # increase pulse by 1 whenever interrupt occurred
   elapse = time.time() - start_timer      # elapse for every 1 complete rotation made!
   start_timer = time.time()            # let current time equals to start_timer

def calculate_speed(r_cm):
   global pulse,elapse,rpm,dist_km,dist_meas,km_per_sec,km_per_hour
   if elapse !=0:                     # to avoid DivisionByZero error
      rpm = 1/elapse * 60
      circ_cm = (2*math.pi)*r_cm         # calculate wheel circumference in CM
      dist_km = circ_cm/100000          # convert cm to km
      km_per_sec = dist_km / elapse      # calculate KM/sec
      km_per_hour = km_per_sec * 3600      # calculate KM/h
      dist_meas = (dist_km*pulse)*1000   # measure distance traverse in meter
      return km_per_hour

def init_interrupt():
   GPIO.add_event_detect(sensor, GPIO.FALLING, callback = calculate_elapse, bouncetime = 20)

if __name__ == '__main__':
   init_GPIO()
   init_interrupt()
   while True:
      calculate_speed(24)   # call this function with wheel radius as parameter
      print('rpm:{0:.0f}-RPM kmh:{1:.0f}-KMH dist_meas:{2:.2f}m pulse:{3}'.format(rpm,km_per_hour,dist_meas,pulse))
      sleep(0.1)

我得到这样的速度输出

rpm:0-RPM kmh:0-KMH dist_meas:0.00m pulse:0

rpm:4-RPM kmh:0-KMH dist_meas:1.51m pulse:1

rpm:4-RPM kmh:0-KMH dist_meas:1.51m pulse:1

rpm:4-RPM kmh:0-KMH dist_meas:1.51m pulse:1

rpm:4-RPM kmh:0-KMH dist_meas:1.51m pulse:1

rpm:4-RPM kmh:0-KMH dist_meas:1.51m pulse:1

rpm:104-RPM kmh:9-KMH dist_meas:3.02m pulse:2

rpm:433-RPM kmh:39-KMH dist_meas:4.52m pulse:3

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:365-RPM kmh:33-KMH dist_meas:6.03m pulse:4

rpm:22-RPM kmh:2-KMH dist_meas:7.54m pulse:5

rpm:22-RPM kmh:2-KMH dist_meas:7.54m pulse:5

rpm:229-RPM kmh:21-KMH dist_meas:9.05m pulse:6

rpm:388-RPM kmh:35-KMH dist_meas:10.56m pulse:7

rpm:388-RPM kmh:35-KMH dist_meas:10.56m pulse:7

rpm:971-RPM kmh:88-KMH dist_meas:13.57m pulse:9

rpm:627-RPM kmh:57-KMH dist_meas:15.08m pulse:10

rpm:318-RPM kmh:29-KMH dist_meas:16.59m pulse:11

rpm:1949-RPM kmh:176-KMH dist_meas:19.60m pulse:13

rpm:656-RPM kmh:59-KMH dist_meas:21.11m pulse:14

【问题讨论】:

  • 波动可能是由于没有通过取平均值来消除读数的结果吗?我认为在很短的距离上测量速度所产生的不准确性需要大量平均。
  • RPM 读数增加和减少,但不显示 0。例如,如果我开始测量,读数从 0 开始,随着速度的增加而增加并降低到一定水平,如果我们停止车轮,那么它将继续显示上次读数,例如,如果上次读数是 2rpm,那么它将继续显示 2 rpm 而不是显示 0。
  • 是因为您不再接收来自霍尔效应传感器的脉冲吗?这是意料之中的,我想。如果我快速停止我的电动自行车,那么显示器会开始降低当前速度(可能是线性的),并且需要几秒钟才能降低到零。您可能必须自己做。
  • 是的,我知道如果脉冲开始减少读数会减少,但是当我停止旋转车轮时,我没有从传感器收到任何脉冲,所以我的计数器应该自动重置为 0保持显示最后一个值。我只是需要帮助更改代码来实现这一点。感谢您的帮助
  • 好吧,如果它与大多数电动自行车上的磁铁/传感器配置类似,那么不会:只有当磁铁经过传感器时,您才会收到脉冲(开/关)。因此,如果您停下来,或者骑得非常慢,那么最后一个脉冲就会变得很久以前,那么您的速度计算基本上已经过时了,您需要手动将速度逐渐减小到零。如果您认为您的“计数器应该自动重置为 0”,那么您能确定上面显示的哪段代码是这样做的吗?

标签: python-2.7 python-3.x raspberry-pi raspberry-pi2


【解决方案1】:

我确实找到了可以快速获得结果的代码。也许它可以帮助你......无论如何我使用霍尔效应磁传感器

$

import RPi.GPIO as GPIO
import time


GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

pulse = 0
distance = 0
rpm = 0.00
speed = 0.00
wheel_c = 20
hall = 18
elapse = 0.00

start = time.time()

GPIO.setup(hall, GPIO.IN, pull_up_down = GPIO.PUD_UP)


def get_rpm():
    return rpm

def get_speed():
    return speed

def get_distance():
    return distance

def get_elapse():
    return elapse

def get_pulse(number):
    global elapse,distance,start,pulse,speed,rpm,multiplier
    cycle = 0
    pulse+=1
    cycle+=1
    if pulse > 0:
        elapse = time.time() - start
        pulse -=1
    if cycle > 0:
        distance += wheel_c
        cycle -= 1

    speed = (wheel_c*multiplier)/100000
    rpm = 1/elapse *60

    start = time.time()



try:

    time.sleep(1)

    GPIO.add_event_detect(hall,GPIO.FALLING,callback = get_pulse,bouncetime=20)
    while True:
    print('rpm:{0:.2f} speed:{1:.2f} distance:{2} elapse:{3:.4f}'.format(rpm,speed,distance,elapse))
        time.sleep(0.1) #to reduce CPU load, print every 100 milliseconds


except KeyboardInterrupt:
    print('You have pressed Ctrl+C! How dare you stopped this beautiful thing?!')
    GPIO.cleanup()
$

【讨论】:

    猜你喜欢
    • 2020-03-29
    • 1970-01-01
    • 2011-08-25
    • 2017-11-24
    • 2023-02-16
    • 1970-01-01
    • 2012-10-03
    • 2021-12-13
    • 2011-06-27
    相关资源
    最近更新 更多