Aller au contenu

Testeur de Servomoteur Arduino (avec code programmation, utilisant la librairie servo arduino)

Testeur de servo arduino, projet DIY électronique avec Arduino Nano, servomoteur, écran OLED, et touches de navigation menu couleur avec réglages

Envie de découvrir comment tester ses servomoteurs avec un Arduino ? Alors vous êtes au bon endroit, avec ce testeur de servo arduino ! Aujourd’hui, je vous propose de voir ensemble un montage simple et basique, pour débutant, permettant de piloter un servomoteur avec un Arduino Nano, lui même piloté par potentiomètre.

Ainsi, il s’agit là d’un montage ludique, mettant l’accent sur la partie pilotage-logiciel (software), plutôt que sur le matériel (hardware). Ici, nous verrons comment générer un signal PWM pour commander un servomoteur, comment gérer un menu de navigation à l’aide de boutons physiques, et comment stocker puis lire la config en EEPROM. Au passage, nous verrons également quelques points techniques, notamment au niveau de la liaison I²C entre l’écran oled 3,3V et l’arduino 5V. Ça vous dit ? Alors par ici la suite 😉

Ce contenu vous plaît ? Alors abonnez-vous à la Newsletter pour ne rien louper !

Encore une fois, il s’agit là d’un montage didactique, ayant pour but de se familiariser avec Arduino et son environnement (écran OLED i2c, servo pwm, …). Ce projet ne vise en aucun cas à se substituer à tout autre testeur de servo « déjà tout prêt »; vendu sur internet ! Ici, le but est d’apprendre, et ce au travers d’un montage simple, pratique, et concret (idéal si vous débutez en électronique, en somme !). Alors en avant !

Intro : pourquoi ce testeur de servo arduino ?

Comme évoqué en intro, ce projet est à but éducatif ; et plus particulièrement destiné à ceux qui débutent en électronique. Ici, peu de composants seront mis en œuvre ; toutefois, la partie logicielle (le programme arduino) sera bien plus riche, notamment du fait de la présence d’un « menu de navigation » à gérer, et de valeurs à lire/écrire en mémoire EEPROM, le cas échéant.

Plus précisément, nous verrons dans ce projet :

  • comment générer un signal PWM, pour « prendre le contrôle » du servomoteur, et faire tourner son axe « au doigt et à l’œil » !
  • comment gérer un ensemble de « touches de navigation », pour rendre ce projet interactif
  • comment sauvegarder ou lire des données stockées en mémoire EEPROM (ici, nous utiliserons la mémoire EEPROM interne du microcontrôleur de la carte arduino)
  • et comment afficher le tout sur un écran graphique bicolore, format OLED, de taille 0.96 pouces, contrôlé via bus I²C depuis l’Arduino

Comme vous le voyez, nous irons bien au delà d’un simple potentiomètre de pilotage servomoteur ! D’ailleurs, vous pourrez le constater par vous même, lorsque vous verrez la longueur du programme arduino 😉

Mais pour l’heure, voyons la partie matérielle. Et pour commencer, voyons la liste détaillée des composants mis en œuvre dans ce projet !

Liste des composants nécessaires, pour ce projet

Pour réaliser ce projet de testeur de servomoteur piloté par arduino (« servo tester », en anglais), voici ce dont vous aurez besoin :

QtéDésignationLien achat
1Arduino Nano, monté sur picots mâles (header)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Écran OLED i2c jaune/bleu 0,96 pouce (contrôleur SSD1306)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Potentiomètre vertical 10 kohm (format RV09)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Condensateur électrolytique 10 µF (10 volts min)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Ensemble de boutons de navigation A14 type B3F-4055 ( à 5 directions : haut, droit, bas, gauche, et OK au centre)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Micro servomoteur SG90 (si vous n’en n’avez pas, pour faire vos essais)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Ensemble de headers femelle au pas de 2,54mm (connecteurs qui permettront de surélever l’arduino, et l’écran OLED)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Ensemble de headers mâle au pas de 2,54mm (connecteur qui permettra de brancher le servo à tester directement sur le PCB)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Ensemble d’entretoises nylon de taille M3 (pour surélever le circuit imprimé PCB)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Ensemble d’entretoises nylon de taille M2 (pour surélever l’écran OLED)Caddie plein 24x24, icone passion électronique fr, achat de matériels d'élec, idéal débutant et amateurs d'électronique
1Circuit imprimé PCB (voir le fichier Gerber au format ZIP, tout en bas de cet article, si vous souhaitez reproduire ce circuit imprimé à l’identique)

Comme vous le voyez, il n’y a que peu de composants mis en œuvre ici (surtout si on enlève les « petits accessoires » !). Mais attention, car la partie logicielle sera quant à elle bien plus chargée 😉

D’ailleurs, à ce sujet, voyons comment s’articule ce projet, de manière fonctionnelle (le programme arduino n’en sera au final que la transcription écrite !).

Schéma fonctionnel

Pour entrevoir de quelle manière va fonctionner ce testeur de servo arduino, voici son schéma fonctionnel, détaillant les contours du projet :

Schéma fonctionnel testeur servomoteur arduino, avec potentiomètre de commande, menu de navigation à boutons poussoirs, et affichage couleur

Du point de vue fonctionnel, ce projet est somme toute assez simple : en fait, le servo est piloté par le potentiomètre, au travers d’un Arduino qui fait une conversion tension électrique → signal PWM (car le potentiomètre de pilotage fournit une tension entre 0 et +5V, et le servo requiert un signal PWM de fréquence 50 Hz et d’amplitude +5V).

Au final, le reste n’est que du bonus, si je puis dire. On retrouve ainsi :

  • des touches physiques, pour naviguer dans le menu et modifier des valeurs (consignes min/max d’impulsion PWM, en fait)
  • une mémoire EEPROM (interne à l’arduino), qui nous permettra d’y sauvegarder/récupérer nos valeurs de consigne
  • et un affichage OLED, qui nous permettra de visualiser les infos dont nous avons besoin

Et d’ailleurs, au sujet de ce dernier, laissez-moi vous en dire un peu plus !

Écran d’affichage, avec menu de navigation

Histoire d’arriver à mieux visualiser les choses encore, voici les différentes pages pouvant s’afficher, sur l’écran OLED de ce testeur de servomoteur :

  • soit le menu principal, avec la possibilité de régler certaines valeurs de consigne
  • soit la page de réinitialisation, qui propose de remettre à l’état par défaut les valeurs de consigne

Difficile de faire plus simple, avouez ! Et visuellement, voici comment se présentent ces pages :

#Page affichéeDétail
1Servotester avec menu de navigation couleur, réglage PWM des seuils min et max de durée d'impulsion produite par carte Arduino via i2cMenu principal
Ici, 4 lignes sont affichées :
– ligne 1 (Tmin) : la valeur minimale (en µs) de l’impulsion PWM envoyée au servo ; cette valeur est MODIFIABLE (1000 µs, par défaut)
– ligne 2 (Tmax) : la valeur maximale (en µs) de l’impulsion PWM envoyée au servo ; cette valeur est MODIFIABLE (2000 µs, par défaut)
– ligne 3 (Tactuel) : la valeur courante (en µs) de l’impulsion PWM actuellement envoyée au servomoteur (non sélectionnable et non modifiable, car purement indicative) ; cette valeur varie tout simplement en fonction de combien est tourné le potentiomètre (et des valeurs limites en consigne, bien évidemment)
– ligne 4 : un lien pour aller sur la page de réinitialisation (cf. seconde image, ci-dessous)
2Écran oled couleur I²C de 0.96 pouces permettant de réinitialiser valeurs par défaut, pilotage par Arduino et code de programmation fourni avecPage de reset
Ici est proposé de remettre par défaut (réinitialiser) les valeurs min/max des consignes PWM :
– si vous choisissez l’option NON, vous serez ramené à la page du menu principal, sans changement
– si vous choisissez l’option OUI, cela remettra les valeurs par défaut au niveau des valeurs min/max de l’impulsion servo, et vous retournerez automatiquement à la page du menu principal, avec ces nouvelles valeurs

