Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Bouw een nauwkeurige lineaire servoactuator met positiefeedback – stapsgewijze handleiding

In deze tutorial leren we hoe we een lineaire servo-actuator kunnen maken. In tegenstelling tot reguliere lineaire actuatoren die in een bepaalde richting bewegen wanneer er spanning op wordt gezet, biedt deze op maat gemaakte lineaire servoactuator nauwkeurige en herhaalbare bewegingen die gemakkelijk kunnen worden gecontroleerd.

Het wordt een servoactuator genoemd omdat het een feedbacklussysteem heeft waarmee we de uitgangsbeweging van de actuator nauwkeurig kunnen regelen.

Je kunt de volgende video bekijken of de schriftelijke tutorial hieronder lezen.

Overzicht

De ingang voor het aansturen van deze lineaire servoactuator kan analoog of digitaal zijn. In het geval van een analoge ingang kan dit elk type potentiometer zijn, zoals hier weergegeven. Een lineaire potentiometer, een gewone draaipotentiometer of bijvoorbeeld een joystick die weer een draaipotentiometer is enzovoort.

In het geval van digitale ingang kunnen we de actuator aansturen met een RC-zender. Uiteraard hebben we voor deze opstelling ook een RC-ontvanger nodig die als ingang naar de actuator gaat.

Voor zowel deze analoge als digitale invoermodi hebben we slechts 3 draden nodig om een verbinding te maken, waarvan er 2 voor de voeding van het invoerapparaat zijn en de derde voor het invoersignaal.

Een coole functie van deze op maat gemaakte lineaire servo-actuator is dat we een aangepaste start- en eindpositie voor de uitgangsstang kunnen instellen en de gevoeligheid kunnen aanpassen of hoe snel de actuator op onze input zal reageren. 

Mijn favoriete functie is echter de mogelijkheid om deze actuator vanaf een pc of laptop te bedienen via een seriële poortcommunicatie. We kunnen waarden in millimeters invoeren via de Arduino IDE Serial-monitor en de actuator zal naar die positie bewegen.

Wat nog cooler is, is dat we herhaalbare bewegingen kunnen maken of de posities kunnen opslaan door op elke gewenste positie 'save' op de seriële monitor te typen, en vervolgens de actuator te vertellen de bewegingen in een lus te herhalen door 'run' op de seriële monitor te typen.

Laat me nu alles uitleggen wat je moet weten over deze op maat gemaakte lineaire servo-actuator, hoe deze werkt en hoe ik hem heb ontworpen, zodat je er ook zelf een kunt bouwen. 

Hoe het werkt

Het gesloten regelsysteem is dus gebaseerd op de AS5600 magnetische roterende positiesensor en de geïmplementeerde PID-regeling voor het aandrijven van de gelijkstroommotor.

Eigenlijk gebruik ik hetzelfde aangepaste servomotorcontrollerbord dat ik in mijn vorige video heb gemaakt, dat een eigen microcontroller en al het andere bevat om elke gelijkstroommotor eenvoudig in een zelfstandige servomotor te veranderen.

Je kunt die tutorial bekijken voor een gedetailleerde uitleg van hoe een servomotor en een gesloten lusbesturingssysteem werken.  

Heel snel is een servomotor een gesloten regelsysteem waarbij het ingangssignaal, of de gewenste positie, wordt vergeleken met de werkelijke positie van de motor die we krijgen van de positiefeedbacksensor.

Het verschil dat optreedt, dat de fout wordt genoemd, wordt vervolgens verwerkt in de controller die de motor opdracht geeft te bewegen totdat deze de gewenste positie bereikt. 

Deze lineaire servoactuator heeft dus hetzelfde werkingsprincipe als een servomotor, maar met een extra stap:het omzetten van de roterende beweging van de motor in een lineaire beweging met behulp van een spindelmechanisme.

Lineair servo-actuatorontwerp

