I've got a little problem while creating the GUI for my Python program.
In the code, i've implemented this function:
def simula_partita(modello, squadraCasa, squadraOspite, max_gol=10):
media_gol_casa = modello.predict(pd.DataFrame(data={'Squadra': squadraCasa,
'Avversaria': squadraOspite, 'Casa':1},
index=[1])).values[0]
media_gol_ospiti = modello.predict(pd.DataFrame(data={'Squadra': squadraOspite,
'Avversaria': squadraCasa, 'Casa':0},
index=[1])).values[0]
previsione_squadra = [[poisson.pmf(i, media_squadra) for i in range(0, max_gol+1)]
for media_squadra in [media_gol_casa, media_gol_ospiti]]
ris = np.outer(np.array(previsione_squadra[0]), np.array(previsione_squadra[1]))
print(ris)
return(ris)
It takes four arguments (modello, squadraCasa, squadraOspite, max_gol).
If I call it in the code, like this:
simula_partita(modello_poisson, 'Juventus', 'Liverpool', max_gol=4)
It goes smoothly and gives me the desidered output.
Now, at the end of the code, I tried doing a GUI with this code:
root = Tk()
m = StringVar()
c = StringVar()
o = StringVar()
g = StringVar()
sceltaModello = Entry(root, textvariable = m)
sceltaCasa = Entry(root, textvariable = c)
sceltaOspite = Entry(root, textvariable = o)
sceltaGol = Entry(root, textvariable = g)
sceltaModello.pack()
sceltaCasa.pack()
sceltaOspite.pack()
sceltaGol.pack()
m.set('modello_poisson')
c.set('Squadra di Casa')
o.set('Squadra Ospite')
g.set('Max Gol')
modello = m.get()
squadraCasa = c.get()
squadraOspite = o.get()
max_gol = g.get()
avvia = Button(root, text = "Avvia Simulazione", command = simula_partita)
avvia.pack()
root.mainloop()
My wish was to get "modello", "squadraCasa", "squadraOspite" and "max_gol" as the Entry() input, but it doesn't seems to work and it gives me the error that the function "simula_partita" needs those parameters.
Could you help me figure out this problem?
Thanks a lot in advance!
Your function is defined with 4 parameters. You have to pass those parameters when the function is called via the command option in the Button. I don't exactly know what you function does, so, i'll replace it to print the 4 parameters for now.
from tkinter import *
import sqlite3
root = Tk()
def simula_partita(modello, squadraCasa, squadraOspite, max_gol=10):
print(modello, squadraCasa, squadraOspite, max_gol)
m = StringVar()
c = StringVar()
o = StringVar()
g = StringVar()
sceltaModello = Entry(root, textvariable = m)
sceltaCasa = Entry(root, textvariable = c)
sceltaOspite = Entry(root, textvariable = o)
sceltaGol = Entry(root, textvariable = g)
sceltaModello.pack()
sceltaCasa.pack()
sceltaOspite.pack()
sceltaGol.pack()
m.set('modello_poisson')
c.set('Squadra di Casa')
o.set('Squadra Ospite')
g.set('Max Gol')
avvia = Button(root, text = "Avvia Simulazione", command = lambda: simula_partita(m.get(), c.get(), o.get(), g.get()))
avvia.pack()
root.mainloop()
Edit: To answer OP's specific question
The entry field has to be set to a string. I understand that you are trying to pass as argument a variable. But the output of the entry field will be a string.
What you can do is create a dict with the string as key and the variable as value (ie 'data' in the below code) and the send the variable like data[m.get()]. If you have more variable that can be give you can add it as another key value pair in that dictionary.
Also the 4th parameter is an int so i have made it an int before passing using int().
Try changing to these lines in your full code.
m.set('modello_poisson')
c.set('Squadra di Casa')
o.set('Squadra Ospite')
g.set('Max Gol')
data={'modello_poisson':modello_poisson}
avvia = Button(root, text = "Avvia Simulazione", command = lambda: simula_partita(data[m.get()], c.get(), o.get(), int(g.get())))
I gave the following in the 4 entry fields entries
modello_poisson
Juventus
Atalanta
4
and got an output
[[0.03608837 0.03099437 0.0133097 0.00381033 0.00081812]
[0.08888343 0.07633721 0.03278097 0.00938461 0.00201498]
[0.1094572 0.09400692 0.04036875 0.01155685 0.00248139]
[0.0898621 0.07717774 0.03314191 0.00948794 0.00203717]
[0.0553312 0.047521 0.02040662 0.00584205 0.00125436]]
printed to my console.
Full code:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn
from scipy.stats import poisson,skellam
from tkinter import *
serieA_1819 = pd.read_csv("http://www.football-data.co.uk/mmz4281/1819/I1.csv")
serieA_1819 = serieA_1819[['HomeTeam','AwayTeam','FTHG','FTAG']]
serieA_1819 = serieA_1819.rename(columns={'FTHG': 'GolCasa', 'FTAG': 'GolOspiti'})
serieA_1819.head()
print(serieA_1819.head())
# Faccio una media dei gol segnati dalla squadra di casa e quelli segnati dalla squadra ospite.
# Come si può notare dall'output, generalmente la squadra di casa ha una media gol più alta.
# Questo fenomeno viene definito come "Home Field Advantage".
serieA_1819.mean()
print(serieA_1819.mean())
# Costruisco una distribuzione di Poisson per ogni media gol.
# La distribuzione di Poisson è una distribuzione di probabilità discreta,
# che descrive la probabilità che si verifichino un determinato numero di eventi
# in un arco di tempo predefinito (nel caso di una partita di calcio, 90 minuti),
# basandosi su un tasso di verifica dell'evento già noto.
poisson_pred = np.column_stack([[poisson.pmf(i, serieA_1819.mean()[j]) for i in range(8)] for j in range(2)])
# Plotto l'istogramma dei gol
plt.hist(serieA_1819[['GolCasa', 'GolOspiti']].values, range(9),
alpha=0.7, label=['Casa', 'Ospiti'],density=True, color=["#41FF32", "#20B2AA"])
# Aggiungo le linee per la distribuzione di Poisson
pois1, = plt.plot([i-0.5 for i in range(1,9)], poisson_pred[:,0],
linestyle='-', marker='o',label="Casa", color = '#000080')
pois2, = plt.plot([i-0.5 for i in range(1,9)], poisson_pred[:,1],
linestyle='-', marker='o',label="Ospiti", color = '#FF0000')
legenda=plt.legend(loc='upper right', fontsize=13, ncol=2)
legenda.set_title("Poisson Reale ", prop = {'size':'14', 'weight':'bold'})
plt.xticks([i-0.5 for i in range(1,9)],[i for i in range(9)])
plt.xlabel("Gol a Partita",size=13)
plt.ylabel("Proporzione per Partita",size=13)
plt.title("Numero di Gol per Partita (Serie A 2018/2019)",size=14,fontweight='bold')
plt.ylim([-0.004, 0.4])
plt.tight_layout()
plt.show()
# Ovviamente il numero di gol segnato da una squadra è indipendente dall'altro.
# La differenza tra due distribuzioni di Poisson viene chiamata "Distribuzione di Skellam",
# che ci permetterà di calcolare le probabilità che la partita finisca in pareggio
# o con la vittoria di una delle due squadre.
# Effettuo una previsione dei gol basandomi sulla distribuzione di Skellam
prev_skellam = [skellam.pmf(i, serieA_1819.mean()[0], serieA_1819.mean()[1]) for i in range(-6,8)]
plt.hist(serieA_1819[['GolCasa']].values - serieA_1819[['GolOspiti']].values, range(-6,8),
alpha=0.7, label='Reale',density=True)
plt.plot([i+0.5 for i in range(-6,8)], prev_skellam,
linestyle='-', marker='o', label="Skellam", color='#FF0000')
plt.legend(loc='upper right', fontsize=13)
plt.xticks([i+0.5 for i in range(-6,8)],[i for i in range(-6,8)])
plt.xlabel("Gol Casa - Gol Ospiti", size=13)
plt.ylabel("Proporzione per partita", size=13)
plt.title("Differenza Gol segnati (Squadra di Casa vs Squadra Ospite)", size=14, fontweight='bold')
plt.ylim([-0.004, 0.30])
plt.tight_layout()
plt.show()
# Per adattare questo modello a una partita specifica, dobbiamo conoscere
# il numero medio di gol segnati per partita da ogni squadra.
# Utilizziamo come esempio Juventus e Inter.
fig,(ax1,ax2) = plt.subplots(2, 1)
# Creo delle distribuzioni di Poisson sui gol fatti in casa e fuori casa di entrambe le squadre
inter_casa = serieA_1819[serieA_1819['HomeTeam']=='Inter'][['GolCasa']].apply(pd.value_counts, normalize=True)
inter_casa_poisson = [poisson.pmf(i, np.sum(np.multiply(inter_casa.values.T, inter_casa.index.T), axis=1)[0])
for i in range(8)]
juve_casa = serieA_1819[serieA_1819['HomeTeam']=='Juventus'][['GolCasa']].apply(pd.value_counts, normalize=True)
juve_casa_poisson = [poisson.pmf(i, np.sum(np.multiply(juve_casa.values.T, juve_casa.index.T), axis=1)[0])
for i in range(8)]
inter_ospiti = serieA_1819[serieA_1819['AwayTeam']=='Inter'][['GolOspiti']].apply(pd.value_counts, normalize=True)
inter_ospiti_poisson = [poisson.pmf(i, np.sum(np.multiply(inter_ospiti.values.T, inter_ospiti.index.T), axis=1)[0])
for i in range(8)]
juve_ospiti = serieA_1819[serieA_1819['AwayTeam']=='Juventus'][['GolOspiti']].apply(pd.value_counts, normalize=True)
juve_ospiti_poisson = [poisson.pmf(i, np.sum(np.multiply(juve_ospiti.values.T, juve_ospiti.index.T), axis=1)[0])
for i in range(8)]
# Questa è stata la parte che mi ha fatto smadonnare di più.
# Inizialmente i vettori "squadra_casa.values" e "squadra_ospiti.values" davano errore
# poiché venivano interpretati come vettori in 2D anzichè in 1D.
# Dopo varie analisi e ricerche su internet (le consiglio, se non lo conosce già,
# il forum "StackOverflow", veramente ben fornito, mi hanno aiutato a risolvere in meno di 5 minuti.),
# ho scoperto che bastava aggiungere ".flatten()" al vettore per poterlo avere in 1D.
# Questo ha risolto il mio problema, e in questa parte, sempre tramite la distribuzione di Poisson,
# genero un grafico che mi fa vedere le statistiche riguardo i gol fatti dalle due squadre
# quando giocano in casa e quando giocano fuori casa.
ax1.bar(inter_casa.index-0.4, inter_casa.values.flatten(), width=0.4, color="#034694", label="Inter")
ax1.bar(juve_casa.index, juve_casa.values.flatten(), width=0.4, color="#000000", label="Juventus")
pois1, = ax1.plot([i for i in range(8)], inter_casa_poisson,
linestyle='-', marker='o', label="Inter", color="#0A7BFF")
pois1, = ax1.plot([i for i in range(8)], juve_casa_poisson,
linestyle='-', marker='o', label="Juventus", color="#FF7C89")
legenda = ax1.legend(loc='upper right', fontsize=12, ncol=2)
legenda.set_title("Poisson Reale ", prop={'size':'14', 'weight':'bold'})
ax1.set_xlim([-0.5,7.5])
ax1.set_ylim([-0.01,0.65])
ax1.set_xticklabels([])
ax1.text(7.65, 0.585, ' Casa ', rotation=-90,
bbox={'facecolor':'#FFBCF6', 'alpha':0.5, 'pad':5})
ax2.text(7.65, 0.585, ' Ospiti ', rotation=-90,
bbox={'facecolor':'#FFBCF6', 'alpha':0.5, 'pad':5})
ax2.bar(inter_ospiti.index-0.4, inter_ospiti.values.flatten(), width=0.4, color="#034694", label="Inter")
ax2.bar(juve_ospiti.index, juve_ospiti.values.flatten(), width=0.4, color="#000000", label="Juventus")
pois1, = ax2.plot([i for i in range(8)], inter_ospiti_poisson,
linestyle='-', marker='o', label="Inter", color="#0A7BFF")
pois1, = ax2.plot([i for i in range(8)], juve_ospiti_poisson,
linestyle='-', marker='o', label="Juventus", color="#FF7C89")
ax2.set_xlim([-0.5,7.5])
ax2.set_ylim([-0.01,0.65])
ax1.set_title("Numero di Gol per Partita (Serie A 2018/2019)", size=14, fontweight='bold')
ax2.set_xlabel("Gol per Partita", size=13)
ax2.text(-1.15, 0.9, 'Proporzione per Partita', rotation=90, size=13)
plt.tight_layout()
plt.show()
# Ora costruirò un modello di Regressione di Poisson per analizzare
# tutti i risultati possibili per ogni partita possibile.
# Citando Wikipedia: La regressione di Poisson assume che
# la variabile di risposta Y ha una distribuzione di Poisson,
# e assume che il logaritmo del suo valore aspettato possa essere modellato
# da una combinazione lineare di parametri sconosciuti.
import statsmodels.api as sm
import statsmodels.formula.api as smf
modello_gol = pd.concat([serieA_1819[['HomeTeam','AwayTeam','GolCasa']].assign(Casa=1).rename(
columns={'HomeTeam':'Squadra', 'AwayTeam':'Avversaria','GolCasa':'Gol'}),
serieA_1819[['AwayTeam','HomeTeam','GolOspiti']].assign(Casa=0).rename(
columns={'AwayTeam':'Squadra', 'HomeTeam':'Avversaria', 'GolOspiti':'Gol'})])
modello_poisson = smf.glm(formula="Gol ~ Casa + Squadra + Avversaria", data=modello_gol,
family=sm.families.Poisson()).fit()
modello_poisson.summary()
print(modello_poisson.summary())
# Cosa significa l'output di questa porzione di codice?
# Il modello della distribuzione di Poisson avviene tramite
# il "GLM", ovvero un "Modello Lineare Generalizzato".
# Il paramentro da prendere in considerazione è quello della
# colonna "coef".
# Esso è da intendere come il coefficiente che indica la probabilità
# che la squadra faccia gol, utilizzandolo come esponente di "e".
# Un valore positivo di "coef" indica una maggiore possibilità di segnare,
# mentre un valore più vicino allo zero indica una neutralità (e^0 = 1).
# Alla fine della lista è possibile notare che "Casa" ha un valore "coef" di 0.2510.
# Ciò significa che la squadra che gioca in casa ha più probabilità di fare gol
# (nello specifico, e^0.2510 = 1.28 volte più probabile che segni).
# Ovviamente non tutte le squadre hanno lo stesso livello.
# Andando ad analizzare, per esempio, Frosinone e Sampdoria,
# i valori di "coef" sono -1.1868 (Frosinone) e -0.2197 (Sampdoria).
# Da ciò si evince appunto che la Sampdoria ha molte più probabilità
# di fare gol (0.80) rispetto al Frosinone (0.30).
# Se andiamo invece ad analizzare lo stesso valore quando la squadra è ospite,
# viene considerata quindi come "Avversaria", un valore più alto di "coef" indica
# una minor probabilità di poter segnare contro quella squadra,
# ovvero la probabilità che quella squadra ha di non subire gol.
# Prendiamo ad esempio Roma e Lazio.
# La Roma come avversaria ha un "coef" di -0.1366, mentre la Lazio -0.2766.
# Questo significa che avrei più probabilità di segnare contro
# la Lazio (0.75) che contro la Roma (0.87).
# Andiamo ora ad effettuare delle previsioni su alcune partite.
# Il modello Poissoniano riceverà come parametri le due squadre,
# e restituirà come output il valore medio di gol che ogni squadra potrebbe segnare.
# Ipotizziamo una partita Genoa - Milan.
gol_genoa_vs_milan = modello_poisson.predict(pd.DataFrame(data={'Squadra': 'Genoa', 'Avversaria': 'Milan',
'Casa':1},index=[1]))
print(gol_genoa_vs_milan)
gol_milan_vs_genoa = modello_poisson.predict(pd.DataFrame(data={'Squadra': 'Milan', 'Avversaria':'Genoa',
'Casa':0},index=[1]))
print(gol_milan_vs_genoa)
# Queste due previsioni ci daranno in output la probabilità di segnare delle due squadre.
# Ora definisco una funzione che simula una partita tra due squadre che andrò a inserire come parametri.
def simula_partita(modello, squadraCasa, squadraOspite, max_gol=10):
media_gol_casa = modello.predict(pd.DataFrame(data={'Squadra': squadraCasa,
'Avversaria': squadraOspite, 'Casa':1},
index=[1])).values[0]
media_gol_ospiti = modello.predict(pd.DataFrame(data={'Squadra': squadraOspite,
'Avversaria': squadraCasa, 'Casa':0},
index=[1])).values[0]
previsione_squadra = [[poisson.pmf(i, media_squadra) for i in range(0, max_gol+1)]
for media_squadra in [media_gol_casa, media_gol_ospiti]]
ris = np.outer(np.array(previsione_squadra[0]), np.array(previsione_squadra[1]))
print(ris)
return(ris)
# Dopo aver definito la funzione, provo a simulare una partita.
# Scelgo Fiorentina - Sassuolo.
simula_partita(modello_poisson, 'Fiorentina', 'Sassuolo', max_gol=4)
# Come si può notare dall'output, la funzione dà come risultato una matrice.
# Le righe della matrice rappresentano le probabilità della squadra di casa
# (in questo caso la Fiorentina), di segnare da 0 a max_gol,
# mentre le colonne rappresentano la stessa probabilità per la squadra
# ospite, (in questo caso il Sassuolo).
# Lungo la diagonale si trovano le varie probabilità di pareggio, che vanno
# dal caso 0-0 al caso 4-4.
# Sommando tutti gli elementi della diagonale, si ottiene la probabilità di pareggio.
# Se sommiamo gli elementi sotto la diagonale, otteniamo le probabilità di vittoria
# della squadra di casa, mentre la somma degli elementi sopra la diagonale ci darà
# la probabilità di vittoria della squadra ospite.
# Arriviamo dunque alla parte finale del programma, quella che io (e probabilmente anche lei, immagino),
# utilizzeremo per giocarci le future schedine. Ovviamente non garantisco un 100% di affidabilità,
# ma suppongo che affidarsi alla statistica a volte sia megio che farlo all'intuito.
# Il 19 Gennaio ricomincia la Serie A.
# Sfrutteremo l'occasione per calcolare i possibili risultati di alcune partite.
print("Risultati Udinese - Parma")
udinese_parma = simula_partita(modello_poisson, 'Udinese', 'Parma', max_gol=6)
# Vittoria dell'Udinese
udinese_vince_parma = np.sum(np.tril(udinese_parma, -1))
print("Vittoria Udinese:", "{0:.2f}".format(udinese_vince_parma*100), "%")
# Vittoria del Parma
parma_vince_udinese = np.sum(np.triu(udinese_parma, 1))
print("Vittoria Parma:", "{0:.2f}".format(parma_vince_udinese*100), "%")
# Pareggio
pareggio_udinese_parma = np.sum(np.diag(udinese_parma))
print("Pareggio:", "{0:.2f}".format(pareggio_udinese_parma*100), "%")
print("Risultati Napoli - Lazio")
napoli_lazio = simula_partita(modello_poisson, 'Napoli', 'Lazio', max_gol=6)
# Vittoria del Napoli
napoli_vince_lazio = np.sum(np.tril(napoli_lazio, -1))
print("Vittoria Napoli:", "{0:.2f}".format(napoli_vince_lazio*100), "%")
# Vittoria della Lazio
lazio_vince_napoli = np.sum(np.triu(napoli_lazio, 1))
print("Vittoria Lazio:", "{0:.2f}".format(lazio_vince_napoli*100), "%")
# Pareggio
pareggio_napoli_lazio = np.sum(np.diag(napoli_lazio))
print("Pareggio:", "{0:.2f}".format(pareggio_napoli_lazio*100), "%")
root = Tk()
m = StringVar()
c = StringVar()
o = StringVar()
g = StringVar()
sceltaModello = Entry(root, textvariable = m)
sceltaCasa = Entry(root, textvariable = c)
sceltaOspite = Entry(root, textvariable = o)
sceltaGol = Entry(root, textvariable = g)
sceltaModello.pack()
sceltaCasa.pack()
sceltaOspite.pack()
sceltaGol.pack()
m.set(modello_poisson)
c.set(Squadra di Casa)
o.set(Squadra Ospite)
g.set(Max Gol)
avvia = Button(root, text = "Avvia Simulazione", command = lambda: simula_partita(m.get(), c.get(), o.get(), g.get()))
avvia.pack()
root.mainloop()
I am trying to measure a distance with ultrasonic sensor and everything looks well but when I leave the program for a some minutes (3-4 minutes) working, the program stops the measure of distance.
I need that the program dont stops because I need it to a security alarm. The program collects every one second a distance and show it in scree. But if distance is more than 10, the program shows a alert message and dont show the distance until it is less of 10. Following you can see the code:
import time
import RPi.GPIO as GPIO
# Usamos la referencia BOARD para los pines GPIO
GPIO.setmode(GPIO.BOARD)
# Definimos los pines que vamos a usar
GPIO_TRIGGER = 11
GPIO_ECHO = 13
GPIO_LED = 15
# Configuramos los pines como entradas y salidas
GPIO.setup(GPIO_TRIGGER,GPIO.OUT) # Trigger
GPIO.setup(GPIO_ECHO,GPIO.IN) # Echo
GPIO.setup(GPIO_LED ,GPIO.OUT) #Led
# -----------------------
# Definimos algunas funciones
# -----------------------
def medida():
# Esta funcion mide una distancia
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
start = time.time()
while GPIO.input(GPIO_ECHO)==0:
start = time.time()
while GPIO.input(GPIO_ECHO)==1:
stop = time.time()
elapsed = stop-start
distancia = (elapsed * 34300)/2
return distancia
def media_distancia():
# Esta funcion recoge 3 medidas
# y devuelve la media de las 3.
distancia1=medida()
time.sleep(0.1)
distancia2=medida()
time.sleep(0.1)
distancia3=medida()
distancia = distancia1 + distancia2 + distancia3
distancia = distancia / 3
return distancia
# -----------------------
# Programa principal
# -----------------------
print ("Medida con sensor de ultrasonidos")
# Ponemos el Trigger en falso (low)
GPIO.output(GPIO_TRIGGER, False)
# Ponemos el Led en falso (low)
GPIO.output(GPIO_LED, False)
# Metemos el bloque principal en un Try para asi poder
# comprobar si el usuario presiona Ctrl + C
# y poder ejecutar una limpieza del GPIO, esto tambien
# evita el usuario tener que ver muchos mensajes de error
try:
while True: # Este bucle se repite siempre
# Lo primero que hago es medir la distancia
distancia = media_distancia()
# Compruebo si la distancia es menor que 10
# Si es menor que 10 muestro la distancia por pantalla
if distancia < 10:
distancia = media_distancia() # Medidos la distancia
print ("Distancia: %.1f" % distancia, " - " , "Fecha:", time.strftime("%c")) # Mostramos la distancia por pantalla
GPIO.output(GPIO_LED, False)
time.sleep(1) # Esperamos 1 segundo
distancia = media_distancia()
a = 0 # Utilizo la variable a para poder para el proceso mas adelante
# Pregunto si la variable a es igual a 1
# Si lo es no hago nada y repito el if anterior
if a == 1:
pass
# Pero si no es 1 le asigno el valor 0
# Para poder seguir con el IF siguiente
else:
a = 0
if distancia > 10 and a == 0: # Si la distancia es mayor que 10cms
print ("La distancia es mayor de 10 cms. Alarma activada!!", " - ", "Fecha:", time.strftime("%c")) # Se interrumpe el bucle y se muestra un aviso
GPIO.output(GPIO_LED, True)
a = 1 # Pongo la variable en 1 para parar el proceso y que no se repita
distancia = media_distancia() # Seguimos midiento la distancia
while distancia < 10: # Pero si la distancia vuelve a ser menor de 10
break # Se termina este bucle y volvemos al principio nuevamente
except KeyboardInterrupt: # Si el usuario presiona crtl + C
# Limpiamos los pines GPIO y salimos del programa
print ("Apagando LED")
time.sleep(1)
GPIO.output(GPIO_LED, False)
print ("Limpiando GPIO")
GPIO.cleanup()
print ("GPIO limpio")
print ("Saliendo...")
time.sleep(1)
Why does the program stops after some minutes?
In your function medida(): you are triggering the sensor using:
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
Then waiting that the ECHO sets to 0 to start counting time and finally waiting the ECHO to set to 1 to stop counting time
while GPIO.input(GPIO_ECHO)==0:
start = time.time()
while GPIO.input(GPIO_ECHO)==1:
stop = time.time()
Now imagine that any of this two transitions doesn't happen:
maybe the ECHO never gets to 1 because there's no ECHO returned at all (no object, misbehavior of the sensor, misconnection...)
or maybe the ECHO is already 1 when you wait for it to get to 0 (you are doing a time.sleep(0.00001) after the rising edge of TRIGGER. In this time maybe the ECHO already gets to 0 in some cases...
If any of this two things happen, your program will wait forever, which is probably what is happening.
You should include a timeout in your loops, so if thins "hang" you can call the function to trigger the sensor again.
My best guest is that there is an exception somewhere on your code. Please, try this version and add an example of the output:
import time
import RPi.GPIO as GPIO
# Usamos la referencia BOARD para los pines GPIO
GPIO.setmode(GPIO.BOARD)
# Definimos los pines que vamos a usar
GPIO_TRIGGER = 11
GPIO_ECHO = 13
GPIO_LED = 15
# Configuramos los pines como entradas y salidas
GPIO.setup(GPIO_TRIGGER,GPIO.OUT) # Trigger
GPIO.setup(GPIO_ECHO,GPIO.IN) # Echo
GPIO.setup(GPIO_LED ,GPIO.OUT) #Led
# -----------------------
# Definimos algunas funciones
# -----------------------
def medida():
# Esta funcion mide una distancia
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
start = time.time()
while GPIO.input(GPIO_ECHO)==0:
start = time.time()
while GPIO.input(GPIO_ECHO)==1:
stop = time.time()
elapsed = stop-start
distancia = (elapsed * 34300)/2
return distancia
def media_distancia():
# Esta funcion recoge 3 medidas
# y devuelve la media de las 3.
distancia1=medida()
time.sleep(0.1)
distancia2=medida()
time.sleep(0.1)
distancia3=medida()
distancia = distancia1 + distancia2 + distancia3
distancia = distancia / 3
return distancia
# -----------------------
# Programa principal
# -----------------------
print ("Medida con sensor de ultrasonidos")
# Ponemos el Trigger en falso (low)
GPIO.output(GPIO_TRIGGER, False)
# Ponemos el Led en falso (low)
GPIO.output(GPIO_LED, False)
# Metemos el bloque principal en un Try para asi poder
# comprobar si el usuario presiona Ctrl + C
# y poder ejecutar una limpieza del GPIO, esto tambien
# evita el usuario tener que ver muchos mensajes de error
continuar = True
while continuar: # Este bucle se repite siempre
try:
# Lo primero que hago es medir la distancia
distancia = media_distancia()
# Compruebo si la distancia es menor que 10
# Si es menor que 10 muestro la distancia por pantalla
if distancia < 10:
distancia = media_distancia() # Medidos la distancia
print ("Distancia: %.1f" % distancia, " - " , "Fecha:", time.strftime("%c")) # Mostramos la distancia por pantalla
GPIO.output(GPIO_LED, False)
time.sleep(1) # Esperamos 1 segundo
distancia = media_distancia()
a = 0 # Utilizo la variable a para poder para el proceso mas adelante
# Pregunto si la variable a es igual a 1
# Si lo es no hago nada y repito el if anterior
if a == 1:
pass
# Pero si no es 1 le asigno el valor 0
# Para poder seguir con el IF siguiente
else:
a = 0
if distancia > 10 and a == 0: # Si la distancia es mayor que 10cms
print ("La distancia es mayor de 10 cms. Alarma activada!!", " - ", "Fecha:", time.strftime("%c")) # Se interrumpe el bucle y se muestra un aviso
GPIO.output(GPIO_LED, True)
a = 1 # Pongo la variable en 1 para parar el proceso y que no se repita
distancia = media_distancia() # Seguimos midiento la distancia
while distancia < 10: # Pero si la distancia vuelve a ser menor de 10
break # Se termina este bucle y volvemos al principio nuevamente
except KeyboardInterrupt: # Si el usuario presiona crtl + C
continuar = False
except (Exception) as error:
print (str(error))
# Limpiamos los pines GPIO y salimos del programa
print ("Apagando LED")
time.sleep(1)
GPIO.output(GPIO_LED, False)
print ("Limpiando GPIO")
GPIO.cleanup()
print ("GPIO limpio")
print ("Saliendo...")
time.sleep(1)
The correct way to find the reason of such is simple USE A LOGGER!
without blackbox you will hardly find the reason why your place crash!!
python has one ready to use, check the doc
import the logger module:
import logging
configure it to create a file...
logging.basicConfig(filename='example.log',level=logging.DEBUG)
and begging to log on every spot you find suspicious
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything