AVR servodriver för DC motorer

Berätta om dina pågående projekt.
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Det visar sig att jag hade lyckats förstöra gate driver ic:arna :( Får beställa nya och rita upp en ny separat h-brygga...
Nihilim
Inlägg: 121
Blev medlem: 12 mars 2006, 21:00:20

Inlägg av Nihilim »

Kan bidra med en HIP4081A om du behöver en fetdrivare.
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Har beställt 4 IR2111 så det är lungt :)
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Nu har jag till slut återupptagit detta projektet!

Har jag "översatt" formeln korrekt till kod?

Kod: Markera allt

Formel:
  CO(k) = CO(k-1) - Kp * [PV(k) - PV(k-1)] + Ki * T * e(k) - kd / T * [PV(k) - 2PV(k-1) + PV(k-2)]

Pseudo kod:
  PV_2 = PV_1;
  PV_1 = PV;

  e = SP - PV;

  P_term = Kp * (PV - PV_1);
  
  I_term = Ki * T * e;

  D_term = (kd / T) * (PV - (2 * PV_1) + PV_2);

  CO = CO - P_term + I_term - D_term;
Formeln är Typ C härifrån!
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Jag tycker att det du skrivit motsvarar orginalformeln men jag fattar verkligen inte hur den kan fungera.

e finns bara med i I_term, hmmm....
Alla PID-parametrar accumuleras till CO, Jag är helt lost.

Jag måste nog testa att simulera den i morgon om jag ska kunna sova gott på nätterna. :lol:
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Jag hittade en implementering av formeln här:
http://home.hccnet.nl/e.vd.logt/htm/reg ... k.htm#PID2
Den är lite omvänd då den räknar ut P och D negativt och adderar allt i slutet istället!

Jag tror jag ska slänga ihop ett litet test också! :)
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Nu har jag gjort ett enkelt test:

Kod: Markera allt

int main()
{
  //Globala variabler
  int T, E;
  int SP, PV, PV_1, PV_2;
  int CO;    
  float Kp, Ki, Kd;

  //Inställning
  Kp = 1.0;
  Ki = 1.0;
  Kd = 1.0;
  T = 1;

  //Nollställ variabler
  SP = PV = PV_1 = PV_2 = 0;
  CO = 0;

  while(1==1)
  {
    E = SP - PV;

    float Pt = Kp * (PV - PV_1);  
    float It = Ki * T * E;
    float Dt = (Kd / T) * (PV - (2 * PV_1) + PV_2);
    CO = CO - Pt + It - Dt;

    PV_2 = PV_1;
    PV_1 = PV;
        
    cout << "SP: " << SP << "   PV: " << PV << "   Error: " << E << "   CO: " << CO << endl;
    PV += CO * 0.25;
    system("pause");

    SP++;
  }   
}
Controller output påverkar Process variabeln med 25% "verkningsgrad"

Detta blir resultated av koden:

Kod: Markera allt

SP - PV - E - CO
-----------------
0 0 0 0
1 0 1 1
2 0 2 3
3 0 3 6
4 1 3 7
5 2 3 9
6 4 2 8
7 6 1 7
8 7 1 8
9 9 0 5
10 10 0 5
11 11 0 4
12 12 0 3
13 12 1 5
14 13 1 4
15 14 1 4
Sedan verkar den stabilisera sig på CO 4 pga upplösningen.
Som mest var felet 3 så jag orkar inte trimma in P, I och D något :) Men det verkar ju fungera utmärkt vid en så linjär "last" och stegning som jag programerade för iaf!

Edit: när jag får orken ska jag hacka ihop ett grafiskt test. Tänkte man kör SP 0 i 50 steg, sen SP 50 i 100 steg sen SP 0 i 100 steg till...
Sen plottar man ut SP Versus PV.
Tänkte slänga in sliders för P, I och D så man lätt kan justera parametrarna också!
Användarvisningsbild
007sweden
Inlägg: 3500
Blev medlem: 3 mars 2005, 20:18:12
Skype: oo7sweden

Inlägg av 007sweden »

