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

Transformeer elke gelijkstroommotor in een aangepaste 360°-servo – stapsgewijze handleiding

In deze tutorial leren we hoe we van elke DC-motor een zelfstandige, aangepaste servomotor met veel functies kunnen maken. In tegenstelling tot gewone servo's met een beperkte beweging van 180 of 270 graden, heeft deze een onbeperkt bereik van 360 graden en daarnaast hebben we de mogelijkheid om het rotatiebereik aan te passen aan elke waarde die we nodig hebben.

Dat is wel handig denk ik, en bovendien kunnen we zelfs het middelpunt van de servo aanpassen. We kunnen dus zowel het middelpunt als het rotatiebereik tegelijkertijd aanpassen.

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

Een ander kenmerk is dat we de gevoeligheid kunnen aanpassen of hoe snel de servo op onze invoer reageert. Over de invoer gesproken:we kunnen drie verschillende invoermodi hebben.

We kunnen de servo besturen met een analoge spanningsingang of met behulp van een potentiometer, we kunnen de servo besturen met een RC-zender en de servo besturen via een seriële poort door hoekwaarden in te voeren via de seriële monitor op onze pc of laptop.

We kunnen dat ook tegelijkertijd doen, de servo besturen door waarden in te voeren via de seriële monitor en de servo handmatig verplaatsen met behulp van de RC-zender. De servomotor kent te allen tijde zijn huidige positie en kan deze op de seriële monitor zien. 

Bovenop de lijst met functies van deze servomotor staat de continue rotatiemodus. Dat klopt. Zelfs in deze continue rotatiemodus kunnen we de positie van de servomotor controleren en volgen. We kunnen de servomotoras zo instellen dat deze met een oneindig aantal omwentelingen naar elke positie gaat.  

Dit alles is mogelijk dankzij de 12-bits encoder waarvan deze servomotor gebruik maakt, de AS5600 magnetische roterende positiesensor en de geïmplementeerde PID-regeling voor het aandrijven van de DC-motor.

Ik heb dit op maat gemaakte servomotorcontrollerbord gemaakt, dat een eigen microcontroller en al het andere bevat om elke gelijkstroommotor eenvoudig in een zelfstandige servomotor te veranderen.

We hoeven alleen maar het bord in het midden van de uitgaande as te plaatsen (inclusief een specifieke magneet op de as), gelijkstroommotoren van elk formaat aan te sluiten met een nominale stroom tot 3,5 A, het hele systeem te voeden met 12 V en dat is alles, we krijgen een servomotor van een normale gelijkstroommotor met al deze kenmerken.

Nu zal ik je door het hele proces van het maken van deze op maat gemaakte servomotor leiden, zodat je er ook zelf een kunt maken. Ik zal het werkingsprincipe van een servomotor, een closed-loop controller, een PID-controller uitleggen, hoe ik de aangepaste printplaat ervoor en de versnellingsbak heb ontworpen, en de code erachter uitleggen.

Werkprincipe van de servomotor

Om het werkingsprincipe van een servomotor uit te leggen, halen we een typische RC-servomotor uit elkaar en kijken wat erin zit.

We kunnen opmerken dat het een kleine DC-motor, een controllerboard, een potentiometer en een driedraadsaansluiting heeft, twee draden voor de stroom en één voor het ingangssignaal. Er zijn ook enkele versnellingen om de snelheid te verlagen en het koppel van de gelijkstroommotor te vergroten. 

Dit is een typische opstelling voor de meeste RC- of hobbyservomotoren. De potentiometer is bevestigd aan de uitgaande as van de gelijkstroommotor en fungeert als positiesensor. Hij vertelt de controller de huidige positie van de servomotoras. Het controllerbord bestuurt de DC-motor op basis van het ingangssignaal (de gewenste positie) en de werkelijke positie die we krijgen als feedback van de potentiometer. Dit vertegenwoordigt een gesloten regelsysteem.

