Sida 2 av 4
Postat: 26 mars 2007, 00:43:39
av $tiff
Chribbe76 skrev:Din motor kommer helt enkelt få PWM (spänning), Strömbegränsningen är bara ett skydd.
I mina servo-tester har PID'en bara styrt motor-strömmen (linjär-regleras med opamp) vilket ger ett korrekt resultat.
Enligt mina personliga teorier krävs det ett beräknings-steg mellan PID'en och motorns PWM-värde om man ska köra med PWM, har man ingen beräkning mellan så kommer regleringen bli väldigt dålig.
Det ska bli mycket intressant att se resultatet när du styr motorn utan denna extra beräkning.
Det är helt rätt att börja "basic" och höja ribban senare.
Det är inte bara dina egna teorier som säger att en motor inte går att reglera speciellt bra med en enkel PID-regulator med avseende på varvtal (eller position). Eftersom hela kedjan (vartalsreferens -> vridmoment(rotorström) -> rotorspänning) innehåller två integratorer blir det svårt att få till en stabil regulator med vettiga prestanda enbart med den konventionella PID-regulatorn.
För att lösa detta bättre kan man antingen använda en mer avancerad (tillståndsåterkopplad) regulator eller så kaskadkopplar man flera P(I)-regulatorer. Mao bör man ha en relativt enkel men snabb regulator för att hantera ett börvärde i rotorströmm med rotorspäning som styrsignal. Utanpå denna lägger man en regulator med varvtal som börvärde och rotorström som styrsignal.
Men, jag håller med Chribbe76 om att det är bäst att börja på lagom nivå. När man trimmat sig till vanvett vet man att det är dags att använda en annan regulator och försöka igen.
Postat: 4 april 2007, 00:02:26
av JBV
Nu har jag börjat experimentera och koda lite!!
Hittade just lite intressant info!
http://bestune.50megs.com/typeABC.htm
Typ C kanske vore det man ska satsa på!?
Postat: 4 april 2007, 23:46:10
av JBV
Synpunkter på min enkoder input?
Kod: Markera allt
void ENCODER_Init()
{
cbi(DDRD, DDD2);
cbi(DDRD, DDD3);;
EIMSK |= _BV(INT0) | _BV(INT1);
EICRA |= _BV(ISC00);
EICRA |= _BV(ISC10);
}
ISR(INT0_vect) //A
{
if(bit_is_set(PIND, PD2)) //rising edge
{
if(bit_is_set(PIND, PD3))
{
ProcessVariable--;
} else {
ProcessVariable++;
}
} else { //falling edge
if(bit_is_set(PIND, PD3))
{
ProcessVariable++;
} else {
ProcessVariable--;
}
}
}
ISR(INT1_vect) //B
{
if(bit_is_set(PIND, PD3)) //rising edge
{
if(bit_is_set(PIND, PD2))
{
ProcessVariable++;
} else {
ProcessVariable--;
}
} else { //falling edge
if(bit_is_set(PIND, PD2))
{
ProcessVariable--;
} else { //Else increment
ProcessVariable++;
}
}
}
Det fungerar sådär, tappar steg om jag vrider för fort, men det beror förhoppningsvis på att jag använder en mekanisk pulsgivare i stil med dennna:
http://www.elfa.se/elfa-bin/dyndok.pl?dok=2030.htm
Postat: 4 april 2007, 23:53:48
av strombom
Små avkopplingskondensatorer kanske behövs?
Så här såg koden ut när jag använde exakt en sådan enkoder du visade bild på (kommer inte ihåg varför det är en delay där i koden):
Kod: Markera allt
u08 navigatorState;
#define navigatorStateMax 2
void initNavigator()
{
SFIOR &= ~(1<<PUD);
// Set Nav-ports to input w/ pullup
DDRD &= ~(1<<NAV_A) & ~(1<<NAV_B) & ~(1<<NAV_BTN);
PORTD |= (1<<NAV_A) | (1<<NAV_B) | (1<<NAV_BTN);
// Trig on falling edge
cbi(EICRA, ISC00);
sbi(EICRA, ISC01);
cbi(EICRA, ISC10);
sbi(EICRA, ISC11);
//Enable interrupts
sbi(EIMSK, INT1);
}
ISR(SIG_INTERRUPT1)
{
u16 delay, a;
for(delay=0;delay<550;delay++)
for(a=0;a<10;a++);
if((EICRA & (1<<ISC10)) == 0)
{
sbi(EICRA, ISC10);
if((PIND & (1<<NAV_B)) != 0) {
if(navigatorState == navigatorStateMax)
navigatorState =0;
else
navigatorState++;
} else {
if(navigatorState == 0)
navigatorState = navigatorStateMax;
else
navigatorState--;
}
}
else
{
cbi(EICRA, ISC10);
if((PIND & (1<<NAV_B)) == 0) {
if(navigatorState == navigatorStateMax)
navigatorState =0;
else
navigatorState++;
} else {
if(navigatorState == 0)
navigatorState = navigatorStateMax;
else
navigatorState--;
}
}
updateLedDrivers();
}
Postat: 5 april 2007, 00:01:28
av JBV
Ska testa imorrn! Jag skulle ju iofs även kunna pröva simulera AB genom datorn! då märks det ju snabbt om man tappar pulser!
Vet någon var man kan få tag på vinklade läsgafflar (så dom läser i samma plan som kretskortet)? Tänkte pröva bygga en egen enkoder!
Btw så triggar jag på logical change!
Postat: 5 april 2007, 12:00:09
av Nihilim
Jag kanske kan låna ut en encoder om det finns intresse. Har tillgång till ett gäng relativt högupplösta optiska varianter.
Postat: 5 april 2007, 12:30:44
av $tiff
Exakt vad jag svamlade om i mitt förra inlägg! Välj typ C och slipp många problem från början!