Les touches de navigation (présentes sur le PCB), qui interagissent directement avec cet afficheur, permettent les choses suivantes :

  • si vous êtes sur la page « menu principal », alors :
    • les touches haut/bas permettent de monter ou descendre dans le menu (seules les lignes 1, 2, et 4 sont sélectionnables, pour rappel)
    • la touche OK permet de mettre en surbrillance une valeur, ou de l’enregistrer après changement (en mémoire interne EEPROM arduino) ; à noter que cette touche permet également de passer à la page de « réinitialisation », si la ligne « Réinitialiser » (ligne 4) est sélectionnée
    • les touches gauche/droite permettent de diminuer ou d’augmenter la valeur mise en surbrillance, lorsque c’est le cas
  • si vous êtes sur la page « réinitialiser », alors :
    • les touches gauche/droite permettent de sélectionner « OUI » ou « NON » (en sachant que « non » permet de revenir au menu principal, et « oui » remettre les valeurs par défaut, dans le programme)
    • la touche OK permet de valider le choix effectué (exécuter un RESET des valeurs de consigne, si souhaité, sinon revenir au menu principal)

Schéma électronique

D’un point de vue schéma électronique, ce testeur de servomoteur à base d’arduino est particulièrement simple, comme vous pourrez le constater ci-dessous ! Toutefois, il y a là quelques points techniques que j’aurais à vous présenter, au sujet des pull-up « masquées » pour les boutons poussoirs de navigation et la ligne i2c (qui d’ailleurs jouent un rôle dans la communication « Arduino 5 volts » → « Ecran OLED 3,3 volts », au niveau du bus I²C, j’entends).

Schéma du testeur de servo arduino

Voici le schéma électronique de ce testeur de servo, à proprement parler (une version PDF, plus lisible, est disponible tout en bas de cet article, si vous souhaitez) :

Schéma testeur de servo arduino électronique, servotester schematic DIY avec affichage des infos sur écran I2C oled couleur et menu navigation

Grosso modo, le schéma de ce servotester est divisé en 5 blocs principaux :

  • une partie « commande », matérialisée par l’Arduino Nano en lui-même
  • une partie « boutons de navigation menu », comprenant 5 boutons poussoirs (haut, bas, gauche, droite, et centre)
  • une partie « affichage », matérialisée par un écran OLED I²C
  • une partie « sortie servo » (basiquement, il s’agit là d’un simple connecteur mâle à 3 broches, avec un condensateur de stabilisation, au niveau de l’alim)
  • une partie « potentiomètre de pilotage servo », composée d’un simple potentiomètre analogique, manœuvrable à la main

Nota : les étiquettes présentes sur ce schéma vous montrent les liens entre ces différentes parties. Par exemple « D2/HAUT » vous montre comment est relié la broche D2 (de l’Arduino Nano) au bouton poussoir « HAUT » (du pavé de navigation).

Comme je vous l’avais dit, ce projet est vraiment simple et basique, au niveau « composants électroniques ». Cela étant dit, il y a 2 points techniques que j’aimerais aborder avec vous à présent : l’un est assez simple, et l’autre, un peu plus complexe.

Point technique 1/2 : les pull-up « cachées » des boutons poussoirs (« facile »)

Comme vous le savez, un arduino est capable de lire l’état de ses entrées, « à tout moment ». Et lorsqu’il s’agit d’entrées digitales (comme celles où sont branchés nos boutons de navigation), il est capable de dire si elles sont à l’état BAS ou l’état HAUT. Mais pour dire cela, il faut effectivement qu’il y ait des tensions basses ou hautes, sur ces entrées.

Or, lorsqu’on utilise de simples boutons pouvant faire contact avec la masse (comme c’est le cas ici, dans notre montage), l’état ramené au niveau des entrées arduino est :

  • soit égal à 0V, lorsque le bouton correspondant est appuyé (il met alors la ligne à la masse)
  • soit égal à une tension inconnue (haute impédance), lorsque le bouton correspondant est relâché

Nous avons donc 2 états possibles : soit un état bas (0V), soit un état à haute impédance ; alors que nous souhaitons que l’arduino indique soit un état bas (0V), soit un état haut (+5V, dans le cas de notre Arduino Nano). C’est pourquoi il faut impérativement mettre en place une résistance dite de « pull-up », pour « remplacer » cet état à haute impédance, par un état haut (lorsqu’aucune mise à la masse n’est faite par le bouton poussoir correspondant, donc).

Et nous arrivons là où je voulais en venir ! Ici, il y a 2 façons de faire :

  • soit mettre une résistance pull-up externe (généralement 10 kohm) sur chaque ligne, de chaque bouton poussoir
  • soit activer les résistances pull-up internes de l’Arduino (faisant environ 50 kohm), au niveau de ses entrées digitales

Et comme vous vous en doutez, c’est cette deuxième option que j’ai choisi ici, afin de limiter le nombre de composants mis en œuvre !

Maintenant, passons à quelque chose d’un peu plus subtil, mais basé sur ce que je viens juste de vous expliquer 😉

Point technique 2/2 : les pull-up « cachées » des lignes I²C, avec adaptation 3,3 V ↔ 5 V (« plus subtil »)

L’autre point technique que je souhaitais aborder avec vous concerne l’écran OLED de ce servotester. Alors, ici, il y a 2 choses à savoir :

  • l’écran OLED s’alimente généralement entre 3,3 et 5 volts ; et un régulateur interne à l’écran OLED abaisse à +3,3V maximum, cette tension fournie
  • les lignes de communication i²c (SDA et SCL) ont besoin de résistances pull-up pour fonctionner. Car qu’il s’agisse d’une communication de la part du maître (arduino) ou de l’esclave (écran oled), seules des mises à la masse sont opérées, dans le cadre de cette communication (voir cet article sur les liaisons séries i2c, pour mieux comprendre cela). Or l’Arduino Nano fonctionne en +5V, et l’écran OLED en +3,3V, au niveau des lignes I2C

Sur le schéma que je vous ai présenté plus haut, aucune résistance pull-up n’apparaît, ni dispositif de conversion 3,3V ↔ 5V. Alors comment tout cela fonctionne, et s’adapte, me direz-vous ?

En fait, toute la « magie » s’opère au sein de l’écran OLED. Histoire de bien visualiser ce dont je parle, voici un schéma filaire partiel, montrant le raccordement de notre Arduino Nano à l’écran OLED i²c :

Raccordement bus i2c d'un Arduino 5 volts avec écran OLED 3,3 volts, via résistances pull-up côté 3V3 alimentant contrôleur SSD1306 affichage couleur

