4. Prototypage électronique#
Cette semaine, nous avons été initiés à l’utilisation d’un microcontrôleur (kit) ainsi qu’au logiciel Arduino.
Configurer Arduino#
Pour commencer, j’ai installé Arduino, ensuite j’ai suivi le tutoriel du Fablab : j’ai ouvert le logiciel puis je suis allé dans l’onglet File > Preferences…
Ensuite j’ai copié-collé ce lien : https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json à l’endroit indiqué sur la photo ci-dessous.
Puis, dans la barre de recherche de la section Boards Manager, j’ai tapé “Raspberry Pi Pico/RP2040” et je l’ai installé.
Détecteur de température et d’humidité#
Le but de cet exercice est de mesurer la température et l’humidité à l’aide d’un sensor. Pour ça, j’ai dû installer la library DHT20 en l’écrivant dans la barre de recherche après avoir cliqué sur library manager (les livres sur la gauche).
Une fois installé, je suis allé dans l’onglet File > Examples > DHT20 > DHT20_plotter
Après ça, un exemple de code pour faire fonctionner le sensor s’est affiché :
//
// FILE: DHT20_plotter.ino
// AUTHOR: Rob Tillaart
// PURPOSE: Demo for DHT20 I2C humidity & temperature sensor
//
// Always check datasheet - front view
//
// +--------------+
// VDD ----| 1 |
// SDA ----| 2 DHT20 |
// GND ----| 3 |
// SCL ----| 4 |
// +--------------+
#include "DHT20.h"
DHT20 DHT(&Wire);
void setup()
{
Wire.begin();
DHT.begin(); // ESP32 default pins 21 22
Serial.begin(115200);
Serial.println("Humidity, Temperature");
}
void loop()
{
if (millis() - DHT.lastRead() >= 1000)
{
// note no error checking
DHT.read();
Serial.print(DHT.getHumidity(), 1);
Serial.print(", ");
Serial.println(DHT.getTemperature(), 1);
}
}
// -- END OF FILE --
Pour que le code fonctionne sur le RP2040, il faut remplacer la ligne DHT.begin();
par :
Wire.setSDA(0);
Wire.setSCL(1);
Wire.begin();
Ces lignes signifient que les bornes SDA et SCL du sensor devront être branchées respectivement aux pins 0 et 1 du microcontrôleur.
Voici la localisation des pins du RP2040, que j’ai trouvé sur le guide du Fablab :
Et voilà les différents pins du sensor que j’ai trouvé dans le datasheet du sensor :
J’ai donc relié les pins, allant du sensor au RP2040, comme ceci :
- VDD –> 3V3
- SDA –> GP0
- GND –> GND
- SCL –> GP1
Ensuite, j’ai branché le microcontrôleur sur mon ordinateur puis je suis allé sur Arduino et j’ai sélectionné Generic RP2040 dans le menu déroulant en haut :
Avant d’upload le programme sur le microcontrôleur, j’ai cliqué sur Verify tout en haut à gauche puis après seulement, j’ai cliqué sur Upload juste à côté :
Premier problème#
Après avoir upload le programme, une erreur s’est affichée :
Je ne savais pas pourquoi cela se passait ni comment le régler. J’ai donc cherché dans les documentations des années précédentes pour voir si quelqu’un n’avait pas eu le même problème. J’ai vu sur le module 4 de Morgan Tonglet qu’en branchant le microcontrôleur, il maintenait le bouton boot enfoncé afin d’effacer le programme déjà présent dessus.
Je me suis donc dit qu’il y avait sûrement déjà un programme inséré par un étudiant de l’année passée dans mon microcontrôleur. Alors j’ai essayé en suivant cette méthode et ça a marché.
Deuxième problème#
Malheureusement, il y a eu un autre problème. Mon PC ne reconnaissait pas le port USB :
J’ai vérifié si j’avais bien modifié la ligne DHT.begin();
quand je remarquai qu’il y avait une incohérence. Quand je remplaçais uniquement la ligne DHT.begin();
, il y avait 2 fois la commande Wire.begin();
. J’ai alors effacé celui du dessus. Ma partie void setup()
ressemble donc à ça :
Après avoir modifié ça, je n’ai plus eu de problèmes.
Une fois l’upload correctement executé, j’ai cliqué sur “Serial Plotter” tout en haut à droite :
Un graphique avec la température (en orange) et l’humidité (en bleu) s’est affiché. Pour vérifier que le sensor marchait bien, j’ai expiré dessus de sorte à augmenter la température et l’humidité. Il y a bel et bien eu un pic sur les deux courbes :
Utiliser la LED RGB#
Pour cet exercice, je devais réussir à faire fonctionner ma LED. Pour cela, j’ai installé la library Adafruit Neopixel effectuant les mêmes étapes que pour la library DHT20 (voir plus haut). Ensuite, j’ai pris comme exemple le buttoncycler de la section Adafruit Neopixel :
// Simple demonstration on using an input device to trigger changes on your
// NeoPixels. Wire a momentary push button to connect from ground to a
// digital IO pin. When the button is pressed it will change to a new pixel
// animation. Initial state has all pixels off -- press the button once to
// start the first animation. As written, the button does not interrupt an
// animation in-progress, it works only when idle.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Digital IO pin connected to the button. This will be driven with a
// pull-up resistor so the switch pulls the pin to ground momentarily.
// On a high -> low transition the button press logic will execute.
#define BUTTON_PIN 2
#define PIXEL_PIN 6 // Digital IO pin connected to the NeoPixels.
#define PIXEL_COUNT 16 // Number of NeoPixels
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
boolean oldState = HIGH;
int mode = 0; // Currently-active animation mode, 0-9
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
// Get current button state.
boolean newState = digitalRead(BUTTON_PIN);
// Check if state changed from high to low (button press).
if((newState == LOW) && (oldState == HIGH)) {
// Short delay to debounce button.
delay(20);
// Check if button is still low after debounce.
newState = digitalRead(BUTTON_PIN);
if(newState == LOW) { // Yes, still low
if(++mode > 8) mode = 0; // Advance to next mode, wrap around after #8
switch(mode) { // Start the new animation...
case 0:
colorWipe(strip.Color( 0, 0, 0), 50); // Black/off
break;
case 1:
colorWipe(strip.Color(255, 0, 0), 50); // Red
break;
case 2:
colorWipe(strip.Color( 0, 255, 0), 50); // Green
break;
case 3:
colorWipe(strip.Color( 0, 0, 255), 50); // Blue
break;
case 4:
theaterChase(strip.Color(127, 127, 127), 50); // White
break;
case 5:
theaterChase(strip.Color(127, 0, 0), 50); // Red
break;
case 6:
theaterChase(strip.Color( 0, 0, 127), 50); // Blue
break;
case 7:
rainbow(10);
break;
case 8:
theaterChaseRainbow(50);
break;
}
}
}
// Set the last-read button state to the old state.
oldState = newState;
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
for(int a=0; a<10; a++) { // Repeat 10 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
// Hue of first pixel runs 3 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 3*65536. Adding 256 to firstPixelHue each time
// means we'll make 3*65536/256 = 768 passes through this outer loop:
for(long firstPixelHue = 0; firstPixelHue < 3*65536; firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the single-argument hue variant. The result
// is passed through strip.gamma32() to provide 'truer' colors
// before assigning to each pixel:
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
int firstPixelHue = 0; // First pixel starts at red (hue 0)
for(int a=0; a<30; a++) { // Repeat 30 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int hue = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}
Avant de l’upload, j’ai changé la PIXEL_PIN à 23 et le BUTTON_PIN à 24. Après ça, je l’ai branché en maintenant bien le bouton boot enfoncé puis j’ai upload. Au début, il ne se passait rien mais quand j’ai appuyé sur le bouton (le bouton avec écrit USR au-dessus), la LED s’est allumée :
Puis à chaque fois que j’appuyais, elle changeait de couleur, passait en mode clignotant et en mode multicolor.
Faire tourner un servomoteur#
Dans cet exercice, le but était de faire fonctionner un servomoteur à l’aide d’un potentiomètre. J’ai comme exemple “Knob” sur le site d’Arduino directement.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
Ensuite, j’ai fait ce circuit (trouvé sur le même site) :
Il faut prendre en compte que les bornes négatives et positives de la pile correspondent respectivement à GND et 3V3/VUSB. Pour le servomoteur, il faut le brancher à une entrée de 5V (VUSB) tandis que le potentiomètre à une de 3V (3V3). Le potentiomètre, contrairement à tout le reste, donne un signal analogique et non pas un signal numérique. La différence entre un signal analogique et un signal numérique, c’est que le signal analogique envoie un signal continu sans interruption. De ce fait, il faut veiller à ce que sa sortie de signal soit branché à un pin prévu à cet effet (A0, A1 ou A2). J’ai donc modifié int potpin = 0;
par int potpin = A0;
.
Une fois le programme upload sur le microcontrôleur, le servomoteur s’est mis à tourner. Le potentiomètre sert ici à contrôler la vitesse de rotation du servomoteur.