(Å andra sidan missar du kanske nöjet att uppleva och åtgärda problemen)
Postat: 5 april 2007, 13:00:18
av JBV
Hehe känns lite baklänges att välja en sämre variant när man har informationen serverad

Jag lär väl pröva en P regulator först bara för att få nånting att snurra
Nihilim: Tack för erbjudandet, men jag tror jag ska försöka bygga en själv! Hade jag bara haft en schmitt trigger hemma hade jag offrat en gammal datormus!
Jag försöker få igång pin change interrupt för Step ingången men det händer inget! Har jag missat något?
Kod: Markera allt
void INPUT_Init()
{
cbi(DDRC, DDC0); //Step
cbi(DDRC, DDC1); //Dir
cbi(DDRC, DDC2); //Enable
PCMSK1 |= _BV(PCINT8);
}
ISR(PCINT1_vect) //Step
{
USART_Transmit('x'); //Debug
if(bit_is_set(PINC, PC0)) //Step
{
if(bit_is_set(PINC, PC1)) //Dir
{
SetPoint++;
} else {
SetPoint--;
}
}
}
Postat: 5 april 2007, 13:17:05
av JBV
Nu löste jag problemet! Hade missat PCICR |= _BV(PCIE1);
Postat: 5 april 2007, 21:23:26
av JBV
Nu blev det för mycket på experimentplattan så jag ritade ihop ett kretskort! Det är bara för lite experiment så jag har inte lagt ner allt för mycket tid!
Skulle jag få igång allt ska jag försöka få ner det på ett 100*75 mm kretskort med ytmonterade komponenter!
Stor bild!
Postat: 11 april 2007, 02:00:10
av JBV
Kretskortet är klart och verkar fungera som tänkt! Har testkört lite med den här koden:
Kod: Markera allt
void PID_Init()
{
sbi(TCCR0B, CS00);
sbi(TCCR0A, WGM00);
sbi(TCCR0A, COM0A1); //Output A
sbi(DDRD, PD6);
OCR0A = 0x00;
sbi(TCCR0A, COM0B1); //Output B
sbi(DDRD, PD5);
OCR0B = 0x00;
}
void PID()
{
OCR0A = 0x00;
OCR0B = 0x00;
int PWM = 0;
int Error = SetPoint - ProcessVariable;
PWM = Error * 4;
if(PWM < 0) //Output A, negative error
{
PWM = abs(PWM);
if(PWM > 200) PWM = 200;
OCR0A = PWM;
} else if(PWM > 0) //Output B, positive error
{
if(PWM > 200) PWM = 200;
OCR0B = PWM;
}
}
Har testat med lysdioder på µC utgångarna och det fungerar som väntat efter koden! Har även testat med gate driver kretsarna ikopplade men då fungerar bara utgång B! Jag har även bytt plats på dom och även då fungerar bara utgång B, så jag tvingas löda lös och byta FET:arna imorrn! Vet inte vad som gick fel

Postat: 11 april 2007, 02:17:44
av Andax
JBV och Strombom, den mekaniska enkodern som ni körde med (den som ELFA hade) hur är friktionen i den? Snurrar den lätt? (gissar/hoppas att ni körde med den utan distinkta lägen)
Postat: 11 april 2007, 02:35:39
av JBV
Den jag har är med distinkta lägen och passar verkligen inte för det här! Det är bara för att experimentera lite tills jag orkar bygga nå vettigare

Postat: 11 april 2007, 07:30:39
av strombom
Jag har testat två från elfa, en som är grön tror jag, den har distinkta lägen, en som var helt metallfärgad, den hade inte lika tydliga lägen men var lite "seg".
Jag har även sett ett instrument som hade en:
http://www.elfa.se/elfa-bin/dyndok.pl?l ... 130152.htm
Den användes till en stor ratt, extremt lättsnurrad och bra känsla... och dyr

Postat: 11 april 2007, 11:35:59
av Andax
Hittade en enkoder från Bourns modell ECW1J-B24-AC0024 med distinkta steg. Öppnade den för att se hur den funkade...
Det var en mycket enkel konstruktion. Ska se om jag kan få upp några bilder om någon är intresserad.
Ska försöka modda den så att jag kan använda den för positionsåtermatningen av min
inverterade pendel.
Att få bort de distinkta stegen var lätt... Det var bara att vända bladfjädern i enkodern 180 grader eftersom stegen alstrades av ett litet veck på fjädern.