''' | |
Lecture d'une page web par le Raspberry Pi Pico W | |
(Le Raspberry Pi Pico W récupère le | |
titre du plus récent article publié | |
sur le blog "Électronique en Amateur") | |
Pour plus d'informations: | |
https://electroniqueamateur.blogspot.com/2022/08/raspberry-pi-pico-w-lire-le-contenu.html | |
''' | |
import network | |
import urequests | |
import time | |
# à remplacer par le nom du réseau wifi et le mot de passe | |
ssid = 'nom_du_reseau_wifi' | |
password = 'mot_de_passe' | |
# connexion au réseau wifi | |
wlan = network.WLAN(network.STA_IF) | |
wlan.active(True) | |
wlan.connect(ssid, password) | |
max_wait = 10 # si pas connecté en 10 secondes, on abandonne | |
print('Attente de la connection', end='') | |
while max_wait > 0: | |
if wlan.status() < 0 or wlan.status() >= 3: | |
break | |
max_wait -= 1 | |
print('.', end='') | |
time.sleep(1) | |
print ('') | |
if wlan.status() != 3: | |
raise RuntimeError('Echec de la connexion a ' + ssid) | |
else: | |
print('Connexion reussie') | |
status = wlan.ifconfig() | |
print('') | |
# on récupère la page web | |
print("Le plus recent article publie sur le blog est:") | |
page_web = urequests.get("http://electroniqueamateur.blogspot.com") | |
# extraction de l'information recherchée | |
position = page_web.text.find("<h3 class='post-title entry-title' itemprop='name'>") | |
extrait = page_web.text[position + 80:position + 300] | |
position = extrait.find(">") | |
extrait = extrait[position + 1:] | |
position = extrait.find("<") | |
extrait = extrait[:position] | |
print(extrait) | |
page_web.close() |
samedi 27 août 2022
Raspberry Pi Pico W: lire le contenu d'une page web (Micropython)
samedi 20 août 2022
Dans un blog près de chez vous (24)
Quelques publications passionnantes trouvées sur d'autres blogs...
- Parallel breakout: carte DIY pour redécouvrir le port parallèle, carte cobbler pour faire du prototypage avec le port parallèle en Python , assemblage et contrôle des cartes, tests d'entrée/sorties en Python, Publication des cartes en Open-Source + Suite du projet
- Raspberry Pi Pico W: Adresse IP fixe
- Carte 4 relais WiFi avec Raspberry-Pi Pico - faire de l'IoT en Python
- Pico Wireless: Comment utiliser WEBRepl
- Récupération: exploration d'une sonde coloscopique médicale
jeudi 11 août 2022
Utilisation d'un écran OLED SPI SSD1306 avec Arduino
Dans cet article, nous explorons l'utilisation d'un écran OLED SPI SSD1306 avec un Arduino.
OLED signfie "organic light-emitting diode": chaque pixel de l'écran peut s'allumer comme s'il s'agissait d'une LED (par opposition à d'autres technologies d'affichage qui nécessitent un rétroéclairage). Ces petits écrans monochromes ne coûtent pas cher et offrent un excellent contraste peu importe l'éclairage ambiant.
J'ai fait mes tests avec un afficheur dont la résolution est 128 par 64 pixels (c'est la résolution la plus fréquente).
Jusqu'à tout récemment, j'avais exclusivement utilisé des écrans OLED qui utilisaient une interface I2C: 4 connecteurs étaient suffisants pour les faire fonctionner. Les modèles SPI, qui sont en principe plus rapides, comportent 7 connecteurs.
Les broches de mon afficheur sont identifiées de cette façon:
- GND (la masse)
- VCC (alimentation qui, sur ce modèle, peut être de 5 V ou de 3,3 V)
- D0 : qui est en fait le signal d'horloge SPI (SCLK)
- D1: qui transmet les infos du microcontrôleur vers l'écran (MOSI)
- RES: reset
- DC: permet permuter entre les modes "data" ou "command"
- CS: "chip select", essentiel si plusieurs appareils sont branchés sur le même bus SPI.
Connexions de l'écran OLED à un Arduino Uno
J'ai fait mes premiers tests avec un Arduino Uno, et j'ai branché l'écran OLED de cette façon:
- GND de l'écran OLED : GND de l'Arduino Uno
- VCC de l'écran OLED: sortie 5 V de l'Arduino Uno
- D0 : broche 13 de l'Arduino Uno
- D1: broche 11 de l'Arduino Uno
- RES: broche 8 de l'Arduino Uno
- DC: broche 9 de l'Arduino Uno
- CS: broche 10 de l'Arduino Uno
Vous branchez RES, DC et CS où vous voulez, en n'oubliant pas de modifier le sketch en conséquence.
Bibliothèque u8g2 ou Adafruit?
Les deux bibliothèques les plus utilisées pour piloter un écran OLED avec une carte Arduino sont u8g2 et la bibliothèque d'Adafruit. Chacune des deux constitue un excellent choix.
J'ai testé les deux bibliothèques avec un Arduino Uno, un ESP32, un ESP8266 et un STM32 "Blue Pill". Tout a fonctionné correctement avec la bibliothèque u8g2, mais je ne suis pas parvenu à faire fonctionner la Blue Pill avec la bibliothèque d'Adafruit (l'écran demeurait noir).
Il me semble que la bibliothèque d'Adafruit est un peu plus conviviale, et que u8g2 présente un plus grand choix de polices de caractères (incluant des polices accentuées, ce qui est bien pratique en français).
Évidemment, chacune des deux bibliothèques est accompagnée d'un grand nombre de fichiers d'exemples qui permettent de visualiser rapidement plusieurs résultats possibles.
Vous trouverez ci-dessous deux sketches qui sont assez similaire: ils affichent un peu de texte et quelques formes géométriques simples, ainsi qu'une illustration bitmap. Le premier sketch est conçu pour être utilisé avec la bibliothèque u8g2, alors que l'autre nécessite la bibliothèque d'Adafruit.
Sketch utilisant la bibliothèque u8g2
Ce premier sketch utilise la bibliothèque u8g2, que vous pouvez installer à partir du gestionnaire de bibliothèques.
-
/******************************************************* | |
Utilisation d'un écran OLED SSD1306 SPI 128*64 | |
(bibliothèque u8g2) | |
Plus d'infos: | |
https://electroniqueamateur.blogspot.com/2022/08/utilisation-dun-ecran-oled-spi-ssd1306.html | |
********************************************************/ | |
#include <U8g2lib.h> | |
#include <SPI.h> | |
// connexion hardware spi: | |
U8G2_SSD1306_128X64_NONAME_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8); | |
// U8G2_R0 ou U8G2_R2: mode paysage, U8G2_R1 ou U8G2_R3: mode portrait | |
/* Définition d'une image bitmap: logo du blog Électronique en Amateur | |
sauvegardé dans un fichier XBM, puis ouvert avec un éditeur de texte: */ | |
static const unsigned char logoBitmap[] PROGMEM = { | |
0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0x06, 0xf0, 0xff, 0x03, 0x3f, 0x04, | |
0x00, 0xf8, 0x03, 0x1f, 0x06, 0x00, 0x80, 0x03, 0x0f, 0x84, 0x0f, 0x85, | |
0x03, 0x07, 0x86, 0x9f, 0x8f, 0x03, 0x07, 0xc4, 0xdf, 0x8f, 0x03, 0x03, | |
0xc4, 0xff, 0x9f, 0x03, 0x03, 0xc6, 0xff, 0x9f, 0x03, 0x03, 0xc4, 0xf9, | |
0x9f, 0x03, 0x03, 0xc4, 0x70, 0x8e, 0x03, 0x03, 0xc4, 0x30, 0x8c, 0x03, | |
0x03, 0x84, 0x39, 0x84, 0x03, 0x03, 0x04, 0x6f, 0x86, 0x03, 0x03, 0x04, | |
0xc4, 0x81, 0x03, 0x03, 0x84, 0x01, 0x80, 0x03, 0x03, 0x84, 0x01, 0x98, | |
0x03, 0x03, 0x04, 0x03, 0x98, 0x03, 0x03, 0x04, 0x0e, 0x8e, 0x03, 0x03, | |
0x0c, 0xf8, 0x83, 0x03, 0x03, 0xff, 0x17, 0x80, 0x03, 0x83, 0x00, 0xfc, | |
0x97, 0x03, 0x63, 0x00, 0x00, 0xfc, 0x03, 0x23, 0x00, 0x00, 0x80, 0x03, | |
0x13, 0x00, 0x00, 0x80, 0x03, 0x0b, 0x00, 0x00, 0x80, 0x03, 0x8f, 0x07, | |
0x00, 0x80, 0x03, 0x07, 0x06, 0x06, 0x80, 0x03, 0x03, 0x07, 0x07, 0x86, | |
0x03, 0x03, 0x06, 0x86, 0x86, 0x03, 0x03, 0x06, 0x06, 0x86, 0x03, 0x03, | |
0x06, 0x06, 0xc6, 0x03, 0x07, 0x07, 0x06, 0xe6, 0x03, 0x0f, 0x06, 0x06, | |
0xf6, 0x03, 0x1f, 0x06, 0x06, 0xf6, 0x03, 0xff, 0x06, 0x06, 0xf6, 0x03, | |
0xff, 0x06, 0x76, 0xf6, 0x03, 0xff, 0x76, 0x76, 0xf6, 0x03, 0xff, 0x76, | |
0x76, 0xf6, 0x03, 0xff, 0x76, 0x76, 0xf6, 0x03, 0xff, 0x76, 0x76, 0xf6, | |
0x03, 0xff, 0x76, 0x76, 0xf6, 0x03, 0xff, 0x76, 0x76, 0xf6, 0x03, 0xff, | |
0x76, 0x76, 0xf6, 0x03, 0xff, 0x76, 0x76, 0xf6, 0x03, 0xff, 0x70, 0x74, | |
0xf6, 0x03, 0xff, 0x7f, 0x7c, 0xf0, 0x03, 0xff, 0xff, 0xff, 0xf8, 0x03 | |
}; | |
void setup(void) { | |
u8g2.begin(); | |
u8g2.enableUTF8Print(); //nécessaire pour écrire des caractères accentués | |
} | |
void loop(void) { | |
u8g2.firstPage(); | |
do { | |
u8g2.drawXBMP( 2, 8, 34, 48, logoBitmap); // position, largeur, hauteur | |
/************** On écrit "Électronique en amateur" *********************/ | |
u8g2.setFont(u8g2_font_7x13B_tf); // choix d'une police de caractère | |
u8g2.setCursor(40, 25); // position du début du texte | |
u8g2.print("Électronique"); // écriture de texte | |
u8g2.setCursor(70, 35); | |
u8g2.print("en"); | |
u8g2.setCursor(55, 45); | |
u8g2.print("amateur"); | |
} while ( u8g2.nextPage() ); | |
delay(2000); | |
/******************** Dessiner une ligne ******************************************/ | |
u8g2.firstPage(); | |
do { | |
// ligne horizontale au centre de l'écran | |
u8g2.drawLine(0, 32, 128 , 32); // point de départ, point d'arrivée | |
// ligne verticale au centre de l'écran | |
u8g2.drawLine(64, 0, 64, 64); | |
/********************* Dessiner des contours de formes géométriques ******************/ | |
u8g2.drawFrame(15, 5, 30, 15); // coin supérieur gauche, coin inférieur droit | |
u8g2.drawCircle(95, 15, 8); // centre et rayon | |
u8g2.drawRFrame(15, 40, 30, 16, 5); // coin supérieur gauche, coin inférieur droit, rayon du coin | |
//il n'y a pas de fonction pour tracer un triangle vide | |
u8g2.drawLine(95, 40, 80, 55); | |
u8g2.drawLine(80, 55, 110, 55); | |
u8g2.drawLine(110, 55, 95, 40); | |
} while ( u8g2.nextPage() ); | |
delay(2000); | |
/******************* Dessiner des formes géométriqeus pleines *************************/ | |
u8g2.firstPage(); | |
do { | |
// ligne horizontale au centre de l'écran | |
u8g2.drawLine(0, 32, 128 , 32); // point de départ, point d'arrivée | |
// ligne verticale au centre de l'écran | |
u8g2.drawLine(64, 0, 64, 64); | |
u8g2.drawBox(15, 5, 30, 15); // coin supérieur gauche, coin inférieur droit | |
u8g2.drawDisc(95, 15, 8); // centre et rayon | |
u8g2.drawRBox(15, 40, 30, 16, 5); // coin supérieur gauche, coin inférieur droit, rayon du coin | |
u8g2.drawTriangle(95, 40, 80, 55, 110, 55); // les 3 coins | |
} while ( u8g2.nextPage() ); | |
delay(2000); | |
/***************** dessiner pixel par pixel ***********************/ | |
u8g2.firstPage(); | |
do { | |
// on trace une fonction sinusoidale, point par point | |
for (int x = 1; x < 128; x++) { | |
int y = 32 + round(16.0 * sin(x / 5.0)); | |
u8g2.drawPixel(x, y); | |
} | |
} while ( u8g2.nextPage() ); | |
delay(2000); | |
/******************* Écrire du texte *******************************/ | |
u8g2.firstPage(); | |
do { | |
u8g2.setFont(u8g2_font_ncenB10_tf); // choix de la police | |
u8g2.setCursor(5, 20); // position du début du texte | |
u8g2.print("Caractères"); // on écrit le texte | |
u8g2.setCursor(5, 35); | |
u8g2.print("accentués:"); | |
u8g2.setCursor(5, 55); | |
u8g2.print("ÀàÂâÉéÈèÊêÇç"); | |
} while ( u8g2.nextPage() ); | |
delay(2000); | |
} | |
-
Sketch utilisant la bibliothèque Adafruit
La bibliothèque Adafruit SSD1306 nécessite également la bibliothèque Adafruit GFX. Les deux bibliothèques peuvent être installées dans le gestionnaire de bibliothèques.
-
/********************************************************************* | |
Utilisation d'un écran OLED SSD1306 SPI 128*64 | |
(avec les biliothèques SSD1306 et GFX d'Adafruit) | |
Pour plus d'infos: | |
https://electroniqueamateur.blogspot.com/2022/08/utilisation-dun-ecran-oled-spi-ssd1306.html | |
*********************************************************************/ | |
#include <Adafruit_GFX.h> | |
#include <Adafruit_SSD1306.h> | |
#include <SPI.h> | |
#define SCREEN_WIDTH 128 | |
#define SCREEN_HEIGHT 64 | |
#define OLED_DC 9 | |
#define OLED_CS 10 | |
#define OLED_RESET 8 | |
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, | |
&SPI, OLED_DC, OLED_RESET, OLED_CS); | |
/* Définition d'une image bitmap: logo du blog Électronique en Amateur | |
Réalisée avec l'outil en ligne http://javl.github.io/image2cpp/ */ | |
const unsigned char myBitmap [] PROGMEM = { | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0xf0, 0x00, 0x00, 0x03, 0x9f, 0xff, 0xe0, 0x00, 0x07, | |
0x9f, 0xff, 0xfe, 0x00, 0x0f, 0xdf, 0x0f, 0xbe, 0x00, 0x1f, 0xde, 0x06, 0x0e, 0x00, 0x3f, 0xdc, | |
0x04, 0x0e, 0x00, 0x3f, 0xdc, 0x00, 0x06, 0x00, 0x3f, 0xdc, 0x00, 0x06, 0x00, 0x3f, 0xdc, 0x60, | |
0x06, 0x00, 0x3f, 0xdc, 0xf1, 0x8e, 0x00, 0x3f, 0xdc, 0xf3, 0xce, 0x00, 0x3f, 0xde, 0x63, 0xde, | |
0x00, 0x3f, 0xdf, 0x09, 0x9e, 0x00, 0x3f, 0xdf, 0xfc, 0x7e, 0x00, 0x3f, 0xde, 0x7f, 0xfe, 0x00, | |
0x3f, 0xde, 0x7f, 0xf6, 0x00, 0x3f, 0xdf, 0x3f, 0xe6, 0x00, 0x3f, 0xdf, 0x8f, 0x8e, 0x00, 0x3f, | |
0xdf, 0xe0, 0x3e, 0x00, 0x3f, 0x00, 0x3f, 0xfe, 0x00, 0x3e, 0xff, 0xc0, 0x1e, 0x00, 0x3d, 0xff, | |
0xff, 0xc0, 0x00, 0x3b, 0xff, 0xff, 0xfe, 0x00, 0x37, 0xff, 0xff, 0xfe, 0x00, 0x2f, 0xff, 0xff, | |
0xfe, 0x00, 0x0e, 0x1f, 0xff, 0xfe, 0x00, 0x1f, 0x9f, 0x9f, 0xfe, 0x00, 0x3f, 0x9f, 0x9f, 0x9e, | |
0x00, 0x3f, 0x9f, 0x9f, 0x9e, 0x00, 0x3f, 0x9f, 0x9f, 0x9e, 0x00, 0x3f, 0x9f, 0x9f, 0x9c, 0x00, | |
0x1f, 0x9f, 0x9f, 0x98, 0x00, 0x0f, 0x9f, 0x9f, 0x90, 0x00, 0x07, 0x9f, 0x9f, 0x90, 0x00, 0x00, | |
0x9f, 0x9f, 0x90, 0x00, 0x00, 0x9f, 0x91, 0x90, 0x00, 0x00, 0x91, 0x91, 0x90, 0x00, 0x00, 0x91, | |
0x91, 0x90, 0x00, 0x00, 0x91, 0x91, 0x90, 0x00, 0x00, 0x91, 0x91, 0x90, 0x00, 0x00, 0x91, 0x91, | |
0x90, 0x00, 0x00, 0x91, 0x91, 0x90, 0x00, 0x00, 0x91, 0x91, 0x90, 0x00, 0x00, 0x91, 0x91, 0x90, | |
0x00, 0x00, 0xf1, 0xd1, 0x90, 0x00, 0x00, 0x01, 0xc1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00 | |
}; | |
void setup() { | |
display.begin(); // initialisation de l'afficheur | |
display.clearDisplay(); // ça efface à la fois le buffer et l'écran | |
} | |
void loop() { | |
/**************** Éxcriture de texte ***************/ | |
// taille par défaut | |
display.setCursor(30, 15); // coordonnées du point de départ du texte | |
display.setTextColor(WHITE); | |
display.setTextSize(1); // taille par défaut | |
display.println("Petit..."); | |
display.display(); // affichage à l'écran | |
delay(1000); | |
// deux fois plus gros | |
display.setCursor(30, 35); // coordonnées du point de départ du texte | |
display.setTextSize(2); // taille double | |
display.println("GROS!"); | |
display.display(); // affichage à l'écran | |
delay(1000); | |
display.clearDisplay(); // on efface tout | |
/******************** Dessiner une ligne ******************************************/ | |
// ligne horizontale au centre de l'écran | |
display.drawLine(0, display.height() / 2, display.width() , display.height() / 2, WHITE); | |
// ligne verticale au centre de l'écran | |
display.drawLine(display.width() / 2, 0, display.width() / 2, display.height(), WHITE); | |
/********************* Dessiner des contours de formes géométriques ******************/ | |
display.drawRect( 15, 5, 30, 15, WHITE); // contour d'un rectangle | |
display.drawCircle(95, 15, 8, WHITE); // contour d'un cercle | |
display.drawRoundRect(15, 40, 30, 16, 5, WHITE); // contour d'un rectangle à coins arrondis | |
display.drawTriangle(95, 40, 80, 55, 110, 55, WHITE); // contour d'un triangle | |
display.display(); | |
delay(1000); | |
/******************* Dessiner des formes géométriqeus pleines *************************/ | |
display.fillRect( 15, 5, 30, 15, WHITE); // contour d'un rectangle | |
display.fillCircle(95, 15, 8, WHITE); // contour d'un cercle | |
display.fillRoundRect(15, 40, 30, 16, 5, WHITE); // contour d'un rectangle à coins arrondis | |
display.fillTriangle(95, 40, 80, 55, 110, 55, WHITE); // contour d'un triangle | |
display.display(); | |
delay(1000); | |
display.clearDisplay(); | |
/********************** Dessiner un pixel à la fois ***********************************************/ | |
// on trace une fonction sinusoidale, point par point | |
for (int x = 1; x < 128; x++) { | |
int y = 32 + round(16.0 * sin(x / 5.0)); | |
display.drawPixel(x, y, WHITE); | |
} | |
display.display(); | |
delay(1000); | |
display.clearDisplay(); | |
/**************************** Dessiner une image bitmap **********************************/ | |
// on affiche l'image stockée dans la constante myBitmap définie au début de ce fichier. | |
display.fillRect(5,5,44,58,WHITE); // fond blanc derrière l'image bitmap | |
display.drawBitmap(10, 10, myBitmap, 34, 48, BLACK); | |
display.setCursor(60, 30); // coordonnées du point de départ du texte | |
display.setTextColor(WHITE); | |
display.setTextSize(1); // taille par défaut | |
display.println("Au revoir!"); | |
display.display(); | |
delay(2000); | |
display.clearDisplay(); | |
} |
-
Affichage d'un dessin bitmap
Les deux scripts ci-dessus affichent un dessin bitmap dont les données se trouvent au début du sketch. Pour transformer un dessin bitmap en données exploitables par un Arduino, plusieurs options sont possible: on peut utiliser un logiciel comme Gimp pour sauvegarder l'illustration sous la forme d'un fichier XBM qu'on ouvre ensuite avec un éditeur de texte, ou on peut utiliser un outil en ligne comme celui-ci.
À lire également:
J'ai publié quelques articles concernant l'utilisation d'un écran OLED I2C SH1106: avec un Arduino Uno, avec une carte ESP8266 ou ESP32, ou avec une carte STM32.
D'autres articles concernent l'utilisation d'autres afficheur avec un Arduino: Écran couleur ST7735, afficheur Nokia 5110, afficheur LCD 2 X 16, etc.
Yves Pelletier (Facebook)
samedi 6 août 2022
Lire des fichiers mp3 avec Raspberry Pi Pico et VS1053 (micropython)
Dans un récent article sur l'utilisation d'un module I2S, je déplorais que le décodage du format mp3 ne soit pas supporté par le langage micropython pour l'instant. Une solution consiste à déléguer le décodage à un circuit intégré spécialement conçu pour cette tâche, comme le VS1053, qui peut décoder les principaux formats de fichiers musicaux: Ogg Vorbis, MP3, AAC, FLAC, WMA, MIDI...
Dans cet article, j'utilise un Raspberry Pi Pico (programmé en micropython) et un module VS1053 pour faire jouer les fichiers mp3 enregistrés sur une carte SD.
Module VS1053
Mon module VS1053 a été fabriqué par LCSOFT STUDIO et porte la mention "VS1003/1053 MP3 CODEC". Il existe d'autres modules VS1053 différents de celui-ci, mais j'imagine qu'ils sont équivalents. Je crois qu'il existe des modules VS1053 qui comportent un lecteur de carte SD intégré. Dans mon cas, j'ai dû utiliser un lecteur de carte SD en plus du module VS1053.
Connexions
Le module VS1053 et le module de carte SD partagent le même bus SPI.
Connexions du module VS1053:
- Broche 5 V du module VS1053 : Broche VBUS du Raspberry Pi Pico
- Broche DGND du module VS1053: Broche GND du Raspberry Pi Pico
- Broche MISO du module VS1053: Broche GP4 du Raspberry Pi Pico
- Broche MOSI du module VS1053: Broche GP7 du Raspberry Pi Pico
- Broche SCK du module VS1053: Broche GP6 du Raspberry Pi Pico
- Broche DREQ du module VS1053: Broche GP10 du Raspberry Pi Pico
- Broche XRST du module VS1053: Broche GP13 du Raspberry Pi Pico
- Broche XCS du module VS1053: Broche GP12 du Raspberry Pi Pico
- Broche XDCS du moudle VS1053: Broche GP11 du Raspberry Pi Pico
Connexions du module lecteur de carte SD:
- GND du lecteur SD: Broche GND du Raspberry Pi Pico
- +3.3 du lecteur SD: Sortie 3,3 V du Raspberry Pi Pico
- Broche SCK du lecteur SD: broche GP6 du Raspberry Pi Pico
- Broche MOSI du lecteur SD: broche GP7 du Raspberry Pi Pico
- Broche MISO du lecteur SD: broche GP4 du Raspberry Pi Pico
- Broche CS du lecteur SD: broche GP15 du Raspberry Pi Pico
Bibliothèques
Deux pilotes micropython sont nécessaires pour ce projet: micropython-vs1053 par Peter Hinch, et le pilote officiel pour la carte SD.
Les fichiers sdcard.py et vs1053_syn.py devront être copiés dans la mémoire flash du Raspberry Pi Pico pour que le script ci-dessous fonctionne correctement.
Script
Voici un script qui exécute tous les fichiers mp3 qui se trouvent sur la carte SD. Comme vous pouvez le constater, il s'agit d'un script très court: les deux bibliothèques font tout le travail pour nous!
-
''' | |
Raspberry Pi Pico et VS1053. Tous les fichiers mp3 | |
sur la carte SD sont joués l'un après l'autre. | |
Pour plus d'infos, consultez le blog: | |
https://electroniqueamateur.blogspot.com/2022/08/lire-des-fichiers-mp3-avec-raspberry-pi.html | |
''' | |
from vs1053_syn import * # https://github.com/peterhinch/micropython-vs1053 | |
from machine import SPI, Pin | |
import time | |
import os | |
# initialisation de SPI | |
spi = SPI(0, sck=Pin(6), mosi=Pin(7), miso=Pin(4)) | |
# broche CS de la carte SD: | |
sdcs = Pin(15, Pin.OUT, value=1) | |
# broches du module VS1053 | |
reset = Pin(13, Pin.OUT, value=1) | |
xcs = Pin(12, Pin.OUT, value=1) | |
xdcs = Pin(11, Pin.OUT, value=1) | |
dreq = Pin(10, Pin.IN) | |
player = VS1053(spi, reset, dreq, xdcs, xcs, sdcs=sdcs, mp='/fc') | |
player.volume(-25, -25) # réglage du volume sonore | |
songs = sorted([x for x in os.listdir('/fc') if x.endswith('.mp3')]) | |
for song in songs: | |
print("En train de jouer: ", song) # affichage du titre | |
fn = ''.join(('/fc/', song)) | |
with open(fn, 'rb') as f: | |
player.play(f) |
-
À lire également:
jeudi 4 août 2022
Jouer de la musique (fichiers WAV) avec un Raspberry Pi Pico et un décodeur I2S (micropython)
Dans cet article, nous utilisons un Rasbperry Pi Pico programmé en micropython et un décodeur I2S UDA1334A pour jouer la musique stockée sous forme de fichiers .wav sur une carte SD.
Module I2S
I2S est le nom d'un protocole de communication série permettant de connecter entre eux des appareils audio numériques. Un décodeur I2S est un convertisseur numérique-analogique: il produit un signal analogique audio à partir des informations numériques que lui envoie le Raspberry Pi Pico
J'ai utilisé le décodeur I2S stéréo UDA1334A qui était fabriqué par Adafruit, mais qui ne l'est plus. Adafruit l'a remplacé par un nouveau modèle basé sur le MAX98357A, et il existe d'autres modules du même genre (basés sur le PCM5102). En principe, vous devriez obtenir des bons résultats avec tous ces modules, mais moi je n'ai testé que l'UDA1334A d'Adafruit.
Bibliothèques wavplayer.py et sdcard.py
Connexions
J'ai utilisé les connexions proposées par Mike Teachman.
Connexions du module décodeur I2S:
- Broche VIN du module I2S : Sortie 3,3 V du Raspberry Pi Pico
- Broche GND du module I2S: Broche GND du Raspberry Pi Pico
- Broche BCLK du module I2S: Broche GP16 du Raspberry Pi Pico
- Broche WSEL du module I2S: Broche GP17 du Raspberry Pi Pico
- Broche DIN du module I2S: Broche GP18 du Raspberry Pi Pico
(les autres broches du décodeur I2S peuvent être laissées déconnectées)
Connexions du module lecteur de carte SD:
- GND du lecteur SD: Broche GND du Raspberry Pi Pico
- +3.3 du lecteur SD: Sortie 3,3 V du Raspberry Pi Pico
- Broche SCK du lecteur SD: broche GP14 du Raspberry Pi Pico
- Broche MOSI du lecteur SD: broche GP15 du Raspberry Pi Pico
- Broche MISO du lecteur SD: broche GP12 du Raspberry Pi Pico
- Broche CS du lecteur SD: broche GP13 du Raspberry Pi Pico
Script
Voici un script qui joue l'un après l'autre tous les fichiers .wav enregistrés à la racine de la carte SD (avant de l'utiliser, il faut évidemment avoir préalablement enregistré quelques fichiers en format .wav sur la carte). Vous pouvez écouter le résultat en branchant un casque d'écoute à la sortie jack du module I2S.
-
''' | |
Raspberry Pi Pico, décodeur I2S UDA1334A et lecteur | |
de cartes SD. | |
Les fichiers .wav présent sur la carte SD sont lus | |
tour à tour. | |
Pour plus d'infos, consultez le blog: | |
https://electroniqueamateur.blogspot.com/2022/08/jouer-de-la-musique-fichiers-wav-avec.html | |
''' | |
import os | |
import time | |
from machine import Pin, SPI | |
from wavplayer import WavPlayer # https://github.com/miketeachman/micropython-i2s-examples | |
from sdcard import SDCard # https://github.com/micropython/micropython/blob/master/drivers/sdcard/sdcard.py | |
# lecteur de carte SD | |
cs = Pin(13, Pin.OUT) | |
spi = SPI(1, baudrate=1_000_000, polarity=0, | |
phase=0, bits=8, firstbit= SPI.MSB, | |
sck=Pin(14), mosi=Pin(15), miso=Pin(12),) | |
sd = SDCard(spi, cs) | |
sd.init_spi(25_000_000) | |
os.mount(sd, "/sd") | |
# module décodeur I2S | |
wp = WavPlayer(id=0, sck_pin=Pin(16),ws_pin=Pin(17), | |
sd_pin=Pin(18),ibuf=40000,) | |
# on joue chaque fichier .wav présent sur la carte SD | |
for filename in (os.listdir("/sd")): | |
print("En train de jouer: ", filename) | |
wp.play(filename, loop=False) | |
while wp.isplaying() == True: | |
pass | |
os.umount("/sd") |
-
Mais pas de mp3?
Tout ceci fonctionne très bien, mais je préférerais pouvoir jouer de la musique en format mp3: un fichier wav, ça prend beaucoup de place! Malheureusement, ça ne semble pas possible pour l'instant en Micropython. CircuitPython, en revanche, supporte le décodage du format mp3; c'est assez tentant d'aller faire quelques essais de ce côté...
À lire également: