简体   繁体   English

Python 中的倒数计时器(用于电机 RPM 的 Raspberry Pi)

[英]Countdown timer in Python (Raspberry Pi for motor RPM)

I am trying to get a reasonable RPM for a motor.我正在尝试为电机获得合理的 RPM。 I have a photo-interrupter that sends 0 or 1 if it detects a slit that passes by.我有一个光断续器,如果它检测到一个经过的狭缝,它会发送 0 或 1。 My code is as following, what I simply need is to time 0-60 seconds, and add the number of times 1 was detected and then divide it by 60, thus RPM.我的代码如下,我只需要计时 0-60 秒,加上检测到 1 的次数,然后除以 60,即 RPM。

I don't want to complicate my code, also keep in mind this is running on the Raspberry Pi with many other scripts and webservers running behind it.我不想让我的代码复杂化,还要记住这是在 Raspberry Pi 上运行的,并且有许多其他脚本和网络服务器在它后面运行。 So not a bad code like "sleep" that would hog down the entire cpu.因此,像“睡眠”这样的糟糕代码会占用整个 CPU。

I'm not looking for a crazy accurate measurement, just a reasonable idea of how fast the motor is spinning.我不是在寻找一个疯狂的准确测量,只是一个关于电机旋转速度的合理想法。 Also does the slit size make a difference?狭缝大小也有区别吗?

import RPi.GPIO as GPIO 
import time
signal = 21

from time import sleep     # this lets us have a time delay (see line 15)  
GPIO.setmode(GPIO.BCM)     # set up BCM GPIO numbering  
GPIO.setup(signal, GPIO.IN)    # set GPIO21 as input (signal)  
GPIO.add_event_detect(signal,GPIO.BOTH)


try:  
    while True:            # this will carry on until you hit CTRL+C  
        if GPIO.event_detected(signal): # if port 21 == 1  
            print "Port 21 is 1/HIGH/True - LED ON"  
            slit=slit+1       # Counts every time slit passes

        else:  
            print "Port 21 is 0/LOW/False - LED OFF"  
        rpm = slit/60         # Calculates the RPM
        sleep(0.0001)         # wait 0.0001 seconds  

finally:                   # this block will run no matter how the try block exits  
    GPIO.cleanup()         # clean up after yourself  

With the reservation that I have never programmed an RPi using Python, this is how I would try to tackle this task:保留我从未使用 Python 对 RPi 进行编程的保留,这就是我尝试解决此任务的方式:

import RPi.GPIO as GPIO 
import threading

signal = 21
GPIO.setmode(GPIO.BCM)     # set up BCM GPIO numbering  
GPIO.setup(signal, GPIO.IN)    # set GPIO21 as input (signal)  

slit = 0
rpm = 0

def increment():
    global slit
    print("Port 21 is 1/HIGH/True - LED ON")
    slit += 1

def count_complete():
    global slit
    global rpm
    rpm = slit/60
    print ("RPM = {}".format(rpm))
    # reset and restart timer
    slit = 0
    t = threading.Timer(60, count_complete)

# Bounce will prevent double detection of the same rising edge (for 1 ms)
GPIO.add_event_detect(signal, GPIO.RISING, callback=increment, bounce=1)

t = threading.Timer(60, count_complete)
try:  
    while True:            # this will carry on until you hit CTRL+C
        pass               # Do nothing but wait for callbacks and timer
finally:                   # this block will run no matter how the try block exits
    t.cancel()             # stop the timer  
    GPIO.cleanup()         # clean up after yourself  

As can be seen, I have added a callback function that will be called as soon as a rising edge is detected on the input.可以看出,我添加了一个回调函数,一旦在输入上检测到上升沿,就会调用该函数。 Here the clit counter is incremented.这里阴蒂计数器增加。 The bounce parameter is a protection that will stop the program from counting the same slit double.反弹参数是一种保护,将阻止程序计算相同的狭缝双倍。

Setting at 1 ms means that the RPM needs to be (well) below 1,000 or some slits will be missed.设置为 1 ms 意味着 RPM 需要(远)低于 1,000,否则会遗漏一些狭缝。 It is possible to experiment by removing this.可以通过删除它来进行实验。 I don't know if it is possible to give a fractional bounce time.我不知道是否可以给出分数反弹时间。 That may be another option.那可能是另一种选择。

The main program then, stats a timer, that lets the increment run for 1 minute, after which the RPM is calculated and the system reset and a new count is initiated.然后,主程序统计一个计时器,让增量运行 1 分钟,之后计算 RPM 并重置系统并启动新的计数。 (There is a risk of a race condition here, where a slit interrupt may happen while doing the calculation. This could be missed in these cases.) (这里存在竞争条件的风险,在进行计算时可能会发生狭缝中断。在这些情况下可能会错过这一点。)

Then in the main loop, nothing happens, except for the program waiting for interrupts (slit, timer or ctrl-c).然后在主循环中,除了等待中断(slit、timer 或 ctrl-c)的程序之外,什么也没有发生。 This is a busy wait, since it will continuously run the pass statement, doing nothing.这是一个忙碌的等待,因为它会不断地运行pass语句,什么都不做。 Maybe there is a way to improve performance and make the program completely event driven, freeing up the CPU in the mean time, but that is a bigger task than I am attempting here.也许有一种方法可以提高性能并使程序完全由事件驱动,同时释放 CPU,但这比我在这里尝试的任务更大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM