Care este rolul si cum functioneaza un PID control?
#63
Postat 11 May 2015 - 09:11 PM
Suruburile la motoare la placa din mijloc sunt stranse.
Placa din mijloc, defapt is doua plate-uri prinse intre ele chiar de brate este un textolit de 1.6mm (cam asa pare )
Nu am spatiu intre motor si elici, elicile sunt 9443 din carbon cu autostrangere pe filet de 6,
Frumos quad-ul tau homemade,
As incerca faza cu profilele de aluminiu macar cu doua motoare la un capat si senzorul pe mijloc si sa reusesc sa fac pid-ul ok ( stiu ca plant model-ul va fi diferit) .
Is constient ca imi era mult mai simplu sa cumpar o platforma gen multiwii sau ccd, insa asta a fost si idea de la inceput,
Acum daca fac lucrul asta se duce naibii toata munca/softeala cu care m-am chinuit, mai ales ca am reusit sa-i integrez si sistemul gps si wirelessul, si parca n-as da un imu facut pe arm 32biti cu un arduino :)
Nu imi este de banii cheltuiti ( in jur de 150 euro), daca ar fii as mai da inca odata atat dar sa stiu ca il fac cu mana mea sa zboare, daca ma intelegi :)
Mi-a crescut sufletul cand am vazut dupa esecul de acum 2 luni, cand am vazut ca incepe sa se tina vizibil mai bine.
Am stat aproape tot weekendul fiind singur acasa cu cabluri, matlab si nebunii incercand s-o fac sa stea macar in echilibru pe o axa. Asta vizavi de filmulete pe youtube cu
drone calibrate si prinse doar cu sireturi de pantofi de un cadru mai rigid :)
O sa vad in prima faza cu un cadru mai rigid ce reusesc.
Apropo, ansamblu motor/elice cum echilibreaza? se pune efectiv banda pe elice?
http://s21.postimg.org/druczktyb/IMG_20150511_214115.jpg
http://s1.postimg.org/rmhv16t7v/IMG_20150511_214449.jpg
#65
Postat 11 May 2015 - 10:32 PM
am reference point pt axa X setat manual pe 0.00
inputul in pid imi este un semnal ce imi vine din blocul imu respectiv intre 1.000 (pitch up) 0.000(perfect plan) -1.000(pitch down), valorile astea daca le imultesc cu
180/PI imi rezulta unghiurile lui euler.
eroarea pid-ului imi este practic 0 minus semnalul din IMU pe axa pitch (x)
apoi am un semnal de la telecomanda pt throttle,
Si imi rezulta asa
pwm1 = throttle_din_telecomanda - pid_output // valoarea pt esc motor1
pwm2 = throttle_din telecomanda + pid_output // valoarea pt esc motor2
Inamicul meu acolo sunt vibratiile, am vazut posturile lui hash/renatoa si voi renunta la ideea unei chestii soft intre motor-cadru.
Amu` astept sa-mi vina platforma aia antivibratie (3$ la chinezi ) + ceva suruburi M3 cu guma intre capeti...
Va tin la curent
#66
Postat 11 May 2015 - 10:39 PM
uint16_t pwm1=0; uint16_t pwm2=0; float iState,pTerm,dState; float wind=100; float output=0; float pGain=1.1000; float iGain=0.2000; float dGain=0.5000; error = 0.00 - xEulerAngles.m_fPitch; pTerm = pGain*error;// calculate proportional term iState += error; iState =constrain(iState, -wind,wind); iTerm = iGain * iState; // calculate integral term dTerm = dGain * (dState - xEulerAngles.m_fPitch); dState = xEulerAngles.m_fPitch; output= pTerm +dTerm+iTerm; // PID output if (TM_NRF24L01_DataReady()) { TM_NRF24L01_GetData(dataIn);} // preiau semnalul de throttle din telecomanda myremote(dataIn, remoteCh); throtlle=(remoteCh[3]*22.5); //22.5 constanta pt valori 1000 - 2000 pwm1=throtlle+output; pwm2=throtlle-output; motor1PWM(pwm1); // 1000 - 2000 range motor2PWM(pwm2); // 1000 - 2000 range
#67
Postat 12 May 2015 - 07:24 AM
moro696, la 11 May 2015 - 09:11 PM, a spus:
hash84, la 10 March 2015 - 09:56 PM, a spus:
motoarele toate se echilibreaza. si elicile la fel.
eu fac echilibrare dinamica a lucrurilor in felul urmator.
iei o bucata de banza izoliera si o pui pe una din palele elicii cam pe la mijloc. pornesti motorul, si vezi cum vibreaza. mai tare sau mai incet ca inainte.
daca vibreaza mai tare, muti band pe pala cealalta. o sa vibreze mai incet. muti banda mai sus sau mai aproape de axul elicii, tot facand incercari, pana obtii vibratii minime.
in felul asta echilibrezi ansamblul elice motor. daca desfaci elicea, si o sa o pui in alta pozitie fata de motor, trebuie sa reiei procedeul :).
placa se prinde de cadru prin scoci dublu adeziv din ala mai gros. eu cu asta am obtinut rezultate mai bune. a atenuat cel mai bine vibratiile
cadrul e bun. l-am avut si eu. doar ca e greu. cu 150g mai greu decat ala facut de mine din aluminiu.
tu echilibreaza ansamblul elice motor. cu cate un motor 1 data. pui pur si simplu banda pe o pala a elicii. de preferinta, iei sa zicem 1.5 cm de banda, si ii pui pe bordul de atac astfel incat sa ai 7.5mm deasupra elicii si 7.5mm sub elice folosind procedura de echilibrare de mai sus.
/------------------------\ |~~\_____/~~\__ | | Hash84 |______________ \______====== )-+ | | ~~~|/~~ | \------------------------/ ()
#68
Postat 12 May 2015 - 07:36 AM
Cand o zbura A.R.C.A.! © 2010 All rights reserved.
#70
Postat 12 May 2015 - 08:41 AM
Unghiurile sunt foarte stabile (lasat pe masa 24 ore nemiscat am drift +/- 0.3 grade) , nu imi fac griji pentru sistemul de orientare.
Legat de teste, sa zicem ca am vrut sa obtin un echilibru in "hover mode" unde ii dau o turatie fixa din telecomanda, iar diferenta o stabileste softul prin pid si deviatia
unghiulara... momentan o sa fac tot posibilul sa reduc vibratiile,
Legat de vibratii am vazut pe net ca o valoare acceptata ar fi undeva la +/- 0.05 G ca zgomot... daca stau sa compar cu zgomotul meu ( +/- 0.8-1g), diferenta este foarte mare...
hash84 o sa incerc astazi metoda ta cu banda izolatoare pe elicit, am o intrebare
Citeaza
#71
Postat 12 May 2015 - 08:56 AM
moro696, la 12 May 2015 - 08:41 AM, a spus:
Legat de vibratii am vazut pe net ca o valoare acceptata ar fi undeva la +/- 0.05 G ca zgomot... daca stau sa compar cu zgomotul meu ( +/- 0.8-1g), diferenta este foarte mare...
hash84 o sa incerc astazi metoda ta cu banda izolatoare pe elicit, am o intrebare care/ce este bordul de atac?
Nu pot sa cred ca le ai asa de mari, nu stiu cum ai masurat g-urile alea... am aceleasi motoare/elici si zboara fara nici o echilibrare :unsure:
In softul tau ai vreun low pass filter ?
Ce procesor ai, nu am gasit in prima pagina ce placa folosesti ?
Aceasta postare a fost editata de renatoa: 12 May 2015 - 08:57 AM
#72
Postat 12 May 2015 - 10:31 AM
Eu in secventa am asa
citesc toti senzorii cu 100hz rate
filtrez cele 3 axe ale acelerometrului cu un lpf 4 order la 200hz , toate astea le fac intr-o rutina ce ruleaza la fiecare 5ms ( 200hz rate )
Procesorul este un arm m4 ( stm32f4) placa in stadiul actual este o placa pt dezvoltare Discovery F4. Pe cadrul dronei fiind montat doar un mic pcb de 3x3cm care contine senzorii.
Sistemul de rulare se foloseste in principal de intreruperea sysclock-ului, care incremeneaza o variabila counter la fiecare milisecunda ( sistemul ruland cu un fosc de 168MHZ)
apoi cand counterul ajunge la 5 ( 5 milisecunde) execut o bucla if in main loop , iar in acel if sunt executate functiile pt calcul unghiuri, calcul pid-uri si setare esc-uri.
cand counterul ajunge la valoare 10 ( 10 miliescunde) execut o alta bucla if aflata in main loop, iar acolo citesc gyro,acc, si mag.
Output-ul intern al senzorilor este setat la 400hz ( ODR), fiind mai rapid decat face programul (200hz)
Mai jos este codul pentru system clock si programul principal si cum se face achizitia datelor de la senzori, si control motoare
renatoa tu ce valori ai pt pid cu motoarele si elicile acelea?
Ma gandesc sa schimb putin abordarea software fata de softul current de mai jos, respective sa folosesc 2 timere distincte cu intreruperi prioritizate ca si level.
Respectiv timer1 la 10ms masor senzorii, in tot acest timp timer2 nu executa nimic, abia dupa ce termina timer1 de executat intreruperea, sa urmeze executia intreruperii timer2 la fiecare 5 ms ( 200hz)
Spun asta pentru am o banuiala, atunci cand incep sa numar de la 10 sa zicem am eventul de 10ms, ajung cu numaratoarea la 15ms, si execut eventul de 5 ms, apoi iar ajung la 20ms si imi executa doua eventuri in paralel
Sunt ferm convins ca ceva imi scapa, un detaliu oricat de mic, nu pot sa cred ca sunt oameni care isi calibreaza dronele folosind sireturi de la pantofi sau cazul lui renatoa fara
sa echilibreze nimic la motoare elici.
Negru`i dracu doamne
uint8_t frame_200Hz = 0; uint8_t frame_100Hz = 0; #define COUNT_200HZ 5 #define COUNT_100HZ 10 #define FRAME_COUNT 1000 uint32_t deltaTime1000Hz,previous1000HzTime; static volatile uint32_t sysTickUptime = 0; static volatile uint32_t sysTickCycleCounter = 0; static volatile uint32_t usTicks = 0; static volatile uint32_t frameCounter=0; static void cycleCounterInit(void) { RCC_ClocksTypeDef clocks; RCC_GetClocksFreq(&clocks); usTicks = clocks.SYSCLK_Frequency / 1000000; // enable DWT access CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // enable the CPU cycle counter DWT_CTRL |= CYCCNTENA; } uint32_t micros(void) { register uint32_t oldCycle, cycle, timeMs; __disable_irq(); cycle = *DWT_CYCCNT; oldCycle = sysTickCycleCounter; timeMs = sysTickUptime; __enable_irq(); return (timeMs * 1000) + (cycle - oldCycle) / usTicks; } void SysTick_Handler(void) { uint8_t index; uint32_t currentTime; sysTickCycleCounter = *DWT_CYCCNT; sysTickUptime++; frameCounter++; // incrementez counter sysclock general pana la valoarea maxim admisa de frame_cout, respectiv 1ms (1000 microsecunde) if (frameCounter > FRAME_COUNT) frameCounter = 1; currentTime = micros(); deltaTime1000Hz = currentTime - previous1000HzTime; previous1000HzTime = currentTime; if ((frameCounter % COUNT_100HZ) == 0) { frame_100Hz = 1; } // cand ajung la 10 numaratori de sysclock setez flag-ul pt executia buclei de 100hz in main program if ((frameCounter % COUNT_200HZ) == 0) { frame_200Hz = 1; } // cand ajung la5 numaratori de sysclock setez flag-ul pt executia buclei de 200hz in main program } /////////////////////// DE JOS INCEPE PROGRAMUL PRINCIPAL ////////////////////////////// void main(void) { // initializare pid-uri float pGain=1.1000; float iGain=0.2000; float dGain=0.5000; SystemInit(); cycleCounterInit(); // pornesc sysclock SysTick_Config(SystemCoreClock / 1000); ////// initializez senzorii, pwm-uri etc etc /////////////// while(1) { // de aici incepe loop-ul programului principal if(frame_100Hz==1){ // cand systick numara 10 milisecunde se steaza flag-ul frame_100hz pe 1 si execut if-ul GPIO_ToggleBits(GPIOD, GPIO_Pin_14); // fac led-ul sa jongleze Lsm303dlhcMagReadMag(fMagXYZ); // citesc magnetometrul L3gd20ReadAngRate(fGyroXYZ); // citesc gyro Lsm303dlhcAccReadAcc(fAccXYZ); // citesc accelerometru frame_100Hz=0; // curat if-ul pana la urmatoarea numaratoare } // sfarsitul if de 100hz if(frame_200hz ==1){ // cand sysclock ajunge la 5ms incep si execut bucla aceasta xSensorData.m_fAcc[0]=fAccXYZ[0]*9.8f/1000.0f; xSensorData.m_fAcc[1]=-fAccXYZ[1]*9.8f/1000.0f; xSensorData.m_fAcc[2]=-fAccXYZ[2]*9.8f/1000.0f; xSensorData.m_fMag[0]=fMagXYZ[0]/1000.0; xSensorData.m_fGyro[0]=fGyroXYZ[0]*3.141592f/180.0f; xSensorData.m_fMag[1]=-fMagXYZ[1]/1000.0; xSensorData.m_fGyro[1]=-fGyroXYZ[1]*3.141592f/180.0f; xSensorData.m_fMag[2]=-fMagXYZ[2]/1000.0; xSensorData.m_fGyro[2]=-fGyroXYZ[2]*3.141592f/180.0f; update_imu(&xSensorData, &xEulerAngles, &xQuat); // calculeaza unghiurile in baza datelor de la senzori xEulerAngles.m_fPitch = xEulerAngles.m_fPitch * 180/PI; // convertesc in grade axa X ( pitch-ul) if (TM_NRF24L01_DataReady()) { TM_NRF24L01_GetData(dataIn);} // citesc canalul pt throttle din telecomanda myremote(dataIn, remoteCh); throtlle=(remoteCh[1]*22.5); // 1000 - 2000 xEulerAngles.m_fPitch=computeFourthOrder200Hz(xEulerAngles.m_fPitch, &fourthOrder200Hz); //filtrez suplimentar unghiul pitch error = 0.00 - xEulerAngles.m_fPitch; pTerm = pGain*error;// calculate proportional term iState += error; iState =constrain(iState, -wind,wind); iTerm = iGain * iState; // calculate integral term dTerm = dGain * (dState - xEulerAngles.m_fPitch); dState = xEulerAngles.m_fPitch; output= pTerm +dTerm+iTerm; // PID output pwm1=throtlle+output; pwm2=throtlle-output; motor1PWM(pwm1); // load pwm in esc1 motor2PWM(pwm2); // load pwm in esc2 frame_200Hz=0; // curat flag-ul de 200hz pana la urmatoarea numaratoare } // sfarsitul if-ului de 200hz } }
#73
Postat 12 May 2015 - 10:49 AM
moro696, la 12 May 2015 - 10:31 AM, a spus:
renatoa tu ce valori ai pt pid cu motoarele si elicile acelea?
...
Spun asta pentru am o banuiala, atunci cand incep sa numar de la 10 sa zicem am eventul de 10ms, ajung cu numaratoarea la 15ms, si execut eventul de 5 ms, apoi iar ajung la 20ms si imi executa doua eventuri in paralel
Sunt ferm convins ca ceva imi scapa, un detaliu oricat de mic, nu pot sa cred ca sunt oameni care isi calibreaza dronele folosind sireturi de la pantofi sau cazul lui renatoa fara sa echilibreze nimic la motoare elici.
...
Valorile PID de la multiwii/baseflight probabil ca sunt nerelevante pentru alt controller/algoritm
Pentru banuiala aia... foloseste un semafor
Oamenilor le zboara din prima pentru ca folosesc softuri deja maturizate... pana la urma vrei sa zbori sau sa redescoperi elicea ? :)
#74
Postat 12 May 2015 - 11:01 AM
trebuie sa o faci intr-o intrerupere atunci cand pinul de semnal devine high.
nu ai pus codul complet de la :
if (TM_NRF24L01_DataReady()) { TM_NRF24L01_GetData(dataIn);} // citesc canalul pt throttle din telecomanda myremote(dataIn, remoteCh);
tu cum citesti impulsul ala care trebuie sa fie intre 1 si 2 ms ?
astepti sa fie low si apoi sa fie high si contorizezi pana se face iar low ?
/------------------------\ |~~\_____/~~\__ | | Hash84 |______________ \______====== )-+ | | ~~~|/~~ | \------------------------/ ()
#75
Postat 12 May 2015 - 11:13 AM
deocamdata trimit un semnal constant ca valoare, nu citesc potentiometre.
Initializez prima oara esc-urile cu 1000 minim si 2000 maxim.
In telecomanda am un microcontroller cu 2 butoane + si - pt throttle, fiind totul in faza de prototip, eu ce fac este sa incrementez sau sa decrementez valoarea de la 0 la 45 apoi o
trimit pe wifi in drone. Nu folosesc potentiometru tocmai din considerentul acesta ca imi poate varia degetul pe stick, si implicit throttle nu va fi constant.
in momentul cand chipul radio a primit buffer complet de date, umple valoarea in variabila remotech.
Acea valoare nu se modifica daca sa zicem se intrerupe semnalul de la telecomanda, bufferul tine ultima valoare citita. deci flowul de date este stabil.
#76
Postat 12 May 2015 - 11:18 AM
ai o greseala undeva :)
/------------------------\ |~~\_____/~~\__ | | Hash84 |______________ \______====== )-+ | | ~~~|/~~ | \------------------------/ ()
#77
Postat 12 May 2015 - 11:24 AM
#81
Postat 12 May 2015 - 10:51 PM
Timp am, is tanar, nervi mai am :)) Pt moment astept noul microcontroler, oricum era in plan sa achizitionez alte controlere, deoarece acesta are multe write/erase la activ
Daca vruiam una gata de zbor, imi luam la pachet totul facut... Unii poate nu ma inteleg, si eu ii inteleg, ideea a pornit sa-mi fac acest proiect in niciun caz cu vreun scop
comercial mai mult de dragul diy from scratch si de ce nu chiar sa-mi dau licenta peste 3 ani :)
Vreo doua saptamani o sa fiu plecat in concediu, dar revin.I will be back :ph34r:
#82
Postat 14 May 2015 - 01:58 PM
moro696, la 12 May 2015 - 10:31 AM, a spus:
filtrez cele 3 axe ale acelerometrului cu un lpf 4 order la 200hz , toate astea le fac intr-o rutina ce ruleaza la fiecare 5ms ( 200hz rate )
Sper ca iti dai seama ca orice lowpass peste 50Hz este complet inutil atunci cand ai 100Hz sample rate. Nyquist theorem... d'oh.
Cat despre cod, sincer mi-a fost lene sa il analizez in detaliu, dar am observat cateva lucruri legate de PID:
- ai amestecat calculul pid cu restul, ar trebui sa bagi ce tine de pid intr-un header.
- nu ai folosit lowpass pe derivative, foarte important.
Daca vrei sa reusesti, incepe de jos, nu te arunca in sisteme complexe fara sa ai o baza solida.
Aceasta postare a fost editata de Zen: 14 May 2015 - 01:58 PM
#83
Postat 21 May 2015 - 07:29 AM
multumesc pt sfaturi, intre timp noul microcontroler este pe drum.
Ultima oara cand am incercat stiu ca citeam senzorii + pid in bucla de 200hz si rezultatele erau vizibil mai ok, in sensul ca aveam reactie mai prompta cand modificam pid-ul. Senzorii la nivel de registrii is configurati la 400hz ODR.
De exemplu la naze32 in aceasi bucla (care daca nu ma insel ruleaza pe la 280hz) ia date de la senzori, calculeaza orientarea si pid-urile.
Prin header te referi sa fac pid-ul ca pe o functie discreta, gen getpid(input,KP,KI,KD,output) ?
#84
Postat 23 May 2015 - 03:50 PM
Sample rate-ul intern al senzorilor nu conteaza decat daca aplici LPF intern (mpu6050 are optiunea asta), in rest conteaza doar la ce sample rate ii citesti efectiv.
Si da, functie separata, valabil pentru orice... e mai usor de observat erori, testat, etc.