2016-04-05 10 views
2

Özel bir arazi aracı için veri toplama sistemi oluşturmak için çalışma. RPM'yi ölçmek için Raspberry Pi ve özel bir takometre (test edilmiş ve onaylanmış çalışma) kullanma. RPM değerini almak için aşağıdaki kodda kesmeleri kullanın.Buji, ateşleme tahrikine bağlı olarak yanma motorunun durumunu öğrenmek için kullanın.

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 

Bu kod yalnızca motor çalışıyor ve kıvılcım çıkıyorsa çalışır. Kıvılcım yoksa, kod o kenarı bekliyor ve devam etmiyor. get_rpm() numaralı telefonu arayarak, kod bir kenar bekliyorsa, bu diğer işlemlerin askıda kalmasına neden olur.

Bunun için gerekli olan geçici çözümüm, motorun durumunu başka bir işlemde almaktır. Bence en iyi iki kısımda çalışacak. Ayrı bir iplik

Bölüm 1, çalışan (ilmek): Gerektiğinde

GPIO.wait_for_edge(17, GPIO.RISING) 
last = time.time 

Bölüm 2, bir fonksiyonu olarak, akan: Bölüm 1 ile

def get_state(): 
    while time.time - last < .5: 
     engine_state = true 
    else: 
     engine_state = false 
    return engine_state 

erişilebilir bellek last tasarruf Bölüm 2, Kısım 2, bujinin kıvılcımlandığı son zamana göre aracın çalışıp çalışmadığını belirler. Bir karşılaştırıcı olarak engine_state kullanarak, veri edinme sistemi 'dan sadece engine_state doğru olduğunda RPM değerini alır ve saklar.

Bölüm 1'i, Bölüm 2'de last değişkenini kullanabileceğim şekilde nasıl uygularım? last çok ama çok hızlı değişiyor. last güncelleştirildiğinde her zaman Raspberry Pi'nin SD kartındaki bir metin dosyasına depolamak istemiyorum. RAM'de last depolamak istiyorum.

Çok teşekkürler!

+0

'zaten RAM içinde, ben') (tek ihtiyacınız için 'get_state (son)' .. –

+0

'time.time'' olmalıdır time.time bir değişken olarak geçmektir last' düşünüyorum edilir Bence – jDo

+0

Pin konfigürasyonunu başka bir yere mi kuruyorsunuz ya da hiç kurmuyor musunuz? Bunun yerine kesme geri çağrılarını kullanamazdınız mı? Doğa tarafından işleniyorlar ve engellemeyecekler. Kenarı beklemek zorunda olduğunu düşünmüyorum. İlginç proje btw. :) – jDo

cevap

1

Bu sadece ilham almak içindir. Elimdeki Pisom yok, bu yüzden bu hafızadan körü körüne yazılmış.

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() 
""" 
+0

Bu, dişli geri aramaların nasıl kullanılacağına dair gerçekten harika bir örnektir ve kesinlikle yararlıdır. Sıkıştığım bir şey, bu yöntemi kullanarak RPM'yi doğru bir şekilde elde etmektir. Sinyalimizin yüksek harcadığı zaman, düşük harcadığı zamana eşit değildir. Kıvılcımlar arasındaki zaman (alçaktan yükseğe), kıvılcımın yüksekten alçalmasına kadar geçen süreden daha büyüktür. Görev döngüsü% 20 gibi bir şey olabilir. (Https: //en.wikipedia.org/wiki/Duty_cycle #/media/Dosya: PWM_duty_cycle_with_label.gif) Bu nedenle, RPM'yi hesaplamak için iki yükselen kenar veya iki düşen kenar arasındaki süreyi bulmamız gerekiyor. Kullanamıyoruz (devam) – Bobothetwit

+0

RPM'yi hesaplamak için yükselen kenar ile düşen kenar arasındaki süreyi kullanamıyoruz. Dişli bir geri çağrı kullanarak, geri dönüş (veya yükselen) kenarı algılandığında geri arama çalışır. Bu, mevcut RPM belirleme yöntemimiz ile uyumsuz. Pim 17'deki Wait_for_edge, aynı kod dosyasında add_event_detect ile birlikte kullanılamaz. Burada herhangi bir fikir var mı? jDo get_state işlevi BÜYÜK çalışıyor, ancak şu anda uygulandığı şekilde get_RPM ile aynı kodda aynı anda kullanamıyoruz. – Bobothetwit

+0

@Bobothetwit Sorunu unutmadım btw. Sadece okuyordum, ör. [burada] (http://forums.hybridz.org/topic/14725-pulsewidth-vs-dutycycle-vg30et-ecu/) ve takometre girişini taklit etmek için thread ve randomness kullanarak birkaç test yapıyor. RPM'nin görev döngüsü% 20 olduğunda ne olması gerektiğini biliyor musunuz? (Testlerim kapalı ya da gerçekten yararlı bir şey üretiyorsa bana söylerdi). – jDo

İlgili konular