Hier is het 3D-model van deze lineaire servo-actuator, van waaruit we kunnen zien hoe alles werkt.

De AS5600 magnetische roterende positiesensor bevindt zich aan de achterkant van de actuator en houdt de rotatie van de spindel bij. De spindel die ik gebruik heeft een spoed van 8 mm, wat betekent dat de spindelmoer bij elke volledige rotatie een lineaire beweging van 8 mm maakt.

De AS5600 is een 12-bit encoder, wat betekent dat hij 4096 posities per draai kan uitvoeren. Als we 8 delen door 4096, krijgen we een resolutie van 0,001953 mm. Dat is de kleinste positieverandering die de AS5600-encoder kan detecteren. Dat is behoorlijk indrukwekkend, denk ik. 

De DC-motor die ik gebruik is een 12V-motor met meegeleverde reductiekast die 480 RPM levert. Als we de 480 delen door 60, krijgen we een waarde van 8 omwentelingen per seconde, en als we dat getal met 8 vermenigvuldigen, omdat de spindel een spoed van 8 mm heeft, krijgen we een lineaire snelheid van 64 mm/s van de actuator.

Ik ontdekte dat dit ter plaatse was, omdat de maximale slag van deze actuatorstang 150 mm is, dus het zou ongeveer 2,5 seconden duren van de start- tot de eindpositie op maximale snelheid, of ongeveer 3 seconden als we de versnelling en vertraging meetellen. Daarom gebruikte ik een tandwieloverbrengingsverhouding van 1:1 voor het aandrijven van de spindel. 

Het ontwerp van de hele lineaire actuator is gebaseerd op de grootte van de op maat gemaakte servomotorcontroller-PCB en uiteraard de spindel en spindelmoer. De print had een afmeting van 40x40mm, dus dat was de minimale maat van het cilinderblok.

De 8 mm spindelmoer had een buitenmaat van 22 mm, dus dienovereenkomstig ontwierp ik de staaf. De moer en de stang zijn verbonden met vier M3-bouten en schroefdraadinserts. Aan de bovenkant van de stang bevindt zich een lager dat over het cilinderblok schuift en wordt gebruikt om de stang te geleiden en te voorkomen dat deze gaat draaien. 

Aan de uitgaande cilinderkap hebben we 4 kleine lagers die de stang uit het cilinderblok geleiden.

Over het geheel genomen denk ik dat de lineaire actuator compact genoeg is, gezien alle gebruikte componenten.

Ik ben er ook in geslaagd om een micro-eindschakelaar in het cilinderblok te plaatsen, die wordt gebruikt voor het naar huis sturen en het instellen van de startpositie van de actuator.

3D-model downloaden

U kunt het 3D-model van deze op maat gemaakte lineaire servo-actuator rechtstreeks in uw webbrowser bekijken en verkennen met Onshape. (daarvoor heb je een Onshape-account nodig, je kunt een gratis account aanmaken voor thuisgebruik)

De STL-bestanden die nodig zijn voor 3D-printen, evenals het STEP-bestand van dit 3D-model, kunt u verkrijgen bij Cults3D.

Wat we hier nog meer moeten vermelden, is dat u eenvoudig de maximale slaglengte van deze lineaire actuator kunt vergroten, door simpelweg de lengte van het cilinderblok en de stang te vergroten. Ik heb voor deze afmetingen gekozen omdat ik wilde dat alle onderdelen op een 3D-printer zouden passen met een kleiner printbed van 220x220 mm. Het grootste onderdeel hier is de hengel, die 215 mm lang is.

3D-printen

Mijn nieuwe Creality Ender-3 V3 SE heeft het uitstekend gedaan door hem horizontaal langs de Y-as af te drukken. Hoewel we een beetje moeten verzenden, zal het afdrukken van de hengel in deze richting bijdragen aan een soepelere werking en een sterkere hengel.