Vad kul, en till från Älvsbyn! :) Trodde jag var ensam här.
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Världen är liten! :)

Sitter och funderar på hur man primitivt skulle kunna simulera en servo med enkoder...
Om vi tänker oss en motor på max 3000 RPM @ 100V, 400 pulser per varv och en dc spänning på h-bryggan av 100V samt PID på 1kHz:

100/256 = 0,390625 V upplösning

3000/100 = 30 RPM / V

0,390625 * 30 = 11,71875 varv per 1/256 PWM Dutycycle och minut

11,71875 / 60 = 0,1953125 varv per per 1/256 PWM Dutycycle och sekund

0,1953125 / 1000 = 0,0001953125 varv per 1/256 PWM Dutycycle och PID loop.

Detta tal multipliceras först med PWM från PIDen och adderas/subtraheras från en räknare varje PID loop beroende på riktning.

1/400 = 0,0025 varv per puls. Varje gång räknaren ser en summerad ändring större än en puls så ändras Process variabeln.

Har jag tänkt rätt? (om man bortser från att den är helt opåverkad från fysikens lagar) :D
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Nu har jag knåpat ihop ett grafiskt test, dock har jag bara prövat PV = CO * 0.25 ännu. Ska skriva in en enkel servomodell senare!

Kurvan är: 0 - 50 - 0
Bild
Användarvisningsbild
Chribbe76
EF Sponsor
Inlägg: 1167
Blev medlem: 17 januari 2004, 22:43:17
Ort: Stockholm

Inlägg av Chribbe76 »

Jag blir inte riktigt klok på den PIDen, mina tester gav bara konstiga resultat.
Det verkar som om jag gör något fundamentalt fel men jag ska göra ett nytt försök om några dagar.

Har du provat att simulera med ett rörligt(interpolerande) mål?
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Jag råkade bli full innan jag hann testa... HEY WTF GÖR JAG HÄR?
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Btw så känns det bara som I påverkar kurvan positivt :S... måste fixa bättre simulering eller en riktig servo
Millox
Inlägg: 559
Blev medlem: 10 december 2005, 22:10:43
Ort: Östhammar

Inlägg av Millox »

Um, jag tycker det där ser minst sagt konstigt ut...

Om jag tolkat variablerna rätt:

SP = set point, dvs börvärde.
PV = Present value, dvs nuvärdet.
PV_1 = föregående värde
PV_2 = förr-föregående värde.
E = error, felet.
CO = controller output, dvs det du matar ut till vad det nu är.

Då tycker jag att:
P-termen i ditt första värde ser mycket mer ut som derivata-termen. Det borde vara felet som multipliceras, inte skillnaden mellan nuvarande och föregående värde som ju ungefär är derivatan.

I-termen är din proportionella förstärkning eftersom du bara multiplicerar felet med något här.

D-termen är skum.

Du borde göra såhär istället:

PV_1 = PV;
PV = läs in pv;

E = SP-PV;
E-integral = E-integral + E;

P-term = Kp * E;
I-term = Ki * E-integral;
D-term = Kd * (PV-PV_1);

CO = P-term + I-term + D-term;

I Kp, Ki och Kd förkortar du bort alla andra konstantberäkningar(vilket iofs kompilatorn sannolikt gör åt dig i alla fall).

Det här borde ge dig en enkel och smidig pid-regulator, sätt någon av Kp,Ki,Kd till noll för att ta bort någon regulatordel.
JBV
Inlägg: 411
Blev medlem: 4 maj 2006, 11:44:28
Ort: Älvsbyn

Inlägg av JBV »

Detta är ju en "Allen Bradley Logix5550 Independent PID equation" eller "textbook PID":

CO = CO + Kp * [E - E_1] + Ki * T * E + (Kd/T) * [E - (2 * E_1) + E_2]

Såvtt jag förstått allt är skälet till att man tar bort Setpoint från P och D är att stora förändringar i setpoint inte ska påverka controller output. Istället ska bara felet samt förändringstakten av process variabeln påverka.

Jag ska pröva den ovan istället senare ikväll!
Skriv svar