Comme vous pouvez le constater, des résistances pull-up (internes à l’écran OLED) sont rattachées au +3,3 volts, issu du régulateur de tension embarqué. Ainsi :

  • la ligne SDA (ou SCL) a une tension égale à 0 volt, lorsqu’elle est mise à la masse (soit par l’Arduino, soit par l’écran Oled)
  • la ligne SDA (ou SCL) a une tension égale à 3,3 volts, lorsqu’elle est laissée au repos (sa résistance pull-up ramenant son niveau +3V3)

Du coup, la communication i²c se fait donc sur du 0/3,3V, avec le « niveau de tension haut » fixé par l’écran OLED. Mais concernant l’Arduino fonctionnant en 5V, me direz-vous : comment est interprété ce +3,3 volt ?! Eh bien… comme si c’était un niveau haut (+5V). Car le microcontrôleur ATmega328P, monté sur la carte Arduino Nano, interprète :

  • une tension comprise entre -0,5V et 0,3Vcc (donc 0,3 * 5V = 1,5 volts) comme un niveau bas
  • une tension comprise entre 0,6Vcc (donc 0,6 * 5V = 3 volts) et Vcc+0,5 (donc 5V+0,5 = 5,5 volts) comme un niveau haut

Nota : ces infos sont issues du datasheet du microcontrôleur ATmega, présent sur la carte Arduino Nano (cf. page 258 du datasheet de l’ATmega328P)

En résumé : l’état haut à 3,3 volts sur les lignes I2C, induit par les résistances pull-up côté écran OLED, est bien compris comme du +5V (état haut), côté Arduino ! Ainsi, pas besoin de convertir les niveaux 3V3 ↔ 5V, ce qui nous économise là-aussi, bon nombre de composants « inutiles » 😉

Code programme arduino

À présent, entrons dans le cœur de cet article, à savoir : le code arduino de ce testeur de servomoteur ! Et comme vous allez voir, c’est quand même assez fourni (bien qu’il s’agisse là d’un « petit projet » !)

Mais avant d’entrer dans les détails, laissez-moi vous présenter le logigramme sur lequel repose ce programme :

Logigramme servo tester arduino, explication code de programmation pour pilotage PWM d'un servomoteur via microcontrôleur, avec affichage oled

Vu de loin, c’est assez simple, me direz-vous ! En effet, mise à part l’étape d’initialisation au départ, tout le reste ne fait que boucler indéfiniment (lecture des boutons et traitement en conséquence, puis ajustement signal PWM, puis mise à jour de l’affichage sur l’écran OLED, puis rebouclage).

Cela étant dit, ce code va être assez touffu, du fait de la gestion individuelle des boutons, et de l’affichage conditionnel des infos présentées à l’écran !

Du reste, de manière générale, j’ai 2 remarques importantes à vous faire ici, avant de vous présenter le code :
ici, nous allons faire appel à la librairie SSD1306 d’Adafruit ; si celle-ci n’est pas déjà installée dans votre IDE Arduino, il faudra alors l’installer (au besoin, je vous renvoie vers un article que j’avais fait au sujet de cet écran OLED, détaillant la procédure d’installation de cette librairie SSD1306).
la fréquence de pilotage d’un servomoteur est de 50 Hz, usuellement. Ce qui correspond à une période de 1 / 50 = 0.02 secondes (soit 20 ms). Sur ces 20 millisecondes de « durée totale » de période, « l’impulsion à l’état haut » doit basiquement durer entre 1 ms (si vous souhaitez que le servo soit tourné à fond dans un sens) et 2 ms (si vous souhaitez que le servo soit tourné à fond dans l’autre sens) ; alors qu’une position neutre serait aux alentours de 1,5 ms de durée d’impulsion à l’état haut, sur les 20 ms de période totale. Cela étant dit, certains fabricants de servomoteur requièrent des durées plus basses et/ou plus hautes, pour atteindre des rotations angulaires de -90° à +90°, au niveau de l’axe de sortie du servo. C’est pourquoi ce programme vous permettra de modifier ces limites (que j’appelle des « consignes »), en proposant une plage étendue, allant de 550 µs (0,55 ms) à 2400 µs (2,4 ms).

À présent, voici le code de ce « servotester arduino », tant attendu !:

/*
   ______               _                  _///_ _           _                   _
  /   _  \             (_)                |  ___| |         | |                 (_)
  |  [_|  |__  ___  ___ _  ___  _ __      | |__ | | ___  ___| |_ _ __ ___  _ __  _  ___  _   _  ___
  |   ___/ _ \| __|| __| |/ _ \| '_ \_____|  __|| |/ _ \/  _|  _| '__/   \| '_ \| |/   \| | | |/ _ \
  |  |  | ( ) |__ ||__ | | ( ) | | | |____| |__ | |  __/| (_| |_| | | (_) | | | | | (_) | |_| |  __/
  \__|   \__,_|___||___|_|\___/|_| [_|    \____/|_|\___|\____\__\_|  \___/|_| |_|_|\__  |\__,_|\___|
                                                                                      | |
                                                                                      \_|
  Fichier :       prgArduino-TesteurDeServo.ino
  
  Description :   Programme permettant de tester un servomoteur, tout en pouvant
                  régler les seuils haut/bas pour le rapport cyclique du signal PWM,
                  avec affichage sur écran OLED
                  
  Remarques :     - l'arduino utilisé ici sera un modèle Nano
                  - la librairie utilisée pour contrôler le servomoteur sera la "bibliotèque Servo", native sous Arduino IDE
                    https://www.arduino.cc/reference/en/libraries/servo/
                  - la librairie utilisée pour contrôler l'écran OLED (modèle 0.96" avec contrôleur SSD1306) sera celle d'Adafruit
                    https://github.com/adafruit/Adafruit_SSD1306?pseSrc=pgEcranOledArduino
                                    
  Auteur :        Jérôme TOMSKI (https://passionelectronique.fr/)
  Créé le :       03.11.2023

*/


// Inclusion des librairies dont nous allons nous servir ici
#include <EEPROM.h>
#include <Servo.h>
#include <Adafruit_SSD1306.h>


// Affectation des broches de l'Arduino
#define pinArduinoRaccordeeAuBoutonDuHaut   2       // La pin D2 de l'Arduino est connectée au "bouton du HAUT" (bloc de 5 boutons : haut/bas/gauche/droite/ok)
#define pinArduinoRaccordeeAuBoutonDeDroite 3       // La pin D3 de l'Arduino est connectée au "bouton de DROITE"
#define pinArduinoRaccordeeAuBoutonDuBas    4       // La pin D4 de l'Arduino est connectée au "bouton du BAS"
#define pinArduinoRaccordeeAuBoutonDeGauche 5       // La pin D5 de l'Arduino est connectée au "bouton de GAUCHE"
#define pinArduinoRaccordeeAuBoutonDuCentre 6       // La pin D6 de l'Arduino est connectée au "bouton du CENTRE" (noté "ok")
#define pinArduinoRaccordeeAuServomoteur    9       // La pin D9 de l'Arduino est connectée à la broche "signal" du servomoteur
#define pinArduinoRaccordeeAuPotentiometre  A0      // La pin A0 de l'Arduino est connectée au point milieu du potentiomètre de réglage de la position angulaire du servo
#define pinArduinoRaccordeeAuSDAecranOLED   A4      // La pin A4 de l'Arduino est connectée à la broche SDA de l'écran OLED
#define pinArduinoRaccordeeAuSCLecranOLED   A5      // La pin A5 de l'Arduino est connectée à la broche SCL de l'écran OLED


