peppe855 Inserito: 20 agosto 2016 Segnala Inserito: 20 agosto 2016 Buon giorno a tutti, sto' utilizzando un dspic30f6010a ed ho "scoperto" la libreria DSP che tra le altre cose contiene la funzione PID. Senza dilungarmi troppo vedo che il calcolo dell'OUTPUT viene cosi' implementato:controlOutput[n] = controlOutput[n-1]+ controlHistory[n] * abcCoefficient[0]+ controlHistory[n-1] * abcCoefficient[1]+ controlHistory[n-2] * abcCoefficient[2]where,abcCoefficient[0] = Kp + Ki + KdabcCoefficient[1] = -(Kp + 2*Kd)abcCoefficient[2] = KdControlHistory[n] =MeasuredOutput[n] - ReferenceInput[n]dove il calcolo di abcCoefficient se lo fa' lui richiamando una delle tre funzioni PID mentre a me tocca inserire Kp Ki e Kd (dichiarate come fractional) percui mi chiedo ma il Td è sottointeso nel valore da me inserito in Ki e Kd visto che nel calcolo di abcCoefficient non c'è traccia? Inoltre aprendo un esempio microchip dove si fa uso delle tre funzioni PID noto che Kp Ki Kd sono forniti nel seguente modo: kCoeffs[0] = Q15(0.7); kCoeffs[1] = Q15(0.2); kCoeffs[2] = Q15(0.07); il vettore che contiene i kCoeffs è dichiarato fractional. Aprendo l'Header file dsp.h mi accorgo che chiamando Q15(x) lui fa' questo calcolo: #define Q15(X) \ ((X < 0.0) ? (int)(32768*(X) - 0.5) : (int)(32767*(X) + 0.5)) che non ho assolutamente compreso, perchè se la interpreto come una divisione allora qualsiasi valore ci metta ad X il risultato mi viene sempre uguale ad 1 per via del casting int fatto al dividendo e divisore comunque facendo un debug vedo che ad esempio Q15(0.7) viene trasformato in un numero pari a 0.7x2^15 cioè nel formato Q15 PERO' visto che sicuramente il mio Kp sarà maggiore di 1 come lo si riporta in formato Q15? (Non credo si faccia ad esempio se Kp=30 allora 30x2^15) Un saluto
Ctec Inserita: 20 agosto 2016 Segnala Inserita: 20 agosto 2016 Io i Pic non li conosco affatto. Ti posso però dire che la #DEFINE sostituisce Q15(X) con l'operatore ternario (.. ? .. : ..). E funziona così: se X <0.0, sostituisce con (int)(32768*(X) - 0.5) altrimenti con (int)(32767*(X) + 0.5). In pratica effettua una moltiplicazione con arrotondamento per eccesso. Poi che in una PID non possa essere Kp inferiore o uguale a 1, non è mica vero...
peppe855 Inserita: 20 agosto 2016 Autore Segnala Inserita: 20 agosto 2016 Ciao Ctec grazie per l'intervento molto chiaro, pero' non discuto che un Kp possa valere meno di 1 ma non capisco se vale piu' di uno come faccio a restare coerente con questo formato??
Ctec Inserita: 20 agosto 2016 Segnala Inserita: 20 agosto 2016 Supponiamo di avere il primo caso Q15(0.7). Per quanto detto lo traduce in (int)(32768*(0.7)+0.5) => (int)(22937.6 + 0.5) => (int)(22938.1) => 22938 Il casting a (int) viene effettuato alla fine, mentre tutti i calcoli dentro la parentesi successiva al casting vengono fatti in float, essendo 0.5 di questo tipo. Il compilatore nelle operazioni eleva sempre al tipo "più capiente" tutti gli elementi dell'espressione in gioco, fa le operazioni con questo tipo, poi se specificato esegue il casting specificato. E' il cosiddetto casting automatico.
peppe855 Inserita: 20 agosto 2016 Autore Segnala Inserita: 20 agosto 2016 Quello che pero' non mi risulta chiaro è se Kp invece di essere 0.7 è ad esempio 20 come lo trasformo in Q15??
Ctec Inserita: 21 agosto 2016 Segnala Inserita: 21 agosto 2016 La #define è una macro. Sostituisce letteralmente quello che è scritto con Q15(X) con quella specie di formuletta, mettendo il valore di X nella Q15(X) dentro la X che c'è nella definizione. Pertanto, se te scrivessi Q15(20), il compilatore lo sostituirebbe con (int)(32768*(20)+0.5) => (int)(655360 + 0.5) => (int)(655360.5) => 655360 Se hai ulteriori dubbi, consiglio una lettura al Kernigan Ritchie...
peppe855 Inserita: 21 agosto 2016 Autore Segnala Inserita: 21 agosto 2016 Ctec ancora grazie per la pazienza, pero' scusa 655360 non puo' piu' essere considerato in formato Q15 poichè non ci entra nei 16bit ! Io penso che andrebbe fatta una scalatura a monte mi spiego: ho Kp=20; Ki'=Ki*Td=0.2; Kd'=Kd/Td=0.04; allora faccio Kp+Kd+Ki'=20.24; quindi assumo Base=20.24; e faccio Kp'=20/BASE Ki''=0.2/BASE Kd'=0.04/BASE La funzione PID() nei suoi calcoli si va' a prendere Riferimento=Q15(x); Output=Q15(x); e quindi mi chiedo come scalo questi valori? usando Base=20.24 non avrei un valore <1 poichè il riferimento ad esempio viene dall'ADC e restituisce un valore da 0-1024; Io farei una cosa del genere: Scalo i parametri del regolatore come detto sopra invece per il setpoint (che proviene da adc a 10bit) e la misura dell'uscita (in questo caso velocità motore che esce con un numero compreso tra +- 600) farei cosi: La misura da adc me la faccio dare in formato Q15 cioè con il MSB in posizione [15] ovvero ad esempio 0111111111 000000; La misura di velocità per confrontarla con il numero dell'adc la shifterei di 5 bit a sinistra esempio 0110001101 000000; Il PID mi restituira' l'uscita a 16 bit in formato Q15 che io dovro' manipolare per darlo in pasto al mio PWM che per le scelte fatte accetta un valore da 0-4096, e questo lo faccio cosi: (uscitaPID<<1)>>4; (nella prima parentesi elimino il segno, con la seconda operazione scalo tra 0-4096) che chiaramente si puo' fare UscitaPID>>3; Resta' pero' il fatto che i parametri del pid sono stati scalati con BASE e non avendo io accesso alle operazioni intermedie fatte dalla funzione PID che mi da' direttamente l'uscita come tengo conto di quella scalatura fatta prima? Spero si sia capito qualcosa.
Ctec Inserita: 21 agosto 2016 Segnala Inserita: 21 agosto 2016 Peppe, io stavo solo parlando della sintassi del C. Come ho detto, i PIC non li conosco, uso altra roba (8051 derivati e ARM CORTEX). In particolare per questi ultimi, gli int sono a 32bit... Per i primi a 16bit.. Normalmente la dimensione dipende dal compilatore... Non so assolutamente la dimensione di un int per un dspic... Per il resto, mi sa che dovrai chiedere a chi si intende di tali micro e chi ha visto le librerie in questione...
Messaggi consigliati
Crea un account o accedi per commentare
Devi essere un utente per poter lasciare un commento
Crea un account
Registrati per un nuovo account nella nostra comunità. è facile!
Registra un nuovo accountAccedi
Hai già un account? Accedi qui.
Accedi ora