RASPBERRY – TKinter pour Python

nous abordons ici quelques bases de la boite a outils TKinter qui permet de créer des interfaces graphiques sous python.

cet article est une reprise et une traduction de certains tutos en langue anglaise trouvés ça et là sur le net (voir liste en fin d’article).

INSTALATION DE TKinter:

si TK inter n’est pas present par defaut sur votre version de l’OS linux, voici la commande pour installer la bibliotheque:

sudo apt-get install python-tk

STRUCTURE DE TKinter

TKinter utilise deux grands principes, la fenêtre (Window/frame) et le Widget ( gadget) qui s’affiche dans une Frame créant ainsi une relation parent/enfant entre le frame et le widget.

il y a 4 stades pour créer un Widget:

  • Création du widget dans une frame
  • Configuration des attributs du widget ( police de caractères, style, couleur ,etc..)
  • encapsulation dans une zone de position de la frame pour le rendre visible
  • liaison/association du widget a une fonction ou un évènement ( saisie de texte par exemple)

voyons tout de suite des exemples pour rentrer dans le vif du sujet:

Creation de BOUTONS:

 import tkinter as tk  
  
 def write_slogan():
     print("Tkinter est facile a utiliser!")
  
 root = tk.Tk()
 frame = tk.Frame(root)
 frame.pack()
  
 button = tk.Button(frame,text="QUIT",fg="red", command=quit)
 button.pack(side=tk.LEFT)
  
 slogan = tk.Button(frame,text="Hello",command=write_slogan)               
 slogan.pack(side=tk.LEFT)
  
 root.mainloop() 

l’exécution de ce bout de python dans thonny python ouvre la fenêtre ci dessous. si on clique sur Hello avec la souris , un message s’affiche, si on clique sur QUIT, on sort du programme et la fenetre se referme.

analysons la structure du module python créé:

import tkinter as tk  

cette ligne importe la boite a outil TKinter et les commandes associées

def write_slogan():
    print("Tkinter est facile a utiliser!")

ici on defini une fonction “write” qui va afficher la chaine de caractere “TKinter est facile a utiliser”

 root = tk.Tk()
frame = tk.Frame(root)
frame.pack()

Ces 3 lignes initialisent la fenetre du programme(root), definis le frame dans root et encapsulation dans root=>pack()           

button = tk.Button(frame,text="QUIT",fg="red", command=quit)
button.pack(side=tk.LEFT)