Het ingangssignaal, oftewel de gewenste positie, wordt vergeleken met de werkelijke positie van de motor die we van de positiefeedbacksensor krijgen. Het verschil dat optreedt, wat de fout wordt genoemd, wordt vervolgens verwerkt in de controller die de motor opdracht geeft te bewegen totdat deze de gewenste positie bereikt.

Een aangepaste servomotor maken

Dus als we onze eigen servomotor willen bouwen met een aantal grotere gelijkstroommotoren dan deze typische RC-servo's gebruiken, kunnen we hetzelfde gesloten-lusbesturingssysteem implementeren.

We hebben alleen een positiesensor nodig die op de een of andere manier aan de uitgaande as is bevestigd en een microcontroller voor het aandrijven van de gelijkstroommotor.  

Wat de positiesensor betreft, de eenvoudigste oplossing is het gebruik van een eenvoudige potentiometer, net zoals die we in de RC-servo's zagen. Het probleem met dit soort potentiometers is echter dat ze een beperkt draaibereik hebben van slechts 270 graden, wat het draaibereik van de servomotor direct beperkt. Er zijn ook andere soorten potentiometers die meerdere slagen kunnen maken en een beter bereik en resolutie kunnen bieden, maar toch een beperkte rotatie hebben.

Als we willen dat de servomotor een onbeperkt rotatiebereik heeft, moeten we een encoder gebruiken. Encoders zijn elektromechanische apparaten die de hoekpositie van de as met onbeperkte rotatie kunnen volgen. Er zijn veel soorten encoders, zoals incrementeel of absoluut, of afhankelijk van hun detectietechnologie optisch, magnetisch of capacitief. Natuurlijk heeft elk van hen zijn eigen voor- en nadelen.

AS5600-encoder – magnetische roterende positiesensor

Ik heb ervoor gekozen om een magnetische encoder te gebruiken, of de AS5600 magnetische roterende positiesensor, omdat deze zeer compact en eenvoudig te implementeren is en een hoge nauwkeurigheid en resolutie biedt. Kijk maar eens hoe klein deze microchip is.

Het heeft een ingebouwde Hall-Effect-sensor die veranderingen in de richting van het magnetische veld kan detecteren. We hoeven dus alleen maar een magneet aan de uitgaande as van de motor te bevestigen en deze dicht bij de microchip te plaatsen op een afstand van 0,5 tot 3 mm.

Terwijl de motoras en de magneet gaan roteren, zal de Hall-Effect-sensor die veranderingen in de richting van het magnetische veld registreren. Met behulp van de ingebouwde 12-bit A/D-converter kan de AS5600-sensor 4096 posities per draai of 360 graden rotatie uitvoeren.

Dat betekent dat het veranderingen in de hoekpositie van slechts 0,0878 graden kan detecteren. Dat is behoorlijk indrukwekkend, en omdat het zeer betaalbaar en gemakkelijk te verkrijgen is, is het de juiste keuze voor een op maat gemaakte servomotor. 

Oké, dus wat hebben we nog meer nodig, een microcontroller en een driver voor de gelijkstroommotor. Ik heb gekozen voor de DRV8871 DC-motordriver die tot 3,5 ampère stroom kan verwerken, en de Atmega328-microcontroller.

Ik heb gekozen voor de opbouwversie, omdat deze veel compacter is dan de DIP-versie, en mijn doel was om een zo klein mogelijke printplaat op maat te maken waarop ik alles kan plaatsen, zodat de servo als zelfstandig apparaat kan werken.

Aangepast schakelschema servomotor

Hier is het volledige schakelschema van deze op maat gemaakte servomotor.

U kunt de benodigde componenten voor dit project verkrijgen via de onderstaande links:

  • 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.

We hebben dus de Atmega328-microcontroller samen met het aanbevolen minimale circuit, dat een 16 MHz-oscillator, enkele condensatoren en een weerstand bevat.