Bij 3D-printen is het belangrijk om de functie Horizontale expansie in uw slicingsoftware te gebruiken om de uitzetting van het filament te compenseren en dimensioneel nauwkeurigere onderdelen te verkrijgen.

Ik heb een waarde van –0,1 mm gebruikt, maar je moet een aantal testprints maken om te zien welke waarde bij jouw 3D-printer past. 

Ik heb het cilinderblok langs de Z-as geprint om te voorkomen dat er veel ondersteunend materiaal werd geprint. Ook voor deze print deed de Creality Ender-3 V3 SE uitstekend werk.

Ik was aangenaam verrast door de printkwaliteit die deze 3D-printer biedt, gezien de prijs. Het is super eenvoudig om de 3D-printer in te stellen, hij beschikt over automatische bednivellering, directe extruder, geweldige printkwaliteit en hogere printsnelheden tot 250 mm/s. Dit alles voor iets minder dan $ 200 maakt het een van de beste 3D-printers voor mensen met een beperkt budget.

Bekijk deze 3D-printer in de Creality store of Amazon . Bekijk ook mijn gedetailleerde recensie erover op mijn website.

Monteren

Hoe dan ook, hier zijn alle 3D-geprinte onderdelen, dus we kunnen nu beginnen met het assembleren van de lineaire actuator.

Onderdelenlijst

U kunt de componenten die nodig zijn voor dit lineaire servo-actuatorproject verkrijgen via de onderstaande links:

Mechanisch:

  • Lodenschroef 8 mm Tr8x8 …………………………………….. Amazon / AliExpress
  • Kogellager 8x22x7mm …………………………………. Amazone  / AliExpress
  • Kogellager 4x9x4mm x 4 …………………………………….. Amazon / AliExpress
  • Kogellager 6x13x5mm 686-2RS x1 ……………..….. Amazon  / AliExpress
  • M3x5mm en M4x5mm inzetstukken met schroefdraad ……….. Amazon  / AliExpress
  • M3 en M4 bouten en moeren ……………….…………….…. Amazone  / AliExpress
    Bouten:M3x8 – 10 stuks; M3x10 – 2 stuks; M3x10 verzinkboor – 1 stuks; M4x6 – 2 stuks; M4x25 – 2 stuks; M4x30 – 2 stuks; M2x8 – 6 stuks; M4x5 draadstift – 5 stuks

Elektronica:

  • AS5600 magnetische encoder ………………….. Amazon / AliExpress
  • DRV8871 DC-motordriver ……………….…. Amazon / AliExpress
  • Atmega328p-AU ……………………………. Amazon / AliExpress
  • 16 MHz kristaloscillator …………………….. Amazon / AliExpress
  • AMS1117 5V spanningsregelaar ………..…. Amazon / AliExpress
  • 3386P vierkante potentiometer ………………. Amazon / AliExpress
  • Condensatoren 0805-set …………………………….…. Amazon / AliExpress
  • 12V DC-motor – ~ 50 RPM …………….……. Amazone  / AliExpress

Openbaarmaking:dit zijn affiliatielinks. Als Amazon Associate verdien ik aan in aanmerking komende aankopen.

Monteren van het spindelmechanisme

Eerst moeten we de spindel op zijn plaats in het cilinderbasisblok installeren. Voor dat doel moeten we eerst deze 3D-geprinte moer plaatsen, die dezelfde schroefdraad heeft als de spindel.

Het is een beetje moeilijk om de moer op de spindel te draaien, omdat deze goed vastzit, maar dat is wat we hier nodig hebben. Deze moer houdt de volledige kracht vast wanneer de hengel duwt, dus hoe strakker de pasvorm, hoe meer kracht hij kan vasthouden. Daarnaast heeft de moer ook een gat waarin een inzetstuk met schroefdraad kan worden geplaatst, zodat deze met een stelschroef aan de as kan worden bevestigd.

