在python中返回速度传感器读数为零

时间:2018-02-14 13:57:58

标签: python

我使用霍尔效应传感器和附在车轮上的小磁铁来测量旋转车轮的速度,单位为m / s。

代码是用python编写的,在测量速度,距离,转速等时工作得相当好。但是当车轮停止时,速度永远不会恢复到0m / s。

我尝试修改if语句,这样如果经过的时间(即旋转所需的时间)大于3秒,我们可以假设轮子处于静止状态。

这可能是一个简单的修复,但我似乎无法弄清楚,有人可以建议吗?提前谢谢。

我的代码

Distance = 0.00
mps = 0
rpm = 0
elapse = 0
sensor = 5
pulse = 0
start_timer = time.time()

def init_GPIO():                                   # initialize GPIO
        GPIO.setmode(GPIO.BCM)
        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_m,Distance,mps
        if elapse !=0 and elapse < 3:              # to avoid DivisionByZero error
                rpm = 1/elapse * 60
                circ_cm = (2*math.pi)*r_cm         # calculate wheel circumference in CM
                dist_m = circ_cm/100               # convert cm to m
                mps = dist_m / elapse              # calculate m/sec      
                Distance = (dist_m*pulse)          # measure distance
                return mps
        else: 
                mps = 0
                return mps

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(3.4)               # call this function with wheel radius as parameter
                print('{0:.0f}rpm     {1:.2f}m/s     {2:.2f}m     Counter:{3}'.format(rpm,mps,Distance,pulse))
                sleep(0.1)

1 个答案:

答案 0 :(得分:0)

如果车轮没有转动,则不会调用calculate_elapse。这意味着elapse永远不会设置为“大”(&gt; = 3)值,因此永远不会触发mps = 0短路。

你使用全局变形让我心烦意乱,所以我有机会重写这个...这是未经测试的,但希望你会明白为什么这会更好一些:

import math
import time

import RPi.GPIO as GPIO  # This is my best guess :-)


SENSOR_ID = 5
WHEEL_RADIUS_CM = 3.4


class UnknownRotationError(Exception):
    pass


class WheelTimer:
    MAX_ACCEPTABLE_DURATION = 3.0

    def __init__(self, wheel_radius_cm):
        self.wheel_radius_cm = wheel_radius_cm
        self._wheel_circ_m = ((2 * math.pi) * self.wheel_radius_cm) / 100

        self.num_full_rotations = 0
        self.total_distance_m = 0.0

        self.last_rotation_duration_s = None
        self._rotation_started_time = time.time()

    def complete_rotation(self):
        """Record a completed revolution."""
        self.num_full_rotations += 1
        self.total_distance_m = self._wheel_circ_m * self.num_full_rotations
        now = time.time()
        self.last_rotation_duration_s = self.rotation_started_time - now
        self._rotation_started_time = now

    @property
    def current_rotation_duration(self):
        return self.rotation_started_time - time.time()

    def _validate_rotation(self):
        if not self.last_rotation_duration_s:
            raise UnknownRotationError()
        if self.last_rotation_duration_s > self.MAX_ACCEPTABLE_DURATION:
            raise UnknownRotationError()
        if self.current_rotation_duration > self.MAX_ACCEPTABLE_DURATION:
            raise UnknownRotationError()

    @property
    def current_speed_ms(self):
        self._validate_rotation()
        return self._wheel_circ_m / self.last_rotation_duration_s

    @property
    def current_rpm(self):
        self._validate_rotation()
        return (1.0 / self.last_rotation_duration_s) * 60.0


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


def init_interrupt(callback_func):
    GPIO.add_event_detect(SENSOR_ID, GPIO.FALLING, callback=callback_func, bouncetime=20)


if __name__ == '__main__':
    init_GPIO()
    wheel_timer = WheelTimer(WHEEL_RADIUS_CM)
    init_interrupt(callback_func=wheel_timer.complete_rotation)
    while True:
        time.sleep(0.1)
        try:
            print('{0:.0f}rpm     {1:.2f}m/s     {2:.2f}m     Counter:{3}'.format(
                wheel_timer.current_rpm,
                wheel_timer.current_speed_ms,
                wheel_timer.total_distance_m,
                wheel_timer.num_full_rotations,
            ))
        except UnknownRotationError:
            print("Wheel moving too slowly to measure!")