// Constantes concernant le servomoteur
      // Juste pour rappel, concernant les servomoteurs :
      //   - durée/période du signal de commande servomoteur            => 20 ms (20000 µs)     => cela correspond à un signal à 50 Hz, tout simplement
      //   - délai d'impulsion pour tourner le servo de -90° environ    =>  1 ms (1000 µs)
      //   - délai d'impulsion pour tourner le servo de +90° environ    =>  2 ms (2000 µs)
      //   - délai minimal d'impulsion (imposé par librairie Servo.h)   =>  0.544 ms (544 µs)   => je vais prendre 550 µs dans ce code, pour simplifier les choses
      //   - délai maximal d'impulsion (imposé par librairie Servo.h)   =>  2.400 ms (2400 µs)
#define valeurMinSeuilBasImpulsionServo       550     // Avec ces 3 valeurs (550/1000/1400), on spécifie que la valeur min d'une impulsion servo
#define valeurDefautSeuilBasImpulsionServo    1000    // sera comprise entre 550 et 1400 µs (avec 1000µs, par défaut)
#define valeurMaxSeuilBasImpulsionServo       1400
#define valeurMinSeuilHautImpulsionServo      1600    // Avec ces 3 valeurs (1600/2000/2400), on spécifie que la valeur max d'une impulsion servo
#define valeurDefautSeuilHautImpulsionServo   2000    // sera comprise entre 1600 et 2400 µs (avec 2000µs, par défaut)
#define valeurMaxSeuilHautImpulsionServo      2400
#define pasDeModificationDelaiImpulsionServo  50      // Avec les boutons de navigation du menu, on pourra modifier les valeurs par pas de 50 µs


// Constantes concernant l'écran OLED
#define nombreDePixelsEnLargeurEcranOLED    128     // Taille de l'écran OLED, en pixel, au niveau de sa largeur
#define nombreDePixelsEnHauteurEcranOLED    64      // Taille de l'écran OLED, en pixel, au niveau de sa hauteur
#define brocheResetOLED                     -1      // Reset de l'écran OLED partagé avec l'Arduino, d'où la valeur à -1 ici (et non un numéro de pin)
#define adresseI2CdeLecranOLED              0x3C    // Adresse i2c de l'écran OLED (généralement 0x3C par défaut, sinon 0x3D)


// Constantes concernant l'EEPROM interne à l'Arduino
      // Pour rappel :
      //     - la mémoire d'un Arduino Nano (microcontrôleur ATmega328P, donc) dispose de 1024 octets d’EEPROM (allant de l'adresse eeprom 0 à 1023)
      //     - par défaut, si l'arduino est neuf ou si son EEPROM n'a jamais servi, les cases eeprom contienent la valeur 255
#define adresseMemoireValeurBasseImpulsionServo       0       // On utilisera 2 octets ici, pour pouroir stocker une valeur entre 0 et 65535 (idéal pour nos "~1000 µs")
#define adresseMemoireValeurHauteImpulsionServo       2       // On utilisera 2 octets ici, pour pouvoir stocker une valeur entre 0 et 65535 (idéal pour nos "~2000 µs")
#define adresseMemoireCodeArduinoNeufOuPas            4       // On utilisera 2 octets ici, pour pouvoir stocker un code "aléatoire particulier",qui nous dira si notre
#define valeurParticulierePourDireSiArduinoNeufOuPas  9876    // arduino a déjà servi ou non (toute valeur autre que 2 octets à 255 aurait pu convenir, dans l'absolu)


// Constantes du menu de navigation
#define nombreDeLigneMaxDansMenu            3

// Variables librairies
Servo servomoteur;
Adafruit_SSD1306 ecran_oled(nombreDePixelsEnLargeurEcranOLED, nombreDePixelsEnHauteurEcranOLED, &Wire, brocheResetOLED);


// Autres variables
int ligne_selectionnee_dans_menu = 1;               // Contiendra le numéro de ligne sélectionné dans le menu de l'écran OLED
                                                    // (1=Tmin, 2=Tmax, et 4=Réinitialiser ; la 3ème ligne étant une ligne d'information, elle ne sera pas sélectionnable)
int valeurMinCouranteServo = 0;                     // Valeur minimale courante pour l'impulsion servo, servant de base au PWM
int valeurMaxCouranteServo = 0;                     // Valeur maximale courante pour l'impulsion servo, servant de base au PWM
int valeurCouranteImpulsionServo = 0;               // Valeur courante de l'impulsion PWM, actuellement envoyée au servo
int valeurPrecendentePotentiometre = -1;            // Mémorisation de la précédente valeur du potentiomètre, pour ne modifier le signal PWM que si nécessaire (-1 pour forcer la mise à jour)
bool boutons_haut_bas_actifs = true;                // Booléen qui dira si les boutons haut/bas doivent être actifs ou non (selon si on navigue dans le menu, ou non)
bool boutons_gauche_droite_actifs = false;          // Booléen qui dira si les boutons gauche/droite doivent être actifs ou non (selon si on est en mode édition/modification/validation, ou non)
bool afficher_menu_principal = true;                // Booléen qui dira si on doit afficher le menu principal ou l'écran de réinitialisation
bool annuler_reinitialisation = true;               // Booléen qui dire si on a sélectionné l'option "NON" ou "OUI", sur la page "réinitialiser les valeurs"


// ========================
// Initialisation programme
// ========================
void setup() {

    // Initialisation de la liaison série (PC <-> arduino nano), pour le débuggage, si besoin
    Serial.begin(9600);
    Serial.println(F("================"));
    Serial.println(F("Testeur de servo"));
    Serial.println(F("================"));
    Serial.println("");

    // Initialisation de l'écran OLED
    if(!ecran_oled.begin(SSD1306_SWITCHCAPVCC, adresseI2CdeLecranOLED)) {
      Serial.println(F("[ERREUR] Impossible de communiquer avec l'écran OLED (arrêt du programme)"));
      Serial.flush();
      while(1);
    } else {
      Serial.println(F("Écran OLED présent (initialisation du contrôleur SSD1306 réussie)"));
    }


    // Récupère les valeurs sauvegardées en EEPROM (ou les initialise, si elles sont absentes)
    recupereValeursEnEEPROM();
    

    // Définition des entrées/sorties de l'Arduino
    pinMode(pinArduinoRaccordeeAuBoutonDuHaut, INPUT_PULLUP);
    pinMode(pinArduinoRaccordeeAuBoutonDeDroite, INPUT_PULLUP);
    pinMode(pinArduinoRaccordeeAuBoutonDuBas, INPUT_PULLUP);
    pinMode(pinArduinoRaccordeeAuBoutonDeGauche, INPUT_PULLUP);
    pinMode(pinArduinoRaccordeeAuBoutonDuCentre, INPUT_PULLUP);    
    // Remarques : 
    //   - les résistances pull-up internes de l'Arduino sont activées sur les broches ci-dessus, car il n'y en a pas sur le montage, à proprement parler
    //   - pas besoin d'utiliser "pinMode" pour déclarer la broche "signal servo" en sortie, car cela est implicitement fait par la biliothèque Servo
    //   - pas besoin d'utiliser "pinMode" pour déclarer A0 en entrée, car toutes les broches sont de type INPUT, au démarrage programme
    //   - pas besoin d'utiliser "pinMode" pour gérer les lignes SDA (A4) et SCL (A5), car cela est géré par la librairie gérant l'écran OLED


    // Raccordement logiciel de la ligne "signal" du servomoteur, à la broche arduino (D9, pour rappel)
    servomoteur.attach(pinArduinoRaccordeeAuServomoteur);

    // Petite pause, avant d'attaquer la boucle loop
    delay(500);

}