Voor het voeden van de microcontroller en de andere componenten die 5V nodig hebben, gebruiken we de AMS1117-spanningsregelaar, die de 12V-voedingsingang verlaagt naar 5V.

Hier is de AS5600-positiesensor met het aanbevolen circuit, dat twee condensatoren en twee pull-up-weerstanden bevat voor de IC2-communicatie.

De DRV8871 DC-motordriver heeft slechts één weerstand nodig om de stroom te beperken, en twee ontkoppelcondensatoren. Dan hebben we twee potentiometers aangesloten op de analoge ingangen van de microcontroller, één voor het aanpassen van het rotatiebereik en de andere voor het aanpassen van de gevoeligheid van de servo. De drukknop wordt gebruikt voor het instellen van het middelpunt van de servo, en de tweeweg-dipschakelaar voor het selecteren van de werkmodi van de servo. Er is een pin-header voor de ingangen van de servo, ofwel een analoge spanningsingang of een digitale PWM-ingang van een RC-ontvanger, samen met een 5V en een aardingspin. Er is ook een pin-header voor het programmeren van de microcontroller via het SPI-protocol en de seriële poort. 

Hier is een samenvatting van dit circuit en de workflow ervan. De invoer, of de gewenste hoekpositie, wordt ontvangen via deze twee pinnen en kan een analoge spanning zijn die afkomstig is van een potentiometer of een digitaal PWM-signaal dat afkomstig is van een RC-ontvanger. De invoer gaat naar de microcontroller waar deze wordt vergeleken met de werkelijke hoekpositie die wordt gedetecteerd door de encoder of de AS5600-positiesensor. Deze sensor communiceert met de microcontroller via het IC2-protocol.

Vervolgens voert de microcontroller de berekeningen uit, berekent hij de fout en stuurt op basis daarvan een PWM-signaal naar de DRV8871-driver, die de DC-motor aandrijft totdat deze de gewenste positie bereikt. 

Het hele circuit wordt gevoed door 12V, en de AS1117-spanningsregelaar levert 5V voor de microcontroller en de andere componenten.

PCB-ontwerp

Volgens het schakelschema heb ik geprobeerd de printplaat zo klein mogelijk te ontwerpen, en deze bleek 40 x 40 mm te zijn.

De encoder plaats ik aan de onderzijde en precies in het midden van de printplaat, zodat deze eenvoudig gemonteerd en uitgelijnd kan worden met de uitgaande as van de servo.

Alle andere componenten bevinden zich aan de andere kant, zodat ze de encoder en de uitgaande as niet hinderen.

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.

Niettemin arriveerde na enkele dagen de printplaat. De kwaliteit van de printplaat is geweldig, alles is hetzelfde als in het ontwerp, en ik heb hem in een immersiegouden oppervlakteafwerking gekregen.

Oké, dus nu kunnen we verder gaan met het solderen van de componenten eraan. Ik begon met de kleinere componenten zoals deze indicator-LED, en de condensatoren en de weerstanden.

Dit is eigenlijk de eerste keer dat ik deze kleine SMD-componenten soldeer, en ik was er echt heel slecht in. 

De grootste uitdaging was het solderen van de Atmega328-microcontroller, omdat de pinnen erg klein zijn en heel dicht bij elkaar liggen, maar het is me op de een of andere manier gelukt.

De microchip van de AS5600-encoder was eenvoudig te solderen aan de achterkant van de printplaat, evenals de grotere componenten met doorlopende gaten, zoals de dip-schakelaar, de potentiometers, de aansluitblokken en de pin-headers.

Hoe dan ook, hier is het uiteindelijke uiterlijk van het controllerbord, dat naar mijn mening toch behoorlijk is geworden.

Nu is het tijd om een geschikte versnellingsbak te maken voor de DC-motor en dit controllerbord. 

Aangepast servo 3D-model