De spindel wordt op zijn plaats gehouden in het cilinderbasisblok met behulp van twee kogellagers met een buitendiameter van 22 mm.

Aan de achterkant bevindt zich het tandwiel dat de spindel aandrijft. Dit tandwiel heeft ook een bijpassende schroefdraad en twee gaten voor inzetstukken met schroefdraad om het met stelschroeven aan de spindel te bevestigen.

Deze verbinding is ook van cruciaal belang omdat deze het volledige koppel van de motor overbrengt naar de spindel en dus niet mag wegglijden. 

Om dit subsamenstel te maken, moeten we eerst de inzetstukken met schroefdraad op hun plaats op het tandwiel en de moer installeren, evenals enkele op het cilinderblok.

We schroeven het tandwiel en de moer in de tegenovergestelde richting, maar niet te strak, omdat dit axiale krachten op de lagers toevoegt. Vervolgens kunnen we met behulp van enkele stelschroeven de moer en het tandwiel aan de spindel bevestigen.

Eenmaal vastgezet, kunnen we merken dat de spindel nog niet op zijn plaats zit. Deze plaat moeten we aan het cilinderblok toevoegen, zodat de lagers in het cilinderblok op hun plaats blijven.

Hiermee is deze subassemblage voltooid; de spindel staat nu stevig op zijn plaats terwijl hij vrij kan draaien. 

Vervolgens kunnen we de staaf voorbereiden. De staaf is over de gehele lengte hol om plaats te bieden aan de spindel. Om de spindelmoer en de stang met elkaar te verbinden, moeten we eerst enkele inzetstukken met schroefdraad installeren. 

Aan de bovenzijde van de stang moeten we het geleidelager installeren met een buitendiameter van 13 mm en een binnendiameter van 6 mm.

We plaatsen het lager op een 3D-geprinte holle as van 6 mm en bevestigen het aan de stang met een M3 verzonken schroef met een lengte van 10 mm. De stang is nu klaar en we kunnen zien hoe deze in de geleiderails van de cilinder zal glijden.

Vervolgens moeten we de cilinder aan het cilinderbasisblok bevestigen. Maar voordat we dat doen, moeten we de micro-eindschakelaar op zijn plaats installeren.

Eerst moeten we de draden erop solderen, bij de NC-aansluiting. De draden moeten ongeveer 15 cm lang zijn. De draden worden door een gat aan de bovenkant van de cilinder geleid en vervolgens kunnen we de micro-eindschakelaar aan de cilinder bevestigen met behulp van twee M2-bouten met een lengte van 8 mm.

Deze micro-eindschakelaar heeft u specifiek nodig om ervoor te zorgen dat het geleidelager deze precies op het juiste moment activeert, zonder iets anders te raken.

Als u het exacte model van de eindschakelaar niet kunt vinden, kunt u natuurlijk de gaten en het mechanisme aanpassen. 

Om de cilinder aan het basisblok te bevestigen, moeten we hier enkele inzetstukken met schroefdraad installeren. Vervolgens kunnen we hem op zijn plaats vastzetten met twee M4-bouten met een lengte van 25 mm. Op dit moment moeten we alleen de bovenste twee bouten plaatsen.

De onderste twee gaan iets later bij het installeren van de versnellingsbak en het printplaatdeksel, omdat dezelfde gaten worden gebruikt voor het vastzetten van het deksel. 

Vervolgens kunnen we de staaf in de spindel schroeven. Het geleidelager moet tussen de geleiderails op de cilinder passen.

Door het tandwiel aan de achterkant te draaien, beweegt de stang naar achteren, helemaal tot aan de micro-eindschakelaar. 

Vervolgens kunnen we de cilinderdop op zijn plaats bevestigen. De cilinderkap biedt plaats aan vier kleine lagers met een buitendiameter van 9 mm. De assen voor deze lagers kunnen 3D-geprint worden.

