Home » Tutoriel

Category: Tutoriel

Apprendre le microPython avec la carte Raspberry Pi Pico

 

Ce tutoriel a pour objectif d’apprendre la programmation en langage microPython en utilisant la carte Raspberry Pi Pico. Cette carte est équipé d’un microcontrôleur RP2040. Le langage microPython est le portage du langage Python adapté aux microcontrôleurs.

Matériels & Logiciel nécessaire

  • Une carte Raspberry Pi Pico
  • Une câble micro-usb
  • Un PC avec le logiciel Thonny (thonny.org)

Présentation de la carte Raspberry Pi Pico

Voici le pinout de la carte Pico :

Le microcontrôleur RP2040

Voici l’architecture du microcontrôleur RP2040 :

  • 2 cœur ARM Cortex M0+ à 48 Mhz (32 bits)
  • 264 KB RAM
  • 2MB de mémoire flash
  • 26 GPIO, PWM, SPI, I2C, UART
  • USB 1.1

Installation du logiciel IDE Thonny

Voir la page : thonny.org

Premier programme, Hello avec le shell

Un premier exemple très simple d’affichage de texte avec la fonction print() :

Gestion d’une led avec le shell

Un exemple de programmer pour allumer une led.

  • La led est connecté sur la pin n°2 (GP2)

Vous pouvez essayer de taper ces lignes de code dans le shell :

Et la lumière fut, allumer et éteindre une led !

Un exemple très simple de programme pour allumer une led :

  • La led doit être connectée sur la GPIO n°2
from machine import Pin
led = Pin(2, Pin.OUT) # configuration de la pin 2 en sortie
led.value(1) # mise à l'état haut de la pin 2, la led s'allume !

Un exemple simple de programme pour allumer une led pendant 2 secondes et ensuite l’éteindre :

from machine import Pin
import time

led = Pin(2, Pin.OUT) # configuration de la pin 2 en sortie

while True: # boucle infini
  led.value(1)
  time.sleep(2) # pause de 2 secondes
  led.value(0)
  time.sleep(1) # pause de 1 seconde

Un autre exemple avec l’utilisation de la fonction toggle():

  • La led va clignoter toutes les 2 secondes
from machine import Pin
import time

led = Pin(2, Pin.OUT)

while True:
  led.toggle()
  time.sleep(2)

Utilisation du shell, print

Utilisation de la fonction print() pour afficher du texte dans le shell :

from machine import Pin
import time

print("Hello Raspberry Pi Pico ! ")

Le résultat dans le shell :

Gestion d’un bouton poussoir

Un exemple pour lire le manière continue l’état d’un bouton poussoir connecter sur la pin 3 de la carte Raspberry Pi Pico :

from machine import Pin, ADC, PWM
import time

bouton = Pin(3, Pin.IN, Pin.PULL_UP) # configuration pin 3 en entrée

while True:
  valeur = bouton.value() #Lecture de l'état du bouton
  print(valeur)
  time.sleep(1)

Résultat sur le shell de l’appuie sur le bouton poussoir, passage de l’état haut à l’état bas :

  • Bouton non appuyé : état haut (1)
  • Bouton appuyé : état haut (0)

Un autre exemple pour gérer l’allumage de la led avec le bouton :

from machine import Pin, ADC, PWM
import time

led = Pin(2, Pin.OUT)
bouton = Pin(3, Pin.IN, Pin.PULL_UP)

while True:
  valeur = bouton.value()

  if valeur == 1:
    led.value(1)
    print("Bouton OFF")
  else:
    print("Bouton ON") 
    led.value(0)
time.sleep(0.5)

Gestion d’une entrée analogique

Un exemple pour lire une entrée analogique :


from machine import Pin, ADC
import time

adc = ADC(Pin(26)) # configuration pin 26 en entrée analogique

while 1:
  print("Valeur adc = ", adc.read_u16())
  time.sleep(0.2)