De versnellingsbak voor deze custom servomotor heb ik ontworpen met Onshape. Het ontwerp van de versnellingsbak is uiteraard afhankelijk van de DC-motor. Zoals ik al zei, kunnen we gelijkstroommotoren van elk formaat gebruiken in combinatie met het controllerbord dat we zojuist hebben gemaakt.

Hier gebruik ik een DC-motor met een diameter van 37 mm en een ingebouwde versnellingsbak die 50 RPM levert. 50 RPM is een goede snelheid voor een servomotor, maar ik wilde iets lager gaan, om een ​​beter koppel te krijgen, dus heb ik een versnellingsbak gemaakt met een drievoudige reductie. Ik heb daarvoor visgraattandwielen gebruikt, omdat deze efficiënt zijn en gemakkelijk met een 3D-printer te maken zijn.

Natuurlijk hebben we hier de vrijheid om dit versnellingsbakontwerp te maken zoals we willen, omdat het afhangt van de gelijkstroommotor die we willen gebruiken en welke uitgangssnelheden we willen bereiken. 

Ik heb de controllerkaart op de achterkant van deze versnellingsbak geplaatst en perfect in het midden van de uitgaande as uitgelijnd.

Als we de DC-motoras direct als uitgang willen gebruiken, kunnen we gewoon een 1:1 tandwielset gebruiken, zodat we de positie van de as correct kunnen volgen. Of we kunnen in zo’n geval ook een gordelsysteem gebruiken. Zoals ik al zei, we hebben eindeloze mogelijkheden voor het maken van de versnellingsbak. 

Download 3D-model- en STL-bestanden

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

Natuurlijk download je hier ook het 3D-model, evenals de STL-bestanden die nodig zijn voor het 3D-printen van de onderdelen:

STEP-bestand:

STL-bestanden voor 3D-printen:

De aangepaste servo samenstellen

Hier zijn de 3D-geprinte onderdelen voor deze build, zodat we kunnen beginnen met het monteren van de servomotor.

Daarnaast hebben we enkele M3-bouten en inzetstukken met schroefdraad nodig, en enkele lagers. 

Eerst heb ik de DC-motor aan de basisplaat bevestigd met enkele M3-bouten met een lengte van 8 mm.

Dan kunnen we de twee tandwielen op hun plaats installeren. Het kleinere tandwiel gaat rechtstreeks naar de DC-motoras en het grotere tandwiel is de output van de servo. De uitgaande as van de bestaat echter uit twee delen.

Aan beide zijden van dit uitgaande asdeel heb ik inzetstukken met schroefdraad gemonteerd, aan de ene kant om het tandwiel erop aan te sluiten, en aan de andere kant om dingen aan de uitgang van de servo te bevestigen. 

Ik heb ook inzetstukken met schroefdraad geïnstalleerd op het kleinere tandwiel dat zal worden gebruikt om het aan de gelijkstroommotoras te bevestigen. Nu kunnen we de tandwielen in hun positie schuiven. Omdat dit visgraattandwielen zijn, moeten we ze allebei tegelijkertijd op hun plaats schuiven, anders kunnen we ze niet koppelen als we ze één voor één insteken.

Met behulp van een stelschroef heb ik het kleine tandwiel op de gelijkstroommotoras bevestigd. Ik heb 12V op de gelijkstroommotor gezet om te controleren of de tandwielset goed werkt. 

We kunnen de montage van de versnellingsbak voltooien door het zijpaneel, het kogellager voor de uitgaande as en de bovenkap te plaatsen.

Ik heb een aantal M3-inserts met schroefdraad op de achterplaat geïnstalleerd, zodat we het hele geheel kunnen vastzetten met een paar 20 mm lange M3-bouten. Ik heb de versnellingsbak opnieuw getest, deze werkt prima. We kunnen zien hoe de uitgaande as aan de achterkant draait en hier moeten we de magneet plaatsen die de AS5600-encoder zal volgen.

