PID-reglering + stanna motor exakt
Re: PID-reglering + stanna motor exakt.
lizerdboy: Jag har inte gjort spaltskivan själv, men jag tror att den först är utsvarvad och att spalterna sen är fräste med en 0,5mm pinfräs med skivan sittandes i den fjärde axeln.
Nu har jag kopplat in en komparator på detta viset:
(PIC'ens INT1 ingång är kopplad direkt till komparatorns utgång) signalen ut från komparatorn ser ut såhär:
(Att signalen är full av störningar beror antagligen bara på de långa oskärmade kablarna jag har till ljudkortsoscilloskopet..) problemet med att den tappar räkningen har jag lyckats lokalisera nu till att den ibland triggar alldeles för många interrupt vid en enda spalt, men endast vid låga hastigheter verkar det som. Snurrar jag motorn för hand kan jag inte se några såna tendenser (men de är inte alltid så lätta att se då det ofta är kanske var hundrade spalt den räknar dubbelt). Men om jag ger motorn spänning och håller fast den så att den bara kan snurra långsamt, då kan den ibland trigga ett hundratal interrupt av en enda spalt..
Detta fick mig att misstänka att det var störningar från motorn, så jag testade att driva motorn från en annan spänningskälla, men det gjorde ingen skillnad..
Nu har jag kopplat in en komparator på detta viset:
(PIC'ens INT1 ingång är kopplad direkt till komparatorns utgång) signalen ut från komparatorn ser ut såhär:
(Att signalen är full av störningar beror antagligen bara på de långa oskärmade kablarna jag har till ljudkortsoscilloskopet..) problemet med att den tappar räkningen har jag lyckats lokalisera nu till att den ibland triggar alldeles för många interrupt vid en enda spalt, men endast vid låga hastigheter verkar det som. Snurrar jag motorn för hand kan jag inte se några såna tendenser (men de är inte alltid så lätta att se då det ofta är kanske var hundrade spalt den räknar dubbelt). Men om jag ger motorn spänning och håller fast den så att den bara kan snurra långsamt, då kan den ibland trigga ett hundratal interrupt av en enda spalt..
Detta fick mig att misstänka att det var störningar från motorn, så jag testade att driva motorn från en annan spänningskälla, men det gjorde ingen skillnad..
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: PID-reglering + stanna motor exakt.
Hej squiz3r,
Nu ser signalen betydligt bättre ut. Det du kallar störning förmodar jag är vågformen som bland annat syns under den höga tiden. Denna har ingen större betydelse för funktionen enär signalen tydligt är noll eller ett.
Anledningen till att du tappar pulser är förmodligen att uC:n inte hinner klart interuptsekvensen tillräckligt snabbt. I princip skulle jag säga att du har satsat på fel lösning enär det normalt är bättre att använda en timer-ingång och låta timern räkna pulserna.
Nu ser signalen betydligt bättre ut. Det du kallar störning förmodar jag är vågformen som bland annat syns under den höga tiden. Denna har ingen större betydelse för funktionen enär signalen tydligt är noll eller ett.
Anledningen till att du tappar pulser är förmodligen att uC:n inte hinner klart interuptsekvensen tillräckligt snabbt. I princip skulle jag säga att du har satsat på fel lösning enär det normalt är bättre att använda en timer-ingång och låta timern räkna pulserna.
Re: PID-reglering + stanna motor exakt.
> Anledningen till att du tappar pulser...
??
> ...att den ibland triggar alldeles för många interrupt vid en enda spalt,
Tvärtom alltså.
Det kan lika gärna vara ett programfel som ett mekansikt/elektriskt fel.
Jag funderar på din ISR, kör du med dubbla interrupt prio nivåer?
Och i så fall, notera att de automatiska shadow-registren bara har en nivå.
I 99 fall av 100 så är det enklare att köra med en prionivå...
??
> ...att den ibland triggar alldeles för många interrupt vid en enda spalt,
Tvärtom alltså.
Det kan lika gärna vara ett programfel som ett mekansikt/elektriskt fel.
Jag funderar på din ISR, kör du med dubbla interrupt prio nivåer?
Och i så fall, notera att de automatiska shadow-registren bara har en nivå.
I 99 fall av 100 så är det enklare att köra med en prionivå...
Re: PID-reglering + stanna motor exakt.
För att lättare kunna utesluta fel så gjorde jag ett minsta möjliga scenario där jag fortfarande hade felet. Jag använde inga andra interrupt, inga andra timrar och liknande... Plockade bort alla variabler som inte var absolut nödvändiga för testet. Efter ett tag slutade allt helt plötsligt att fungera, och efter ett tag började det fungera igen, nu helt perfekt.. Då jag inte kunde förstå varför det nu helt plötsligt fungerade så laddade jag in det gamla, kompletta, programmet i den igen, vilket också fungerade perfekt. Väldigt irriterande när ett problem helt plötsligt försvinner utan att man vet varför..
Men nu kunde jag i alla fall börja med den betydligt roligare delen, själva regleringsprocessen!
Jag började lugnt och försiktigt med att implementera en P-del. PWM duty cycle = 30*(eftersträvat varvtal - varvtal). Om det blir mindre än 0 aktiverar jag bromsfunktionen (kortsluter motorn). Inget speciellt upphetsande...
Motorns varvtal stabiliserade sig direkt vid uppstart men låg bara på runt 60% av önskat varvtal... Här behövs en integrerande del!
Jag tog då och räknade ihop det ackumulerade felet i en variabel och satte ett stopp vid 1000 så att det inte skulle kunna bli hur stort som helst. Till duty cycle variablen adderade jag sedan 15*ackumulerat fel. Resultatet blev en reglering som utan belastning lägger sig på rätt varvtal men som överkompenserar något enormt så fort den belastas vilket skapar en oscillation... Även vid motorstarten blir det en stor överkompensering som tar någon sekund innan den stabiliserar sig... Nu låg dock regleringen i main-loopen som var riktigt seg, så det var ca 5Hz i uppdateringsfrekvens, detta bidrog ju också till de stora överkompenseringarna som syns i diagrammet nedan. Grön linje är motorns varvtal, blå linje är eftersträvat varvtal och den röda är duty cycle som kan variera mellan 0 och 1000. Efter det tog jag och lade in hela regleringsprocessen i min interrupt service rutin som kör var 13'e mS, dvs 77Hz i uppdateringsfrekvens. Nu blev det en ganska rak linje trots att jag belastade den en hel del med fingret. (Vad som hände i den stora toppen mitt i diagrammet vet jag inte riktigt..) Denna grafen visar hur det ser ut när jag ändrar det önskade varvtalet. Och en inzoomning på en av "uppförsbackarna". På bilderna syns ju tydligt att den överkompenserar, speciellt då jag ändrar önskat varvtal. Därför behövs även en deriverande bit. Tillbaks till elektronikrummet!
Nu blev det ju lite av en projekttråd av detta, så jag hoppas att någon tycker att det är intressant eller lär sig något av mina misstag
Men nu kunde jag i alla fall börja med den betydligt roligare delen, själva regleringsprocessen!
Jag började lugnt och försiktigt med att implementera en P-del. PWM duty cycle = 30*(eftersträvat varvtal - varvtal). Om det blir mindre än 0 aktiverar jag bromsfunktionen (kortsluter motorn). Inget speciellt upphetsande...
Jag tog då och räknade ihop det ackumulerade felet i en variabel och satte ett stopp vid 1000 så att det inte skulle kunna bli hur stort som helst. Till duty cycle variablen adderade jag sedan 15*ackumulerat fel. Resultatet blev en reglering som utan belastning lägger sig på rätt varvtal men som överkompenserar något enormt så fort den belastas vilket skapar en oscillation... Även vid motorstarten blir det en stor överkompensering som tar någon sekund innan den stabiliserar sig... Nu låg dock regleringen i main-loopen som var riktigt seg, så det var ca 5Hz i uppdateringsfrekvens, detta bidrog ju också till de stora överkompenseringarna som syns i diagrammet nedan. Grön linje är motorns varvtal, blå linje är eftersträvat varvtal och den röda är duty cycle som kan variera mellan 0 och 1000. Efter det tog jag och lade in hela regleringsprocessen i min interrupt service rutin som kör var 13'e mS, dvs 77Hz i uppdateringsfrekvens. Nu blev det en ganska rak linje trots att jag belastade den en hel del med fingret. (Vad som hände i den stora toppen mitt i diagrammet vet jag inte riktigt..) Denna grafen visar hur det ser ut när jag ändrar det önskade varvtalet. Och en inzoomning på en av "uppförsbackarna". På bilderna syns ju tydligt att den överkompenserar, speciellt då jag ändrar önskat varvtal. Därför behövs även en deriverande bit. Tillbaks till elektronikrummet!
Nu blev det ju lite av en projekttråd av detta, så jag hoppas att någon tycker att det är intressant eller lär sig något av mina misstag
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: PID-reglering + stanna motor exakt.
> Väldigt irriterande när ett problem helt plötsligt försvinner utan att man vet varför..
Koden i processorn ändrar sig ju inte av sig självt, och samma kod
bör fungera i princip likadant igår, idag och i morgon.
Återstår något externt fel i dina övriga kopplingar. Glapp?
Koden i processorn ändrar sig ju inte av sig självt, och samma kod
bör fungera i princip likadant igår, idag och i morgon.
Återstår något externt fel i dina övriga kopplingar. Glapp?
Re: PID-reglering + stanna motor exakt.
Precis. Det sitter ju på ett breadboard, så risken för glapp eller strörningar finns ju alltid där även om jag har ägnat mycket tid åt att lyfta ur och sätta i kablar, mäta på olika punkter osv..
Re: PID-reglering + stanna motor exakt.
Kul att det funkar tillslut! 
Största felet med mina breadboard brukar vara att sladdar sitter på fel ställen.
Har vart med om otroliga fel men är man superenvis så går det alltid till slut, detta är den stora fördelen med att göra "allt" själv det är liksom ingen att skylla på
Största felet med mina breadboard brukar vara att sladdar sitter på fel ställen.
Har vart med om otroliga fel men är man superenvis så går det alltid till slut, detta är den stora fördelen med att göra "allt" själv det är liksom ingen att skylla på
Re: PID-reglering + stanna motor exakt
Att implementera den derivativa delen gick inte lika snabbt som de två andra, det beter sig inte riktigt som jag vill... Men största problemet är att min seriella överföring mellan PIC och dator inte fungerar som det ska...
Jag har gjort så att jag i PIC'en delar upp mina signed int till två 8-bitars variabler på följande vis:
Det finns tre stycken signed int som jag gör likadant med (först lastNbrPassed, sen pidOut och till sist wantedNbrPassed). Sedan skickar jag bara iväg det genom att lägga en byte i taget i RX-registret (den höga byten först, sen den låga). Efter det fångar jag upp det i datorn med PICKIT2 och dess eget USART program inställt på ASCII-mode. På skärmen blir det då bara en bunke med jox eftersom siffrorna är binära och inte i ascii, men detta sparas i alla fall till en textfil. Textfilen läser jag sedan in i ett java-program som spottar ut en annan textfil i ASCII. Den viktiga delen i java-programmet ser ut såhär:
ASCII-filen läser jag sedan in i Matlab och plottar graferna på följande vis:
Av någon anledning blir dock pidOut helt galen... lastNbrPassed och wantedNbrPassed fungerar utmärkt, men dessa går bara mellan 0-80 ungefär, och då verkar det fungera. Om jag testar att köra pidOut i korta steg från -2000 till 2000 så blir det mer eller mindre bråte som jag tar emot... Den ligger konstant på vissa tal, tex 16183, sen hoppar den till ett annat tal osv.. Till synes ingen logik över huvud taget... Felet ligger i alla fall inte i Matlab koden, för redan i ascii-filen ser man att siffrorna är på det viset..
Är det någon som vågar gissa sig på vad för fel jag kan ha gjort? Kan det vara så att felet blir när jag försöker ta emot binär data med usart-programmet inställt på ASCII?
Väldigt tacksam för svar
Jag har gjort så att jag i PIC'en delar upp mina signed int till två 8-bitars variabler på följande vis:
Kod: Markera allt
unsigned char * pByte = (unsigned char *)&lastNbrPassed;
txBuffer[0] = pByte[1];
txBuffer[1] = pByte[0];
Har också med samma resultat testat:
txBuffer[0] = (unsigned char) (lastNbrPassed >> 8);
txBuffer[1] = (unsigned char) lastNbrPassed;Kod: Markera allt
fileName = "C:\\Temp\\pic.txt";
f = new File(fileName);
System.out.println("Filen " + fileName + " öppnas...");
try{
FileInputStream fileInput = new FileInputStream(f);
DataInputStream dataIn = new DataInputStream(fileInput);
System.out.println("Filen " + fileName + " har nu öppnas...");
while (true){
try{
Data += Integer.toString(dataIn.readShort()) + "\t"; // Läs av första variabeln på en rad..
Data += Integer.toString(dataIn.readShort()) + "\t"; // Läs av andra variabeln på samma rad..
Data += Integer.toString(dataIn.readShort()) + "\n"; // Läs av tredje variabeln på samma rad..
}
catch (IOException eof){
break;
}
}
System.out.print(Data);
}
catch (IOException e){
System.out.println(e);
}
// SKRIV UT TILL NY FIL I ASCII FORMAT...
System.out.println("Skriver till ny fil...");
try
{
FileOutputStream out = new FileOutputStream("C:\\Users\\Daniel Andersson\\Documents\\MATLAB\\PIC_testAscii.txt");
PrintStream p = new PrintStream(out);
p.print(Data.replace("\n", System.getProperty("line.separator")));
p.close();
}Kod: Markera allt
vars = load('PIC_testAscii.txt');
nbrPassed = vars(:,1);
pwmDc = vars(:,2);
wanted = vars(:,3);
figure(1);
% Rita ut motorns varvtal, rpm och PWM Duty Cycle i samma graf..
wantedRpm = wanted * 60/(50*0.0131072);
rpm = nbrPassed * 60/(50*0.0131072);
x = 1:1:length(vars);
x = x*0.0131072;
plot(x, wantedRpm, x, rpm, x, pwmDc);
legend('Eftersträvat varvtal', 'Motorns varvtal', 'PWM duty cycle (0-1000)');
title('Motorns varvtal och PWM duty cycle som funktion av tiden');
xlabel('Tid [s]');
ylabel('RPM (varv per minut)');
figure(2);
% Rita ut passerade spalter per timer-interrupt..
subplot(3,1,1);
plot(1:length(nbrPassed), nbrPassed);
title('Passerade spalter per interrupt');
xlabel('Interrupt, dT = 13,1072mS');
ylabel('Passerade spalter (50 per varv)');
% Rita ut motor varvtal, rpm..
rpm = nbrPassed * 60/(50*0.0131072);
subplot(3,1,2);
plot(1:length(rpm), rpm);
title('Motorns varvtal');
xlabel('Interrupt, dT = 13,1072mS');
ylabel('RPM (varv per minut)');
% Rita ut positione (totalt antal passerade varv (= 100*spalter))..
totalNbrPassed = zeros(1,length(nbrPassed));
for i = 1:length(nbrPassed)
totalNbrPassed(i) = 0;
for j = 1:i
totalNbrPassed(i) = totalNbrPassed(i) + nbrPassed(j);
end
end
subplot(3,1,3);
plot(1:length(totalNbrPassed), totalNbrPassed/50);
title('Antal snurrade varv');
xlabel('Interrupt, dT = 13,1070mS');
ylabel('Antal varv');Är det någon som vågar gissa sig på vad för fel jag kan ha gjort? Kan det vara så att felet blir när jag försöker ta emot binär data med usart-programmet inställt på ASCII?
Väldigt tacksam för svar
Re: PID-reglering + stanna motor exakt
Nu skickar jag datan som ASCII istället, det fungerar i nuläget, men har jag fler variabler som jag vill skicka så kommer den inte att hinna med det... (Ta som exempel talet -13000, med ascii är det 6 bytes (en för var tecken) medan binärt är det bara två byte (signed int))
Regleringen fungerar si och så nu.. Den kommer lätt in i självsvängning, jag vet inte riktigt hur jag löser detta...
Här syns att varvtalet påverkas knappt när jag belastar den hårt med ett finger, men hela tiden hoppar den ju lite upp och ner i någon självsvängning.. Här syns självsvängningen bättre... Några tips?
Regleringen fungerar si och så nu.. Den kommer lätt in i självsvängning, jag vet inte riktigt hur jag löser detta...
Här syns att varvtalet påverkas knappt när jag belastar den hårt med ett finger, men hela tiden hoppar den ju lite upp och ner i någon självsvängning.. Här syns självsvängningen bättre... Några tips?
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: PID-reglering + stanna motor exakt
Det jag tycker sticker ut är sifrorna 100+50+100, som jag antar är PID parametrarna? Nu har jag inte koll på din kod, vad du har för "skala" på respektive parameter där och varje applikation är såklart unik men P 'brukar' landa på minst 10*I och D brukar landa på minst 10*P.
På ett servo jag har kör jag P:1200, I:70, D:10000 och på ett annat P:450, I:18, D:2000
Skippa D till att börja med och sätt I till noll. Öka på P till den börjar självsvänga när du "stör" den, försök kompensera det med lite D. Öka P igen till den börjar självsvänga, kompensera med D. Prova sedan att lägga på lite I för att får bort eventuellt steady-state error som blir vid belastning och/eller högre hastighet.
Till sist, hur var det nu, kan din drivelektronik BÅDE 'driva' och 'bromsa' motorn eller kan den bara driva och sedan frihjula den?
På ett servo jag har kör jag P:1200, I:70, D:10000 och på ett annat P:450, I:18, D:2000
Skippa D till att börja med och sätt I till noll. Öka på P till den börjar självsvänga när du "stör" den, försök kompensera det med lite D. Öka P igen till den börjar självsvänga, kompensera med D. Prova sedan att lägga på lite I för att får bort eventuellt steady-state error som blir vid belastning och/eller högre hastighet.
Till sist, hur var det nu, kan din drivelektronik BÅDE 'driva' och 'bromsa' motorn eller kan den bara driva och sedan frihjula den?
Re: PID-reglering + stanna motor exakt
Tack för utmärkta tips, nu har jag en aning om var jag skall börja
. Jag driver motorn på ena hållet, sen kortsluter jag bara den för att bromsa, så i princip är det bara driva och frihjula som du säger. Så fort den röda, 'pidOut', går under noll så kortsluter jag motorn för att få den att stanna lite fortare. Allt över 1000 blir till 1000 som då är 100% duty cycle.
Re: PID-reglering + stanna motor exakt
Det där kan ju var lurigt eftersom det troligen inte blir symetriskt då. Jag menar att motorn kan accelerera hårdare än den kan retardera eller tvärt om, då "svarar" motorn annorlunda beroende på "polaritet" på signalen från regulatorn. +5 på utgången ger lite ström till motorn, +500 ger mycket ström till motorn. -5 ger kortsluten motor, -500 ger kortsluten motor.
Självklart beror det på belastningen på motorn och det 'ska' ju fungera men det kan nog vara klurigare att justera på ett bra ett sätt.
Självklart beror det på belastningen på motorn och det 'ska' ju fungera men det kan nog vara klurigare att justera på ett bra ett sätt.
Re: PID-reglering + stanna motor exakt
Min derivativa bit beter sig fortfarande inte riktigt som jag önskar.. Jag ställde in den proportionella först, till 50, så att den gick stabilt när den var obelastad men började svänga när jag lade ett finger på motorn. Efter det införde jag D-delen. Det som märktes mest var att den började självsvänga när den var obelastad, medan svängningarna när jag lade ett finger på förändrades väldigt lite.. upp till ungefär 50 på D-delen också fungerade, men när jag kom över det börjar den självsvänga väldigt mycket i obelastat läge, speciellt vid låga varvtal.
Här syns 50P + 5I + 500D med målvarvtal på 250RPM. Motorn stannar helt, sen går den upp till 1000RPM innan den stannar igen.. Samma inställning, men 1500RPM som målvarvtal istället. Här går den riktigt bra när den inte belastas. När den belastas på 1500RPM verkar den dock komma in i en självsvängning.. Den kombination som jag än så länge har hittat som fungerar bäst på både låga och högre varvtal är 50P + 5I + 40D. Den förändras inte så farligt mycket när den belastas vid 1500RPM. Finare inzoomning på en bit av ovanstående diagram: Obelastad på 1500RPM fungerar den mycket bra. Obelastad på 280RPM ser det relativt OK ut. Belastad på 280RPM: Inte klockrent direkt, men motorn är ju väldigt svårstyrd på såhär lågt varvtal.. (om jag inte har någon reglering är det lägsta varvtalet som jag kan få den att snurra i strax under 1000RPM...) -----------------
Kanske går det inte att få regleringen helt perfekt... Som sagt så kan jag bara driva på ena hållet. Motorn är väldigt snabb på att ändra varvtal så kanske hade högre uppdateringsfrekvens behövts. Min insignal har rätt låg upplösning, det är ett heltal som vid 280RPM ligger på 3 passerade spalter per interrupt, och vid 1500RPM är det 16 passerade spalter per interrupt.
Här syns 50P + 5I + 500D med målvarvtal på 250RPM. Motorn stannar helt, sen går den upp till 1000RPM innan den stannar igen.. Samma inställning, men 1500RPM som målvarvtal istället. Här går den riktigt bra när den inte belastas. När den belastas på 1500RPM verkar den dock komma in i en självsvängning.. Den kombination som jag än så länge har hittat som fungerar bäst på både låga och högre varvtal är 50P + 5I + 40D. Den förändras inte så farligt mycket när den belastas vid 1500RPM. Finare inzoomning på en bit av ovanstående diagram: Obelastad på 1500RPM fungerar den mycket bra. Obelastad på 280RPM ser det relativt OK ut. Belastad på 280RPM: Inte klockrent direkt, men motorn är ju väldigt svårstyrd på såhär lågt varvtal.. (om jag inte har någon reglering är det lägsta varvtalet som jag kan få den att snurra i strax under 1000RPM...) -----------------
Kanske går det inte att få regleringen helt perfekt... Som sagt så kan jag bara driva på ena hållet. Motorn är väldigt snabb på att ändra varvtal så kanske hade högre uppdateringsfrekvens behövts. Min insignal har rätt låg upplösning, det är ett heltal som vid 280RPM ligger på 3 passerade spalter per interrupt, och vid 1500RPM är det 16 passerade spalter per interrupt.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: PID-reglering + stanna motor exakt
Mmm, högre upplösning skulle nog inte skada - din upplösning är ju bara runt 100rpm/count så att säga. Så när din graf visar att motorn varierar +/-200 rpm så är ju inte det mer än +/-2 counts för regulatorn - det är inte mycket att jobba med.
Hur ofta kör du regulatorn? Om du inte kan öka upplösningen på "enkodern" så testa att inte köra regulatorn så ofta.
Hur ofta kör du regulatorn? Om du inte kan öka upplösningen på "enkodern" så testa att inte köra regulatorn så ofta.