We moeten voorzichtig zijn bij het plaatsen ervan, omdat het gedeelte waar deze schachten naartoe gaan vrij klein is en gemakkelijk kan breken. Het is mij een paar keer overkomen, dus zorg ervoor dat ze gemakkelijk passen. Deze lagers ondersteunen en geleiden de stang voor een soepelere werking.

De cilinderkap wordt op zijn plaats vastgezet met vier M4-bouten.

De DC-motor installeren

Oké, dus nu kunnen we de DC-motor op zijn plaats plaatsen. We zetten de DC-motor vast met zes M3-bouten. Vervolgens kunnen we het tandwiel op de motoras installeren.

Om het tandwiel op zijn plaats te bevestigen, gebruiken we twee inzetstukken met schroefdraad en stelschroeven. 

Zodra de tandwielen goed zijn gekoppeld, kunnen we verder gaan met het bevestigen van de tandwielen en de PCB-afdekking aan de achterkant van de lineaire actuator. Voor dat doel moeten we eerst nog een paar schroefdraadinserts in het cilinderbasisblok installeren.

Vervolgens kunnen we de draden op de DC-motor aansluiten. In mijn geval heb ik ze rechtstreeks aan de gelijkstroommotor gesoldeerd.

De lengte van de draden moet ongeveer 20 cm zijn. Er zit een gat in het cilinderbasisblok waar we de draden van zowel de gelijkstroommotor als de eindschakelaar doorheen moeten voeren.

Dan moeten we ze ook door twee houders op de hoes halen, die ervoor zorgen dat ze uit de buurt van de uitrusting blijven. 

Op dit punt kunnen we de hoes aan het basisblok bevestigen. Hiervoor moeten we eerst de twee M4-bouten aan de onderkant inbrengen, maar niet helemaal erin.

We moeten ongeveer 2 mm of 3 mm vrijhouden, zodat we de dekselhouder ertussen kunnen plaatsen en vervolgens die bouten samen met de deksel kunnen vastzetten.

Deze hele operatie is een beetje rommelig, maar dat moest wel zo zijn, want ik wilde dat de omslag zo klein mogelijk was en een enkele print, en de PCB-houders blokkeerden de weg voor de bouten.

De aangepaste servocontroller-PCB installeren

Hoe dan ook, zodra we klaar zijn met de hoes, kunnen we de aangepaste servomotorcontrollerkaart op zijn plaats installeren. Zoals ik al zei, het is dezelfde controller uit mijn vorige video waarin ik je liet zien hoe je van elke DC-motor een servomotor kunt maken.

Het belangrijkste onderdeel hier is de magnetische roterende positie-encoder AS5600, die de hoekpositie van de magneet op de uitgaande as bijhoudt. In dit geval bevestigen we de magneet aan het uitgaande tandwiel op de spindel. De magneet wordt perfect uitgelijnd met de AS5600-sensor wanneer de printplaat op zijn plaats wordt geplaatst.

Om de printplaat vast te zetten, moeten we eerst M2-moeren in de sleuven van de houders plaatsen en vervolgens de printplaat vastdraaien met vier M2-bouten.

Wat we nu nog moeten doen, is de draden op hun plaats aansluiten. De DC-motordraden gaan naar het motorklemmenblok en de polariteit moet bovendien worden gecontroleerd, zodat deze overeenkomt met het controllerprogramma.

Voordat we de motor op de printplaat aansluiten, kunnen we er wat spanning op zetten om te controleren of het spindelmechanisme goed werkt.

Wat betreft de draden van de eindschakelaars:aangezien ik geen speciale pinnen voor dit doel heb, heb ik de aardedraad aan het aardingspad op de elektrolytische condensator gesoldeerd, en de NC-verbindingsdraad aan de SCK-pin, wat digitale pinnummer 13 is op de ATMEGA328-microcontroller.