We bevestigen het controllerbord aan de versnellingsbak met behulp van enkele M2-bouten en moeren. De AS5600-positiesensor is nu perfect uitgelijnd met de magneet, zodat de verandering in het magnetische veld correct wordt gemeten wanneer de uitgaande as draait.

Houd er rekening mee dat de magnetisatierichting van de permanente magneet erg belangrijk is. Afhankelijk van of hij axiaal of diametraal gemagnetiseerd is, moeten we de magneet loodrecht of evenwijdig aan die AS5600 IC plaatsen.

Uiteindelijk veranderde ik de richting van mijn magneet, omdat deze niet de juiste magnetisatie had zodat de AS5600-encoder deze kon meten.

Vervolgens heb ik twee draden aan de DC-motor gesoldeerd en de motor met het klemmenblok op de controller aangesloten. Wat de stroom betreft, heb ik twee draden aangesloten op het stroomklemmenblok, die aan de andere kant een DC-voedingsconnector hebben voor het aansluiten van een 12V-voeding. En dat is alles, onze op maat gemaakte servomotor is klaar.

De controller programmeren

Wat we nu nog moeten doen, is deze servo tot leven brengen, of de controller programmeren. Voor dat doel moeten we eerst een bootloader op de ATmega328p-microcontroller branden. Zonder een bootloader kan de microcontroller de taal of de code die we ernaar sturen niet begrijpen. 

Bootloader branden

Om de bootloader naar de ATmega328p te branden, hebben we een Arduino-bord nodig, in mijn geval zal ik een Arduino Nano-bord gebruiken.

We zullen de SPI-communicatie gebruiken, dus we moeten de geschikte SPI-pinnen op het Arduino-bord en ons controllerbord aansluiten.

Nu moeten we met behulp van de Arduino IDE de ArduinoISP-voorbeeldschets openen en deze uploaden naar het Arduino Nano-bord. Met deze code is de Arduino Nano nu in staat om de bootloader naar de ATmega328-microcontroller te branden. 

Vervolgens moeten we als programmeur in het menu Tools Arduino als ISP selecteren en vervolgens op Burn Bootloader klikken.

Tijdens het branden van de bootloader moeten we merken dat de Arduino NANO-lampjes veel zullen knipperen, en dat zal resulteren in een succesvolle bootloader-branding. 

Code-upload

Als we daarmee klaar zijn, kunnen we de code nu programmeren of uploaden naar het controllerbord met behulp van een USB naar UART-interfacemodule.

De controllerkaart heeft speciale pinnen waarmee u ze eenvoudig kunt aansluiten, zoals weergegeven in dit schakelschema. 

Nu kunnen we de code voor deze op maat gemaakte servo die ik heb gemaakt openen en naar de controller uploaden. Maar voordat we dat doen, moeten we eerst de bibliotheken voor de AS5600-sensor en de PID-regeling installeren. We kunnen dat eenvoudig doen vanuit de Arduino IDE Library Manager. Zodra we op de uploadknop drukken, wordt de code naar onze ATmega328-controller geschreven via de USB naar UART-interfacemodule.

En dat is alles, onze op maat gemaakte servomotor is klaar. Nu kunnen we er een potentiometer op aansluiten om het uit te testen. Even een opmerking:de analoge ingang gaat naar de “S”-pin op het controllerbord, in plaats van de “A”-pin.

Bij het ontwerpen van de printplaat heb ik deze twee pinnen verkeerd op de ATmega328 aangesloten. Vervolgens kunnen we via de DIP-schakelaar de analoge ingangsmodus selecteren en de servo van stroom voorzien.

En hier is het, we kunnen de positie van de servomotor regelen met behulp van de analoge ingang van de potentiometer. We hebben onze DC-motor met succes omgebouwd tot een servomotor.

Broncode

Laten we nu eens kijken naar de code van deze op maat gemaakte servomotor.

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

Codeoverzicht

We starten de lus dus door de encoderwaarde of de huidige positie van de as te lezen.

