Différences entre versions de « RASP-PYGAME-GUI-Analogique »
(8 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
{{RASP-PYGAME-GUI-NAV}} | {{RASP-PYGAME-GUI-NAV}} | ||
− | |||
− | |||
== Entrée Analogique == | == Entrée Analogique == | ||
Ligne 7 : | Ligne 5 : | ||
{{ADFImage|RASP-PYGAME-GUI-Analogique-00.jpg}} | {{ADFImage|RASP-PYGAME-GUI-Analogique-00.jpg}} | ||
− | + | Cet exemple utilise un potentiomètre de 10K pour fournir une tension variable. Pour la conversion analogique vers digital nous utilisons habituellement un [http://jeremyblythe.blogspot.co.uk/2012/09/raspberry-pi-hardware-spi-analog-inputs.html MCP3008 via SPI]. Mais cela n'est pas possible ici puisque le PiTFT utilise les deux canaux SPI disponibles sur le Pi. Par conséquant, nous optons pour un convertisseur ADC I2C: [http://www.adafruit.com/product/1085 ADC 16-Bit ADS1115 - 4 canaux avec un gain programmable]. | |
− | + | Pour obtenir la bibliothèque Python Adafruit: | |
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Ligne 16 : | Ligne 14 : | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | Vous aurez besoin d'activer [[Rasp-Hack-GPIO_Configurer_I2C|le support I2C en suivant ce guide]] | |
{{ADFImage|RASP-PYGAME-GUI-Analogique-01.jpg}} | {{ADFImage|RASP-PYGAME-GUI-Analogique-01.jpg}} | ||
== Démarrage == | == Démarrage == | ||
+ | Au tout début du script nous faisons quelques {{fname|import}} pour le support multitâche (''threading'') et la conversion ADC. | ||
− | + | Le gain et le taux d'échantillonnage sont configurés et le convertisseur ADC est initialisé. | |
− | |||
− | |||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
Ligne 43 : | Ligne 40 : | ||
ADS1115 = 0x01 # 16-bit ADC | ADS1115 = 0x01 # 16-bit ADC | ||
− | # | + | # Sélectionner le gain |
# gain = 6144 # +/- 6.144V | # gain = 6144 # +/- 6.144V | ||
gain = 4096 # +/- 4.096V | gain = 4096 # +/- 4.096V | ||
Ligne 51 : | Ligne 48 : | ||
# gain = 256 # +/- 0.256V | # gain = 256 # +/- 0.256V | ||
− | # | + | # Sélectionner le taux d'échantillonnage |
− | sps = 8 # 8 | + | sps = 8 # 8 échantillons par seconde |
− | # sps = 16 # 16 | + | # sps = 16 # 16 échantillons par seconde |
− | # sps = 32 # 32 | + | # sps = 32 # 32 échantillons par seconde |
− | # sps = 64 # 64 | + | # sps = 64 # 64 échantillons par seconde |
− | # sps = 128 # 128 | + | # sps = 128 # 128 échantillons par seconde |
− | # sps = 250 # 250 | + | # sps = 250 # 250 échantillons par seconde |
− | # sps = 475 # 475 | + | # sps = 475 # 475 échantillons par seconde |
− | # sps = 860 # 860 | + | # sps = 860 # 860 échantillons par seconde |
− | # | + | # Initialiser le convertisseur ADC en utilisant le mode par défaut (et adresse I2C par défaut) |
− | # | + | # Utilisez ADS1015 ou ADS1115 en fonction de l'ADC que vous utilisez! |
adc = ADS1x15(ic=ADS1115) | adc = ADS1x15(ic=ADS1115) | ||
− | # | + | # Configurer les GPIOs en sortie (OUTPUT) - seuls 4 et 17 sont disponibles |
GPIO.setmode(GPIO.BCM) | GPIO.setmode(GPIO.BCM) | ||
GPIO.setup(4, GPIO.OUT) | GPIO.setup(4, GPIO.OUT) | ||
Ligne 85 : | Ligne 82 : | ||
== Le thread du potentiomètre == | == Le thread du potentiomètre == | ||
− | + | Un thread est utilisé pour lire continuellement la valeur du potentiomètre. Si l'on fait la lecture du potentiomètre dans la mise-à-jour de la Scene alors le taux de rafraîchissement de l'écran diminuera de façon importante. | |
+ | |||
+ | Ce thread séparé permet à l'écran d'être redessiné en même temps (en parallèle) que la lecture de la valeur depuis l'ADC. | ||
+ | |||
+ | La classe est définie comme {{fname|callable}} appela - d'où la méthode {{fname|__call__}}. Il prend une référence vers la classe pitft de sorte qu'il est possible d'y mettre les valeurs à-jour. Il y a un schéma d'arrêt relativement simple basé sur la vérification d'un variable (un ''flag''/''drapeau'') à chaque tour de boucle. Nous verrons plus tard comment terminer proprement le programme en modifiant la variable ''flag''. | ||
+ | |||
+ | Donc, nous lisons simplement la valeur depuis l'ADC et modifie la valeur du libellé et la position de la barre de progression (visible sur le pitft). | ||
+ | |||
+ | <syntaxhighlight lang="python"> | ||
+ | class PotReader(): | ||
+ | def __init__(self, pitft): | ||
+ | self.pitft = pitft | ||
+ | self.terminated = False | ||
+ | |||
+ | def terminate(self): | ||
+ | self.terminated = True | ||
+ | |||
+ | def __call__(self): | ||
+ | while not self.terminated: | ||
+ | # Lecture du canal 0 en mode single-ended en utilisant la configuration ci-avant | ||
+ | volts = adc.readADCSingleEnded(0, gain, sps) / 1000 | ||
+ | self.pitft.set_volts_label(volts) | ||
+ | self.pitft.set_progress(volts / 3.3) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Définition de l'interface utilisateur == | ||
+ | Nous avons ajouté quelques widget supplémentaires sur la Scene et modifié la taille des boutons (pour que tout se présente correctement). | ||
+ | |||
+ | Nous allons afficher la tension sur un widget label (''libellé'') et un widget progress (''barre de progression''). | ||
+ | |||
+ | Les méthodes {{fname|set_progress}} et {{fname|set_volts_label}} sont appelées depuis le thread PotReader pour faire la mise-à-jour des valeurs dans ces Widgets. | ||
+ | |||
+ | <syntaxhighlight lang="python"> | ||
+ | class PiTft(ui.Scene): | ||
+ | def __init__(self): | ||
+ | ui.Scene.__init__(self) | ||
+ | |||
+ | self.on17_button = ui.Button(ui.Rect(MARGIN, MARGIN, 130, 60), '17 on') | ||
+ | self.on17_button.on_clicked.connect(self.gpi_button) | ||
+ | self.add_child(self.on17_button) | ||
+ | |||
+ | self.on4_button = ui.Button(ui.Rect(170, MARGIN, 130, 60), '4 on') | ||
+ | self.on4_button.on_clicked.connect(self.gpi_button) | ||
+ | self.add_child(self.on4_button) | ||
+ | |||
+ | self.off17_button = ui.Button(ui.Rect(MARGIN, 100, 130, 60), '17 off') | ||
+ | self.off17_button.on_clicked.connect(self.gpi_button) | ||
+ | self.add_child(self.off17_button) | ||
+ | |||
+ | self.off4_button = ui.Button(ui.Rect(170, 100, 130, 60), '4 off') | ||
+ | self.off4_button.on_clicked.connect(self.gpi_button) | ||
+ | self.add_child(self.off4_button) | ||
+ | |||
+ | self.progress_view = ui.ProgressView(ui.Rect(MARGIN, 200, 280, 40)) | ||
+ | self.add_child(self.progress_view) | ||
+ | |||
+ | self.volts_value = ui.Label(ui.Rect(135, 170, 50, 30), '') | ||
+ | self.add_child(self.volts_value) | ||
+ | |||
+ | def gpi_button(self, btn, mbtn): | ||
+ | logger.info(btn.text) | ||
+ | |||
+ | if btn.text == '17 on': | ||
+ | GPIO.output(17, False) | ||
+ | elif btn.text == '4 on': | ||
+ | GPIO.output(4, False) | ||
+ | elif btn.text == '17 off': | ||
+ | GPIO.output(17, True) | ||
+ | elif btn.text == '4 off': | ||
+ | GPIO.output(4, True) | ||
+ | |||
+ | def set_progress(self, percent): | ||
+ | self.progress_view.progress = percent | ||
+ | |||
+ | def set_volts_label(self, volts): | ||
+ | self.volts_value.text = '%.2f' % volts | ||
+ | |||
+ | def update(self, dt): | ||
+ | ui.Scene.update(self, dt) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Et pour finir... == | ||
+ | Pour démarrer le programme nous initialisons pygameui, construisons la classe pitft class et démarrons le thread potreader avec le pitft en référence. | ||
+ | |||
+ | Puisque nous exécutons un thread supplémentaire, nous avons également besoin d'une '''méthode propre''' pour terminer le programme. | ||
+ | |||
+ | Un gestionnaire de signal (''signal handler'') est utilisé pour capturer ctrl+c et terminer le thread PotReader avant d'appeler sys.exit - sinon le programme ne se fermera pas. | ||
+ | |||
+ | <syntaxhighlight lang="python"> | ||
+ | ui.init('Raspberry Pi UI', (320, 240)) | ||
+ | pygame.mouse.set_visible(False) | ||
+ | |||
+ | pitft = PiTft() | ||
+ | |||
+ | # démarrer le thread exécutant le ''callable'' | ||
+ | potreader = PotReader(pitft) | ||
+ | threading.Thread(target=potreader).start() | ||
+ | |||
+ | def signal_handler(signal, frame): | ||
+ | print 'Vous avez pressé Ctrl+C!' | ||
+ | potreader.terminate() | ||
+ | sys.exit(0) | ||
+ | |||
+ | # Enregister le gesionnaire signal_handler pour le lignal SIGINT (interruption) | ||
+ | signal.signal(signal.SIGINT, signal_handler) | ||
+ | |||
+ | ui.scene.push(pitft) | ||
+ | ui.run() | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Exécuter == | ||
+ | Vous pouvez exécuter cet exemple final depuis le projet pygamelcd: | ||
+ | |||
+ | <syntaxhighlight lang="bash"> | ||
+ | sudo python test5.py | ||
+ | </syntaxhighlight> | ||
{{RASP-PYGAME-GUI-TRAILER}} | {{RASP-PYGAME-GUI-TRAILER}} |
Version actuelle datée du 15 août 2016 à 15:41
Entrée Analogique
Crédit: AdaFruit Industries www.adafruit.com
Cet exemple utilise un potentiomètre de 10K pour fournir une tension variable. Pour la conversion analogique vers digital nous utilisons habituellement un MCP3008 via SPI. Mais cela n'est pas possible ici puisque le PiTFT utilise les deux canaux SPI disponibles sur le Pi. Par conséquant, nous optons pour un convertisseur ADC I2C: ADC 16-Bit ADS1115 - 4 canaux avec un gain programmable.
Pour obtenir la bibliothèque Python Adafruit:
cd /home/pi
git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git
Vous aurez besoin d'activer le support I2C en suivant ce guide
Crédit: AdaFruit Industries www.adafruit.com
Démarrage
Au tout début du script nous faisons quelques import pour le support multitâche (threading) et la conversion ADC.
Le gain et le taux d'échantillonnage sont configurés et le convertisseur ADC est initialisé.
import sys
sys.path.append('/home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_ADS1x15')
import pygame
import os
import pygameui as ui
import logging
import RPi.GPIO as GPIO
import signal
from Adafruit_ADS1x15 import ADS1x15
import threading
import time
ADS1015 = 0x00 # 12-bit ADC
ADS1115 = 0x01 # 16-bit ADC
# Sélectionner le gain
# gain = 6144 # +/- 6.144V
gain = 4096 # +/- 4.096V
# gain = 2048 # +/- 2.048V
# gain = 1024 # +/- 1.024V
# gain = 512 # +/- 0.512V
# gain = 256 # +/- 0.256V
# Sélectionner le taux d'échantillonnage
sps = 8 # 8 échantillons par seconde
# sps = 16 # 16 échantillons par seconde
# sps = 32 # 32 échantillons par seconde
# sps = 64 # 64 échantillons par seconde
# sps = 128 # 128 échantillons par seconde
# sps = 250 # 250 échantillons par seconde
# sps = 475 # 475 échantillons par seconde
# sps = 860 # 860 échantillons par seconde
# Initialiser le convertisseur ADC en utilisant le mode par défaut (et adresse I2C par défaut)
# Utilisez ADS1015 ou ADS1115 en fonction de l'ADC que vous utilisez!
adc = ADS1x15(ic=ADS1115)
# Configurer les GPIOs en sortie (OUTPUT) - seuls 4 et 17 sont disponibles
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(17, GPIO.OUT)
log_format = '%(asctime)-6s: %(name)s - %(levelname)s - %(message)s'
console_handler = logging.StreamHandler()
console_handler.setFormatter(logging.Formatter(log_format))
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(console_handler)
os.putenv('SDL_FBDEV', '/dev/fb1')
os.putenv('SDL_MOUSEDRV', 'TSLIB')
os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')
MARGIN = 20
Le thread du potentiomètre
Un thread est utilisé pour lire continuellement la valeur du potentiomètre. Si l'on fait la lecture du potentiomètre dans la mise-à-jour de la Scene alors le taux de rafraîchissement de l'écran diminuera de façon importante.
Ce thread séparé permet à l'écran d'être redessiné en même temps (en parallèle) que la lecture de la valeur depuis l'ADC.
La classe est définie comme callable appela - d'où la méthode __call__. Il prend une référence vers la classe pitft de sorte qu'il est possible d'y mettre les valeurs à-jour. Il y a un schéma d'arrêt relativement simple basé sur la vérification d'un variable (un flag/drapeau) à chaque tour de boucle. Nous verrons plus tard comment terminer proprement le programme en modifiant la variable flag.
Donc, nous lisons simplement la valeur depuis l'ADC et modifie la valeur du libellé et la position de la barre de progression (visible sur le pitft).
class PotReader():
def __init__(self, pitft):
self.pitft = pitft
self.terminated = False
def terminate(self):
self.terminated = True
def __call__(self):
while not self.terminated:
# Lecture du canal 0 en mode single-ended en utilisant la configuration ci-avant
volts = adc.readADCSingleEnded(0, gain, sps) / 1000
self.pitft.set_volts_label(volts)
self.pitft.set_progress(volts / 3.3)
Définition de l'interface utilisateur
Nous avons ajouté quelques widget supplémentaires sur la Scene et modifié la taille des boutons (pour que tout se présente correctement).
Nous allons afficher la tension sur un widget label (libellé) et un widget progress (barre de progression).
Les méthodes set_progress et set_volts_label sont appelées depuis le thread PotReader pour faire la mise-à-jour des valeurs dans ces Widgets.
class PiTft(ui.Scene):
def __init__(self):
ui.Scene.__init__(self)
self.on17_button = ui.Button(ui.Rect(MARGIN, MARGIN, 130, 60), '17 on')
self.on17_button.on_clicked.connect(self.gpi_button)
self.add_child(self.on17_button)
self.on4_button = ui.Button(ui.Rect(170, MARGIN, 130, 60), '4 on')
self.on4_button.on_clicked.connect(self.gpi_button)
self.add_child(self.on4_button)
self.off17_button = ui.Button(ui.Rect(MARGIN, 100, 130, 60), '17 off')
self.off17_button.on_clicked.connect(self.gpi_button)
self.add_child(self.off17_button)
self.off4_button = ui.Button(ui.Rect(170, 100, 130, 60), '4 off')
self.off4_button.on_clicked.connect(self.gpi_button)
self.add_child(self.off4_button)
self.progress_view = ui.ProgressView(ui.Rect(MARGIN, 200, 280, 40))
self.add_child(self.progress_view)
self.volts_value = ui.Label(ui.Rect(135, 170, 50, 30), '')
self.add_child(self.volts_value)
def gpi_button(self, btn, mbtn):
logger.info(btn.text)
if btn.text == '17 on':
GPIO.output(17, False)
elif btn.text == '4 on':
GPIO.output(4, False)
elif btn.text == '17 off':
GPIO.output(17, True)
elif btn.text == '4 off':
GPIO.output(4, True)
def set_progress(self, percent):
self.progress_view.progress = percent
def set_volts_label(self, volts):
self.volts_value.text = '%.2f' % volts
def update(self, dt):
ui.Scene.update(self, dt)
Et pour finir...
Pour démarrer le programme nous initialisons pygameui, construisons la classe pitft class et démarrons le thread potreader avec le pitft en référence.
Puisque nous exécutons un thread supplémentaire, nous avons également besoin d'une méthode propre pour terminer le programme.
Un gestionnaire de signal (signal handler) est utilisé pour capturer ctrl+c et terminer le thread PotReader avant d'appeler sys.exit - sinon le programme ne se fermera pas.
ui.init('Raspberry Pi UI', (320, 240))
pygame.mouse.set_visible(False)
pitft = PiTft()
# démarrer le thread exécutant le ''callable''
potreader = PotReader(pitft)
threading.Thread(target=potreader).start()
def signal_handler(signal, frame):
print 'Vous avez pressé Ctrl+C!'
potreader.terminate()
sys.exit(0)
# Enregister le gesionnaire signal_handler pour le lignal SIGINT (interruption)
signal.signal(signal.SIGINT, signal_handler)
ui.scene.push(pitft)
ui.run()
Exécuter
Vous pouvez exécuter cet exemple final depuis le projet pygamelcd:
sudo python test5.py
Source: Raspberry Pi Pygame UI basics créé par by Jeremy Blythe pour www.adafruit.com
Traduit par Meurisse D. pour MCHobby SPRL Toute référence, mention ou extrait de cette traduction doit être explicitement accompagné du texte suivant : « Traduction par MCHobby (www.MCHobby.be) - Vente de kit et composants » avec un lien vers la source (donc cette page) et ce quelque soit le média utilisé.
L'utilisation commercial de la traduction (texte) et/ou réalisation, même partielle, pourrait être soumis à redevance. Dans tous les cas de figures, vous devez également obtenir l'accord du(des) détenteur initial des droits. Celui de MC Hobby s'arrêtant au travail de traduction proprement dit.
Traduit avec l'autorisation d'AdaFruit Industries - Translated with the permission from Adafruit Industries - www.adafruit.com