Transformez n'importe quel moteur à courant continu en un servo personnalisé à 360° – Guide étape par étape
Dans ce didacticiel, nous apprendrons comment transformer n'importe quel moteur à courant continu en un servomoteur personnalisé autonome doté de nombreuses fonctionnalités. Contrairement aux servos ordinaires qui ont un mouvement limité à 180 ou 270 degrés, celui-ci a une portée illimitée de 360 degrés et en plus de cela, nous avons la possibilité d'ajuster la plage de rotation à la valeur dont nous avons besoin.
C’est assez pratique je trouve, et en plus, on peut même ajuster le point central du servo. Ainsi, nous pouvons ajuster à la fois le point central et la plage de rotation.
Vous pouvez regarder la vidéo suivante ou lire le didacticiel écrit ci-dessous.
Une autre fonctionnalité est que nous pouvons ajuster la sensibilité ou la rapidité avec laquelle le servo répondra à notre entrée. En parlant de saisie, nous pouvons avoir trois modes de saisie différents.
Nous pouvons contrôler le servo avec une entrée de tension analogique ou à l'aide d'un potentiomètre, nous pouvons contrôler le servo avec un émetteur RC ainsi que contrôler le servo via un port série en entrant des valeurs d'angle via le moniteur série de notre PC ou ordinateur portable.
Nous pouvons également le faire simultanément, contrôler le servo en entrant des valeurs via le moniteur série et déplacer manuellement le servo à l'aide de l'émetteur RC. Le servomoteur connaîtra à tout moment sa position actuelle et pourra la voir sur le moniteur série.
En plus de la liste des caractéristiques de ce servomoteur se trouve le mode de rotation continue. C'est exact. Nous pouvons contrôler et suivre la position du servomoteur même dans ce mode de rotation continue. Nous pouvons régler l’arbre du servomoteur pour qu’il aille dans n’importe quelle position avec un nombre infini de tours.
Tout cela est possible grâce à l'encodeur 12 bits utilisé par ce servomoteur, au capteur de position rotatif magnétique AS5600 et au contrôle PID mis en œuvre pour piloter le moteur à courant continu.
J'ai créé cette carte contrôleur de servomoteur personnalisée qui comprend son propre microcontrôleur et tout le reste pour transformer facilement n'importe quel moteur à courant continu en un servomoteur autonome.
Il suffit de positionner la carte au centre de l'arbre de sortie (y compris un aimant spécifique sur l'arbre), de connecter n'importe quelle taille de moteur à courant continu avec un courant nominal allant jusqu'à 3,5 A, d'alimenter l'ensemble du système en 12 V et c'est tout, nous obtenons un servomoteur à partir d'un moteur à courant continu normal avec toutes ces fonctionnalités.
Je vais maintenant vous guider tout au long du processus de fabrication de ce servomoteur sur mesure afin que vous puissiez également en fabriquer un vous-même. J'expliquerai le principe de fonctionnement d'un servomoteur, d'un contrôleur en boucle fermée, d'un contrôleur PID, comment j'ai conçu le PCB personnalisé pour celui-ci et la boîte de vitesses, ainsi que le code derrière celui-ci.
Principe de fonctionnement du servomoteur
Afin d'expliquer le principe de fonctionnement d'un servomoteur, démontons un servomoteur RC typique et voyons ce qu'il y a à l'intérieur.
On peut remarquer qu'il dispose d'un petit moteur à courant continu, d'une carte contrôleur, d'un potentiomètre et d'une connexion à trois fils, deux fils pour l'alimentation et un pour le signal d'entrée. Il existe également des engrenages permettant de réduire la vitesse et d’augmenter le couple du moteur à courant continu.
Il s'agit d'une configuration typique pour la plupart des servomoteurs RC ou amateurs. Le potentiomètre est fixé à l'arbre de sortie du moteur à courant continu et agit comme un capteur de position. Il indique au contrôleur la position actuelle de l'arbre du servomoteur. La carte contrôleur contrôle le moteur à courant continu en fonction du signal d'entrée (la position souhaitée) et de la position réelle que nous obtenons en retour du potentiomètre. Cela représente un système de contrôle en boucle fermée.
Le signal d'entrée, ou la position souhaitée, est comparé à la position réelle du moteur que nous obtenons du capteur de retour de position. La différence qui se produit, appelée erreur, est ensuite traitée dans le contrôleur qui commande au moteur de se déplacer jusqu'à ce qu'il atteigne la position souhaitée.
Comment créer un servomoteur personnalisé
Ainsi, si nous voulons construire notre propre servomoteur avec des moteurs à courant continu plus gros que ceux utilisés par ces servomoteurs RC typiques, nous pouvons implémenter le même système de contrôle en boucle fermée.
Nous avons juste besoin d'un capteur de position fixé d'une manière ou d'une autre à l'arbre de sortie et d'un microcontrôleur pour piloter le moteur à courant continu.
Maintenant en ce qui concerne le capteur de position, la solution la plus simple est d'utiliser un simple potentiomètre comme celui que nous avons vu dans les servos RC. Le problème avec ces types de potentiomètres est qu'ils ont une plage de rotation limitée de seulement 270 degrés, ce qui limite directement la plage de rotation du servomoteur. Il existe également d'autres types de potentiomètres qui peuvent effectuer plusieurs tours et offrir une meilleure portée et résolution, mais leur rotation est néanmoins limitée.
Si nous avons besoin que le servomoteur ait une plage de rotation illimitée, nous devons alors utiliser un encodeur. Les codeurs sont des dispositifs électromécaniques capables de suivre la position angulaire de l'arbre avec une rotation illimitée. Il existe de nombreux types de codeurs, incrémentaux ou absolus, ou, selon leur technologie de détection, optique, magnétique ou capacitif. Bien sûr, chacun d'eux a ses propres avantages et inconvénients.
Encodeur AS5600 – Capteur de position rotatif magnétique
J'ai choisi d'utiliser un codeur magnétique, ou le capteur de position rotatif magnétique AS5600, car il s'agit d'un codeur très compact et facile à mettre en œuvre offrant une haute précision ou résolution. Jetez simplement un œil à la petite taille de cette micropuce.
Il dispose d'un capteur à effet Hall intégré qui peut détecter les changements de direction du champ magnétique. Il suffit donc de fixer un aimant sur l'arbre de sortie du moteur et de le positionner près de la puce électronique à une distance de 0,5 à 3 mm.
Désormais, à mesure que l'arbre du moteur et l'aimant tournent, le capteur à effet Hall capture ces changements dans la direction du champ magnétique. Grâce au convertisseur A/D 12 bits intégré, le capteur AS5600 peut produire 4 096 positions par tour ou une rotation de 360 degrés.
Cela signifie qu’il peut détecter des changements de position angulaire aussi petits que 0,0878 degrés. C'est assez impressionnant, et comme il est très abordable et facile à obtenir, c'est le bon choix pour un servomoteur sur mesure.
Très bien, alors de quoi d'autre avons-nous besoin, un microcontrôleur et un pilote pour le moteur à courant continu. J'ai choisi le pilote de moteur CC DRV8871 qui peut gérer jusqu'à 3,5 ampères de courant, et le microcontrôleur Atmega328.
J'ai choisi la version à montage en surface, car elle est beaucoup plus compacte que la version DIP, et mon objectif était de créer un PCB personnalisé aussi petit que possible sur lequel je peux tout inclure pour que le servo puisse fonctionner comme un appareil autonome.
Schéma de circuit de servomoteur personnalisé
Voici le schéma de circuit complet de ce servomoteur sur mesure.
Vous pouvez obtenir les composants nécessaires à ce projet à partir des liens ci-dessous :
- Encodeur magnétique AS5600 ………………….. Amazon / AliExpress
- Driver de moteur à courant continu DRV8871 ……………….…. Amazon / AliExpress
- Atmega328p-AU …………………………………. Amazon / AliExpress
- Oscillateur à cristal 16 MHz …………………….. Amazon / AliExpress
- Régulateur de tension AMS1117 5V ………..…. Amazon / AliExpress
- Potentiomètre carré 3386P ………………. Amazon / AliExpress
- Kit Condensateurs 0805 …………………………….…. Amazon / AliExpress
- Moteur 12 V CC – ~ 50 tr/min …………….……. Amazon / AliExpress
Divulgation :ce sont des liens d'affiliation. En tant qu'associé Amazon, je gagne des revenus grâce aux achats éligibles.
Nous avons donc le microcontrôleur Atmega328 avec son circuit minimum recommandé, qui comprend un oscillateur de 16 MHz, quelques condensateurs et une résistance.
Pour alimenter le microcontrôleur et les autres composants nécessitant 5 V, nous utilisons le régulateur de tension AMS1117, qui fera chuter l'entrée d'alimentation 12 V à 5 V.
Voici le capteur de position AS5600 avec son circuit recommandé qui comprend deux condensateurs et deux résistances de rappel pour la communication IC2.
Le pilote de moteur CC DRV8871 n'a besoin que d'une seule résistance pour limiter le courant et de deux condensateurs de découplage. Nous avons ensuite deux potentiomètres connectés aux entrées analogiques du microcontrôleur, un pour régler la plage de rotation et l'autre pour régler la sensibilité du servo. Le bouton poussoir est utilisé pour régler le point central du servo et le commutateur DIP bidirectionnel pour sélectionner les modes de fonctionnement du servo. Il y a un en-tête de broche pour les entrées du servo, soit une entrée de tension analogique, soit une entrée numérique PWM provenant d'un récepteur RC, ainsi qu'une broche de 5 V et une broche de masse. Il existe également un en-tête de broche pour programmer le microcontrôleur via le protocole SPI et le port série.
Voici un récapitulatif de ce circuit et de son flux de travail. L'entrée, ou la position angulaire souhaitée, est reçue via ces deux broches et il peut s'agir soit d'une tension analogique provenant d'un potentiomètre, soit d'un signal numérique PWM provenant d'un récepteur RC. L'entrée va dans le microcontrôleur où elle est comparée à la position angulaire réelle détectée par l'encodeur ou le capteur de position AS5600. Ce capteur communique avec le microcontrôleur via le protocole IC2.
Ensuite, le microcontrôleur fait le calcul, il calcule l'erreur et en fonction de cela, il envoie un signal PWM au pilote DRV8871 qui pilote le moteur à courant continu jusqu'à ce qu'il atteigne la position souhaitée.
L'ensemble du circuit est alimenté en 12 V et le régulateur de tension AS1117 fournit 5 V au microcontrôleur et aux autres composants de manière appropriée.
Conception de PCB
D'après le schéma de circuit, j'ai essayé de concevoir le PCB aussi petit que possible, et il s'est avéré qu'il mesurait 40 x 40 mm.
Je positionne l'encodeur sur la face inférieure et exactement au point central du PCB, afin qu'il puisse être facilement monté et aligné avec l'arbre de sortie du servo.
Tous les autres composants sont situés de l'autre côté afin qu'ils n'interfèrent pas avec l'encodeur et l'arbre de sortie.
J'ai commandé le PCB chez PCBWay. Ici, nous pouvons simplement télécharger le fichier Gerber, choisir les propriétés de notre PCB et le commander à un prix raisonnable.
J'ai conçu le PCB pour qu'il ait 4 couches, celles du milieu sont pour GND, ce qui augmente un peu le prix. Je n'ai modifié aucune des propriétés par défaut, à l'exception de la couleur du PCB que j'ai choisi comme blanc, et je coche que j'accepte le changement de finition de surface en Or par immersion, le cas échéant, sans frais supplémentaires.
Vous pouvez trouver et télécharger le Gerber depuis la communauté de partage de projets PCBWay à travers laquelle vous pouvez également commander directement le PCB.
Néanmoins, après plusieurs jours, le PCB est arrivé. La qualité du PCB est excellente, tout est le même que dans la conception, et je l'ai obtenu avec une finition de surface dorée par immersion.
Très bien, nous pouvons maintenant passer à la soudure des composants. J'ai commencé avec les composants plus petits comme ce voyant LED, ainsi que les condensateurs et les résistances.
C'est en fait la première fois que je soude ces petits composants CMS, et j'étais vraiment très mauvais dans ce domaine.
Le plus difficile a été de souder le microcontrôleur Atmega328, car les broches sont vraiment petites et très proches les unes des autres, mais j'ai réussi d'une manière ou d'une autre à le faire.
La puce de l'encodeur AS5600 était facile à souder sur la face arrière du PCB, ainsi que les composants traversants les plus gros, comme le commutateur DIP, les potentiomètres, les borniers et les embases à broches.
Quoi qu'il en soit, voici l'apparence finale de la carte contrôleur qui, après tout, s'est avérée décente, je pense.
Il est maintenant temps de créer un réducteur adapté au moteur à courant continu et à cette carte contrôleur.
Modèle 3D de servo personnalisé
J'ai conçu la boîte de vitesses de ce servomoteur personnalisé en utilisant Onshape. La conception de la boîte de vitesses dépend bien entendu du moteur à courant continu. Comme je l'ai mentionné, nous pouvons utiliser n'importe quelle taille de moteur à courant continu en combinaison avec la carte contrôleur que nous venons de fabriquer.
Ici, j'utilise un moteur à courant continu de 37 mm de diamètre et une boîte de vitesses intégrée qui produit 50 tr/min. 50 tr/min est une bonne vitesse pour un servomoteur, mais je voulais aller un peu plus bas que cela, pour obtenir un meilleur couple, j'ai donc fabriqué une boîte de vitesses avec une réduction de 3 fois. J'ai utilisé des engrenages à chevrons à cet effet car ils sont efficaces et faciles à réaliser avec une imprimante 3D.
Bien sûr, nous avons ici la liberté de concevoir cette boîte de vitesses comme nous le souhaitons, car cela dépend du moteur à courant continu que nous souhaitons utiliser et des vitesses de sortie que nous souhaitons obtenir.
J'ai positionné la carte contrôleur à l'arrière de cette boîte de vitesses et je l'ai parfaitement alignée au centre de l'arbre de sortie.
Dans le cas où nous souhaitons utiliser l'arbre du moteur à courant continu directement comme sortie, nous pouvons simplement utiliser un engrenage 1:1 afin de pouvoir suivre correctement la position de l'arbre. Ou nous pourrions également utiliser un système de ceinture dans un tel cas. Comme je l'ai dit, nous avons des possibilités infinies pour fabriquer la boîte de vitesses.
Téléchargez le modèle 3D et les fichiers STL
Vous pouvez visualiser et explorer le modèle 3D de ce servomoteur sur mesure directement sur votre navigateur Web avec Onshape. (Vous avez besoin d'un compte Onshape pour cela, vous pouvez créer un compte gratuit pour un usage domestique)
Bien sûr, vous téléchargez également le modèle 3D, ainsi que les fichiers STL nécessaires à l'impression 3D des pièces, à partir d'ici :
Fichier STEP :
Fichiers STL pour l'impression 3D :
Assembler le servo personnalisé
Voici les pièces imprimées en 3D pour cette construction afin que nous puissions commencer à assembler le servomoteur.
Avec eux, nous avons besoin de boulons M3 et d'inserts filetés, ainsi que de roulements.
Tout d'abord, j'ai fixé le moteur à courant continu à la plaque de base avec des boulons M3 de 8 mm de longueur.
Ensuite, nous pouvons installer les deux engrenages en place. Le plus petit engrenage va directement à l'arbre du moteur à courant continu, et le plus gros engrenage sera la sortie du servo. Cependant, l'arbre de sortie du est composé de deux parties.
J'ai installé des inserts filetés des deux côtés de cette partie d'arbre de sortie, d'un côté pour y connecter l'engrenage, et de l'autre côté pour fixer des objets sur la sortie du servo.
J'ai également installé des inserts filetés sur le plus petit engrenage qui sera utilisé pour le fixer à l'arbre du moteur à courant continu. Nous pouvons maintenant faire glisser les engrenages réduits dans leur position. Comme ce sont des engrenages à chevrons, nous devons les faire glisser tous les deux en même temps, sinon nous ne pouvons pas les coupler si nous les insérons un par un.
À l'aide d'une vis sans tête, j'ai fixé le petit engrenage à l'arbre du moteur à courant continu. J'ai appliqué 12 V au moteur à courant continu pour vérifier si le train d'engrenages fonctionnera correctement.
Nous pouvons terminer l'assemblage de la boîte de vitesses en insérant le panneau latéral, le roulement à billes pour l'arbre de sortie et le couvercle supérieur.
J'ai installé des inserts filetés M3 sur la plaque arrière afin que nous puissions fixer l'ensemble avec des boulons M3 de 20 mm de long. J'ai encore testé la boîte de vitesses, elle fonctionne très bien. Nous pouvons remarquer comment l'arbre de sortie tourne à l'arrière et ici nous devons insérer l'aimant dont l'encodeur AS5600 gardera la trace.
Nous fixons la carte contrôleur à la boîte de vitesses à l'aide de boulons et d'écrous M2. Le capteur de position AS5600 est maintenant parfaitement aligné avec l'aimant et ainsi, lorsque l'arbre de sortie tournera, il mesurera correctement le changement du champ magnétique.
Veuillez noter ici que la direction de magnétisation de l'aimant permanent est très importante. Selon qu'il est magnétisé axialement ou diamétralement, nous devons positionner l'aimant perpendiculairement ou parallèlement à ce circuit intégré AS5600.
J'ai fini par changer la direction de mon aimant, car il n'avait pas la bonne magnétisation pour que l'encodeur AS5600 puisse le mesurer.
Ensuite, j'ai soudé deux fils au moteur à courant continu et connecté le moteur au contrôleur avec le bornier. Quant à l'alimentation, j'ai connecté deux fils au bornier d'alimentation, qui de l'autre côté disposent d'un connecteur d'alimentation CC pour connecter une alimentation 12V. Et voilà, notre servomoteur sur mesure est terminé.
Programmation du contrôleur
Il ne reste plus qu'à donner vie à ce servo, ou à programmer le contrôleur. Pour cela, nous devons d’abord graver un chargeur de démarrage sur le microcontrôleur ATmega328p. Sans bootloader, le microcontrôleur ne pourra pas comprendre le langage ni le code que nous lui enverrons.
Gravure du chargeur de démarrage
Pour graver le chargeur de démarrage sur l'ATmega328p, nous avons besoin d'une carte Arduino, dans mon cas j'utiliserai une carte Arduino Nano.
Nous utiliserons la communication SPI, nous devons donc connecter les broches SPI appropriées sur la carte Arduino et notre carte contrôleur.
Maintenant, à l’aide de l’IDE Arduino, nous devons ouvrir l’exemple d’esquisse ArduinoISP et le télécharger sur la carte Arduino Nano. Avec ce code, l'Arduino Nano est désormais capable de graver le chargeur de démarrage sur le microcontrôleur ATmega328.
Ensuite, dans le menu Outils, en tant que programmeur, nous devons sélectionner Arduino comme FAI, puis cliquer sur Graver le chargeur de démarrage.
Lors de la gravure du chargeur de démarrage, nous devrions remarquer que les voyants Arduino NANO clignotent beaucoup, ce qui entraînera une gravure réussie du chargeur de démarrage.
Téléchargement de code
Une fois que nous avons terminé, nous pouvons maintenant programmer ou télécharger le code sur la carte contrôleur à l'aide d'un module d'interface USB vers UART.
La carte contrôleur dispose de broches dédiées pour les connecter facilement, comme indiqué dans ce schéma de circuit.
Nous pouvons maintenant ouvrir le code de ce servo personnalisé que j'ai créé et le télécharger sur le contrôleur. Mais avant de faire cela, nous devons d’abord installer les bibliothèques pour le capteur AS5600 et le contrôle PID. Nous pouvons facilement le faire à partir du gestionnaire de bibliothèque Arduino IDE. Une fois que nous avons appuyé sur le bouton de téléchargement, le code sera écrit sur notre contrôleur ATmega328 via le module d'interface USB vers UART.
Et voilà, notre servomoteur sur mesure est terminé. Nous pouvons maintenant y connecter un potentiomètre pour le tester. Notez simplement que l'entrée analogique va à la broche "S" de la carte contrôleur, au lieu de la broche "A".
Lors de la conception du PCB, j'ai mal connecté ces deux broches à l'ATmega328. Ensuite, nous pouvons sélectionner le mode d'entrée analogique via le commutateur DIP et alimenter le servo.
Et voilà, nous pouvons contrôler la position du servomoteur à l'aide de l'entrée analogique du potentiomètre. Nous avons réussi à convertir notre moteur à courant continu en servomoteur.
Code source
Jetons maintenant un coup d'œil au code de ce servomoteur personnalisé.
/*
* Custom-built Servo Motor - Arduino Code
* by Dejan, www.HowToMechatronics.com
*
* Libraries:
* AS5600 encoder: https://github.com/RobTillaart/AS5600
* PID conroller: https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h
*/
#include "AS5600.h"
#include "Wire.h"
#include <PID_v1.h>
AS5600 as5600; // use default Wire
double Pk1 = 2; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.025;
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint, Pk1, Ik1, Dk1, DIRECT);
#define motor_IN1 5
#define motor_IN2 6
#define ch1 2
#define centerSet 7
#define inputSwitch 3
#define modeSwitch 4
int ch1Value;
int encoderValue, inputValue, pwmValue;
String inString = ""; // string to hold input
int centerAngle = 2047; // 180 degrees
int angleDifference = 0;
int angleValue = 0;
int leftLimit = 30;
int rightLimit = 4067;
int rangeAdjustment = 0;
float sensitivityAdjustment = 0;
float angle = 0;
int quadrantNumber = 2;
int previousQuadrantNumber = 3;
int numberOfTurns = 0;
float totalAngle = 0;
int error = 0;
char incomingByte = 0;
int intInput = 0;
void setup() {
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AS5600_LIB_VERSION: ");
Serial.println(AS5600_LIB_VERSION);
Wire.begin();
pinMode(motor_IN1, OUTPUT);
pinMode(motor_IN2, OUTPUT);
// Activate the Arduino internal pull-up resistors
pinMode(centerSet, INPUT_PULLUP);
pinMode(inputSwitch, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
myPID.SetMode(AUTOMATIC); // PID Setup
myPID.SetOutputLimits(-255, 255);
myPID.SetSampleTime(20);
}
void loop() {
// Read encoder value - current position
encoderValue = as5600.readAngle();
// Continuous rotation mode
if (digitalRead(modeSwitch) == 0) {
// Enter desired angle for the servo to go to through the serial monitor
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar)) {
// convert the incoming byte to a char and add it to the string:
inString += (char)inChar;
}
// if you get a newline, print the string, then the string's value:
if (inChar == '\n') {
Setpoint = inString.toInt(); // Setpoint - desired angle
// clear the string for new input:
inString = "";
}
}
if (digitalRead(inputSwitch) == 0) { // Potentiometer as input
inputValue = analogRead(A0);
if (inputValue < 400) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 300) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 200) {
Setpoint = Setpoint - 0.3;
}
if (inputValue > 600) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 700) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 800) {
Setpoint = Setpoint + 0.3;
}
}
else if (digitalRead(inputSwitch) == 1) {
inputValue = pulseIn(ch1, HIGH, 30000); // RC receiver as input
if (inputValue < 1450) {
Setpoint--;
}
if (inputValue < 1350) {
Setpoint--;
}
if (inputValue < 1250) {
Setpoint--;
}
if (inputValue < 1150) {
Setpoint--;
}
if (inputValue > 1550) {
Setpoint++;
}
if (inputValue > 1650) {
Setpoint++;
}
if (inputValue > 1750) {
Setpoint++;
}
if (inputValue > 1850) {
Setpoint++;
}
}
// Convert encoder RAW values into angle value
angle = encoderValue * 0.087890625;
// Quadrant 1
if (angle >= 0 && angle <= 90) {
quadrantNumber = 1;
}
// Quadrant 2
if (angle >= 90 && angle <= 180) {
quadrantNumber = 2;
}
// Quadrant 3
if (angle >= 180 && angle <= 270) {
quadrantNumber = 3;
}
// Quadrant 4
if (angle >= 270 && angle <= 360) {
quadrantNumber = 4;
}
if (quadrantNumber != previousQuadrantNumber) {
// Transition from 4th to 1st quadrant
if (quadrantNumber == 1 && previousQuadrantNumber == 4) {
numberOfTurns++;
}
// Transition from 1st to 4th quadrant
if (quadrantNumber == 4 && previousQuadrantNumber == 1) {
numberOfTurns--;
}
previousQuadrantNumber = quadrantNumber;
}
if (totalAngle >= 0) {
totalAngle = (numberOfTurns * 360) + angle;
}
else {
totalAngle = (numberOfTurns * 360) + angle;
}
// Establish Input value for PID
Input = totalAngle;
}
// Limited Rotation Mode
else if (digitalRead(modeSwitch) == 1) {
rangeAdjustment = analogRead(A1);
leftLimit = 0 + 30 + rangeAdjustment;
rightLimit = 4097 - 30 - rangeAdjustment;
if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
// Get value from potentiometer
inputValue = analogRead(A0);
if (inputValue < 15) {
inputValue = 15;
}
if (inputValue > 1008) {
inputValue = 1008;
}
Setpoint = map(inputValue, 15, 1008, -255, 255);
}
else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
inputValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
Setpoint = map(inputValue, 1000, 2000, -255, 255);
}
// Set center angle
if (digitalRead(centerSet) == LOW) {
centerAngle = encoderValue;
angleDifference = 2047 - encoderValue;
delay(1000);
}
// Adjust angle value according to the center point (angleDifference)
if (centerAngle < 2047) {
angleValue = encoderValue + angleDifference;
if (encoderValue < 4097 && encoderValue > (4096 - angleDifference)) {
angleValue = encoderValue - 4097 + angleDifference;
}
}
if (centerAngle > 2047) {
angleValue = encoderValue + angleDifference;
if (encoderValue >= 0 && encoderValue < abs(angleDifference)) {
angleValue = encoderValue + 4097 + angleDifference;
}
}
else if (centerAngle == 2047) {
angleValue = encoderValue;
}
// Establish Input value for PID
Input = map(angleValue , leftLimit, rightLimit, -255, 255);
}
// Adjusting sensitivity
Pk1 = analogRead(A2) * 0.002;
myPID.SetTunings(Pk1, Ik1, Dk1);
// Run PID process to get Output value
myPID.Compute();
// Move right
if (Output > 1 ) {
pwmValue = Output;
if (pwmValue < 30 && pwmValue > 5) {
pwmValue = pwmValue + 30;
}
if (pwmValue <= 5) {
pwmValue = 0;
}
digitalWrite(motor_IN1, LOW);
analogWrite(motor_IN2, pwmValue);
}
// Move left
else if (Output < 1 ) {
pwmValue = abs(Output);
if (pwmValue < 30 && pwmValue > 5) {
pwmValue = pwmValue + 30;
}
if (pwmValue <= 5) {
pwmValue = 0;
}
analogWrite(motor_IN1, pwmValue);
digitalWrite(motor_IN2, LOW);
}
// Do not move
else if (Output > -1 && Output < 1) {
pwmValue = 0;
digitalWrite(motor_IN1, LOW);
digitalWrite(motor_IN2, LOW);
}
//Serial.print(Setpoint);
//Serial.print("\t");
//Serial.println(totalAngle);
}Code language: PHP (php) Présentation du code
Ainsi, nous démarrons la boucle en lisant la valeur de l'encodeur ou la position actuelle de l'arbre.
// Read encoder value - current position
encoderValue = as5600.readAngle();Code language: JavaScript (javascript) Ensuite, si nous sommes en mode rotation continue, nous acceptons les valeurs du moniteur série et les utilisons comme point de consigne ou angle souhaité pour le contrôleur PID.
// Enter desired angle for the servo to go to through the serial monitor
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar)) {
// convert the incoming byte to a char and add it to the string:
inString += (char)inChar;
}
// if you get a newline, print the string, then the string's value:
if (inChar == '\n') {
Setpoint = inString.toInt(); // Setpoint - desired angle
// clear the string for new input:
inString = "";
}
}Code language: JavaScript (javascript) Si le mode d'entrée est réglé sur potentiomètre, nous lisons son entrée analogique et corrigeons la valeur de consigne en fonction de la hauteur dans laquelle nous la tournons.
if (digitalRead(inputSwitch) == 0) { // Potentiometer as input
inputValue = analogRead(A0);
if (inputValue < 400) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 300) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 200) {
Setpoint = Setpoint - 0.3;
}
if (inputValue > 600) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 700) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 800) {
Setpoint = Setpoint + 0.3;
}
}Code language: JavaScript (javascript) On fait la même correction de consigne si l'entrée est le récepteur RC.
Ici, nous convertissons les valeurs de l'encodeur RAW en valeurs d'angle, et avec ces instructions if, nous gardons une trace dans quel quadrant se trouve la position actuelle de l'arbre.
// Convert encoder RAW values into angle value
angle = encoderValue * 0.087890625;
// Quadrant 1
if (angle >= 0 && angle <= 90) {
quadrantNumber = 1;
}
// Quadrant 2
if (angle >= 90 && angle <= 180) {
quadrantNumber = 2;
}
// Quadrant 3
if (angle >= 180 && angle <= 270) {
quadrantNumber = 3;
}
// Quadrant 4
if (angle >= 270 && angle <= 360) {
quadrantNumber = 4;
}Code language: HTML, XML (xml) Grâce à ces informations, nous pouvons suivre la façon dont l’arbre tourne et quand il effectuera un tour complet. L'angle total est la valeur d'entrée du contrôleur PID.
if (quadrantNumber != previousQuadrantNumber) {
// Transition from 4th to 1st quadrant
if (quadrantNumber == 1 && previousQuadrantNumber == 4) {
numberOfTurns++;
}
// Transition from 1st to 4th quadrant
if (quadrantNumber == 4 && previousQuadrantNumber == 1) {
numberOfTurns--;
}
previousQuadrantNumber = quadrantNumber;
}
if (totalAngle >= 0) {
totalAngle = (numberOfTurns * 360) + angle;
}
else {
totalAngle = (numberOfTurns * 360) + angle;
}
// Establish Input value for PID
Input = totalAngle;Code language: JavaScript (javascript) D'un autre côté, si nous sommes en mode de rotation limitée, nous lisons d'abord la valeur du potentiomètre qui est utilisée pour ajuster la plage de rotation et ajustons les limites gauche et droite de rotation en conséquence.
rangeAdjustment = analogRead(A1);
leftLimit = 0 + 30 + rangeAdjustment;
rightLimit = 4097 - 30 - rangeAdjustment; Si le mode d'entrée est le potentiomètre, nous utilisons sa valeur comme valeur de consigne pour le contrôleur PID.
if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
// Get value from potentiometer
inputValue = analogRead(A0);
if (inputValue < 15) {
inputValue = 15;
}
if (inputValue > 1008) {
inputValue = 1008;
}
Setpoint = map(inputValue, 15, 1008, -255, 255);
}Code language: HTML, XML (xml) Si le mode d'entrée est le récepteur RC, nous lisons la valeur PWM entrante du récepteur et utilisons cette valeur comme point de consigne.
else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
inputValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
Setpoint = map(inputValue, 1000, 2000, -255, 255);
}Code language: JavaScript (javascript) Pour définir un point central différent, nous vérifions si nous avons appuyé sur le bouton-poussoir et capturons cette position comme nouveau point central.
// Set center angle
if (digitalRead(centerSet) == LOW) {
centerAngle = encoderValue;
angleDifference = 2047 - encoderValue;
delay(1000);
}Code language: JavaScript (javascript) En fonction de cela, nous devons alors ajuster les lectures réelles de l'encodeur et les compenser de la différence d'angle entre le nouveau et l'ancien point central. Nous utilisons cette valeur comme valeur d'entrée pour le contrôleur PID.
if (centerAngle > 2047) {
angleValue = encoderValue + angleDifference;
if (encoderValue >= 0 && encoderValue < abs(angleDifference)) {
angleValue = encoderValue + 4097 + angleDifference;
}
}
else if (centerAngle == 2047) {
angleValue = encoderValue;
}
// Establish Input value for PID
Input = map(angleValue , leftLimit, rightLimit, -255, 255);Code language: HTML, XML (xml) En utilisant l'entrée analogique de l'autre potentiomètre, nous ajustons le gain proportionnel du contrôleur PID, et enfin nous exécutons le processus PID pour obtenir une valeur de sortie.
// Adjusting sensitivity
Pk1 = analogRead(A2) * 0.002;
myPID.SetTunings(Pk1, Ik1, Dk1);
// Run PID process to get Output value
myPID.Compute();Code language: JavaScript (javascript) Nous utilisons cette valeur de sortie pour piloter les moteurs à courant continu avec un signal PWM, à gauche ou à droite, ou en position immobile en fonction de la valeur de sortie du contrôleur PID, ou en fonction de l'erreur entre la position souhaitée et la position réelle lue par l'encodeur.
// Move right
if (Output > 1 ) {
pwmValue = Output;
if (pwmValue < 30 && pwmValue > 5) {
pwmValue = pwmValue + 30;
}
if (pwmValue <= 5) {
pwmValue = 0;
}
digitalWrite(motor_IN1, LOW);
analogWrite(motor_IN2, pwmValue);
}Code language: HTML, XML (xml) Ce serait donc tout pour cette vidéo. Veuillez noter que le code n'est pas bien optimisé et qu'il peut être amélioré.
De plus, si vous essayez de recréer ce projet, vous devez être prêt à effectuer un dépannage. De nombreuses choses pourraient mal se passer, en particulier lors du soudage de ces petits composants CMS.
Je n'ai pas réussi à faire fonctionner ce servo dès le premier essai. Au départ, j'avais quelques mauvaises connexions sur le PCB, puis j'ai commandé à nouveau le PCB avec de nouvelles mises à jour, mais j'avais encore besoin de quelques essais supplémentaires jusqu'à ce qu'il fonctionne.
Cette section de l'article est encore en construction, veuillez la consulter un peu plus tard….
Processus de fabrication
- Mesurer la fréquence cardiaque et la SpO2 avec MAX30102
- Ce que vous devez savoir sur la pompe
- Comparaison des entraînements cycloïdaux usinés CNC et imprimés en 3D :conception, assemblage et tests de performances
- Moniteur de fréquence cardiaque MAX 30102 sur écran LCD 16x2
- Détecteur EMF Ultra Sensible DIY
- Capteur d'eau haute sensibilité sur MCP3008
- Robot assistant IA avec Arduino et Python
- Qu'est-ce qu'un réducteur de vitesse à angle droit ?
- Obstacles pour éviter le robot avec servomoteur