Bauen Sie einen Präzisions-Linearservoaktuator mit Positionsrückmeldung – Schritt-für-Schritt-Anleitung
In diesem Tutorial lernen wir, wie man einen linearen Servoaktuator herstellt. Im Gegensatz zu herkömmlichen Linearaktuatoren, die sich beim Anlegen einer Spannung in eine bestimmte Richtung bewegen, bietet dieser speziell angefertigte lineare Servoaktuator präzise und wiederholbare Bewegungen, die leicht gesteuert werden können.
Er wird als Servoaktuator bezeichnet, weil er über ein Rückkopplungsschleifensystem verfügt, mit dem wir die Ausgangsbewegung des Aktuators genau steuern können.
Sie können sich das folgende Video ansehen oder das untenstehende schriftliche Tutorial lesen.
Übersicht
Der Eingang zur Steuerung dieses linearen Servoaktuators kann entweder analog oder digital sein. Bei einem analogen Eingang kann es sich wie hier gezeigt um jede Art von Potentiometer handeln. Ein lineares Potentiometer, ein gewöhnliches Drehpotentiometer oder beispielsweise ein Joystick, der wiederum ein Drehpotentiometer ist und so weiter.
Im Falle eines digitalen Eingangs können wir den Aktuator mit einem RC-Sender steuern. Natürlich benötigen wir für dieses Setup auch einen RC-Empfänger, der als Eingang für den Aktuator dient.
Sowohl für diesen analogen als auch für den digitalen Eingabemodus benötigen wir nur drei Drähte, um eine Verbindung herzustellen, von denen zwei für die Stromversorgung des Eingabegeräts und das dritte für das Eingangssignal dienen.
Eine coole Funktion dieses speziell angefertigten linearen Servoaktuators besteht darin, dass wir eine benutzerdefinierte Start- und Endposition für die Ausgangsstange festlegen sowie die Empfindlichkeit oder die Geschwindigkeit anpassen können, mit der der Aktuator auf unsere Eingaben reagiert.
Mein Lieblingsmerkmal ist jedoch die Möglichkeit, diesen Aktuator von einem PC oder Laptop über eine serielle Schnittstelle zu steuern. Wir können Werte in Millimetern über den seriellen Arduino IDE-Monitor eingeben und der Aktuator bewegt sich in diese Position.
Was noch cooler ist:Wir können wiederholbare Bewegungen ausführen oder die Positionen speichern, indem wir an jeder gewünschten Position auf dem seriellen Monitor „Speichern“ eingeben und dann den Aktuator anweisen, die Bewegungen in einer Schleife zu wiederholen, indem wir auf dem seriellen Monitor „Ausführen“ eingeben.
Lassen Sie mich nun alles erklären, was Sie über diesen maßgeschneiderten linearen Servoaktuator wissen müssen, wie er funktioniert und wie ich ihn entworfen habe, damit Sie ihn auch selbst bauen können.
Wie es funktioniert
Das geschlossene Regelsystem basiert also auf dem magnetischen Drehpositionssensor AS5600 und der implementierten PID-Regelung zum Antrieb des Gleichstrommotors.
Tatsächlich verwende ich dieselbe benutzerdefinierte Servomotor-Controllerplatine, die ich in meinem vorherigen Video erstellt habe, die einen eigenen Mikrocontroller und alles andere enthält, um jeden Gleichstrommotor problemlos in einen eigenständigen Servomotor zu verwandeln.
In diesem Tutorial finden Sie eine detaillierte Erklärung der Funktionsweise eines Servomotors und eines Regelsystems mit geschlossenem Regelkreis.
Kurz gesagt, ein Servomotor ist ein geschlossenes Regelsystem, bei dem das Eingangssignal oder die gewünschte Position mit der tatsächlichen Position des Motors verglichen wird, die wir vom Positionsrückmeldesensor erhalten.
Die auftretende Differenz, die als Fehler bezeichnet wird, wird dann in der Steuerung verarbeitet, die dem Motor den Befehl gibt, sich zu bewegen, bis er die gewünschte Position erreicht.
Dieser lineare Servoaktuator hat also das gleiche Funktionsprinzip wie ein Servomotor, verfügt jedoch über einen zusätzlichen Schritt, bei dem die Drehbewegung des Motors mithilfe eines Leitspindelmechanismus in eine lineare Bewegung umgewandelt wird.
Design linearer Servoaktuatoren
Hier ist das 3D-Modell dieses linearen Servoantriebs, von dem aus wir sehen können, wie alles funktioniert.
Der magnetische Drehpositionssensor AS5600 befindet sich auf der Rückseite des Aktuators und verfolgt die Drehung der Leitspindel. Die von mir verwendete Leitspindel hat eine Steigung von 8 mm, was bedeutet, dass die Leitspindelmutter bei jeder vollen Umdrehung eine lineare Bewegung von 8 mm ausführt.
Der AS5600 ist ein 12-Bit-Encoder, was bedeutet, dass er 4096 Positionen pro Umdrehung ausgeben kann. Wenn wir 8 durch 4096 teilen, erhalten wir eine Auflösung von 0,001953 mm. Das ist die kleinste Positionsänderung, die der AS5600-Encoder erkennen kann. Das ist ziemlich beeindruckend, finde ich.
Der Gleichstrommotor, den ich verwende, ist ein 12-V-Motor mit integriertem Untersetzungsgetriebe, der 480 U/min abgibt. Wenn wir die 480 durch 60 teilen, erhalten wir einen Wert von 8 Umdrehungen pro Sekunde, und wenn wir diese Zahl mit 8 multiplizieren, erhalten wir eine lineare Geschwindigkeit des Aktuators von 64 mm/s, da die Leitspindel eine Steigung von 8 mm hat.
Ich habe festgestellt, dass dies genau richtig ist, da der maximale Weg dieser Betätigungsstange 150 mm beträgt, sodass es bei maximaler Geschwindigkeit von der Start- bis zur Endposition etwa 2,5 Sekunden dauern würde, oder etwa 3 Sekunden, wenn wir die Beschleunigung und Verzögerung mit einbeziehen. Daher habe ich für den Antrieb der Leitspindel ein Übersetzungsverhältnis von 1:1 verwendet.
Das Design des gesamten Linearantriebs basiert natürlich auf der Größe der speziell angefertigten Servomotor-Controller-Platine sowie der Leitspindel und Leitspindelmutter. Die Leiterplatte hatte eine Abmessung von 40x40mm, das war also die Mindestgröße des Zylinderblocks.
Die 8-mm-Leitspindelmutter hatte ein Außenmaß von 22 mm, daher habe ich die Stange entsprechend entworfen. Die Mutter und die Stange werden mit vier M3-Schrauben und Gewindeeinsätzen verbunden. An der Oberseite der Stange befindet sich ein Lager, das auf dem Zylinderblock gleitet und dazu dient, die Stange zu führen und zu verhindern, dass sie sich dreht.
Am Abtriebszylinderdeckel haben wir 4 kleine Lager, die die Stange aus dem Zylinderblock führen.
Insgesamt denke ich, dass der Linearantrieb unter Berücksichtigung aller verwendeten Komponenten kompakt genug ausgefallen ist.
Es ist mir auch gelungen, einen Mikro-Endschalter in den Zylinderblock einzubauen, der zur Referenzierung und Einstellung der Startposition des Aktuators dient.
3D-Modell-Download
Mit Onshape können Sie das 3D-Modell dieses maßgeschneiderten linearen Servoantriebs direkt in Ihrem Webbrowser anzeigen und erkunden. (Dafür benötigen Sie ein Onshape-Konto. Sie können ein kostenloses Konto für die Verwendung zu Hause erstellen.)
Sie können die für den 3D-Druck benötigten STL-Dateien sowie die STEP-Datei dieses 3D-Modells von Cults3D erhalten.
Darüber hinaus ist hier noch zu erwähnen, dass Sie die maximale Verfahrlänge dieses Linearantriebs ganz einfach erhöhen können, indem Sie einfach die Länge des Zylinderblocks und der Stange vergrößern. Ich habe diese Maße gewählt, weil ich wollte, dass alle Teile auf einen 3D-Drucker mit einem kleineren Druckbett von 220x220mm passen. Der größte Teil ist hier die Stange, die 215 mm lang ist.
3D-Druck
Mein neuer Creality Ender-3 V3 SE hat beim Drucken in horizontaler Ausrichtung entlang der Y-Achse hervorragende Arbeit geleistet. Auch wenn wir ein wenig senden müssen, trägt das Drucken der Stange in dieser Ausrichtung zu einem reibungsloseren Betrieb und einer stärkeren Stange bei.
Beim 3D-Druck ist es wichtig, die horizontale Expansionsfunktion in Ihrer Slicing-Software zu verwenden, um die Expansion des Filaments auszugleichen und maßgenauere Teile zu erhalten.
Ich habe einen Wert von –0,1 mm verwendet, aber Sie sollten einige Testdrucke machen, um zu sehen, welcher Wert für Ihren 3D-Drucker geeignet ist.
Ich habe den Zylinderblock entlang der Z-Achse gedruckt, um zu vermeiden, dass viel Stützmaterial gedruckt wird. Auch bei diesem Druck hat der Creality Ender-3 V3 SE hervorragende Arbeit geleistet.
Ich war angenehm überrascht von der Druckqualität, die dieser 3D-Drucker angesichts seines Preises bietet. Die Einrichtung des 3D-Druckers ist super einfach, er verfügt über eine automatische Bettnivellierung, einen Direktextruder, eine hervorragende Druckqualität und erhöhte Druckgeschwindigkeiten von bis zu 250 mm/s. All dies für knapp 200 US-Dollar macht ihn zu einem der besten 3D-Drucker für diejenigen, die über ein begrenztes Budget verfügen.
Schauen Sie sich diesen 3D-Drucker im Creality Store an oder Amazon . Schauen Sie sich auch meine ausführliche Rezension dazu auf meiner Website an.
Zusammenbau
Wie auch immer, hier sind alle 3D-gedruckten Teile, sodass wir jetzt mit dem Zusammenbau des Linearantriebs beginnen können.
Teileliste
Sie können die für dieses Linear-Servo-Aktuator-Projekt benötigten Komponenten über die folgenden Links erhalten:
Mechanisch:
- Leitspindel 8mm Tr8x8 ………………………………………….. Amazon / AliExpress
- Kugellager 8x22x7mm ………………………………………. Amazon / AliExpress
- Kugellager 4x9x4mm x 4 …………………………………….. Amazon / AliExpress
- Kugellager 6x13x5mm 686-2RS x1 ……………..….. Amazon / AliExpress
- M3x5mm und M4x5mm Gewindeeinsätze ……….. Amazon / AliExpress
- M3- und M4-Schrauben und Muttern ……………….…………….…. Amazon / AliExpress
Schrauben:M3x8 – 10 Stück; M3x10 – 2 Stück; M3x10 Senker – 1 Stück; M4x6 – 2 Stück; M4x25 – 2 Stück; M4x30 – 2 Stück; M2x8 – 6 Stück; M4x5 Madenschraube – 5 Stück
Elektronik:
- Magnetischer Encoder AS5600 ………………….. Amazon / AliExpress
- DRV8871 DC-Motortreiber ……………….…. Amazon / AliExpress
- Atmega328p-AU …………………………………. Amazon / AliExpress
- 16 MHz Quarzoszillator …………………….. Amazon / AliExpress
- AMS1117 5V Spannungsregler ………..…. Amazon / AliExpress
- 3386P quadratisches Potentiometer ………………. Amazon / AliExpress
- Kondensatoren 0805-Kit …………………………….…. Amazon / AliExpress
- 12-V-Gleichstrommotor – ~ 50 U/min …………….……. Amazon / AliExpress
Offenlegung:Dies sind Affiliate-Links. Als Amazon-Partner verdiene ich an qualifizierten Käufen.
Zusammenbau des Leitspindelmechanismus
Zuerst müssen wir die Leitspindel im Zylindergrundblock installieren. Zu diesem Zweck müssen wir zunächst diese 3D-gedruckte Mutter einsetzen, die das gleiche Gewinde wie die Leitspindel hat.
Es ist etwas schwierig, die Mutter auf die Leitspindel zu schrauben, da sie fest sitzt, aber genau das brauchen wir hier. Diese Mutter hält die gesamte Kraft auf, wenn die Stange drückt. Je fester sie also sitzt, desto mehr Kraft kann gehalten werden. Darüber hinaus verfügt die Mutter über ein Loch zum Einsetzen eines Gewindeeinsatzes zur Befestigung an der Welle mit einer Madenschraube.
Die Leitspindel wird mit Hilfe von zwei Kugellagern mit 22 mm Außendurchmesser im Zylindergrundblock gehalten.
Auf der Rückseite befindet sich das Zahnrad, das die Leitspindel antreibt. Auch dieses Zahnrad verfügt über ein passendes Gewinde und zwei Löcher für Gewindeeinsätze zur Befestigung an der Leitspindel mit Madenschrauben.
Auch diese Verbindung ist von entscheidender Bedeutung, da sie das gesamte Drehmoment des Motors auf die Leitspindel überträgt und daher nicht durchrutschen darf.
Um diese Unterbaugruppe herzustellen, müssen wir zunächst die Gewindeeinsätze am Zahnrad und an der Mutter sowie einige am Zylinderblock anbringen.
Wir schrauben das Zahnrad und die Mutter in die entgegengesetzte Richtung, aber nicht zu fest, da dies die Axialkräfte auf die Lager erhöht. Mithilfe einiger Madenschrauben können wir dann die Mutter und das Zahnrad an der Leitspindel befestigen.
Nach der Sicherung können wir feststellen, dass die Leitspindel noch nicht fixiert ist. Wir müssen diese Platte am Zylinderblock anbringen, um sicherzustellen, dass die Lager im Zylinderblock an ihrem Platz bleiben.
Damit ist diese Unterbaugruppe abgeschlossen; Die Leitspindel steht nun fest an ihrem Platz und kann sich frei drehen.
Als nächstes können wir die Rute vorbereiten. Die Stange ist über die gesamte Länge hohl, um die Leitspindel aufzunehmen. Um die Leitspindelmutter und die Stange zu verbinden, müssen wir zunächst einige Gewindeeinsätze installieren.
An der Oberseite der Stange müssen wir das Führungslager mit 13 mm Außen- und 6 mm Innendurchmesser installieren.
Wir platzieren das Lager auf einer 3D-gedruckten 6-mm-Hohlwelle und befestigen es mit einer M3-Senkschraube mit 10 mm Länge an der Stange. Die Stange ist nun fertig und wir können sehen, wie sie in den Führungsschienen des Zylinders gleitet.
Als nächstes müssen wir den Zylinder am Zylindergrundblock befestigen. Bevor wir das jedoch tun, sollten wir den Mikro-Endschalter installieren.
Zuerst müssen wir die Drähte am NC-Anschluss daran anlöten. Die Drähte sollten etwa 15 cm lang sein. Die Kabel werden durch ein Loch an der Oberseite des Zylinders geführt, und dann können wir den Mikro-Endschalter mit Hilfe von zwei M2-Schrauben mit 8 mm Länge am Zylinder befestigen.
Sie benötigen speziell diesen Mikro-Endschalter, damit das Führungslager genau zum richtigen Zeitpunkt auslöst, ohne auf etwas anderes zu stoßen.
Wenn Sie nicht das genaue Endschaltermodell finden, können Sie natürlich die Löcher und den Mechanismus ändern.
Um den Zylinder am Grundblock zu befestigen, müssen wir hier einige Gewindeeinsätze installieren. Dann können wir es mit zwei M4-Schrauben mit 25 mm Länge befestigen. Zu diesem Zeitpunkt sollten wir nur die oberen beiden Schrauben einsetzen.
Die unteren beiden werden bei der Montage der Getriebe- und Leiterplattenabdeckung etwas später entfernt, da dieselben Löcher zur Befestigung der Abdeckung verwendet werden.
Als nächstes können wir die Stange in die Leitspindel einschrauben. Das Führungslager sollte zwischen den Führungsschienen am Zylinder liegen.
Durch Drehen des Zahnrads auf der Rückseite bewegt sich die Stange rückwärts, bis sie den Mikro-Endschalter erreicht.
Dann können wir den Zylinderdeckel anbringen. Der Zylinderdeckel bietet Platz für vier kleine Lager mit 9 mm Außendurchmesser. Die Wellen für diese Lager können 3D-gedruckt werden.
Wir sollten beim Einsetzen vorsichtig sein, da der Teil, in den diese Schäfte eingeführt werden, recht klein ist und leicht brechen kann. Das ist mir schon ein paar Mal passiert, also stellen Sie sicher, dass sie leicht zu passen sind. Diese Lager stützen und führen die Stange für einen reibungsloseren Betrieb.
Der Zylinderdeckel wird mit vier M4-Schrauben befestigt.
Installieren des Gleichstrommotors
Ok, als nächstes können wir den Gleichstrommotor einsetzen. Wir befestigen den Gleichstrommotor mit sechs M3-Schrauben. Dann können wir das Getriebe auf die Motorwelle montieren.
Zur Befestigung des Getriebes verwenden wir zwei Gewindeeinsätze und Madenschrauben.
Sobald die Zahnräder richtig gepaart sind, können wir mit dem Anbringen der Zahnräder und der Leiterplattenabdeckung an der Rückseite des Linearantriebs fortfahren. Dazu müssen wir zunächst noch ein paar Gewindeeinsätze in den Zylindergrundblock einbauen.
Dann können wir die Drähte an den Gleichstrommotor anschließen. In meinem Fall habe ich sie direkt an den Gleichstrommotor angelötet.
Die Länge der Drähte sollte etwa 20 cm betragen. Im Zylindergrundblock befindet sich ein Loch, durch das wir die Kabel des Gleichstrommotors und des Endschalters führen sollten.
Dann sollten wir sie auch durch zwei Halterungen an der Abdeckung führen, die dafür sorgen, dass sie von der Ausrüstung fern bleiben.
An diesem Punkt können wir die Abdeckung am Basisblock befestigen. Zu diesem Zweck müssen wir zunächst die beiden M4-Schrauben an der Unterseite einführen, jedoch nicht ganz hinein.
Wir sollten etwa 2 mm oder 3 mm übrig lassen, damit wir den Abdeckungshalter dazwischen platzieren und diese Schrauben dann zusammen mit der Abdeckung befestigen können.
Dieser ganze Vorgang ist etwas chaotisch, aber es musste so sein, weil ich wollte, dass die Abdeckung so klein wie möglich und ein einziger Druck ist und die Leiterplattenhalter den Schrauben den Weg versperrten.
Installieren der benutzerdefinierten Servo-Controller-Platine
Wie auch immer, sobald wir mit der Abdeckung fertig sind, können wir die maßgeschneiderte Servomotor-Controllerplatine an Ort und Stelle installieren. Wie gesagt, es ist derselbe Controller aus meinem vorherigen Video, in dem ich Ihnen gezeigt habe, wie Sie jeden Gleichstrommotor in einen Servomotor verwandeln können.
Die Hauptkomponente ist der magnetische Drehwinkelgeber AS5600, der die Winkelposition des an der Abtriebswelle angebrachten Magneten erfasst. In diesem Fall befestigen wir den Magneten am Abtriebsrad der Leitspindel. Der Magnet wird beim Einsetzen der Platine perfekt auf den AS5600-Sensor ausgerichtet.
Um die Platine zu befestigen, müssen wir zunächst M2-Muttern in die Schlitze der Halter einsetzen und dann die Platine mit vier M2-Schrauben festziehen.
Jetzt müssen nur noch die Kabel angeschlossen werden. Die Drähte des Gleichstrommotors gehen zum Motorklemmenblock und die Polarität sollte zusätzlich überprüft werden, damit sie mit dem Steuerungsprogramm übereinstimmt.
Tatsächlich können wir, bevor wir den Motor an die Platine anschließen, etwas Spannung an ihn anlegen, um zu prüfen, ob der Leitspindelmechanismus ordnungsgemäß funktioniert.
Was die Endschalterkabel betrifft, habe ich, da ich für diesen Zweck keine speziellen Pins habe, das Erdungskabel an die Erdungsfläche des Elektrolytkondensators gelötet und das NC-Verbindungskabel an den SCK-Pin, der digitale Pin Nummer 13 am ATMEGA328-Mikrocontroller.
Der Klemmenblock für die Stromversorgung befindet sich direkt neben der Seite der Abdeckung, daher gibt es ein Loch, durch das ich einen 5,5-mm-Stromanschluss angeschlossen habe.
Ich habe dem Gleichstrommotortreiber auch einen Kühlkörper hinzugefügt. Zum Schluss können wir den Schnappdeckel auf der Rückseite anbringen und fertig, wir sind mit diesem Projekt fertig.
Jetzt können wir jede Art von Potentiometer oder einen RC-Empfänger an die entsprechenden Eingangspins anschließen und damit die Position des Linearantriebs steuern.
Wie ich bereits erwähnt habe, habe ich in meinem vorherigen Video ausführlich erklärt, wie dieser Controller funktioniert, seinen Schaltplan und wie ich die Platine hergestellt habe.
Sie sollten sich also dieses Tutorial ansehen, wenn Sie dieses Controller-Board erstellen möchten.
Schaltplan
Ganz schnell, die Hauptkomponente ist der Magnetsensor AS5600, der die Position des Aktuatorausgangs verfolgt. Die Sensordaten gehen in das Gehirn dieser Servo-Controller-Karte, dem Atmega328-Mikrocontroller, der die Berechnungen durchführt und dem DC-Motortreiber DRV8871 mitteilt, wie er den DC-Motor antreiben soll.
Der DC-Motortreiber DRV8871 kann einen Spitzenstrom von bis zu 3,6 A verarbeiten. Zur Stromversorgung der Platine können wir 12 V verwenden, die dann mit einem ASM1117-Spannungsregler für den Atmega328 und die anderen 5-V-Komponenten auf 5 V gesenkt werden. Es gibt einen zweikanaligen DIP-Schalter, über den wir den Eingangsmodus des Aktors auswählen, entweder analog oder digital, oder über die Kommunikation über die serielle Schnittstelle.
Eines der Trimmpotentiometer dient zur Einstellung der Empfindlichkeit des Stellantriebs und der SDM-Druckknopf dient zur Einstellung der Start- und Endpositionen.
Ich habe die Platine bei PCBWay bestellt. Hier können wir einfach die Gerber-Datei hochladen, die Eigenschaften unserer Leiterplatte auswählen und sie zu einem günstigen Preis bestellen.
Ich habe die Platine so konzipiert, dass sie 4 Schichten hat, die mittleren sind für GND, was den Preis etwas erhöht. Ich habe keine der Standardeigenschaften geändert, außer der PCB-Farbe, die ich als Weiß ausgewählt habe, und ich kreuze an, dass ich die Änderung der Oberflächenbeschaffenheit zu Immersionsgold, falls zutreffend, ohne Aufpreis akzeptiere.
Sie können den Gerber in der PCBWay-Projektfreigabe-Community finden und herunterladen, über die Sie die Leiterplatte auch direkt bestellen können.
Natürlich können Sie dieses Linearantriebsprojekt auch ohne diesen speziell angefertigten Servocontroller realisieren.
Sie können den AS5600-Sensor auf einem Breakout-Board in Kombination mit einem Arduino-Board zur Steuerung des Gleichstrommotors verwenden.
Code
Werfen wir nun einen Blick auf den Code dieses linearen Servoaktuators:
/*
Linear Servo Actuator - 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 = 0.65; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.1;
//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 setButton 7
#define inputSwitch 3
#define modeSwitch 4
#define limitSwitch 13
int ch1Value;
long encoderValue, desiredValue, pwmValue;
String serialInput = ""; // string to hold input
int serialIntInput;
double totalDistance = 0;
long startPosition = 358;
long endPosition = 6750;
long rangeAdjustment = 0;
float sensitivityAdjustment = 0;
float angle = 0;
float angleValue = 0;
float rodPosition;
float positionsArray[100];
int positionsCounter = 0;
long quadrantNumber = 2;
long previousQuadrantNumber = 3;
long numberOfTurns = 0;
float totalAngle = 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(setButton, INPUT_PULLUP);
pinMode(inputSwitch, INPUT_PULLUP);
pinMode(modeSwitch, INPUT_PULLUP);
pinMode(limitSwitch, INPUT_PULLUP);
// PID Setup
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(-255, 255);
myPID.SetSampleTime(20);
// --- HOMING ----
// Move backward until you ...
while (digitalRead(limitSwitch) != 1) {
digitalWrite(motor_IN1, LOW);
analogWrite(motor_IN2, 70);
encoderValue = as5600.readAngle();
}
while (digitalRead(limitSwitch) != 0) {
analogWrite(motor_IN1, 50);
digitalWrite(motor_IN2, LOW);
}
digitalWrite(motor_IN1, LOW);
digitalWrite(motor_IN2, LOW);
startPosition = as5600.readAngle() * 0.087890625;
endPosition = 6000;
Setpoint = startPosition;
// --- HOMING End ---
}
void loop() {
// Read encoder value - current position
rodPosition = as5600.readAngle() / 0.001953125; // in millimters - The lead screw is 8mm per rotation, and the encoder RAW value is 4096 per roration, so 8/4096 to get the value in milimiters
// Serial communication mode - Read data from the serial monitor
if (digitalRead(modeSwitch) == 0) {
while (Serial.available() > 0) {
serialInput = Serial.readString();
serialInput.trim();
// If "save" string is sent through the serial monitor, save the current rodPosition into the array
if (serialInput == "save") {
positionsArray[positionsCounter] = totalDistance;
delay(1000);
positionsCounter++;
}
// Clear the saved positions
if (serialInput == "clear") {
// Clear the array data to 0
memset(positionsArray, 0, sizeof(positionsArray));
positionsCounter = 0;
}
// Convert the String to Integer and use it as a Setpoint for the PID control
serialIntInput = serialInput.toInt();
if (serialIntInput != 0) {
if (serialIntInput < 0) {
serialIntInput = 0;
}
if (serialIntInput > 150) {
serialIntInput = 150;
}
Setpoint = serialIntInput * 45; // convert mm into degrees (1mm linear movement equals 45 degrees rotational movement)
}
}
// Run stored positions
if (serialInput == "run") {
while (serialInput != "stop") {
for (int i = 0; i <= positionsCounter - 1; i++) {
if (serialInput == "stop") {
break;
}
while (positionsArray[i] > totalDistance + 25 || positionsArray[i] < totalDistance - 25 || pwmValue != 0) {
// Desired position / setpoint for the PID contorller
Setpoint = positionsArray[i];
// Read encoder - use that value as an Input for the PID control
readEncoder();
// Run motor - PID controller inside
runMotor();
}
delay(2000); // Delay between steps
// Check the serial monitor for a stop command
while (Serial.available() > 0) {
serialInput = Serial.readString();
serialInput.trim();
}
}
}
}
}
// Potentiometer and RC Receiver control mode
else if (digitalRead(modeSwitch) == 1) {
if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
// Get value from potentiometer
desiredValue = analogRead(A0);
if (desiredValue < 15) {
desiredValue = 15;
}
if (desiredValue > 1008) {
desiredValue = 1008;
}
Setpoint = map(desiredValue, 15, 1008, startPosition, endPosition);
} else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
desiredValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
if (desiredValue < 1000 || desiredValue > 2000) {
desiredValue = 1000;
}
Setpoint = map(desiredValue, 1000, 2000, startPosition, endPosition);
}
}
// Confine the minimum and maximum values of the setpoint
if (Setpoint > endPosition) {
Setpoint = endPosition;
}
if (Setpoint < startPosition) {
Setpoint = startPosition;
}
// Adjusting sensitivity
//Pk1 = analogRead(A2) * 0.002; // Adjust the PID gain term
//myPID.SetTunings(Pk1, Ik1, Dk1);
// Read encoder - use that value as an input for the PID control
readEncoder();
// Run motor
runMotor();
// Set start and end positions by pressing the "set" button
if (digitalRead(setButton) == LOW) {
delay(3000);
if (digitalRead(setButton) == LOW) {
endPosition = totalDistance;
while (digitalRead(setButton) != HIGH)
;
} else {
startPosition = totalDistance;
}
}
}
void readEncoder() {
// Convert encoder RAW values into angle values for keeping track of the angular position of the shaft
encoderValue = as5600.readAngle() * 0.087890625;
// Quadrant 1
if (encoderValue >= 0 && encoderValue <= 90) {
quadrantNumber = 1;
}
// Quadrant 2
if (encoderValue >= 90 && encoderValue <= 180) {
quadrantNumber = 2;
}
// Quadrant 3
if (encoderValue >= 180 && encoderValue <= 270) {
quadrantNumber = 3;
}
// Quadrant 4
if (encoderValue >= 270 && encoderValue <= 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 (totalDistance >= 0) {
totalDistance = (numberOfTurns * 360) + encoderValue;
} else {
totalDistance = (numberOfTurns * 360) + encoderValue;
}
// Establish Input value for PID
Input = totalDistance; // current value of the position
}
void runMotor() {
// Run PID process to get Output value
myPID.Compute();
// Move right
if (Output > 1) {
pwmValue = Output;
if (pwmValue < 50 && pwmValue > 15) {
pwmValue = pwmValue + 40;
}
if (pwmValue <= 15) {
pwmValue = 0;
}
analogWrite(motor_IN1, pwmValue);
digitalWrite(motor_IN2, LOW);
}
// Move left
else if (Output < 1) {
pwmValue = abs(Output);
if (pwmValue < 50 && pwmValue > 15) {
pwmValue = pwmValue + 40;
}
if (pwmValue <= 15) {
pwmValue = 0;
}
digitalWrite(motor_IN1, LOW);
analogWrite(motor_IN2, pwmValue);
}
// Do not move
else if (Output > -1 && Output < 1) {
pwmValue = 0;
digitalWrite(motor_IN1, LOW);
digitalWrite(motor_IN2, LOW);
}
}
Code language: PHP (php) Codebeschreibung
Also beginnen wir die Schleife, indem wir den Encoderwert oder die aktuelle Position des Aktuators lesen und ihn in Millimeter umrechnen.
// Read encoder value - current position
rodPosition = as5600.readAngle() / 0.001953125; // in millimters - The lead screw is 8mm per rotation, and the encoder RAW value is 4096 per roration, so 8/4096 to get the value in milimiters
Code language: PHP (php) Wenn wir uns dann im „Seriellen Kommunikationsmodus“ befinden, lesen wir die eingehenden Daten, die wir auf dem seriellen Monitor eingeben. Wenn die Eingabe „Speichern“ ist, speichern wir die aktuelle Position des Aktuators, oder wenn sie „löschen“ ist, löschen wir alle bereits gespeicherten Positionen.
// Serial communication mode - Read data from the serial monitor
if (digitalRead(modeSwitch) == 0) {
while (Serial.available() > 0) {
serialInput = Serial.readString();
serialInput.trim();
// If "save" string is sent through the serial monitor, save the current rodPosition into the array
if (serialInput == "save") {
positionsArray[positionsCounter] = totalDistance;
delay(1000);
positionsCounter++;
}
// Clear the saved positions
if (serialInput == "clear") {
// Clear the array data to 0
memset(positionsArray, 0, sizeof(positionsArray));
positionsCounter = 0;
}Code language: JavaScript (javascript) Wenn die Eingabe eine Ganzzahl oder eine Zahl von 0 bis 150 ist, verwenden wir diesen Wert als Sollwert.
// Convert the String to Integer and use it as a Setpoint for the PID control
serialIntInput = serialInput.toInt();
if (serialIntInput != 0) {
if (serialIntInput < 0) {
serialIntInput = 0;
}
if (serialIntInput > 150) {
serialIntInput = 150;
}
Setpoint = serialIntInput * 45; // convert mm into degrees (1mm linear movement equals 45 degrees rotational movement)
}
}Code language: JavaScript (javascript) Wir geben die Werte in Millimetern ein, aber um den Überblick über die rotierende Welle zu behalten, verwenden wir Grad. Deshalb wandeln wir die Millimeterwerte durch Multiplikation mit 45 in Gradwerte um. Das liegt daran, dass sich die Leitspindel bei einer linearen Bewegung von 1 mm um 45 Grad drehen sollte. Falls Ihre Leitspindel eine andere Steigung hat, sollte diese Zahl unterschiedlich sein.
Wenn wir mit Hilfe einiger while- und for-Schleifen „run“ eingeben, durchläuft das Programm die gespeicherten Positionen wiederholt.
// Run stored positions
if (serialInput == "run") {
while (serialInput != "stop") {
for (int i = 0; i <= positionsCounter - 1; i++) {
if (serialInput == "stop") {
break;
}
while (positionsArray[i] > totalDistance + 25 || positionsArray[i] < totalDistance - 25 || pwmValue != 0) {
// Desired position / setpoint for the PID contorller
Setpoint = positionsArray[i];
// Read encoder - use that value as an Input for the PID control
readEncoder();
// Run motor - PID controller inside
runMotor();
}
delay(2000); // Delay between steps
// Check the serial monitor for a stop command
while (Serial.available() > 0) {
serialInput = Serial.readString();
serialInput.trim();
}
}
}
}Code language: JavaScript (javascript) Wenn wir uns hingegen im Steuerungsmodus für Potentiometer und RC-Empfänger befinden, prüfen wir, ob wir einen analogen oder digitalen Eingang haben.
// Potentiometer and RC Receiver control mode
else if (digitalRead(modeSwitch) == 1) {
if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
// Get value from potentiometer
desiredValue = analogRead(A0);
if (desiredValue < 15) {
desiredValue = 15;
}
if (desiredValue > 1008) {
desiredValue = 1008;
}
Setpoint = map(desiredValue, 15, 1008, startPosition, endPosition);
} else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
desiredValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
if (desiredValue < 1000 || desiredValue > 2000) {
desiredValue = 1000;
}
Setpoint = map(desiredValue, 1000, 2000, startPosition, endPosition);
}
}Code language: JavaScript (javascript) Bei analogen Werten lesen wir den analogen Eingang vom Potentiometer ab und verwenden diesen Wert als Sollwert oder gewünschte Position, die der Aktuator erreichen soll. Wenn der Eingang digital ist, lesen wir in ähnlicher Weise die eingehenden Daten vom RC-Empfänger und verwenden diesen Wert als Sollwert.
Anschließend rufen wir die benutzerdefinierten Funktionen readEncoder() und runMotor() auf, um die aktuelle Position des Aktuators zu lesen und die PID-Regelung auszuführen. Mit der Funktion readEncoder() lesen wir den aktuellen Wert des Sensors in Winkelwerten aus und verfolgen mit diesen if-Anweisungen, in welchem Quadranten sich die aktuelle Position der Welle befindet.
void readEncoder() {
// Convert encoder RAW values into angle values for keeping track of the angular position of the shaft
encoderValue = as5600.readAngle() * 0.087890625;
// Quadrant 1
if (encoderValue >= 0 && encoderValue <= 90) {
quadrantNumber = 1;
}
// Quadrant 2
if (encoderValue >= 90 && encoderValue <= 180) {
quadrantNumber = 2;
}
// Quadrant 3
if (encoderValue >= 180 && encoderValue <= 270) {
quadrantNumber = 3;
}
// Quadrant 4
if (encoderValue >= 270 && encoderValue <= 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 (totalDistance >= 0) {
totalDistance = (numberOfTurns * 360) + encoderValue;
} else {
totalDistance = (numberOfTurns * 360) + encoderValue;
}
// Establish Input value for PID
Input = totalDistance; // current value of the position
}Code language: HTML, XML (xml) Mit diesen Informationen können wir verfolgen, wie sich die Welle dreht und wann sie eine volle Umdrehung macht. Der Gesamtwinkel ist der Eingangswert für den PID-Regler.
Mithilfe des Analogeingangs vom Trimmpotentiometer können wir die Proportionalverstärkung des PID-Reglers anpassen und schließlich den PID-Prozess ausführen, um einen Ausgangswert zu erhalten.
// Adjusting sensitivity
//Pk1 = analogRead(A2) * 0.002; // Adjust the PID gain term
//myPID.SetTunings(Pk1, Ik1, Dk1);Code language: JSON / JSON with Comments (json) void runMotor() {
// Run PID process to get Output value
myPID.Compute();
// Move right
if (Output > 1) {
pwmValue = Output;
if (pwmValue < 50 && pwmValue > 15) {
pwmValue = pwmValue + 40;
}
if (pwmValue <= 15) {
pwmValue = 0;
}
analogWrite(motor_IN1, pwmValue);
digitalWrite(motor_IN2, LOW);
}
// Move left
else if (Output < 1) {
pwmValue = abs(Output);
if (pwmValue < 50 && pwmValue > 15) {
pwmValue = pwmValue + 40;
}
if (pwmValue <= 15) {
pwmValue = 0;
}
digitalWrite(motor_IN1, LOW);
analogWrite(motor_IN2, pwmValue);
}
// Do not move
else if (Output > -1 && Output < 1) {
pwmValue = 0;
digitalWrite(motor_IN1, LOW);
digitalWrite(motor_IN2, LOW);
}
}Code language: JavaScript (javascript) Wir verwenden diesen Ausgangswert zum Antreiben der Gleichstrommotoren mit einem PWM-Signal, links oder rechts, oder in Stillstandsposition, abhängig vom Ausgangswert des PID-Reglers oder abhängig vom Fehler zwischen der gewünschten und der tatsächlichen Position, die der Encoder liest.
Die drei Terme des PID-Reglers, Proportional, Integral und Ableitung, werden oben definiert, und durch deren Anpassung können wir verschiedene Ausgangsreaktionen erhalten.
double Pk1 = 0.65; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.1;Code language: JavaScript (javascript) Die Qualität, wie gut der Aktor funktioniert oder auf unsere Eingaben reagiert, hängt direkt von diesen Werten ab.
Testen
Hier teste ich die Genauigkeit des Aktuators. Es passt sich ordentlich wieder an seinen Platz an. Dann begann er, die Stange um jeweils einen Millimeter zu bewegen. Die erste Bewegung betrug etwa 0,8 mm statt 1 mm, aber die nächsten 4 lagen nahe genug bei 1 mm. Dann war die 4-mm-Bewegung etwa 0,15 mm entfernt.
Wir sollten beachten, dass die Stange ein Spiel von etwa 0,25 mm hat. Dieses Spiel besteht zwischen der Leitspindel und der Leitspindelmutter. Darüber hinaus haben wir wahrscheinlich etwas Spiel in den 3D-gedruckten Zahnrädern sowie den Zahnrädern des Gleichstrommotors selbst.
Wenn wir jetzt eine Kraft auf die Stange ausüben und die Genauigkeit testen, erhalten wir natürlich noch größere Fehler, aber dies kann durch eine Optimierung des PID-Reglers verbessert werden.
Dennoch wäre das alles für dieses Tutorial. Ich hoffe, es hat Ihnen gefallen und Sie haben etwas Neues gelernt.
Herstellungsprozess
- Roll Pin Punches:Verwendung und Anwendungen
- Intelligenter Energiemonitor basierend auf Arduino
- Tricks zur Steuerung von Gleichstrommotoren
- Vakuum-Fluoreszenz-Display-Controller
- Technologien zur Kohlenstoffabscheidung und -speicherung
- PiCy – Der kleine Roboter mit Raspberry Pi-Antrieb!
- Metall-Inertgas-Schweißen (MIG) verstehen
- CNC Drahterodieren:Ihr bester Freund in der Werkstatt
- Dimmen von Lichtern mit PWM über Drucktasten
- Baumwolle