// Read encoder value - current position
 encoderValue = as5600.readAngle();Code language: JavaScript (javascript)

Als we ons vervolgens in de continue rotatiemodus bevinden, accepteren we waarden van de seriële monitor en gebruiken we deze als een instelpunt of gewenste hoek voor de PID-regelaar.

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

Als de ingangsmodus is ingesteld op een potentiometer, lezen we de analoge ingang ervan en corrigeren we de instelwaarde, afhankelijk van hoe ver we hem draaien.

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)

We voeren dezelfde setpointcorrectie uit als de ingang de RC-ontvanger is. 

Hier zetten we de RAW-encoderwaarden om in hoekwaarden, en met deze if-statements houden we bij in welk kwadrant de huidige positie van de as zich bevindt.

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

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.

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)

Aan de andere kant, als we ons in de beperkte rotatiemodus bevinden, lezen we eerst de potentiometerwaarde die wordt gebruikt voor het aanpassen van het rotatiebereik en passen we de linker en rechter rotatielimiet dienovereenkomstig aan.

rangeAdjustment = analogRead(A1);
 leftLimit = 0 + 30 + rangeAdjustment;
 rightLimit = 4097 - 30 - rangeAdjustment;

Als de ingangsmodus de potentiometer is, gebruiken we de waarde ervan als een setpointwaarde voor de PID-regelaar.

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)

Als de ingangsmodus de RC-ontvanger is, lezen we de binnenkomende PWM-waarde van de ontvanger en gebruiken die waarde als setpoint.

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)

Voor het instellen van een ander middelpunt controleren we of we de drukknop hebben ingedrukt en leggen we die positie vast als nieuw middelpunt.

// Set center angle
 if (digitalRead(centerSet) == LOW) {
 centerAngle = encoderValue;
 angleDifference = 2047 - encoderValue;
 delay(1000);
 }Code language: JavaScript (javascript)

Volgens dit moeten we dan de werkelijke meetwaarden van de encoder aanpassen en deze compenseren met het hoekverschil tussen het nieuwe en het oude middelpunt. Die waarde gebruiken we als invoerwaarde voor de PID-regelaar.

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)

Met behulp van de analoge ingang van de andere potentiometer passen we de proportionele versterking van de PID-regelaar aan, en tenslotte voeren we het PID-proces uit om een uitgangswaarde te verkrijgen.

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

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.

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

Dus dat zou alles zijn voor deze video. Houd er rekening mee dat de code niet goed is geoptimaliseerd en dat er ruimte is voor verbetering.

Als u dit project opnieuw probeert te maken, moet u ook voorbereid zijn op het oplossen van problemen. Er zijn veel dingen die fout kunnen gaan, vooral bij het solderen van die kleine SMD-componenten.

Ik kreeg deze servo niet werkend vanaf de eerste poging. Aanvankelijk had ik enkele verkeerde aansluitingen op de printplaat, daarna heb ik de printplaat opnieuw besteld met nieuwe updates, maar ik had nog een paar pogingen nodig voordat ik hem werkend kreeg. 

Aan dit gedeelte van het artikel wordt nog gewerkt. Controleer het later nog eens….


Productieproces

  1. Mijn Motion Activated Security Cam-project
  2. Onderhoud van pons- en snijapparatuur:waarom is goede smering belangrijk?
  3. Eenvoudige FM-radio
  4. Arduino-afstandsmeter en digitaal waterpasproject
  5. Wat is draaien? - Definitie en soorten bewerkingen
  6. Hoe de zaagsnelheid kiezen?
  7. Generieke seriële Bluetooth met Win 10 IoT-Core RPI2
  8. MVP-kosten 2026:deskundige analyse- en besparingsstrategieën
  9. PIR-sensor geactiveerd Halloween Scare Prank
  10. Slim basketbalscorebord
  11. Verschil tussen MIG- en TIG-lassen