// ==================================
// Fonction : recupereValeursEnEEPROM
// ==================================
void recupereValeursEnEEPROM() {

  Serial.println("");
  Serial.println(F("Récupératon des valeurs sauvegardées en EEPROM"));

  // Pour commencer, on lit les 5 premiers octets de la mémoire EEPROM. Pour rappel, ils doivent contenir :
  //      - sur 2 octets : la valeur min de l'impulsion servo sauvegardée
  //      - sur 2 octets : la valeur max de l'impulsion servo sauvegardée
  //      - et sur 1 octet : un code de vérification nous disant si cette application a été tournée sur cet arduino ou non
  //        (si l'arduino est "neuf", on aura la valeur 255 au lieu de la valeur attendue, ce qui nous indiquera qu'il faut initialiser cette mémoire)
  
  int valeurMinImpulsionServoLueEnEEPROM = litValeurIntEnEEPROM(adresseMemoireValeurBasseImpulsionServo);
  int valeurMaxImpulsionServoLueEnEEPROM = litValeurIntEnEEPROM(adresseMemoireValeurHauteImpulsionServo);
  int valeurCodeDeVerificationLuEnEEPROM = litValeurIntEnEEPROM(adresseMemoireCodeArduinoNeufOuPas);

  // 2 cas possibles : le code de vérification est bon, ou pas !
  if(valeurCodeDeVerificationLuEnEEPROM == valeurParticulierePourDireSiArduinoNeufOuPas) {
    // Le code correspond, alors on stocke ces valeurs dans nos variables globales (déclarées tout en haut de ce programme)
    valeurMinCouranteServo = valeurMinImpulsionServoLueEnEEPROM;
    valeurMaxCouranteServo = valeurMaxImpulsionServoLueEnEEPROM;
    Serial.print(F("--> valeurs récupérées avec succès (min="));
    Serial.print(valeurMinImpulsionServoLueEnEEPROM);
    Serial.print(F("/max="));
    Serial.print(valeurMaxImpulsionServoLueEnEEPROM);
    Serial.println(F(")"));
  } else {
    // Le code ne correspond pas, alors on stocke ces valeurs dans les variables globales
    valeurMinCouranteServo = valeurDefautSeuilBasImpulsionServo;
    valeurMaxCouranteServo = valeurDefautSeuilHautImpulsionServo;
    // et on initialise la mémoire EEPROM avec
    ecritValeurIntEnEEPROM(adresseMemoireValeurBasseImpulsionServo, valeurDefautSeuilBasImpulsionServo);
    ecritValeurIntEnEEPROM(adresseMemoireValeurHauteImpulsionServo, valeurDefautSeuilHautImpulsionServo);
    ecritValeurIntEnEEPROM(adresseMemoireCodeArduinoNeufOuPas, valeurParticulierePourDireSiArduinoNeufOuPas);
    Serial.println(F("--> valeurs initialisées (1ère fois que ce programme est utilisé sur cet arduino)"));
  }
  Serial.println("");
}


// ===============================
// Fonction : litValeurIntEnEEPROM
// ===============================
int litValeurIntEnEEPROM(int adresse)
{
  // Une valeur "int" est de type 16 bits ; elle prend donc 2 octets
  byte octet1 = EEPROM.read(adresse);               // 8 bits de poids fort en premier
  byte octet2 = EEPROM.read(adresse + 1);           // 8 bits de poids faible ensuite
  return (octet1 << 8) + octet2;
}

// =================================
// Fonction : ecritValeurIntEnEEPROM
// =================================
void ecritValeurIntEnEEPROM(int adresse, int valeur)
{
  // Une valeur "int" est de type 16 bits ; elle prend donc 2 octets
  EEPROM.update(adresse, valeur >> 8);              // 8 bits de poids fort d'abord
  EEPROM.update(adresse + 1, valeur & 0xFF);        // 8 bits de poids faible après

  // Nota : j'ai utilisé la fonction "EEPROM.update" au lieu de "EEPROM.write" ici, afin d'économiser la "durée de vie" de la mémoire EEPROM ;
  //        en effet, avec "update", une écriture en mémoire EEPROM ne se produit que si la valeur à enregistrer est différente de celle déjà présente
  //        à cette même adresse (en clair, si vous voulez enregistre par exemple 32 à la place de 27, la case est réécrite ; et si vous souhaitez
  //        enregistrer par exemple la valeur 10 à la place de 10, alors l'enregistrement est "sauté", car inutile)
}



// =================================================
// Fonction : contruitEtRafraichitAffichageEcranOLED
// =================================================
void contruitEtRafraichitAffichageEcranOLED() {

  // Effaçage de la mémoire tampon de l'écran OLED
  ecran_oled.clearDisplay();                           

  // Titre
  ecran_oled.setTextColor(WHITE);
  ecran_oled.setTextSize(2);
  ecran_oled.setCursor(10, 0);
  ecran_oled.println("SERVOTEST");

  if(afficher_menu_principal) {

    // ==== Affichage "MENU PRINCIPAL"

    // Ligne #1
    ecran_oled.setTextSize(1);
    ecran_oled.setCursor(10, 25);  ecran_oled.println("T(min) :");
    ecran_oled.setCursor(110, 25);  ecran_oled.println("us");
    if(ligne_selectionnee_dans_menu == 1 && boutons_gauche_droite_actifs == true) {
      ecran_oled.setTextColor(BLACK, WHITE);
    }
    ecran_oled.setCursor(81, 25);  ecran_oled.println(valeurMinCouranteServo);
    
    // Ligne #2
    ecran_oled.setTextColor(WHITE);
    ecran_oled.setCursor(10, 35);  ecran_oled.println("T(max) :");
    ecran_oled.setCursor(110, 35);  ecran_oled.println("us");
    if(ligne_selectionnee_dans_menu == 2 && boutons_gauche_droite_actifs == true) {
      ecran_oled.setTextColor(BLACK, WHITE);
    }
    ecran_oled.setCursor(81, 35);  ecran_oled.println(valeurMaxCouranteServo);

    // Ligne #3
    ecran_oled.setTextColor(WHITE);
    ecran_oled.setCursor(10, 45);  ecran_oled.println("T(actuel) :");
    ecran_oled.setCursor(81, 45);  ecran_oled.println(valeurCouranteImpulsionServo);
    ecran_oled.setCursor(110, 45);  ecran_oled.println("us");
  
    // Ligne #4
    ecran_oled.setTextColor(WHITE);
    ecran_oled.setCursor(10, 55);
    ecran_oled.println("Reinitialiser");
  
    // Curseur (symbole ">")
    switch(ligne_selectionnee_dans_menu) {
      case 1:
        ecran_oled.setCursor(0, 25);
        ecran_oled.println(">");
        break;
      case 2:
        ecran_oled.setCursor(0, 35);
        ecran_oled.println(">");
        break;
      case 4:
        ecran_oled.setCursor(0, 55);
        ecran_oled.println(">");
        break;
      default:
        // On n'affiche pas le curseur, sinon
        break;
    }
    
  } else {

    // ==== Affichage "ÉCRAN DE RÉINITIALISATION VALEURS"

    ecran_oled.setTextSize(1);
    ecran_oled.setTextColor(WHITE);
    ecran_oled.setCursor(11, 25);  ecran_oled.println("Reinitialiser les");
    ecran_oled.setCursor(3, 35);  ecran_oled.println("valeurs par defaut ?");
    if(annuler_reinitialisation) {
      ecran_oled.setTextColor(BLACK, WHITE);
      ecran_oled.setCursor(11, 55);  ecran_oled.println(" NON ");
      ecran_oled.setTextColor(WHITE);
      ecran_oled.setCursor(86, 55);  ecran_oled.println(" OUI ");
    } else {
      ecran_oled.setTextColor(WHITE);
      ecran_oled.setCursor(11, 55);  ecran_oled.println(" NON ");
      ecran_oled.setTextColor(BLACK, WHITE);
      ecran_oled.setCursor(86, 55);  ecran_oled.println(" OUI ");
    }
  }

  // Affichage (transfert de la mémoire tampon à l'écran OLED)
  ecran_oled.display();
}