Het klemmenblok voor de voeding bevindt zich direct naast de zijkant van het deksel, dus er is een gat waardoor ik een 5,5 mm stroomconnector heb aangesloten.

Ik heb ook een koellichaam toegevoegd aan de DC-motordriver. Eindelijk kunnen we het klikdeksel op de achterkant plaatsen en dat is alles, we zijn klaar met dit project. 

Nu kunnen we elk type potentiometer of een RC-ontvanger op de juiste ingangspinnen aansluiten, en kunnen we daarmee de positie van de lineaire actuator regelen.

Zoals ik al zei, heb ik in mijn vorige video gedetailleerd uitgelegd hoe deze controller werkt, het schakelschema en hoe ik de printplaat heb gemaakt.

Je moet dus die tutorial bekijken als je dit controllerbord wilt maken. 

Circuitschema

Het belangrijkste onderdeel is heel snel de AS5600 magnetische sensor, die de positie van de actuatoruitgang bijhoudt. De sensorgegevens gaan naar de hersenen van dit servocontrollerbord, de Atmega328-microcontroller, die de berekeningen uitvoert en de DC-motordriver van de DRV8871 vertelt hoe de DC-motor moet worden aangedreven.

De DRV8871 DC-motordriver kan een piekstroom van maximaal 3,6 A aan. Voor het voeden van het bord kunnen we 12V gebruiken, die vervolgens wordt verlaagd naar 5V met een ASM1117-spanningsregelaar voor de Atmega328 en de andere 5V-componenten. Er is een tweekanaals DIP-schakelaar waarmee we de ingangsmodus van de actuator kunnen selecteren, analoog of digitaal, of via de seriële poortcommunicatie.

Eén van de trimmerpotentiometers wordt gebruikt voor het aanpassen van de gevoeligheid van de actuator, en de SDM-drukknop wordt gebruikt voor het instellen van de start- en eindposities.

Ik heb de printplaat bij PCBWay besteld. Hier kunnen we eenvoudig het Gerber-bestand uploaden, de eigenschappen van onze printplaat kiezen en deze tegen een redelijke prijs bestellen.

Ik heb de PCB ontworpen met vier lagen, de middelste zijn voor GND, wat de prijs een beetje verhoogt. Ik heb geen van de standaardeigenschappen gewijzigd, behalve de PCB-kleur, die ik wit heb gekozen, en ik vink aan dat ik de wijziging voor de oppervlakteafwerking naar Immersion Gold, indien van toepassing, zonder extra kosten accepteer.

Je kunt de Gerber vinden en downloaden via de PCBWay-projectdeelcommunity, waar je de PCB ook rechtstreeks kunt bestellen.

Hoe dan ook, je kunt dit lineaire actuatorproject natuurlijk ook zonder deze op maat gemaakte servocontroller maken.

Je kunt de AS5600-sensor gebruiken op een breakout-board in combinatie met een Arduino-board voor het aansturen van de DC-motor.

Code

Laten we nu eens kijken naar de code van deze lineaire servo-actuator:

