2017-07-03 4 views
0

J'essaie d'obtenir un RPM raisonnable pour un moteur. J'ai un photo-interrupter qui envoie 0 ou 1 s'il détecte une fente qui passe. Mon code est le suivant, ce dont j'ai simplement besoin est de chronométrer 0-60 secondes, et d'ajouter le nombre de fois que 1 a été détecté, puis le diviser par 60, donc RPM.Compte à rebours en Python (Raspberry Pi pour moteur RPM)

Je ne veux pas compliquer mon code, gardez également à l'esprit que cela fonctionne sur le Raspberry Pi avec de nombreux autres scripts et serveurs web. Donc, pas un mauvais code comme "sommeil" qui serait monopoliser tout le cpu.

Je ne cherche pas une mesure précise et folle, juste une idée raisonnable de la vitesse à laquelle le moteur tourne. Est-ce que la taille de la fente fait aussi une différence?

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 
+1

'sleep' est l'opposé de l'accaparement de la CPU. Cela le libérera pour d'autres tâches. Donc, ce serait une bonne solution en utilisant 'sleep', mais vous ne pouvez pas être sûr que vous obtenez exactement 60 secondes de sommeil. Cela peut être un peu plus, donc vous devriez probablement essayer d'obtenir des tampons temporels et de corriger les décalages si vous voulez une valeur plus exacte. – JohanL

+0

@JohanL Merci, mais comment l'implémenterais-je? –

Répondre

1

Avec la réserve que je ne l'ai jamais programmé un RPI en utilisant Python, voilà comment je voudrais essayer d'aborder cette tâche:

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 

Comme on peut le voir, je l'ai ajouté une fonction de rappel sera appelé dès qu'un front montant est détecté sur l'entrée. Ici le compteur de clit est incrémenté. Le paramètre bounce est une protection qui empêchera le programme de compter le même double fente.

Le réglage à 1 ms signifie que le RPM doit être (bien) inférieur à 1 000 ou que certaines fentes seront manquées. Il est possible d'expérimenter en supprimant cela. Je ne sais pas s'il est possible de donner un temps de rebond fractionné. Cela peut être une autre option. Le programme principal calcule alors une minuterie, qui permet à l'incrément de fonctionner pendant 1 minute, après quoi le RPM est calculé et le système réinitialisé et un nouveau compte est lancé. (Il y a un risque de condition de course ici, où une interruption de fente peut se produire pendant le calcul.)

Ensuite, dans la boucle principale, rien ne se passe, sauf pour le programme qui attend interruptions (fente, minuterie ou ctrl-c). Il s'agit d'une attente très occupée, car elle exécutera continuellement l'instruction pass, ne faisant rien. Peut-être y a-t-il un moyen d'améliorer les performances et de rendre le programme complètement axé sur les événements, libérant ainsi le CPU en attendant, mais c'est une tâche plus importante que celle que j'essaie ici.