// =============================================
// Fonction : genereOuAjusteSignalPWMservomoteur
// =============================================
void genereOuAjusteSignalPWMservomoteur() {

  // Ajuste PWM en sortie, en fonction de la valeur du potentiomètre, et des bornes hautes/basses paramétrées
  int valPotentiometre = analogRead(pinArduinoRaccordeeAuPotentiometre);    // Valeur 10 bits (0..1023)
  int valArrondiePot = ((int)(valPotentiometre/25)) * 25;
  if (valArrondiePot != valeurPrecendentePotentiometre) {
      Serial.print(F("Valeur arrondie du potentiomètre = "));
      Serial.print(valArrondiePot);
      Serial.println(F("/1000"));   // 1000 et non 1023, du fait de l'arrondi sans virgule /25 * 25 ci-dessus
      valeurPrecendentePotentiometre = valArrondiePot;
      int dureeImpulsionPWM = map(valArrondiePot, 0, 1000, valeurMinCouranteServo, valeurMaxCouranteServo);
      servomoteur.writeMicroseconds(dureeImpulsionPWM);
      Serial.print(F("Durée impulsion haute PWM = "));
      Serial.print(dureeImpulsionPWM);
      Serial.println(F(" µs"));
      valeurCouranteImpulsionServo = dureeImpulsionPWM;
  }

}


// ===========================================================
// Fonction : scruteEtatBoutonsDeNavigationEtAgitEnConsequence
// ===========================================================
void scruteEtatBoutonsDeNavigationEtAgitEnConsequence() {

  // Nota :
  //   - les boutons HAUT/BAS sont actifs lorsqu'on navigue dans le menu principal ("monter" ou "descendre" dans le menu)
  //   - les boutons GAUCHE/DROITE sont actifs lorsqu'on modifie une valeur (+/-, oui/non)
  //   - le bouton OK sert à éditer une valeur ciblée dans le menu ou valider un choix (ou une modification de valeur)

  // ************************
  // *** Boutons HAUT/BAS ***
  // ************************
  if(boutons_haut_bas_actifs) {

    // On récupère l'état des boutons haut/bas
    bool etatBoutonNavigationHaut = !digitalRead(pinArduinoRaccordeeAuBoutonDuHaut);    // Niveau HAUT si inactif ; niveau BAS si appuyé
    bool etatBoutonNavigationBas = !digitalRead(pinArduinoRaccordeeAuBoutonDuBas);

    // ====== Cas où bouton HAUT actif ======
    if(etatBoutonNavigationHaut) {
      // Si appui vers le haut, alors on remonte dans le menu (on "décrémente" le numéro de ligne sélectionné, donc)
      while(!digitalRead(pinArduinoRaccordeeAuBoutonDuHaut));                           // Attente qu'il repasse au niveau haut
      switch(ligne_selectionnee_dans_menu) {
        case 2:
          ligne_selectionnee_dans_menu = 1;     // On passe de la ligne #2 à la ligne #1
          break;
        case 4:
          ligne_selectionnee_dans_menu = 2;     // On passe de la ligne #4 à la ligne #2
          break;
        default:
          // Remarque 1 : on ne fait rien si on est sur la ligne #1, car on ne peut pas remonter plus haut, dans le menu
          // Remarque 2 : la ligne #3 n'est pas sélectionnable, car purement informative
          break;
      }
      delay(20);      // Anti-rebond "logiciel" basique
    }

    // ====== Cas où bouton BAS actif ======
    if(etatBoutonNavigationBas) {
      // Si appui vers le bas, alors on descend dans le menu (on "incrémente" le numéro de ligne sélectionné, donc)
      while(!digitalRead(pinArduinoRaccordeeAuBoutonDuBas));                            // Attente qu'il repasse au niveau haut
      switch(ligne_selectionnee_dans_menu) {
        case 1:
          ligne_selectionnee_dans_menu = 2;     // On passe de la ligne #1 à la ligne #2
          break;
        case 2:
          ligne_selectionnee_dans_menu = 4;     // On passe de la ligne #2 à la ligne #4
          break;
        default:
          // Remarque 1 : on ne fait rien si on est sur la ligne #4, car on ne peut pas remonter plus bas, dans le menu
          // Remarque 2 : la ligne #3 n'est pas sélectionnable, car purement informative
          break;
      }
      delay(20);      // Anti-rebond "logiciel" basique
    }
  }

  // *****************************
  // *** Boutons GAUCHE/DROITE ***
  // *****************************
  if(boutons_gauche_droite_actifs) {

    // On récupère l'état des boutons gauche/droite
    bool etatBoutonNavigationGauche = !digitalRead(pinArduinoRaccordeeAuBoutonDeGauche);    // Niveau HAUT si inactif ; niveau BAS si appuyé
    bool etatBoutonNavigationDroite = !digitalRead(pinArduinoRaccordeeAuBoutonDeDroite);

    // ====== Cas où bouton GAUCHE actif ======
    if(etatBoutonNavigationGauche) {
      while(!digitalRead(pinArduinoRaccordeeAuBoutonDeGauche));                             // Attente qu'il repasse au niveau haut
      if(ligne_selectionnee_dans_menu == 1) {
        valeurMinCouranteServo = valeurMinCouranteServo - pasDeModificationDelaiImpulsionServo;
        if(valeurMinCouranteServo < valeurMinSeuilBasImpulsionServo) {
          valeurMinCouranteServo = valeurMinSeuilBasImpulsionServo;
        }
      }
      if(ligne_selectionnee_dans_menu == 2) {
        valeurMaxCouranteServo = valeurMaxCouranteServo - pasDeModificationDelaiImpulsionServo;
        if(valeurMaxCouranteServo < valeurMinSeuilHautImpulsionServo) {
          valeurMaxCouranteServo = valeurMinSeuilHautImpulsionServo;
        }
      }
      if(ligne_selectionnee_dans_menu == 4) {
        annuler_reinitialisation = true;
      }
      delay(20);      // Anti-rebond "logiciel" basique
    }

    // ====== Cas où bouton DROITE actif ======
    if(etatBoutonNavigationDroite) {
      while(!digitalRead(pinArduinoRaccordeeAuBoutonDeDroite));                             // Attente qu'il repasse au niveau haut
      if(ligne_selectionnee_dans_menu == 1) {
        valeurMinCouranteServo = valeurMinCouranteServo + pasDeModificationDelaiImpulsionServo;
        if(valeurMinCouranteServo > valeurMaxSeuilBasImpulsionServo) {
          valeurMinCouranteServo = valeurMaxSeuilBasImpulsionServo;
        }
      }
      if(ligne_selectionnee_dans_menu == 2) {
        valeurMaxCouranteServo = valeurMaxCouranteServo + pasDeModificationDelaiImpulsionServo;
        if(valeurMaxCouranteServo > valeurMaxSeuilHautImpulsionServo) {
          valeurMaxCouranteServo = valeurMaxSeuilHautImpulsionServo;
        }
      }
      if(ligne_selectionnee_dans_menu == 4) {
        annuler_reinitialisation = false;
      }
      delay(20);      // Anti-rebond "logiciel" basique
    }
  }

  // *****************
  // *** Bouton OK ***
  // *****************
  bool etatBoutonNavigationCentre = !digitalRead(pinArduinoRaccordeeAuBoutonDuCentre);  // Niveau HAUT si inactif ; niveau BAS si appuyé  
  if(etatBoutonNavigationCentre) {
    
    if(boutons_haut_bas_actifs) {
      // ====== Cas où boutons HAUT/BAS actifs ======
      while(!digitalRead(pinArduinoRaccordeeAuBoutonDuCentre));                         // Attente qu'il repasse au niveau haut
      boutons_gauche_droite_actifs = true;
      boutons_haut_bas_actifs = false;
      if(ligne_selectionnee_dans_menu == 4) {
        afficher_menu_principal = false;
        annuler_reinitialisation = true;
      }
      delay(20);      // Anti-rebond "logiciel" basique
    } else if(boutons_gauche_droite_actifs) {
      // ====== Cas où boutons GAUCHE/DROITE actifs ======
      while(!digitalRead(pinArduinoRaccordeeAuBoutonDuCentre));                         // Attente qu'il repasse au niveau haut
      boutons_gauche_droite_actifs = false;
      boutons_haut_bas_actifs = true;
      if(ligne_selectionnee_dans_menu == 1) {
        ecritValeurIntEnEEPROM(adresseMemoireValeurBasseImpulsionServo, valeurMinCouranteServo);
      }
      if(ligne_selectionnee_dans_menu == 2) {
        ecritValeurIntEnEEPROM(adresseMemoireValeurHauteImpulsionServo, valeurMaxCouranteServo);
      }
      if(ligne_selectionnee_dans_menu == 4) {
        if(annuler_reinitialisation == false) {
          // Si la réinitialisation a été demandée, alors on réinitialise les valeurs par défaut (variables globales + EEPROM)
          ecritValeurIntEnEEPROM(adresseMemoireValeurBasseImpulsionServo, valeurDefautSeuilBasImpulsionServo);
          ecritValeurIntEnEEPROM(adresseMemoireValeurHauteImpulsionServo, valeurDefautSeuilHautImpulsionServo);
          valeurMinCouranteServo = valeurDefautSeuilBasImpulsionServo;
          valeurMaxCouranteServo = valeurDefautSeuilHautImpulsionServo;
          ligne_selectionnee_dans_menu = 1;     // On remet le "curseur" sur la 1ère ligne du menu principal       
        }
        afficher_menu_principal = true;
      }
      valeurPrecendentePotentiometre = -1;    // On force le recalcul du signal PWM, avec ces nouvelles valeurs
      delay(20);      // Anti-rebond "logiciel" basique
    }
  } 
  
}