c’est ici dans ces 2 lignes , que l’on crée le widget bouton appelé “button”), qu’on défini ses attributs ( text=QUIT + police de caractere rouge + command “quit” et qu’on l’encapsule a gauche dans la frame.

slogan=tk.Button(frame,text="Hello",command=write_slogan)              
slogan.pack(side=tk.LEFT)

ici on créé un deuxieme widget bouton appelé “slogan” , avec ses attributs ( text=Hello sans police de caractere particuliere et auquel on associe la commande d’appel de la fonction “write_slogan” definie en debut de programme. pour finir , on encapsule le bouton a droite dans la fenetre.

on termine le programme par une fonction de boucle “root.mainloop()”.

Les WIDGETS d’entrée :

 import tkinter as tk
  
 master = tk.Tk()
 tk.Label(master, text="First Name").grid(row=0)
 tk.Label(master, text="Last Name").grid(row=1)
  
 e1 = tk.Entry(master)
 e2 = tk.Entry(master)
  
 e1.grid(row=0, column=1)
 e2.grid(row=1, column=1)
  
 master.mainloop() 

dans cet exemple, nous utilisons les widgets “Label” et “Entry” qui permettent respectivement de definir deux etiquettes de texte et deux zones de saisie de caracteres. ce coup ci , la particularité pour le positionnement de chacun des widget est d’utiliser le principe des lignes et colonnes pour designer l’emplacement de chaque widget . les chaines de caractères saisies seront affectées chacune a 2 variables e1 et e2 qui pourront etre utiliser par la suite ( pas de traitement dans cet exemple).

LES SLIDERS:

 from Tkinter import 
  
 master = Tk()
 w = Scale(master, from_=0, to=42)
 w.pack()
 w = Scale(master, from_=0, to=200, orient=HORIZONTAL)
 w.pack()
  
 mainloop() 

le widget “Scale” permet de créer des slider de saisie de variables. si rien n’est defini dans l’attribut le slider est vertical , pour le positionner horizontalement , mettre l’attribut orient=HORIZONTAL.

LES MENUS:

 from tkinter import 
 from tkinter.filedialog import askopenfilename
  
 def NewFile():
     print("New File!")
 def OpenFile():
     name = askopenfilename()
     print(name)
 def About():
     print("This is a simple example of a menu")
     
 root = Tk()
 menu = Menu(root)
 root.config(menu=menu)
 filemenu = Menu(menu)
 menu.add_cascade(label="File", menu=filemenu)
 filemenu.add_command(label="New", command=NewFile)
 filemenu.add_command(label="Open...", command=OpenFile)
 filemenu.add_separator()
 filemenu.add_command(label="Exit", command=root.quit)
  
 helpmenu = Menu(menu)
 menu.add_cascade(label="Help", menu=helpmenu)
 helpmenu.add_command(label="About...", command=About)
  
 mainloop() 

dernier widget que nous voyons dans ce post , la création de menus . le bout de programme affiché et disponible dans le fichier zip permet de créer et afficher le menu ci dessus .

QUELQUES LIENS POUR ALLER PLUS LOIN:

en francais:

https://python.doctor/page-tkinter-interface-graphique-python-tutoriel

http://tkinter.fdex.eu/

http://www.xavierdupre.fr/app/teachpyx/helpsphinx/c_gui/tkinter.html

en anglais

https://www.python-course.eu/python_tkinter.php

https://datatofish.com/entry-box-tkinter/

https://docs.python.org/3/library/tk.html

PI & ARDUINO via USB

mariage de raison ou comment faire communiquer un RASPBERRY PI et un ARDUINO UNO via port USB et un software .

ARDUINO et RASPBERRY sont très complémentaires en utilisation. l’ ARDUINO pour commander et communiquer avec des capteurs et globalement pour tout traitment de signal évolué , RASPBERRY PI lui est adapté pour les traitements et les calculs complexes nécessitant de la puissance, pour les affichages haute definition et les traitements grapiques evolués, pour les connexions wifi et inthernet et pour l’utilisation de software gourmants en memoire ou necessitant de la puissance de processeur .

il est donc intéressant de pouvoir les faire communiquer ensemble . partant du fait qu’ils ont tous les deux un port USB , alors autant en profiter . nous allons voir ici comment.

pour traiter la question au travers d’un exemple pratique, nous allons utiliser le montage a base d’un u capteur DHT11 pour mesurer la temperature et l’humidité) utilisé dans la rubrique ARDUINO-TUTOS:

l’idée est tout simplement de lire les données avec l’ARDUINO et de les envoyer au RASPBERRY PI via le port USB pour les afficher en clair soit via une interface graphique simple développée sous TKINTER soit via une interface graphique développée avec PROCESSING.

NOTA: tous les développements expliqués ci dessous peuvent être entièrement réalisés sous RASPBERRY PI 4 ( de preference avec mini 4Go de RAM) à condition d’installer l’IDE ARDUINO et PROCESSING sur le RPI . pour cela voir la partie “RASPBERRY – generalités / utilitaires divers”

PREPARATION DE L’ARDUINO UNO:

rappel des connexions:

programme a télécharger dans l’Arduino UNO:

#include <dht_nonblocking.h>
#define DHT_SENSOR_TYPE DHT_TYPE_11
static const int DHT_SENSOR_PIN = 2;
DHT_nonblocking dht_sensor( DHT_SENSOR_PIN, DHT_SENSOR_TYPE );

void setup( ) {
  Serial.begin( 9600);
}

static bool measure_environment( float *temperature, float *humidity ) {
  static unsigned long measurement_timestamp = millis( );
  /* Measure once every four seconds. */
  if( millis( ) - measurement_timestamp > 3000ul )   {
    if( dht_sensor.measure( temperature, humidity ) == true )
    {
      measurement_timestamp = millis( );
      return( true );
    }
  }
  return( false );
}

void loop( ) {
  float temperature;
  float humidity;
  if( measure_environment( &temperature, &humidity ) == true )
  {
    Serial.print( temperature );
    Serial.print( "," );
    Serial.print( humidity);
    Serial.print( "\n" );
  }
}

GESTION DE LA COMMUNICATION USB avec PYTHON:

avant de continuer , dans un premier temps il faut connecter l’ARDUINO UNO et le RPI via USB ( si pas deja fait pour telecharger l’ARDUINO) puis determiner la dénomination du port USB connecté a l’ARDUINO .

pour cela ouvrir le mode de commande en ligne puis taper la ligne de commande suivante:

dmesg -s 1024

apres avoir validé , un tas de lignes defilent a l’ecran et vers la fin ou trouve l’identifiant du port USB de connexion de l’ARDUINO:

ouvrir Thonny Python et copier/coller dedans le programme ci dessous ( lien du pgme version zip) en verifiant de bien mettre la designation correste du port USB ( ligne 9 partie rouge du pgme ci dessous), bien respecter egalement l’indentation des lignes:

import serial
import tkinter as tk
import datetime

root= tk.Tk()
canvas1 = tk.Canvas(root, width = 400, height = 200)
canvas1.pack()

label11 = tk.Label(root, text= "METEO")
canvas1.create_window(200, 40, window=label11)

ser = serial.Serial(port='/dev/ttyACM0',baudrate = 9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
 
while 1:
    x= str(ser.readline())
    now = datetime.datetime.now().strftime('%d/%m/%Y - %H:%M:%S')
    temp = x[2:7]
    humi = x[8:12]
    if x != "b''" :
        label12 = tk.Label(root, text= now )      
        label21 = tk.Label(root, text= "TEMPERATURE")
        label22 = tk.Label(root, text= temp +' °C')
        label31 = tk.Label(root, text= "HUMIDITE")
        label32 = tk.Label(root, text= humi + ' %')
        canvas1.create_window(200, 80, window=label12)
        canvas1.create_window(120, 120, window=label21)
        canvas1.create_window(120, 150, window=label22)
        canvas1.create_window(300, 120, window=label31)
        canvas1.create_window(300, 150, window=label32)
        label12.update()
        label22.update()
        label31.update()

root.mainloop()

lancer l’execution du programme ( fleche verte en haut dans la barre de commande de thonny python), vous devriez avoir quelque chose comme cela:

mis a part la partie affichage utilisant TKinter ( voir rubrique spécifique), la partie stratégique du programme est en ligne 9 ou l’on vient tout simplement lire le contenu de la chaine de caractère qui arrive sur le port série et la stocker dans une variable chaine “ser” puis ensuite en lignes 13 et 14 ou l’on vient récupérer les portions de chaines de caractère relatives a la température et a l’humidité dans des variables chaine “temp” et “humi” pour ensuite les afficher via l’interface TKinter ( partie dans la boucle “while 1”).

petite particularité , au passage , dans le programme on recupère la date et l’heure du RPI en ligne 12 du pgme pour la stocker dans une variable “now” pour affichage dans le GUI TKinter.

COMMUNICATION USB avec PROCESSING :

pour executer la communication avec processing , ne rien changer a la partie ARDUINO, Ouvrir l’IDE PROCESSING  et copier/coller le programme suivant puis lancer l’execution ( fleche en haut a gauche dans l’IDE processing).

// Import Meter library
import meter.*;
// Import serial library
import processing.serial.*;

Serial port; // Define a port
Meter m, m2;

void setup(){
  // First we need to create a empty window
  size(950, 400); // Size of the window (width, height)
  background(0, 0, 0); // Background color of window (R,G,B)  
  // Create new port
  port = new Serial(this, "/dev/ttyACM0", 9600); //name of the port would be different for linux  
  // Lets add a default meter to empty window
  // TEMPERATURE METER
  m = new Meter(this, 25, 80);  // here 25, 10 are x and y coordinates of meter's upper left corner  
  m.setTitleFontSize(20);
  m.setTitleFontName("Arial bold");
  m.setTitle("Temperature (C)");  
  // Change meter scale values
  String[] scaleLabels = {"0", "10", "20", "30", "40", "50", "60", "70", "80"};
  m.setScaleLabels(scaleLabels);
  m.setScaleFontSize(18);
  m.setScaleFontName("Times new roman bold");
  m.setScaleFontColor(color(200, 30, 70));  
  // We can also display the value of meter
  m.setDisplayDigitalMeterValue(true);  
  // Lets do some more modifications so our meter looks nice
  m.setArcColor(color(141, 113, 178));
  m.setArcThickness(15);  
  m.setMaxScaleValue(80);  
  m.setMinInputSignal(0);
  m.setMaxInputSignal(80);  
  m.setNeedleThickness(3);  
  // HUMIDITY METER
  // lets take some refference from first meter
  int mx = m.getMeterX(); // x coordinate of m
  int my = m.getMeterY(); // y coordinate of m
  int mw = m.getMeterWidth();  
  m2 = new Meter(this, mx + mw + 20, my);  
  m2.setTitleFontSize(20);
  m2.setTitleFontName("Arial bold");
  m2.setTitle("Humidity (%)");  
  // Change meter scale values
  String[] scaleLabels2 = {"0", "10", "20", "30", "40", "50", "60", "70", "80", "90", "100"};
  m2.setScaleLabels(scaleLabels2);
  m2.setScaleFontSize(18);
  m2.setScaleFontName("Times new roman bold");
  m2.setScaleFontColor(color(200, 30, 70));  
  // We can also display the value of meter
  m2.setDisplayDigitalMeterValue(true);  
  // Lets do some more modifications so our meter looks nice
  m2.setArcColor(color(141, 113, 178));
  m2.setArcThickness(15);  
  m2.setMaxScaleValue(100);  
  m2.setMinInputSignal(0);
  m2.setMaxInputSignal(100);  
  m2.setNeedleThickness(3);
}

void draw(){
  // Lets give title to our window
  textSize(30);
  fill(0, 255, 0); // Font color , (r,g,b)
  text("Temperature and Humidity", 250, 40); // ("text", x, y)  
  if (port.available() > 0) {
      String val = port.readStringUntil(10);  // until \n => 10 in  ascii
      if(val!=null){
         String[] list = split(val, ',');
         if(list.length==2){
             float temp = float(trim(list[0]));
             float hum = float(trim(list[1]));
             m.updateMeter(int(temp)); // int is used due to updateMeter accepts only int values
             m2.updateMeter(int(hum)); 
             println("Temperature: " + temp + " C  " + "Humidity: " + hum + "%");
             // delay(1000);             
          } 
      }
  }
}

processing est developpé a la base pour de la gestion graphique poussée , ce que ne sait pas faire TKinter , vous obtiendrez donc un resultat au look bien plus “high tech” sous processing avec des indicateurs genre compteurs/afficheurs du type ci dessous:

Données et Fichiers avec Python

le data loging ou enregistrement de donnée est un basique dans les systeme a microcontroleurs.

nous allons voir ici comment créer un fichier et enregistrer des données avec un programme en Python. pour cela nous allons examiner le cas pratique de données arrivant d’un arduino uno connecté via port USB et reprendre l’exemple de la rubrique PI & ARDUINO via USB. avec l’ARDUINO UNO qui collecte les données d’un DHT11 et voir comment les enregistrer à la volée dans un fichier sur le RPI. nous aurons ainsi les bases d’une petite station météo tournant sous RPI. ce principe pourrais également être appliqué pour un banc de mesure ou tout autre système dont l’objectif est la collecte et la sauvegarde de données.

PREPARATION DE L’ARDUINO UNO:

rappel des connexions:

L’attribut alt de cette image est vide, son nom de fichier est image-70.png.

programme a télécharger dans l’Arduino UNO:

PROGRAMME COTE RPI:

nous allons egalement reprendre le programme de gestion des données arrivant du port série (revoir rubrique PI & ARDUINO série pour le detail) et le modifier pour y ajouter des commandes qui ouvriront un fichier et enregistreront les données au fur et a mesure . ouvrir le fichier ci dessous dans thonny python ou tout autre editeur pyton.

import serial
import tkinter as tk
import datetime

root= tk.Tk()
canvas1 = tk.Canvas(root, width = 400, height = 200)
canvas1.pack()

label11 = tk.Label(root, text= "METEO")
canvas1.create_window(200, 40, window=label11)

ser = serial.Serial(port='/dev/ttyACM0',baudrate = 

9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=1)
 
while 1:
    x= str(ser.readline())
    now = datetime.datetime.now().strftime('%d/%m/%Y,%H:%M:%S')
    temp = x[2:7]
    humi = x[8:12]
    if x != "b''" :
	        f=open(‘/tmp/meteo.csv’,’a’) 
    	        f.write(now + ‘,‘ + temp + ‘,‘ + humi + ‘\n’) 
    	        f.close()
        label12 = tk.Label(root, text= now )      
        label21 = tk.Label(root, text= "TEMPERATURE")
        label22 = tk.Label(root, text= temp +' °C')
        label31 = tk.Label(root, text= "HUMIDITE")
        label32 = tk.Label(root, text= humi + ' %')
        canvas1.create_window(200, 80, window=label12)
        canvas1.create_window(120, 120, window=label21)
        canvas1.create_window(120, 150, window=label22)
        canvas1.create_window(300, 120, window=label31)
        canvas1.create_window(300, 150, window=label32)
        label12.update()
        label22.update()
        label31.update()

root.mainloop

le morceau de programme qui gerer la creation ouverture de fichier et l’enregistrement de données et la partie surlignée en vert dans la copie ci dessous :

il y a 3 lignes:

– la première ouvre le fichier ( le créée si pas existant) , a noter que le fichier créé est au format CSV (Comma-Separated Values) qui st un format texte de données tabulaires permettant une ouverture lecture sur Excel .

– la ligne suivante enregistre les données sous forme concaténée ( addition de chaine avec le signe +) en les séparant d’une virgule pour obtenir le format CSV.

-la troisième ligne referme le fichier.

si vous exécutez le programme et ensuite examinez le fichier sous Notepad ou excel vous aurez quelques chose comme ci dessous:

PIcam et Python

voyons comment intégrer la Pi camera dans un programme Python pour exploiter photos et vidéos dans des appli perso.

dans la partie RASPBERRY – generalités, nous avons vu comment brancher et configurer la camera ainsi que les premiers pas avec le shell.

PIcam dans PYTHON: bases

petit exemple tres basique de commande de la camera en python, ouvrir le programme ci dessous dans thonny python et l’executer ( fleche verte play de TP). attention, ne fonctionne qu’avec un ecran connecté mais pas en mode SSH.

from picamera import PiCamera
from time import sleep

camera = PiCamera()

camera.start_preview()
sleep(5)
camera.stop_preview()

l’apercu de la camera s’affiche en plein ecran pendant 5 secondes puis se referme. la valeur sleep() permet de fixer la durée d’affichage

si par hasard , l’image s’affiche tournée , on peut corriger l’orientation en ajoutant la ligne ci dessous apres “camera = PiCamera()” et en adaptant l’angle a l’orientation souhaitée:

camera.rotation = 180

on peu egalement rendre l’image plus ou moins transparente en ajustant la valeur alpha que l’on precise dans “camera.start_preview()“, par exemple:

camera.start_preview(alpha=150)

la valeur alpha peut varier de 0 a 255.

PRENDRE une PHOTO pendant le liveview:

il suffit d’ajouter une commande “camera.capture()” en précisant le chemin d’enregistrement de l’image.

from picamera import PiCamera
from time import sleep

camera = PiCamera()

camera.start_preview()
sleep(5)
camera.capture('/home/pi/Desktop/image.jpg')
camera.stop_preview()

le capteur de la camera adapte automatiquement la luminosité de l’image a condition de mettre au moins 2 secondes dans la valeur sleep().

en incluant la séquence d’instruction dans une boucle “for i in range()” on peut programmer une sequence de prise de vues automatique

ENREGISTRER de la video dans un fichier:

c’est aussi simple que de prendre une photo, charger et exécuter l’exemple ci dessous:

from picamera import PiCamera
from time import sleep

camera = PiCamera()

camera.start_preview()
camera.start_recording('/home/pi/Desktop/video.h264')
sleep(5)
camera.stop_recording()
camera.stop_preview()

nous venons de voir quelques bases pour l’utilisation de la camera sous python, pour approfondir les sujet , voir le site dédié a la PI camera lien ci dessous:

https://picamera.readthedocs.io/en/release-1.13/

PIcam et TKinter:

dernier point interressant a regarder , l’intégration dePIcam avec un GUI TKinter . pour cela , nous allons utiliser le petit bout de programme ci dessous, l’ouvrir dans Thonny Python et voir ce qu’il fait quand on le lance:

import tkinter as tk
import picamera
camera = picamera.PiCamera()

def CameraON():
    camera.preview_fullscreen=False
    camera.preview_window=(515,230, 640, 480)
    camera.resolution=(640,480)
    camera.sharpness = (100)
    camera.start_preview()    
def CameraOFF():
    camera.stop_preview()    
def EXIT():
    root.destroy
    camera.stop_preview()
    camera.close()
    quit()
def Brightness(value):
    camera.brightness = int(value)    
def Contrast(value):
    camera.contrast = int(value)  
def Saturation(value):
    camera.saturation = int(value)
   
root = tk.Tk()
root.resizable(width=False, height=False)
root.geometry("750x480+400+200")
root.title("PIcam")
root.buttonframe = tk.Frame(root)
root.buttonframe.grid(row=8, column=1)
tk.Button(root.buttonframe, text='Camera  ON', command=CameraON).grid(row=1, column = 1)
tk.Button(root.buttonframe, text='Camera OFF', command=CameraOFF).grid(row=2, column = 1)
tk.Button(root.buttonframe, text=' FIN du PGM ', command=EXIT).grid(row=3, column = 1)
tk.Scale(root.buttonframe, from_=30, to=100, orient=tk.HORIZONTAL, label = "Brightness", command=Brightness).grid(row=4,column=1)
tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL, label = "Contrast", command=Contrast).grid(row=5,column=1)
tk.Scale(root.buttonframe, from_=-100, to=100, orient=tk.HORIZONTAL, label = "Saturation", command=Saturation).grid(row=6,column=1)

root.mainloop()

a l’ouverture du programme , s’affiche un frame TKinter avec des boutons et slider de commande:

quand on clique sur le bouton “Camera ON” , on lance une cession de la camera qui s’affiche en mode vidéo dans une fenêtre :

ensuite on peut modifier les réglages “brightness/contrast et saturation” de la camera :

le bouton “camera OFF” ferme la camera ( la video disparait) et le bouton “FIN du PGME” permet de refermer le programme.

en créant un icone de lancement sur le bureau associé au pgme Python ( voir rubrique RASPBERRY généralités” on peut créer une application indépendante sans thonny python. a ce stade de multiples evlutions/options sont envisageables, ajouter un bouton pour prendre une image, ajouter un bouton pour enregistrer une sequence video dans un fichier , etc….

a vous de jouer !…

RPI GPIO & Python

nous allons aborder ici les bases de l’utilisation des entrées sorties du RPI avec Python sous thonny Python par exemple.

PERMISSIONS:

pour utiliser les GPIO en Python sur un raspberry Pi , il faut etre membre du groupe GPIO . l’utilisateur PI est membre par defaut , par contre , tout autre utilisateur doit etre déclaré manuellement:

sudo usermod -a -G gpio <username>

LES BIBLIOTHEQUES pour la gestion du GPIO:

il existe beaucoup de bibliotheques python pour le raspberry PI , les plus courantes pour la gestion GPIO sont les bibliotheques “RPi.GPIO” et “gpiozero” .

nous allons dans un premier temps explorer les modalité de fonctionnement avec la bibliotheque RPI.GPIO.

CONFIGURATION GENERALE:

le raspberry Pi utilise 2 numerotations , celle du connecteur 40 broches et celle liée a la numerotation de la puce (GPIO.BCM). suivant la numerotation choisie il faudra éventuellement adapter le mode avec les commandes python suivantes:

GPIO.setmode(GPIO.BOARD)

ou

GPIO.setmode(GPIO.BCM)

CONFIGURATION DES ENTREES/SORTIES:

pour initialiser les entrées-sorties , il faut préciser son numero en fonction de la configuration générale choisie et son paramétrage (entrée ou sortie) et peut etre son etat initial si nécessaire . ci dessous 3 exemples de bases:

GPIO.setup(14, GPIO.IN)

GPIO.setup(13, GPIO.OUT)

GPIO.setup(13, GPIO.OUT, initial=GPIO.HIGH)

LIRE UNE ENTREE:

pour recuperer l’etat d’entrée d’une broche , la commande est simple:

GPIO.input(12)

CHANGER L’ETAT D’UNE SORTIE:

GPIO.output(12, GPIO.LOW)

LE PWM:

le PWM fonctionne comme un objet sous python , il faut donc créer une instance avec le canal utilisé et la frequence souhaitée. ci dessous un exemple:

p = GPIO.PWM(channel, frequence)
p.start(rapport_cyclique) #rapport_cyclique entre 0.0 et 100.0
p.ChangeFrequency(nouvelle_frequence)
p.ChangeDutyCycle(nouveau_rapport_cyclique)
p.stop()

regardons maintenant quelques exemples avec la bibliotheque GPIOzero:

PREMIER EXEMPLE SIMPLE , la LED :

pour cet exemple nous allons utiliser la librairie GPIO zero. tous les détails de cette librairie sont disponible ici ( en anglais uniquement malheureusement):

https://gpiozero.readthedocs.io/en/stable/

petit avantage de la gestion GPIO sous Python du RPI par rapport a l’arduino, beaucoup de librairies spécifiques existent pour tous les composants basiques ou plus evolués , par exemple pour gérer l’allumage et l’extinction d’une led , on utilise une librairie , exemple ci dessous ( on fait clignoter une LED a frequence d’une seconde):

NOTA: pour l’utilisation de LEd sur RPI , avec une tension de sortie GPIO a 3,3 V , les resistance standard de 220 Ohms pour du 5V passent a 180 Ohms pour du 3,3V (165 Ohms en calcul theorique pour un courant a 20 mA).

from gpiozero import LED
from time import sleep

led = LED(17)

while True:
    led.on()
    sleep(1)
    led.off()
    sleep(1)

DEUXIEME EXEMPLE , le Bouton :

après avoir testé la commande d’une “sortie” , deuxieme cas simple , une entrée avec la réception d’un appui bouton:

ici , comme avec la LED , on branche le bouton entre la masse et la broche GPIO 2 et suivant la situation du bouton un message est affiché dans la zone de message en bas de l’IDE Thonny Python.

from gpiozero import Button
from time import sleep

button = Button(2)

while True:
    if button.is_pressed:
        print("Pressed")
    else:
        print("Released")
    sleep(1)

TROISIEME EXEMPLE , Bouton + LED:

ici on combine les 2 exemples précédents. après appui sur le bouton , la led s’allume.

from gpiozero import LED, Button

led = LED(17)
button = Button(2)

while True:
    if button.is_pressed:
        led.on()
    else:
        led.off()

COMMANDE de la PI camera avec un Bouton

dans cet exemple , nous allons déclencher la prise d’une image par la PIcamera ( voir rubrique TUTO et généralités pour la PIcamera). le branchement sera le même que pour le bouton seul sans PIcam car rien a rajouter:

et le programme tres simple également:
from gpiozero import Button
from picamera import PiCamera
from datetime import datetime
from signal import pause

button = Button(2)
camera = PiCamera()

def capture():
    timestamp = datetime.now().isoformat()
    camera.capture('/home/pi/%s.jpg' % timestamp)

button.when_pressed = capture

pause()

COMMANDE de la PI camera avec deux Boutons

variante du programme précédent avec 2 boutons qui vont pour l’un commander le start and stop de la camera et l’autre la prise d’une image .le deuxieme bouton est branché sur le GPIO 3.

from gpiozero import Button
from picamera import PiCamera
from datetime import datetime
from signal import pause

left_button = Button(2)
right_button = Button(3)
camera = PiCamera()

def capture():
    timestamp = datetime.now().isoformat()
    camera.capture('/home/pi/%s.jpg' % timestamp)

left_button.when_pressed = camera.start_preview
left_button.when_released = camera.stop_preview
right_button.when_pressed = capture

pause()

de la même façon, on pourrait remplacer le bouton par un détecteur de présence infrarouge ou une barrière lumineuse avec détecteur de luminosité pour détecter le passage dans le faisceau et ainsi déclencher la prise de vue.

GPIO & PHOTORESISTANCE

bien que le GPIO du RPI n’ait pas de broche analogique, nous allons voir comment lire l’intensite lumineuse avec une photo résistance .

le principe de la mesure est simple , on va utiliser la librairie ” gpiozero ” , et un condensateur de 1μF en série avec la photorésistance.

cela va constituer un circuit RC pour lequel la fonction Lightsensor() de la librairie GPIOZERO va mesurer le temps de charge et décharge du condensateur pour en déduire la résistance correspondante et donc la luminosité résultante. R = f ( luminosité).

LE MONTAGE

le programme Python:

from gpiozero import LightSensor

ldr = LightSensor(4)  # ici broche GPIO4
while True:
    print(ldr.value)

ne reste plus soit qu’a faire varier l’intensité lumineuse sur la photorésistance avec une lampe LED ou couvrir plus ou moins avec les doigts et/ou des filtres et voir comment varie la valeur affichée . bien entendu il est possible d’améliorer le programme avec une petite interface visuelle sous Tkinter …

GPIO & Capteur HC-SR501

voyons comment utiliser un capteur HC-SR501 sur le GPIO RPI.

  • broche Vcc du HC-SR501 sur le 5V du RPI
  • broche Gnd du capteur sur Gnd du RPI
  • broche Out (3,3V TTL) sur GPIO 4

LE PROGRAMME PYTHON:

from gpiozero import MotionSensor

pir = MotionSensor(4)

while True:
	pir.wait_for_motion()
	print("Ca Bouge !...")
	pir.wait_for_no_motion()

voila pas plus compliqué que ça , encore une fois c’est la librairie qui fait tout .

GPIO 8 entrées analogiques avec le MCP3008

le MCP3008 est un module de conversion ANALOGIQUE / NUMERIQUE qui fonctionne avec le Bus SPI du RPI .

nous allons voir comment l’utiliser directement sur une breadboard , mais on peut le commander en petit modules du genre du Ras Pio Analog Zero ci dessous :

CONFIGURATION du BUS SPI

pour pouvoir utiliser le Bus SPI du RPI , il va falloir tout d’abord l’activer , pour cela aller dans le menu de config du RPI et activer l’option SPI puis rebooter le RPI.

LE MONTAGE DE TEST

pour tester le fonctionnement du MCP 3008 nous allons utiliser un potentiomètre . ci dessous schéma de câblage de l’ensemble avec le potard sur la breadboard.

pour memo rappel des brochages GPIO SPI du RPI : ( voir RPI generalites)

LE PROGRAMME PYTHON

from gpiozero import MCP3008
pot = MCP3008(0)
while True:
    print(pot.value)

le MCP3008 possède 8 canaux d’entrée notés de 0 a 7 ( de bas en haut sur le montage a droite du MCP3008 ) , dans ce bout de programme on lit le canal 0 que l’on met dans la variable pot via la commande : “pot = MCP3008(0) ” puis on fait afficher la valeur dans une boucle while .

si l’on voulait lire 3 capteur Analogiques ( 3 potards par exemple sur les canaux 0 – 1 et 2 ) , il suffirait d’avoir 3 lignes du genre:

pot1 = MCP3008(0) 
pot2 = MCP3008(1) 
pot3 = MCP3008(2) 

voila synthétisée la façon de pouvoir utiliser jusqu’à 8 capteurs analogiques pour une station meteo par exemple.

moteur Pas a Pas type NEMA 17

comme pour l’Arduino, nous allons voir ici comment piloter un moteur Pas a Pas sur GPIO avec un programme Python. de la meme façon , nous allons utiliser un driver POLOLU A4988 , mais le principe est le même avec les autres drivers de la gamme POLOLU

avant de commencer la partie conexion RPI , petit rappel du schéma de principe d’un POLOLU A4988 (pour memo, le niveau logique TTL admissible est entre 3 et 5,5 V donc compatible avec la logique TTL 3,3V du RPI):

CABLAGE

GPIO 20 sur STEP du Pololu et GPIO 21 sur DIR du Pololu. MS1-MS2-MS3 non connecté => full step. pour le réglage de la limite d’intensité du Pololu voir la rubrique ARDUINO CNC.

ne pas oublier de mettre un condensateur 100micro Fahrad entre + et 6 de l’alim de puissance (Power Supply sur le schéma).

EXEMPLE PROGRAMME PYTHON n°1

le programme ci dessous fait faire un tour dans un sens puis un tour dans l’autre sens

from time import sleep
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(20, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)

GPIO.output(21, 1)
for x in range(200):
	GPIO.output(20, GPIO.HIGH)
	sleep(0.005)
	GPIO.output(20, GPIO.LOW)
	sleep(0.005)

sleep(0.5)

GPIO.output(21, 0)
for x in range(200):
	GPIO.output(20, GPIO.HIGH)
	sleep(0.005)
	GPIO.output(20, GPIO.LOW)
	sleep(0.005)