Arduino - Knappstyrning av motor med Encoder disc & sensorer

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
fosfor
Inlägg: 453
Blev medlem: 13 februari 2013, 05:43:15
Kontakt:

Arduino - Knappstyrning av motor med Encoder disc & sensorer

Inlägg av fosfor »

Hej!

Jag skulle vilja ha rekommendation på Arduino kod att utgå ifrån nu när jag ska styra min motor med en encoder disc. :shock:

Har efter mycket om och men tagit mig dit till att jag har satt upp en motor med en hemgjord encoder, två sensorer och kan nu
läsa av signalerna och visa "framåt och bakåtpulser" på displayen (bifogat foto) när jag manuellt snurrar disken över sensorerna.
Vet att jag framöver kommer behöva något i stil med en H-brygga eller så (eller passar nåt annat bättre?), separat matning till motorn (rekommendationer där)?

Nästa steg är att jag via två fysiska knappar kan styra motorn åt ena eller det andra hållet, och gärna ha en tredje knapp som kan "spara" en position
som den sen när man passerar den via att man åker upp eller ner, bara stannar där, så att man måste trycka igen för att den ska vidare upp eller ner.
Samt väldigt gärna att den visar pulsräkningen på en display, såsom den gör nu.
Ingen särskilt jätteprecision eller hastighet behövs. Så en relativt "enkel" funktion kan tyckas, upp ner och ev. spara en position.

Är nybörjare på detta med motorstyrning & arduino, så vore jättetacksam för tips. :tumupp:
Länkar, kod, youtube, vad ska jag söka på ordagrant etc, vad som helst som kan vara bra. :humm:
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
fosfor
Inlägg: 453
Blev medlem: 13 februari 2013, 05:43:15
Kontakt:

Re: Arduino - Knappstyrning av motor med Encoder disc & sens

Inlägg av fosfor »

I nuläget har jag dessa portar lediga på Arduino Uno'n

4
5~
12
13

Resten tas upp utav displayen och 2 insignaler från sensorerna.
Användarvisningsbild
fosfor
Inlägg: 453
Blev medlem: 13 februari 2013, 05:43:15
Kontakt:

Re: Arduino - Knappstyrning av motor med Encoder disc & sens

Inlägg av fosfor »

Testar just nu med ett H-bridge chip.
L293D
SeniorLemuren
Inlägg: 7779
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Arduino - Knappstyrning av motor med Encoder disc & sens

Inlägg av SeniorLemuren »

Lättast är att ansluta en färdig stegmotordrivare. Då behöver du bara skicka ut det antal pulser som du vill att stegmotorn skall röra sig samt en datapinne som talar om vilket håll den skall snurra, när pinnen är hög snurrar den åt ena hållet och när den är låg så går motorn åt andra hållet. du kan även ställa in olika grader av mikrostegning. Vill du inte vänta på en driver från ebay så finns det säkert någon här på EF som har en att posta till dig för en billig peng. :)

Har du fler motorer på samma Arduino så får du använda en pinne till varje motor för att välja vilken motor som skall köras. Det finns många exempel på nätet hur du styr motorn via Arduino. Här har du en vägledning, men det finns fler om inte denna passar.
kodar-holger
EF Sponsor
Inlägg: 916
Blev medlem: 26 maj 2014, 12:54:35
Ort: Karlskoga

Re: Arduino - Knappstyrning av motor med Encoder disc & sens

Inlägg av kodar-holger »

Jag har inte följt dina andra trådar, men det är en DC-motor om jag inte misstar mig.

Jag skulle tipsa om att läsa på om:

PWM
PID
Feedback

Kanske googla något som

dc motor control pid arduino
eller
servo loop arduino
SeniorLemuren
Inlägg: 7779
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Arduino - Knappstyrning av motor med Encoder disc & sens

Inlägg av SeniorLemuren »

Ok. Jag missade att det var en DC-motor. Då kan du glömma det jag skrivit om stegmotorstyrning, sorry.
SeniorLemuren
Inlägg: 7779
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: Arduino - Knappstyrning av motor med Encoder disc & sens

Inlägg av SeniorLemuren »

Jag gjorde några små experiment för något år sedan med DC-styrning.
Min lösning var att använda 2 st Arduino Uno eftersom de är billiga på ebay. Den ena motorn skötte PID-motorstyrning och ingenting annat. Den andra Unon matade styrenheten med antal pulser motorn skulle snurra samt vilken rotationsriktning den skulle ha. På det viset blir det enkelt att hänga på nödvändiga knappar eller en grafisk LCD med pekskärm på den Arduino som inte är fullt upptagen med att reglera motor.
Här är några video som visar hur det såg ut.



Arduino Uno
Länk till den Motorstyrnning jag använde.
Länk till PID library: PID library.