// =================
// Boucle principale
// =================
void loop() {

  // Scrute l'état des boutons de navigation (boutons haut, droite, bas, gauche, et centre), et agit en conséquence
  scruteEtatBoutonsDeNavigationEtAgitEnConsequence();
    
  // Génère (ou ajuste) le signal PWM à destination du servomoteur
  genereOuAjusteSignalPWMservomoteur();

  // Contruit/rafraîchit affichage écran OLED
  contruitEtRafraichitAffichageEcranOLED();

  // Puis rebouclage, à l'infini

}

Dans ce code, je vous ai mis un maximum de commentaires, afin que vous puissiez bien comprendre à quoi correspond chaque action (ou presque… !).

Ah oui … histoire d’apporter un maximum de clarté : les valeurs Tmin et Tmax affichées sur l’écran OLED correspondent aux durées minimale et maximale de l’état haut du signal PWM. Et ce sont ces valeurs de consignes, qui seront sauvegardées en mémoire EEPROM. Au sujet de ces valeurs, par ailleurs, celles-ci seront :

  • initialisées à Tmin = 1 ms et Tmax = 2 ms (ce sont les valeurs par défaut que j’ai choisi)
    • si c’est la première fois que ce programme tourne sur votre arduino (une case mémoire « spéciale » contiendra un nombre particulier, afin de valider ou d’invalider cela)
    • si vous avez forcé la « réinitialisation des valeurs par défaut », depuis le menu « Réinitialiser »
  • enregistrées en mémoire EEPROM chaque fois que l’utilisateur aura modifié ces valeurs, puis appuyé sur OK
  • lues à chaque (re)démarrage de l’arduino, pour leur prise en compte au niveau du programme

Allez… assez parlé du programme arduino ! Maintenant, passons à la partie électronique et soudage, à proprement parler 😉

Fabrication (pcb et soudage composants)

Tout d’abord, voici le circuit imprimé PCB de ce testeur de servo arduino :

Ici, tous les composants et connecteurs sont implantés sur la « face avant », et soudés sur la « face arrière ». Comme d’habitude, l’idéal est de commencer à souder les éléments les plus petits ou moins encombrants, pour finir avec les plus gros ou plus imposants.

Voici d’ailleurs quelques photos prises de mon côté, au moment du soudage :

Pour être clair, rien de bien compliqué ici, en somme ! Toutefois, il faudra bien faire attention au sens d’implantation du condensateur électrochimique (car il est polarisé), si vous reproduisez ce montage.

Remarque : d’un fabricant à un autre (ou suivant les versions), les dimensions d’un écran OLED peuvent varier. Ainsi, comme ça été le cas pour moi ici, il se peut que les entretoises de fixation ne tombent pas exactement en face des trous de fixation de l’écran. Dans ce cas, ne vous prenez pas la tête, car il suffit de laisser l’afficheur OLED reposer sur les entretoises, sans chercher à y mettre des vis de fixation ; l’écran ne sera donc pas fixé, certes, mais dans le fond, ce n’est pas indispensable !

Essais et remarques

Pour commencer, avant de mettre ce projet sous tension, je vous conseille de sortir l’Arduino Nano de la carte, et de le programmer « en dehors », par sécurité. Car en effet, si jamais vous reprenez un ancien arduino et qu’un autre programme « tourne à l’intérieur », alors vous prendriez potentiellement le risque de provoquer des courts-circuits, sans le vouloir (si une entrée actuelle de bouton poussoir était programmée en sortie auparavant, par exemple, et que vous appuyez sur ce bouton). C’est pourquoi je vous dirai qu’il est toujours préférable et judicieux de programmer son arduino « en dehors » de tout, la première fois, afin d’éviter toute déconvenue de ce style !

