[Débutants] Exemple de simplification de code (+ exemple poo)
Modérateurs : Francois, Manfraid
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code
Le mode pwm n’est pas bloquant, ce qui sous-entend qu’il n’arrête pas le fonctionnement du programme, alors pourquoi ne pas enrichir encore l’objet Led pour s’offrir un mode blink asynchrone en toute simplicité ?
Pour ça il suffit de créer une nouvelle action (blinkasync) qui va passer les bons paramètres à l’action pwm, à savoir un duty cycle à 50% et un délai qui sera posé sous 1 pour convertir en frequence (F = 1/T). J’en ai profité déporté le pwm stop dans une action interne qui a pour rôle d’arrêter le pwm, d’attendre la fin d’un éventuel cycle en cours et remettre les variables _pwmfreq et _pwm a leur état par défaut (ce que j’avais oublié de faire dans le code précédent)
Pour ça il suffit de créer une nouvelle action (blinkasync) qui va passer les bons paramètres à l’action pwm, à savoir un duty cycle à 50% et un délai qui sera posé sous 1 pour convertir en frequence (F = 1/T). J’en ai profité déporté le pwm stop dans une action interne qui a pour rôle d’arrêter le pwm, d’attendre la fin d’un éventuel cycle en cours et remettre les variables _pwmfreq et _pwm a leur état par défaut (ce que j’avais oublié de faire dans le code précédent)
Modifié en dernier par Bud Spencer le ven. 16 août 2019 13:25, modifié 4 fois.
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code
Le petit programme de test qui va avec.
On peut maintenant faire clignoter une led tout en laissant le programme continuer à faire le reste de son boulot. Une simple instruction led.off() ou led.on() suffit pour arrêter le blink et positionner la led dans l’etat demandé.Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code
Un petit recap du fonctionnement de l’objet Led
Import : from led import Led
Création d’un objet : maled = (GPIO,n° de pin)
maled.on() : allume la led
maled.off() : éteint la led
maled.blink(nbblink,delais) : fait clignoter la led nblink fois à un rytme de delais
maled.pwm(pourcentage) : fait éclairer la led avec pourcentage de luninosité (asynchrone)
maled.blinkasync (delais) : fait clignoter la led à un rytme de delais (asynchrone)
maled.etat : retourne l’état de la led (booléen)
maled.etat = bool : positionne la led à l’etat bool (True ou False)
Le code du fichier led.py
et un petit programme pour le tester
Et le résultat du test en console:
Import : from led import Led
Création d’un objet : maled = (GPIO,n° de pin)
maled.on() : allume la led
maled.off() : éteint la led
maled.blink(nbblink,delais) : fait clignoter la led nblink fois à un rytme de delais
maled.pwm(pourcentage) : fait éclairer la led avec pourcentage de luninosité (asynchrone)
maled.blinkasync (delais) : fait clignoter la led à un rytme de delais (asynchrone)
maled.etat : retourne l’état de la led (booléen)
maled.etat = bool : positionne la led à l’etat bool (True ou False)
Le code du fichier led.py
Code : Tout sélectionner
#!/usr/bin/python
# coding: utf-8
from time import sleep
class Led (object):
def __init__(self,gpio,pin):
self._gpio = gpio
self._pin = pin
self._pwm = None
self._pwmfreq = 300
self._gpio.setup(self._pin, self._gpio.OUT, initial = self._gpio.LOW)
def on(self):
if not self._pwm == None: self._pwmstop()
self._gpio.output(self._pin,self._gpio.HIGH)
def off(self):
if not self._pwm == None: self._pwmstop()
self._gpio.output(self._pin,self._gpio.LOW)
def blink(self,count,delais):
if not self._pwm == None: self._pwmstop()
for x in range(count * 2):
self._set_etat(not self._get_etat())
sleep(delais / 2)
def blinkasync(self,delais):
self._pwmfreq = 1 / delais
self.pwm(50)
def pwm(self,percent):
if self._pwm == None:
self._pwm = self._gpio.PWM(self._pin, self._pwmfreq)
self._pwm.start(percent)
else:
self._pwm.ChangeFrequency(self._pwmfreq)
self._pwm.ChangeDutyCycle(percent)
def _pwmstop(self):
self._pwm.stop()
sleep(1/self._pwmfreq)
self._pwmfreq = 300
self._pwm = None
def _set_etat(self,valeur):
if not self._pwm == None: self._pwmstop()
self._gpio.output(self._pin,self._gpio.HIGH if valeur == True else self._gpio.LOW)
def _get_etat(self):
return True if self._gpio.input(self._pin) == self._gpio.HIGH else False
etat = property(_get_etat,_set_etat)
Code : Tout sélectionner
#!/usr/bin/python
# coding: utf-8
import RPi.GPIO as GPIO
from time import sleep
from led import Led
GPIO.setmode(GPIO.BOARD)
maled = Led(GPIO,11)
maled.on()
print("Led On, Etat = " + str(maled.etat ))
sleep(5)
maled.off()
print("Led Off, Etat = " + str(maled.etat ))
sleep(5)
print("Ledpwm")
for x in range (10,100,10):
maled.pwm(x)
print ("Led % = " + str(x) + "%")
sleep(1)
sleep(5)
print("Led clignote 5 fois")
maled.blink(5,0.5)
sleep(5)
print("Led clignote, le programme continue")
maled.blinkasync(0.5)
sleep(5)
maled.on()
print("Led On, Etat = " + str(maled.etat ))
sleep(5)
print("Led etat : False")
maled.etat = False
GPIO.cleanup()
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code
Exemple d’Héritage
Très bien, j’ai un bel objet Led bien complet mais ce serait dommage d’en rester là. Pourquoi ne pas étendre ce concept à tout un ensemble de fonctions pour le GPIO du pi. Entrées, Sorties, sondes diverses ect … Si je regarde mon objet Led, il regroupe déjà toutes les fonctions d’une sortie et les seules actions que l’on peut définir comme étant propre à une led sont seulement on, off et les 2 actions de blink. Donc plutôt que de tout réécrire pour créer un objet Sortie, je vais séparer le code en 2 objets (Sortie et Led) et faire en sorte que l’objet Led soit automatiquement rattaché à un objet Sortie et qu’il utilise ses possibilités. C’est le principe d’héritage.
J’écris donc un nouvel objet Sortie et j’y place le code de Led qui concerne ce nouvel objet. Il ne reste qu’à dire à la class Led qu’elle hérite de Sortie (class Led (Sortie):) et dans ce qui fait office de constructeur (__init__) de Led, j’initialise un objet Sortie en lui passant les paramètres. Bien sûr, il ni a plus de raison que mon fichier s’appelle led.py, je le renomme donc pigpio.py
Très bien, j’ai un bel objet Led bien complet mais ce serait dommage d’en rester là. Pourquoi ne pas étendre ce concept à tout un ensemble de fonctions pour le GPIO du pi. Entrées, Sorties, sondes diverses ect … Si je regarde mon objet Led, il regroupe déjà toutes les fonctions d’une sortie et les seules actions que l’on peut définir comme étant propre à une led sont seulement on, off et les 2 actions de blink. Donc plutôt que de tout réécrire pour créer un objet Sortie, je vais séparer le code en 2 objets (Sortie et Led) et faire en sorte que l’objet Led soit automatiquement rattaché à un objet Sortie et qu’il utilise ses possibilités. C’est le principe d’héritage.
J’écris donc un nouvel objet Sortie et j’y place le code de Led qui concerne ce nouvel objet. Il ne reste qu’à dire à la class Led qu’elle hérite de Sortie (class Led (Sortie):) et dans ce qui fait office de constructeur (__init__) de Led, j’initialise un objet Sortie en lui passant les paramètres. Bien sûr, il ni a plus de raison que mon fichier s’appelle led.py, je le renomme donc pigpio.py
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code
Encapsulation :
Quand j’avais créé mon objet Led, j’avais défini une valeur fixe pour la fréquence du pwm (300Hz). Maintenant que j’ai transformé ca en Sortie, je dois pouvoir utiliser le pwm avec d’autres fréquences. Pour ça je vais créer une propriété (property) qui va me permettre de changer cette valeur. Une propriété est vue de l’extérieur comme une variable de l’objet. Pour faire la lisaion entre la propriété et la variable interne de l’objet, je vais passer par 2 fonctions distinctes. Une première pour pouvoir récupérer la valeur de la variable interne et une seconde pour pouvoir la modifier. Le nom de ces 2 fonctions est défini par convention ( _ , get ou set , nom de la variable interne) et porte les noms d’ accesseur (get qui permet d’accéder à la valeur) et de mutateur (set qui permet de la modifier). C’est le principe d’encapsulation. On accède depuis l’extérieur a des propriétés et tous les traitements et contrôles nécessaires sont fait à l’interieur de l’objet en fonction de ses propres contraintes et de facon totalement transparente pour le reste du programme
La réinitialisation de valeur par défaut de _pwmfreq dans l’action interne _pwmstop n’a plus lieu d’etre donc je la supprime.
Quand j’avais créé mon objet Led, j’avais défini une valeur fixe pour la fréquence du pwm (300Hz). Maintenant que j’ai transformé ca en Sortie, je dois pouvoir utiliser le pwm avec d’autres fréquences. Pour ça je vais créer une propriété (property) qui va me permettre de changer cette valeur. Une propriété est vue de l’extérieur comme une variable de l’objet. Pour faire la lisaion entre la propriété et la variable interne de l’objet, je vais passer par 2 fonctions distinctes. Une première pour pouvoir récupérer la valeur de la variable interne et une seconde pour pouvoir la modifier. Le nom de ces 2 fonctions est défini par convention ( _ , get ou set , nom de la variable interne) et porte les noms d’ accesseur (get qui permet d’accéder à la valeur) et de mutateur (set qui permet de la modifier). C’est le principe d’encapsulation. On accède depuis l’extérieur a des propriétés et tous les traitements et contrôles nécessaires sont fait à l’interieur de l’objet en fonction de ses propres contraintes et de facon totalement transparente pour le reste du programme
La réinitialisation de valeur par défaut de _pwmfreq dans l’action interne _pwmstop n’a plus lieu d’etre donc je la supprime.
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code
Je peux toujours utiliser le pwm avec l’objet Led, mais cela sous entendrait qu’il faudrait déjà que j’initialise la fréquence a une valeur correcte. Pour eviter cela et simplifier l’usage de Led, je vais ajouter une action pwm a Led. Quand j’utiliserais un objet Led, ce sera donc son action pwm qui sera appelée et non plus celle de sortie. De la sorte, je vais pouvoir initialiser en toute transparence la bonne fréquence pour le pwm et ensuite faire appel à la fonction pwm de Sortie
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code
On a maintenant 2 objets pour le prix d’un
Sortie : from pigpio import Sortie
Création d’un objet Sortie : masortie = (GPIO,n° de pin)
masortie.etat = bool : position la sortie à bool (True ou False)
masortie.etat : retourne l’état de la sortie (boolean)
masortie.pwmfreq = Hz : initialise le pwm de la sortie a Hz
masortie.pwmfreq : retourne la valeur courante de la fréquence du pwm
masortie.pwm(pourcentage) : génère un signale pwm pourcentage sur la sortie (asynchrone)
Led : from pigpio import Led
Création d’un objet Led : maled = (GPIO,n° de pin)
maled.on() : allume la led
maled.off() : éteint la led
maled.blink(nb blink, delais) : fais clignoter la led nbblink fois à un rytme de delais
maled.blinkasync (delais) : fait clignoter la led à un rytme de delais (asynchrone)
maled.pwm(pourcentage) : fait éclairer la led avec pourcentage de luminosité (asynchrone)
et bien sur les propriétés etat et pwmfreq de Sortie
maled.etat = bool : position la sortie à bool (True ou False)
maled.etat : retourne l’état de la sortie (boolean)
maled.pwmfreq : retourne la valeur courante de la fréquence du pwm de Sortie
maled.pwmfreq = Hz : Ne sert a rien avec l'objet led vu qu'il impose sa propre fréquence
Le code du fichier pigpio :
Et pour tester, on peu utiliser exactement le meme code que celui qui a été utilisé pour l'objet led ou il suffit juste de modifier la ligne :
en
Sortie : from pigpio import Sortie
Création d’un objet Sortie : masortie = (GPIO,n° de pin)
masortie.etat = bool : position la sortie à bool (True ou False)
masortie.etat : retourne l’état de la sortie (boolean)
masortie.pwmfreq = Hz : initialise le pwm de la sortie a Hz
masortie.pwmfreq : retourne la valeur courante de la fréquence du pwm
masortie.pwm(pourcentage) : génère un signale pwm pourcentage sur la sortie (asynchrone)
Led : from pigpio import Led
Création d’un objet Led : maled = (GPIO,n° de pin)
maled.on() : allume la led
maled.off() : éteint la led
maled.blink(nb blink, delais) : fais clignoter la led nbblink fois à un rytme de delais
maled.blinkasync (delais) : fait clignoter la led à un rytme de delais (asynchrone)
maled.pwm(pourcentage) : fait éclairer la led avec pourcentage de luminosité (asynchrone)
et bien sur les propriétés etat et pwmfreq de Sortie
maled.etat = bool : position la sortie à bool (True ou False)
maled.etat : retourne l’état de la sortie (boolean)
maled.pwmfreq : retourne la valeur courante de la fréquence du pwm de Sortie
maled.pwmfreq = Hz : Ne sert a rien avec l'objet led vu qu'il impose sa propre fréquence
Le code du fichier pigpio :
Code : Tout sélectionner
#!/usr/bin/python
# coding: utf-8
from time import sleep
class Sortie (object):
def __init__(self,gpio,pin):
self._gpio = gpio
self._pin = pin
self._pwm = None
self._pwmfreq = 10
self._gpio.setup(self._pin, self._gpio.OUT, initial = self._gpio.LOW)
def pwm(self,percent):
if self._pwm == None:
self._pwm = self._gpio.PWM(self._pin, self._pwmfreq)
self._pwm.start(percent)
else:
self._pwm.ChangeFrequency(self._pwmfreq)
self._pwm.ChangeDutyCycle(percent)
def _pwmstop(self):
self._pwm.stop()
sleep(1/self._pwmfreq)
self._pwm = None
def _set_etat(self,valeur):
if not self._pwm == None: self._pwmstop()
self._gpio.output(self._pin,self._gpio.HIGH if valeur == True else self._gpio.LOW)
def _get_etat(self):
return True if self._gpio.input(self._pin) == self._gpio.HIGH else False
def _set_pwmfreq(self, valeur):
self._pwmfreq = valeur
def _get_pwmfreq(self):
return self._pwmfreq
etat = property(_get_etat,_set_etat)
pwmfreq = property(_get_pwmfreq,_set_pwmfreq)
class Led (Sortie):
def __init__(self,gpio,pin):
self._gpio = gpio
self._pin = pin
Sortie.__init__(self,gpio,pin)
def on(self):
self._set_etat(True)
def off(self):
self._set_etat(False)
def blink(self,count,delais):
for x in range(count * 2):
self._set_etat(not self._get_etat())
sleep(delais / 2)
def blinkasync(self,delais):
self._pwmfreq = 1 / delais
Sortie.pwm(self,50)
def pwm(self,percent):
self._set_pwmfreq(300)
Sortie.pwm(self,percent)
Code : Tout sélectionner
from led import Led
Code : Tout sélectionner
from pigpio import Led
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code (+ exemple poo)
Dans les épisodes précédents, on a utilisé des itérations pour écrire moins de code dans le programme. Un autre intérêt des itérations, c’est que l’on plus facilement utiliser des fichiers de configuration qui contienne des listes. Plutôt que de définir les pins et les seuils de chaque barre du bargraphe, je vais les mettre dans un fichier de config qui va contenir des objets JSON. Et je l’écris comme ça :
Il y une liste pour les leds cpu, une liste pour les leds ram et une variable Refresh que je vais utiliser pour le timing de la boucle.
Il y une liste pour les leds cpu, une liste pour les leds ram et une variable Refresh que je vais utiliser pour le timing de la boucle.
Modifié en dernier par Bud Spencer le dim. 18 août 2019 13:13, modifié 1 fois.
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code (+ exemple poo)
Pour m’éviter d’avoir à créer des listes que je passerais à la construction des bargraphes, j’enrichis mon objet Bargraph d’une nouvelle fonction (addBarre) qui va me permettre de lui passer des paramètres de barre pour qu’il créé lui-même les objets Barrette :
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).
-
- Raspinaute
- Messages : 1089
- Enregistré le : lun. 15 août 2016 21:38
Re: [Débutants] Exemple de simplification de code (+ exemple poo)
Il existe bien sûr en python comme dans pratiquement tous les langages, une librairie qui permet de charger la structure d’un fichier json (import json) pour pouvoir ‘désérializer’ le contenu du fichier de config. Je peux maintenant réécrire l’équivalent du programme original de façon beaucoup plus ‘synthétique’ en utilisant des itérations, des objets réutilisables et évolutifs et un fichier de configuration :
Code pigpio.py
code bargraph.py
code config.json
code program.py
Code pigpio.py
Code : Tout sélectionner
#!/usr/bin/python
# coding: utf-8
from time import sleep
class Sortie (object):
def __init__(self,gpio,pin):
self._gpio = gpio
self._pin = pin
self._pwm = None
self._pwmfreq = 10
self._gpio.setup(self._pin, self._gpio.OUT, initial = self._gpio.LOW)
def pwm(self,percent):
if self._pwm == None:
self._pwm = self._gpio.PWM(self._pin, self._pwmfreq)
self._pwm.start(percent)
else:
self._pwm.ChangeFrequency(self._pwmfreq)
self._pwm.ChangeDutyCycle(percent)
def _pwmstop(self):
self._pwm.stop()
sleep(1/self._pwmfreq)
self._pwm = None
def _set_etat(self,valeur):
if not self._pwm == None: self._pwmstop()
self._gpio.output(self._pin,self._gpio.HIGH if valeur == True else self._gpio.LOW)
def _get_etat(self):
return True if self._gpio.input(self._pin) == self._gpio.HIGH else False
def _set_pwmfreq(self, valeur):
self._pwmfreq = valeur
def _get_pwmfreq(self):
return self._pwmfreq
etat = property(_get_etat,_set_etat)
pwmfreq = property(_get_pwmfreq,_set_pwmfreq)
class Led (Sortie):
def __init__(self,gpio,pin):
self._gpio = gpio
self._pin = pin
Sortie.__init__(self,gpio,pin)
def on(self):
self._set_etat(True)
def off(self):
self._set_etat(False)
def blink(self,count,delais):
for x in range(count * 2):
self._set_etat(not self._get_etat())
sleep(delais / 2)
def blinkasync(self,delais):
self._pwmfreq = 1 / delais
Sortie.pwm(self,50)
def pwm(self,percent):
self._set_pwmfreq(300)
Sortie.pwm(self,percent)
code bargraph.py
Code : Tout sélectionner
#!/usr/bin/python
# coding: utf-8
class Barrette :
def __init__(self,barre, seuil):
self.barre = barre
self.seuil = seuil
class Bargraph (Barrette):
def __init__(self,barres):
self._barres = barres
def write(self,valeur):
for x in self._barres:
x.barre.etat = valeur >= x.seuil
def addBarre(self,barre,seuil):
self._barres.append(Barrette(barre,seuil))
Code : Tout sélectionner
{
"Refresh": 1,
"LedCpu": [
{
"pin": 11,
"seuil": 20
},
{
"pin": 13,
"seuil": 40
},
{
"pin": 15,
"seuil": 60
},
{
"pin": 12,
"seuil": 80
},
{
"pin": 16,
"seuil": 100
}
],
"LedRam": [
{
"pin": 22,
"seuil": 20
},
{
"pin": 38,
"seuil": 40
},
{
"pin": 35,
"seuil": 60
},
{
"pin": 33,
"seuil": 80
},
{
"pin": 32,
"seuil": 100
}
]
}
Code : Tout sélectionner
#!/usr/bin/python
# coding: utf-8
import RPi.GPIO as GPIO
import psutil
import json
from time import sleep
from bargraph import Bargraph
from pigpio import Led
GPIO.setmode(GPIO.BOARD)
bargraphCpu = Bargraph([])
bargraphRam = Bargraph([])
with open('./config.json', 'r') as f:
config = json.load(f)
for x in config["LedCpu"]:
bargraphCpu.addBarre(Led(GPIO,x["pin"]),x["seuil"])
for x in config["LedRam"]:
bargraphRam.addBarre(Led(GPIO,x["pin"]),x["seuil"])
try:
while (True):
bargraphCpu.write(psutil.cpu_percent())
bargraphRam.write(100 - psutil.virtual_memory().percent)
sleep(config["Refresh"])
except KeyboardInterrupt:
GPIO.cleanup()
Le premier ennemi de la connaissance n’est pas l’ignorance, c’est l’illusion de la connaissance (S. Hawking).