Le résultat de la lecture de l’entrée analogique avec le Plotter :

Écriture/lecture d’un fichier texte

Un exemple très simple d’écriture dans un  fichier :

import time

file = open("test.txt", "w") # Ouverture du fichier texte.txt en mode ecriture

file.write("Ecriture dans le fichier") # ecriture dans le fichier

file.close() # fermeture du fichier

Écriture en boucle d’une variable :

  • str() : permet de convertir en chaine de caractère
  • ‘\n’ : permet le saut d’une ligne
import time

file = open("test.txt", "w")

compteur = 0

while compteur < 10:
  file.write("Bonjour, compteur = ")
  file.write(str(compteur) + "\n")
  print(compteur)
  compteur+=1

file.close()

Gestion d’un signal PWM

  • PWM : Pulse With Modulation ou modulation de la largeur d’impulsion

C’est quoi un signal PWM ?

This file is licensed under the Creative Commons Attribution-Share Alike 4.0 International license. (https://en.wikipedia.org/wiki/Pulse-width_modulation)

Un exemple sur la pin 4, d’un signal PWM. Ce signal PWM permet par exemple de contrôler l’intensité lumineuse d’une led ou encore la commande en vitesse d’un moteur à courant continu.

from machine import Pin, ADC, PWM
import time

signal = Pin(4, mode=Pin.OUT)
signal = PWM(Pin(4))

signal.freq(500) # fréquence de 500 Hz
signal.duty_u16(32000) # rapport cyclique

Un autre exemple de génération d’un signal PWM :

from machine import Pin, ADC, PWM
import time

signal = Pin(4, mode=Pin.OUT)
signal = PWM(Pin(4))

signal.freq(500)

for rapport in range(0,65_536):
  signal.duty_u16(rapport)
  print(rapport)
  time.sleep(0.001)

Contrôle d’un servomoteur

Maintenant, passons au contrôle d’un servomoteur en microPython.

Connexion du servomoteur :

  • Fil rouge : +5V
  • Fil noir : GND
  • Fil orange : GPIO 4

Un exemple de programme pour le contrôle d’un servomoteur :

  • Configuration de la GPIO 4 en signal PWM
  • Pour le contrôle d’un servomoteur la fréquence doit être de 50 Hz
  • Le contrôle angulaire d’un servomoteur varie en fonction du rapport cyclique (entre 1 et 2 ms environ, dépends du type de servomoteurs)
from machine import Pin, PWM
import time

servo = Pin(4, mode=Pin.OUT)
servo = PWM(Pin(4))

servo.freq(50)

while True:
  servo.duty_u16(2314)
  time.sleep(2)
  servo.duty_u16(7600)
  time.sleep(2)

Allumer une led avec un timer !

Un exemple d’utilisation d’un timer pour faire clignoter la led interne de la carte Raspberry Pi PICO toutes les secondes :

from machine import Pin, Timer

led = Pin("LED", Pin.OUT)

timer_led = Timer()

def mon_timer_led(timer):
  global led
  led.toggle()

timer_led.init(freq=1, mode=Timer.PERIODIC, callback=mon_timer_led)

Interruption matérielle avec un bouton poussoir

Un exemple de programme pour gérer l’appui d’un bouton poussoir avec une interruption matérielle (IRQ). Une interruption matérielle est déclenchée par une entrée (GPIO) du microcontrôleur. Dans cet exemple, l’entrée 3 est configurée en interruption.

from machine import Pin
import time

def mon_interruption(pin):
print("Bouton ON")


bouton = Pin(3, Pin.IN, Pin.PULL_UP) # configuration du bouton sur l'entée 3

bouton.irq(trigger=Pin.IRQ_FALLING,handler=mon_interruption)

# boucle infini
while True:
  print("Boucle infini, attendre ...") # attendre l'appuie sur le bouton
  time.sleep(1)

Programmation multicore

Le microcontrôleur RP2040 possédé 2 cœurs de processeur (ARM Cortex M0+)  de 133 Mhz:

  • Core0
  • Core1
from time import sleep
import _thread


def core0_thread():
  compteur= 0
  while True:
    print("Hello, Je suis le core0 : ", compteur)
    compteur+= 1
    sleep(1)


def core1_thread():
  compteur= 1
  while True:
    print("Hello, Je suis le core1 : ", compteur)
    compteur+= 1
    sleep(3)


thread_core1 = _thread.start_new_thread(core1_thread, ())

core0_thread()

 

Fin du Tuto !

Le robot MRPiZ en langage C

Un tutoriel pour programmer le robot mobile MRPiZ en langage C.

Lien pour l’API C : https://github.com/macerobotics/MRPiZ/tree/master/Software/C

Les fichiers doivent être placer dans des répertoires:

  • les fichiers .c dans le répertoire sources
  • les fichiers .h dans le répertoire header

 

Exemple n°1 : simple déplacement

Un exemple pour déplacer le robot MRPiZ:

[pastacode lang=”c” manual=”%23include%20%22MRPiZ.h%22%0A%0A%0Aint%20main(int%20argc%2C%20char*%20argv%5B%5D)%0A%7B%0A%0A%20%20init()%3B%0A%0A%20%20forward(25)%3B%0A%0A%20%20sleep(3)%3B%0A%0A%20%20back(25)%3B%0A%0A%20%20sleep(3)%3B%0A%0A%20%20stop()%3B%0A%7D” message=”” highlight=”” provider=”manual”/]

Compilation du fichier :

[pastacode lang=”c” manual=”gcc%20sources%2F*.c%20-I%20header%20-o%20Exemple1″ message=”” highlight=”” provider=”manual”/]

Exécution du programme :

[pastacode lang=”c” manual=”.%2FExemple1″ message=”” highlight=”” provider=”manual”/]

 

Exemple n°2 : lecture des capteurs laser

Un exemple pour la lecture des 3 capteurs ToF du robot :

[pastacode lang=”c” manual=”%23include%20%22MRPiZ.h%22%0A%0A%0Aint%20main(int%20argc%2C%20char*%20argv%5B%5D)%0A%7B%0Aint%20p2%2C%20p3%2C%20p4%3B%0Aint%20c%3D0%3B%0A%0A%20%20init()%3B%0A%0A%20%20for(c%3D0%3B%20c%20%3C%2010%3B%20c%2B%2B)%0A%20%20%7B%0A%20%20%20%20p2%20%3D%20proxSensor(2)%3B%0A%20%20%20%20p3%20%3D%20proxSensor(3)%3B%0A%20%20%20%20p4%20%3D%20proxSensor(4)%3B%0A%0A%20%20%20%20printf(%22Capteur%20p1%3D%25d%5Cn%22%2C%20p2)%3B%0A%20%20%20%20printf(%22Capteur%20p2%3D%25d%5Cn%22%2C%20p3)%3B%0A%20%20%20%20printf(%22Capteur%20p3%3D%25d%5Cn%22%2C%20p4)%3B%0A%20%20%0A%20%20%20%20sleep(1)%3B%0A%20%20%7D%0A%20%20%0A%7D” message=”” highlight=”” provider=”manual”/]

Exemple n°3 : lecture des encodeurs

Un exemple pour la lecture des 2 encodeurs du robot.

[pastacode lang=”c” manual=”%23include%20%22MRPiZ.h%22%0A%0A%0Aint%20main(int%20argc%2C%20char*%20argv%5B%5D)%0A%7B%0Aint%20eL%2C%20eR%3B%0Aint%20c%3B%0A%0A%20%20init()%3B%0A%0A%20%20for(c%3D0%3B%20c%20%3C%2010%3B%20c%2B%2B)%0A%20%20%7B%0A%09%20%20%0A%09forward(30)%3B%0A%09%0A%20%20%20%20eL%20%3D%20encoderLeft()%3B%0A%20%20%20%20eR%20%3D%20encoderRight()%3B%0A%0A%20%20%20%20printf(%22encoder%20left%3D%25d%5Cn%22%2C%20eL)%3B%0A%20%20%20%20printf(%22encoder%20right%3D%25d%5Cn%22%2C%20eR)%3B%0A%0A%20%20%20%20sleep(1)%3B%0A%20%20%7D%0A%20%20%0A%20%20stop()%3B%0A%0A%7D” message=”” highlight=”” provider=”manual”/]

 

Fin du tuto !

Robot MRPiZ + capteur de gestes

Une vidéo du robot MRPiZ avec le capteur de gestes 3D Flick:

 

Le programme en langage python:

#!/usr/bin/env python
import sys
from mrpiZ_lib import *
import time
import flicklib
from copy import copy
import subprocess


def message(value):
  print value

@flicklib.move()
def move(x, y, z):
  global xyz
  xyz = [x,y,z]

def main():
  time_PasDetection = 0
  global xyz
  xyz = [0,0,0]
  old_xyz = [0,0,0]
  deplacement_axeX = 0

  print "Exemple"

  while True:
    if old_xyz != xyz:
      deplacement_axeX = xyz[0]
      deplacement_axeY = xyz[1]

    print "X", deplacement_axeX
    print "Y", deplacement_axeY

    if(deplacement_axeX < 0.35):
      print "avancer"
      forward(25)
    if(deplacement_axeX > 0.75):
      print "reculer"
      back(25)
    if((deplacement_axeY > 0.75)and(deplacement_axeX > 0.35)and(deplacement_axeX < 0.75)):
      print "tourner droite"
      turnRight(25)
    if((deplacement_axeY < 0.5)and(deplacement_axeX > 0.35)and(deplacement_axeX < 0.75)):
      print "tourner gauche"
      turnLeft(25)
    time.sleep(0.5)
    #stop()
    else:
      print "pas de detection"
      time_PasDetection = time_PasDetection + 1
    if(time_PasDetection > 5):
      stop()
      time_PasDetection = 0
    old_xyz = copy(xyz)
    time.sleep(0.2)

if __name__ == "__main__":
  main()

MRPiZ – suivie de ligne avec openCV & python

Ce tutorial présente l’implémentation d’un suivi de ligne pour le robot mobile MRPiZ.

Matériel nécessaire

  • Un robot MRPiZ
  • Une caméra compatible, idéalement grand angle.
 

Logiciels nécessaire

  • Python 2.7 (déja installé par défaut),
  • La bibliothèque Python MRPiZ (déja installée par défaut),
  • OpenCV pour python

 

Activation de video4linux

Deux méthodes sont possibles pour accéder à la caméra:

  1. PiCamera: la méthode la plus répandue, mais lente car il est nécessaire de transformer l’image pour la mettre au bon format,
  2. v4l: qui s’interface directement avec OpenCV, c’est la méthode choisie pour ce tutorial.

Il nous faut donc activer v4l:

$ sudo modprobe bcm2835-v4l2

Warning

Cette commande est a effectuer à chaque redémarrage.

 

Le suivi de ligne

Le fichier complet se trouve dans Software/Python/tutorials/line_follower/line.py.

Warning

Utilisez CTRL+C pour arrêter le robot.

Importation des modules

import numpy as np
import cv2
import sys
from mrpiZ_lib import *

Paramétrés globaux

# image size
WIDTH = 640
HEIGHT = 480

# turn coeff
COEFF = 0.05
# base robot speed in straight line
SPEED = 30

Activation de la caméra

Pour améliorer les performances, la résolution est réduite à 640 pixels en largeur et 480 en hauteur.

video_capture = cv2.VideoCapture(0)
video_capture.set(3, WIDTH)
video_capture.set(4, HEIGHT)

Boucle principale

La boucle principale va fonctionner à l’infini, pour l’arrêter il faudra appuyer sur CTRL+C.

try:
    while(True):

Capture de l’image

Première étape, on commence par capturer une image.

# Capture the frames
ret, frame = video_capture.read()

Voici un exemple d’image capturée:

0_init.jpg

Suppression de la partie haute

Pour améliorer les performances, on ne va garder que la partie basse de l’image:

# Crop the image
# Keep the 100 lower pixels
crop_img = frame[379:480, 0:640]

1_crop.jpg

Niveaux de gris

Ensuite on passe l’image en niveaux de gris:

# Convert to grayscale
gray = cv2.cvtColor(crop_img, cv2.COLOR_BGR2GRAY)

2_gray.jpg

Flou

Un filtre afin de rendre flou les lignes de l’image est appliqué, il permet de rendre plus efficace les étapes suivantes:

# Gaussian blur
blur = cv2.GaussianBlur(gray,(5,5),0)

3_blur.jpg

Seuillage

Ensuite on va filtrer les parties claires de l’image pour ne garder les parties noires, pour cela, un filtre de seuillage est appliqué:

# Color thresholding
ret,thresh = cv2.threshold(blur,60,255,cv2.THRESH_BINARY_INV)

4_thresh.jpg

Détection de contours

Ensuite, on va utiliser openCV pour détecter les contours:

# Find the contours of the frame
contours,hierarchy = cv2.findContours(thresh.copy(), 1, cv2.CHAIN_APPROX_NONE)

5_contour.jpg

Extraction du plus gros contour

Il nous faut ensuite extraire la ligne la plus large trouvée afin d’éliminer les fausses détections:

# Find the biggest contour (if detected)
if len(contours) > 0:
    c = max(contours, key=cv2.contourArea)
    M = cv2.moments(c)

    # Skip to avoid div by zero
    if int(M['m00']) == 0:
        continue

Calcul du milieu de la ligne

Une fois les contours de la ligne détectée, on calcul le centre de la ligne, c’est la que l’on veut que le robot aille:

# Get the line center
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

Contrôle des moteurs

Une correction proportionnelle à la différence entre la position de la ligne et le milieu de l’image est calculée. Les moteurs sont ensuite commandés pour ralentir un des moteurs et accélérer l’autre, ceci afin de faire tourner le robot en direction du centre de la ligne.

delta = COEFF * (cx - 320)
motorRight(0, SPEED - delta)
motorLeft(0, SPEED + delta)

Clavier

Enfin, deux lignes de code permettent d’arrêter le robot quand on appuie sur CTRL+C.

except KeyboardInterrupt:
    stop()

Dessin avec MRduino2 & Blockly

Tutoriel pour faire dessiner le robot MRduino2.

Matériel nécessaire:

  • Un feutre de couleur

 

Dessiner un petit cercle

Un simple programme pour faire un cercle :

  • Le robot tourne sur lui-même vers la droite à une vitesse de 25%.

 

 

Dessiner un grand cercle

Une autre manière de faire un cercle plus grand en utilisant un seul moteur :

Petit exercice,comment dessiner un très grand cercle ?

La réponse :

Dessiner des vagues

Un petit programme Blockly pour dessiner des vagues avec le robot MRduino2:

Dessiner un carré (un peu près !)

Un programme pour dessiner un carré :

 

Fin du tuto, à vous de réaliser vos propres dessins.

 

Configuration Wifi de la carte Pi Zero W

Article pour la configuration de la communication Wifi de la carte Pi Zero W en ligne de commande.

Version Raspian : April 2017 (Raspian Jessie Lite)

  • Ouvrir avec le terminal le fichier wpa_supplicant.conf :
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
  • Modifier ce fichier comme ci-dessous :
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=GB

network={
    ssid="YOUR_SSID"
    psk="YOUR_PASSWORD"
    key_mgmt=WPA-PSK
}
  • Enregistrer et redémarrer votre carte Raspberry Pi:
sudo reboot