/*
 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)

Codebeschrijving

We starten de lus dus door de encoderwaarde of de huidige positie van de actuator te lezen en deze om te zetten in millimeters.

// 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)

Als we ons vervolgens in de “Seriële communicatiemodus” bevinden, lezen we de binnenkomende gegevens die we invoeren op de seriële monitor. Als de invoer “opslaan” is, slaan we de huidige positie-actuator op, of als deze “vrij” is, wissen we alle reeds opgeslagen posities.

// 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)

Als de invoer een geheel getal of een getal is, van 0 tot 150, gebruiken we die waarde als instelpunt.

// 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)

We voeren de waarden in millimeters in, maar voor het bijhouden van de roterende as gebruiken we graden, dus daarom zetten we de millimeterwaarden om in graden door ze met 45 te vermenigvuldigen. Dat komt omdat voor een lineaire beweging van 1 mm de spindel 45 graden moet draaien. Als uw spindel een andere spoed heeft, moet dit nummer anders zijn. 

Als we “run” typen, met behulp van enkele while- en for-loops, zal het programma herhaaldelijk door de opgeslagen posities lopen.

// 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)

Aan de andere kant, als we ons in de besturingsmodus van de potentiometer en de RC-ontvanger bevinden, controleren we of we een analoge of digitale invoer hebben.

// 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)

Als het analoog is, lezen we de analoge ingang van de potentiometer en gebruiken die waarde als een instelpunt, of de gewenste positie waar de actuator naartoe moet gaan. Op dezelfde manier lezen we, als de invoer digitaal is, de binnenkomende gegevens van de RC-ontvanger en gebruiken die waarde als instelpunt. 

Vervolgens roepen we de aangepaste functies readEncoder() en runMotor() aan om de huidige positie van de actuator te lezen en de PID-regeling uit te voeren. Met de functie readEncoder() lezen we de huidige waarde van de sensor in hoekwaarden, en met deze if-statements houden we bij in welk kwadrant de huidige positie van de as zich bevindt.

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)

Met deze informatie kunnen we bijhouden hoe de as draait en wanneer deze een volledige draai maakt. De totale hoek is de invoerwaarde voor de PID-regelaar. 

Met behulp van de analoge ingang van de trimmerpotentiometer kunnen we de proportionele versterking van de PID-regelaar aanpassen, en tenslotte voeren we het PID-proces uit om een uitgangswaarde te verkrijgen.

// 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)

We gebruiken die uitgangswaarde voor het aansturen van de DC-motoren met PWM-signaal, links of rechts, of in stilstaande positie, afhankelijk van de uitgangswaarde van de PID-regelaar, of afhankelijk van de fout tussen de gewenste en de werkelijke positie die de encoder leest.

De drie termen van de PID-regelaar, proportioneel, integraal en afgeleid, worden bovenaan gedefinieerd, en door ze aan te passen kunnen we verschillende uitgangsreacties krijgen.

double Pk1 = 0.65; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.1;Code language: JavaScript (javascript)

De kwaliteit, hoe goed de actuator zal werken of reageren op onze input, hangt rechtstreeks af van deze waarden.

Testen

Hier test ik de nauwkeurigheid van de actuator. Het komt weer netjes op zijn plek. Toen begon ik de staaf millimeter voor millimeter te bewegen. De eerste beweging was ongeveer 0,8 mm in plaats van 1 mm, maar de volgende vier waren dicht genoeg bij 1 mm.  Toen was de beweging van 4 mm ongeveer 0,15 mm afwijkend. 

We zouden moeten opmerken dat de staaf een speling heeft van ongeveer 0,25 mm. Deze speling bevindt zich tussen de spindel en de spindelmoer. Daarnaast hebben we waarschijnlijk enige speling in de 3D-geprinte tandwielen en in de tandwielen van de DC-motor zelf.  

Als we een kracht op de staaf uitoefenen en nu de nauwkeurigheid testen, krijgen we natuurlijk een nog grotere fout, maar dit kan worden verbeterd door de PID-controller aan te passen. 

Niettemin zou dat alles zijn voor deze tutorial. Ik hoop dat je ervan genoten hebt en iets nieuws hebt geleerd.


Productieproces

  1. Hoe werkt een metaalgieterij?
  2. Typemachine
  3. Een beknopte handleiding voor de snijlijn van staalstrips
  4. Lint
  5. Munt
  6. Hoe de zaagsnelheid kiezen?
  7. AV-kastventilatorcontroller
  8. Naadloze telefoon-naar-auto Bluetooth-installatie:een stapsgewijze handleiding
  9. Laserstraalbewerking ::Principe, Werking, Apparatuur, Toepassing, Voor- en Nadelen
  10. LCD-wekker met vele gezichten
  11. Diffusieverlijming:principe, werking, toepassing, voor- en nadelen