问题
Working to create a data acquisition system for a custom off-road vehicle. Using Raspberry Pi and a custom tachometer (tested and confirmed working) to measure RPM. Using interrupts in the following code to get RPM value.
def get_rpm():
GPIO.wait_for_edge(17, GPIO.FALLING)
start = time.time()
GPIO.wait_for_edge(17, GPIO.FALLING)
end = time.time()
duration = end - start
rpm = (1/duration)*60
return rpm
This code only works if the engine is running and producing a spark. If there is no spark, the code sits waiting for that edge and does not proceed. When calling get_rpm()
, if the code is waiting for an edge, this causes other processes to hang.
My intended workaround for this is to get the state of the engine in another process. I think it will work best in two parts.
Part 1, running (looped) in a separate thread:
GPIO.wait_for_edge(17, GPIO.RISING)
last = time.time
Part 2, running called as a function as needed:
def get_state():
while time.time - last < .5:
engine_state = true
else:
engine_state = false
return engine_state
With Part 1 saving last
to memory accessible to Part 2, Part 2 will determine whether or not the car is running based on the last time the spark plug sparked. Using engine_state
as a comparator, the data acquisition system will get and store the RPM value from get_rpm()
only when engine_state
is true.
How can I implement Part 1 in such a way that I can use the last
variable in Part 2? last
will be changing very, very quickly. I don't want to store it to a text file on the Raspberry Pi's SD card every time last
is updated. I want to store last
in RAM.
Thanks so much!
回答1:
This is just for inspiration. I don't have my Pis at hand so this is written blindly from memory.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)
# the line below is important. It'll fire on both rising and falling edges
# and it's non-blocking
GPIO.add_event_detect(17, GPIO.BOTH, callback=callback_func)
length_of_last_high = 0
length_of_last_low = 0
last_rise = 0
last_fall = 0
last_callback = 0
def callback_func(pin):
# all of these global variables aren't needed
# but I left them in for demo purposes
global last_rise
global last_fall
global last_callback
global length_of_last_high
global length_of_last_low
last_callback = time.time()
if GPIO.input(17):
print "Pin 17 is rising!"
length_of_last_high = last_callback - last_rise
last_rise = last_callback
else:
print "Pin 17 is falling!"
length_of_last_low = last_callback - last_fall
last_fall = last_callback
# last passed as parameter (the preferred solution if it works).
# You test it - I can't at the moment
def get_state(last=last_rise):
engine_state = False
if time.time() - last < .5:
engine_state = True
return engine_state
# last as global variable.
# This works too but global is bad practice if it can be avoided
# (namespace littering)
def get_state2():
global last_rise
engine_state = False
if time.time() - last_rise < .5:
engine_state = True
return engine_state
def main():
while True:
print "Not blocking! This loop could sleep forever. It wouldn't affect the readings"
time.sleep(1)
print get_state()
"""
GPIO.cleanup()
"""
来源:https://stackoverflow.com/questions/36438345/use-python-to-get-state-of-combustion-engine-based-on-spark-plug-actuation