Une fois fait, vérifiez bien que tous les composants soient bien en place (pas d’inversion, et soudures bien faites). Ne riez pas… cela peut également vous éviter bien des soucis !

Ensuite, je vous recommande également de faire des essais à vide, avant de mettre en charge (avant de brancher le moindre servomoteur, j’entends par là). Ainsi, vous pourrez :

  • vérifier que tout fonctionne bien, tant au niveau des réglages que de l’affichage sur l’écran OLED, notamment
  • vérifier qu’un signal PWM « en bonne et due forme » sort bien sur la broche « signal », du bornier où sera branché le servomoteur

Si tout est ok, alors vous pourrez envisager de brancher un servomoteur sur cette carte ! Par contre, ne prenez pas un servo de « forte puissance », car l’alimentation de la carte provient du +5V de l’USB, après être passé au travers d’une diode schottky, sur la carte Arduino Nano (cette diode pourrait rapidement surchauffer, si vous tirez beaucoup trop de courant au travers).

Pour ma part, j’ai utilisé un micro servo SG90, pour les essais (comme ceux qu’on utilise en modélisme amateur, en fait !).

Du reste, voici des images prises à l’occasion des essais que j’ai réalisé de mon côté, sur ce testeur de servo arduino :

À présent, dites-vous que ce projet est essentiellement présenté pour vous inciter à pratiquer l’électronique, en vous montrant comment réaliser « simplement » un petit montage, autour d’arduino. Bien sûr, ce projet n’est pas parfait, loin de là. D’ailleurs, voici quelques améliorations possibles, auxquelles j’ai pensé à posteriori :

  • il faudrait mettre un condensateur de filtrage/stabilisation sur l’entrée analogique arduino, là où est branché le potentiomètre ; ainsi, cela limiterait les fluctuations au moment de la lecture de tension sur cette broche, et ainsi, pouvoir affiner le pas de rotation-servo dans le programme
  • il faudrait prévoir une alimentation +5V externe, indépendante de l’arrivée USB de l’Arduino, pour tester les servomoteurs de plus forte puissance
  • il faudrait également prévoir plusieurs types de branchement différents, au niveau du connecteur-servo en lui-même, car selon les marques, cela peu varier quelque peu (même si le brochage présenté ici reste le plus commun !) ; cela dit, il suffirait de mettre des fils dupont mâle ↔ femelle entre le connecteur de carte, et le servomoteur à tester (en câblant les fils Signal/Vcc/Gnd à sa guise, tout simplement)

Ah oui… j’allais oublier de vous parler de cette partie accessoire : si vous ouvrez le moniteur série d’Arduino IDE, vous devriez voir des infos « intéressantes » s’afficher. À ce niveau, vous pourrez visualiser si le chargement en mémoire EEPROM des consignes s’est bien fait au démarrage, ou, si c’est la 1ère fois que vous lancez ce programme sur votre arduino, si les valeurs de consignes par défaut ont bien été enregistrées en mémoire EEPROM (afin de pouvoir simplement les lire, aux démarrages suivants).

En image, ceci donne cela, dans le cas où c’est la première fois où vous lancez ce programme sur votre Arduino Nano (vous verrez d’écrit « valeurs initialisées », comme ci-dessous) :

Écriture EEPROM arduino lors de l'initialisation du programme, exemple d'enregistrement de valeurs de consigne au démarrage du microcontrôleur

Et pour tous les démarrages suivants, le programme se limitera à charger ces valeurs, stockées en mémoire EEPROM (dans ce cas, vous verrez d’écrit « valeurs récupérées avec succès », comme visible ci-dessous) :

Lecture EEPROM interne Arduino, affichage valeurs sur moniteur série de l'IDE Arduino, exemple de codage projet électronique DIY

Enfin, concernant le déroulement du programme par la suite, sachez que chaque changement au niveau du potentiomètre vous remontera une info à l’écran, avec la valeur lue/arrondie/convertie, et la nouvelle durée d’impulsion servo (car le fait de toucher au potentiomètre aura bel et bien pour conséquence de modifier le rapport cyclique du signal PWM, et donc, la durée de l’impulsion à l’état haut de ce signal).

Voici ce que j’ai obtenu de mon côté, en ayant démarré avec le potentiomètre réglé « au milieu », puis tourné à fond « à gauche », puis tourné à fond « à droite » :

Affichage testeur servo arduino, valeurs pwm et potentiomètre de réglage position angulaire du servomoteur piloté par microcontrôleur ATmega328P

Bien entendu, tout ceci n’est qu’accessoire (optionnel, si vous préférez), car « toutes » les infos importantes s’afficheront sur l’écran OLED de ce servotester arduino !

Liens et téléchargements

Voici les fichiers sources ayant servi au projet :

Nota : le fichier Gerber, au format ZIP, vous permettra de faire reproduire le PCB de ce projet à l’identique, si souhaité ; c’est d’ailleurs celui que j’ai transmis à JLCPCB, pour la réalisation de ce circuit imprimé (bien sûr, libre à vous de choisir le fabricant de votre choix !).

Testeur de servo arduino : conclusion !

Voilà pour ce petit projet de testeur de servo arduino ! J’espère qu’il vous aura plu, même s’il y a au final plus de codage, que de composants électroniques mis en œuvre 😉

De mon côté, il ne me reste plus qu’à retourner bosser, pour préparer le prochain article !
À bientôt !

Jérôme.

À découvrir aussi : un Thermomètre Arduino, pour débuter pas à pas en électronique !

Ce contenu vous plaît ? Alors abonnez-vous à la Newsletter pour ne rien louper !

(*) Mis à jour le 22/01/2024

7 commentaires sur “Testeur de Servomoteur Arduino (avec code programmation, utilisant la librairie servo arduino)”

  1. Site passionelectronique.fr

    Bjr à tous ! J’ai lu rapidement pour l’instant … encore un bon moment d’apprentissage pour les novices.
    Personnellement j’en ai fait un sans Nano il y a qq années, par contre c’est tjrs très formateur d’analyser ce que fait un autre.

    Bon courage !!!

  2. Site passionelectronique.fr

    Merci pour vos partages toujours très instructifs.

    Même si je ne réalise pas les montages que vous proposez (manque de temps et de place) vous me procurez beaucoup de plaisir à comprendre mieux le monde qui nous entoure.

    1. Site passionelectronique.fr

      Merci pour ce retour !

      Et du reste pas de soucis ! Car le but premier des réalisations que je partage ici est justement de permettre au plus grand nombre d’apprendre, par la pratique (les autres buts étant de vous inspirer, et de vous montrer une façon de faire, parmi tant d’autres !).

      Alors à bientôt 🙂

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Symbole danger point d'exclamation site PSE, triangle jaune avec contour noir, texte noir alerte au milieuAfin de filtrer au maximum les messages de type "spam" ou "inappropriés", chaque commentaire est soumis à modération, et validé manuellement. Du coup, il se peut que certains commentaires ne soient pas publiés, ou sinon, avec un peu de retard. Par ailleurs, j'ai malheureusement plus de messages à traiter que de temps pour y répondre ; c'est pourquoi je ne pourrais pas répondre à tout le monde. Désolé …