Det enkla testprogram jag använde för att mata önskade varvtal, rotationsriktningar och antal varv att snurra till styrenheten (Enbart ett enkelt exempel). Här kan man ju lägga in knappar och eller LDC m.m.

Kod: Markera allt

//Urban Hahne
// matar Servo med step
long int var = 0;

int antRev1= 90;
int delay1 = 9900;

int antRev2= 90;
int delay2 = 9900;



int paus1 = 1000;
int paus2 = 1000;

void setup() {  
  pinMode(13, OUTPUT);//Step
  pinMode(12, OUTPUT);//Dir
  
}

void loop() {
  step();  
}

void step(){  
  digitalWrite(12, LOW); 
  while(var < 1008 * antRev1){
  digitalWrite(13, HIGH);  
  delayMicroseconds(delay1);          
  digitalWrite(13, LOW);    
  delayMicroseconds(delay1);            
  var=var+1;  
  }  
  delay(paus1);
  var=0;  
  digitalWrite(12, HIGH);  
  while(var < 1008 * antRev2){
  digitalWrite(13, HIGH);   
  delayMicroseconds(delay2);            
  digitalWrite(13, LOW);   
  delayMicroseconds(delay2);         
  var=var+1;
  }
  delay(paus2);  
  var=0; 

    
}
Servoprogrammet :

Kod: Markera allt

/*
   This program uses an Arduino for a closed-loop control of a DC-motor. 
   Motor motion is detected by a quadrature encoder.
   Two inputs named STEP and DIR allow changing the target position.
   Serial port prints current position and target position every second.
   Serial input can be used to feed a new location for the servo (no CR LF).
   
   Pins used:
   Digital inputs 2 & 8 are connected to the two encoder signals (AB).
   Digital input 3 is the STEP input.
   Analog input 0 is the DIR input.
   Digital outputs 5 & 6 control the PWM outputs for the motor (I am using half L298 here).


   Please note PID gains kp, ki, kd need to be tuned to each different setup. 
*/

#include <PID_v1.h>
#define encoder0PinA  2 // PD2; 
#define encoder0PinB  8  // PB0;
#define M1            5
#define M2            6  // motor's PWM outputs


double kp=1.8,ki=300,kd=0.02;
double input=80, output=0, setpoint=180;
PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);

volatile long encoder0Pos = 0;

long previousMillis = 0;        // will store last time LED was updated

long target1=0;  // destination location at any moment

//for motor control ramps 1.4
bool newStep = false;
bool oldStep = false;
bool dir = false;

void setup() { 
  pinMode(2, INPUT);
  pinMode(encoder0PinA, INPUT); 
  pinMode(encoder0PinB, INPUT);  
  attachInterrupt(0, doEncoderMotor0, CHANGE);  // encoder pin on interrupt 0 - pin 2
  attachInterrupt(1, countStep, RISING);  //on pin 3
  
  Serial.begin (115200);

  //Setup the pid 
  myPID.SetMode(AUTOMATIC);
  myPID.SetSampleTime(2);
  myPID.SetOutputLimits(-255,255);
} 

void loop(){
    input = encoder0Pos; 
    setpoint=target1;
    myPID.Compute();
    pwmOut(output); 
   // print encoder and target every second throgh the serial port 
    if(millis() > previousMillis+1000 )  {Serial.print(encoder0Pos); Serial.print("->"); Serial.println(target1);     previousMillis=millis(); }
    // interpret received data as an integer (no CR LR)
    if(Serial.available()) target1=Serial.parseInt();
}

void pwmOut(int out) {
   if(out<0) { analogWrite(M1,0); analogWrite(M2,abs(out)); }
   else { analogWrite(M2,0); analogWrite(M1,abs(out)); }
  }


void doEncoderMotor0(){
  if (((PIND&B0000100)>>2) == HIGH) {   // found a low-to-high on channel A; if(digitalRead(encoderPinA)==HIGH){.... read PB0
    if ((PINB&B0000001) == LOW) {  // check channel B to see which way; if(digitalRead(encoderPinB)==LOW){.... read PB0
      encoder0Pos-- ;         // CCW
    } 
    else {
      encoder0Pos++ ;         // CW
    }
  }
  else                                        // found a high-to-low on channel A
  { 
    if ((PINB&B0000001) == LOW) {   // check channel B to see which way; if(digitalRead(encoderPinB)==LOW){.... read PB0
                                              // encoder is turning  
      encoder0Pos++ ;          // CW
    } 
    else {
      encoder0Pos-- ;          // CCW
    }
  } 
}

void countStep(){ // pin A0 represents direction
            if (PINC&B0000001) target1++;
            else target1--;
}
Skriv svar