ELSA Online: 12. Regulačné obvody: Rozdiel medzi revíziami
Z SensorWiki
(Vytvorená stránka „Použijeme: ARDUINO Kondenzátory 1 uF a 100 uF. Rezistor 10 kΩ Programy ... Úlohy: Identifikujte parametre regulovanej sústavy – RC člen. Rezistor 10 kΩ…“) |
|||
(2 medziľahlé úpravy od rovnakého používateľa nie sú zobrazené.) | |||
Riadok 1: | Riadok 1: | ||
− | + | '''Úlohy:''' | |
− | |||
− | |||
− | |||
+ | * Identifikujte parametre regulovanej sústavy | ||
+ | ** Sústavu predstavuje RC člen, pozostávajúci z rezistora 10 kΩ a kondenzátora 1µF resp. 100 µF. Použite pripravený program: ( → [[#program1]]) | ||
+ | <BR> | ||
+ | * Pre RC člen (10 kΩ a 100 µF) navrhnite P regulátor. Upravte - doplňte pripravený program: ( → [[#program2]]) | ||
+ | ** Vysvetlite, prečo nedosiahneme dobré výsledky pre časovú konštantu 10ms. | ||
+ | ** Navrhnite P (zosilnenie 1, 2 a 3) regulátor pre časovú konštantu 1s a vypočítajte trvalú regulačnú odchýlku pre w_zel = 3V. | ||
+ | ** Výsledky porovnajte s nameranými. | ||
+ | ** Ako sa mení dynamika uzatvoreného regulačného obvodu? | ||
+ | <BR> | ||
+ | * Bonus. Doplňte program regulátora o I zložku a navrhnite parametre. | ||
+ | ** Najskôr použite celočíselnú aritmetiku. Vysvetlite prečo vznikne trvalá regulačná odchýlka aj pre PI regulator. | ||
+ | ** Použite Float aritmetiku. Doplňte program o zmenu záťaže. Vypočítajte a meraním overte veľkosť trvalej regulačnej odchýlky pri skokovej zmene záťaže. | ||
− | + | ||
+ | |||
+ | '''Poznámky:''' | ||
+ | * Nezabudnite zapojiť na výstup PWM signálu filter. | ||
+ | * Nepoužité OZ v púzdre je v hodné „ošetriť“. | ||
+ | * Nepoužitý vstup A/D prevodníka je vhodné „ošetriť“. | ||
+ | * Nezabudnite, vnútorný odpor zdroja má byť oveľa menší ako je odpor záťaže. | ||
+ | |||
+ | |||
+ | |||
+ | '''Použijeme:''' | ||
+ | * Arduino | ||
+ | * Kondenzátory 1 µF a 100 µF. Rezistor 10 kΩ | ||
+ | * Programy ... | ||
+ | |||
+ | |||
+ | Návod viď príloha v classroome a vysvetlivky na cvičení. | ||
+ | |||
+ | |||
+ | <div id="program1"></div> | ||
+ | <tabs> | ||
+ | <tab name="Meranie prechodovej charakteristiky.ino"><syntaxhighlight lang=c style="background: Cornsilk"> | ||
+ | // Meranie prechodovej charakteristiky | ||
+ | // Použijeme Serial Plotter | ||
+ | |||
+ | #define C_1uF // | ||
+ | #define SerialPlotter // | ||
+ | //#define C_100uF // | ||
− | + | // -------------------------- | |
− | + | // Program pre vykreslenie prechodovej charakteristiky RC člena | |
− | + | // Použite 100uF a 1.0 uF kondezátor | |
− | + | // pinA je vždy zapojený cez 10kOhm rezistor ako OUTPUT. | |
− | + | // pinB je najskôr zapojený ako output a následne nastavený do log. nuly. | |
− | + | // pinB a A0 sú skratnuté. | |
− | + | // za cca 1sekundu (delay(1000)) po resete bude kondenzátor určite vybitý. Potom sa | |
− | + | // pinB prepne do stavu input bez pullup a kondenzátor sa začne nabíjať. | |
− | + | // Keď program dosiahne čas 10*T (T - časová konštanta RC člena) vykreslovanie sa zastaví. | |
− | + | // príkaz micros() vracia systémový čas v us od spustenia programu ako "long" číslo. | |
− | + | // Vykreslovanie na Serial Plotter sa deje v diskrétnom čase. Každých n*Ts (n = 0, 1, 2, ...), | |
− | + | // kde Ts je perióda vzorkovania. | |
− | + | // Vykreslovanie je v pomerných jednotkách. 1SJ = 1023 (10b-ový prevodník). | |
+ | // 1SJ odpovedá napätiu 5V | ||
+ | // Vykreslujú sa tri čiary: | ||
+ | // 1.) Uc, 2.) 1023 (5V) a 3.) 647 = int(0.632*1023) | ||
+ | |||
+ | int pinA = 2; | ||
+ | int pinB = 3; | ||
+ | long t_0_tau = 0; | ||
+ | long Zac_time = 0; | ||
+ | long Kon_time = 0; | ||
+ | long tau = 0; // časová konštanta RC člena | ||
+ | |||
+ | #ifdef C_100uF // T = R*C = 10kOhm*100uF = 1000ms = 1s | ||
+ | // Doplňte | ||
+ | #endif | ||
+ | |||
+ | #ifdef C_1uF // T = R*C = 10kOhm*1uF = 10ms | ||
+ | long Ts = 1000; // 1ms | ||
+ | int t_diskr = 0; // nacitavam pocet Ts | ||
+ | // Dvojnásobok ustálenia prechodovej chrakteristiky: | ||
+ | int t_diskr_kon = 100; // ((2 * 5T) = 0,1sek)/ (Ts = 1 ms)) = 100; | ||
+ | #endif | ||
+ | |||
+ | |||
+ | void setup() { | ||
+ | // úvodná inicializácia | ||
+ | pinMode (pinA, OUTPUT); | ||
+ | digitalWrite(pinA, HIGH); | ||
+ | pinMode (pinB, OUTPUT); | ||
+ | digitalWrite(pinB, LOW); | ||
+ | Serial.begin(115200); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | int nap = 0; | ||
+ | // počkám na ustálenie sa pomerov na RC | ||
+ | delay(1000); // 1000ms | ||
+ | |||
+ | Zac_time = micros(); | ||
+ | // výpis v čase t = 0.0 s | ||
+ | t_0_tau = Zac_time; | ||
+ | nap = analogRead(0); // Počiatočná hodnota napätia na kondenzátore | ||
+ | pinMode (pinB, INPUT); // Od tohto okamžiku sa začne kondenzátor nabíjať | ||
+ | Serial.print(1023); // "5,0V" | ||
+ | Serial.print(" "); | ||
+ | Serial.print(647); // "0,632*5V" | ||
+ | Serial.print(" "); | ||
+ | Serial.println( nap ); | ||
+ | // Meranie prechodovej charakteristiky | ||
+ | do { | ||
+ | Kon_time = micros(); | ||
+ | nap = analogRead(0); | ||
+ | if((Kon_time - Zac_time) >= Ts ){ | ||
+ | //nap = analogRead(0); | ||
+ | //Zac_time = Kon_time; //Takoto by narastala chyba | ||
+ | Zac_time += Ts; // Začiatok predchádzajúcej periódy vzorkovania | ||
+ | // výpisy | ||
+ | Serial.print(1023 ); | ||
+ | Serial.print(" "); | ||
+ | Serial.print(647 ); // 0,63% z1023 | ||
+ | Serial.print(" "); | ||
+ | Serial.println( nap ); | ||
+ | t_diskr++; // počet periód vzokovania | ||
+ | } | ||
+ | if(( nap >= 647 ) && ( !tau )){// Spresnosťou na trvanie A/D prevodu odmeriame tau v mikrosekundach | ||
+ | tau = Kon_time - t_0_tau; | ||
+ | } | ||
+ | } | ||
+ | while( t_diskr < t_diskr_kon); | ||
+ | #ifdef SerialPlotter // | ||
+ | // Vypisujeme na Serial Plotter | ||
+ | #elseif | ||
+ | // vypisujeme na Serial Monitor | ||
+ | delay(1000); // 1000ms | ||
+ | delay(1000); // 1000ms | ||
+ | Serial.print("tau = "); | ||
+ | Serial.print( tau ); | ||
+ | Serial.println(" [us] "); | ||
+ | #endif | ||
+ | //--------------------- | ||
+ | |||
+ | AAA: goto AAA; // tu čakám na ďalší RESET a nové meranie | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | </syntaxhighlight></tab> | ||
+ | </tabs> | ||
+ | |||
+ | <div id="program2"></div> | ||
+ | <tabs> | ||
+ | <tab name="P regulator.ino. "><syntaxhighlight lang=c style="background: Cornsilk"> | ||
+ | #define C_1uF // | ||
+ | // #define C_100uF // | ||
+ | |||
+ | // -------------------------- | ||
+ | // Regulačný obvod s P regulátorom | ||
+ | // Regulovaná sústava 1. rádu, staticka s prenosovou funkciou S(s) = K/(1+T.s) | ||
+ | // časová konštanta je raz cca 10ms a druhý krát 1s. | ||
+ | // Použite 100uF a 1.0 uF kondezátor a 10kOhm rezistor. | ||
+ | // pin3, resp. pin6 je vždy zapojený cez 10kOhm rezistor ako OUTPUT. | ||
+ | // pin A0 je pripojený na spoj rezistor - kondenzátor. | ||
+ | |||
+ | // Keď program dosiahne čas 10*T (T - časová konštanta RC člena) vykreslovanie sa zastaví. | ||
+ | // príkaz micros() vracia systémový čas v us od spustenia programu ako "long" číslo. | ||
+ | // Vykreslovanie na Serial Plotter sa deje v diskrétnom čase. Každých n*Ts (n = 0, 1, 2, ...), | ||
+ | // kde Ts je perióda vzorkovania. | ||
+ | // Vykreslovanie je v pomerných jednotkách. 1SJ = 1023 (10b-ový prevodník). | ||
+ | // 1SJ odpovedá napätiu 5V | ||
+ | // Vykreslujú sa tri čiary: | ||
+ | // 1.) Uc, 2.) 1023 (5V) a 3.) 614 (3V) | ||
+ | |||
+ | int PWM_3_490 = 3; // PWM | ||
+ | int PWM_6_980 = 6; | ||
+ | int PWM = PWM_6_980; | ||
+ | long t_0 = 0; | ||
+ | long Zac_time = 0; | ||
+ | long Kon_time = 0; | ||
+ | long tau = 0; // časová konštanta RC člena | ||
+ | |||
+ | int nap = 0; // regulovaná veličina | ||
+ | int w_zel = 614; // 3V | ||
+ | int e_wy; // regulačná odchýlka | ||
+ | int e_oo = 0; // trvalá regulačná odchýlka | ||
+ | int akc_zas = 0; // akčný zásah, plnenie PWM signálu | ||
+ | int K_P = 1; // Zosilnenie regulátora | ||
+ | |||
+ | #ifdef C_100uF // T = R*C = 10kOhm*100uF = 1000ms = 1s, Ts = 50ms | ||
+ | // doplňte | ||
+ | #endif | ||
+ | |||
+ | #ifdef C_1uF // T = R*C = 10kOhm*1uF = 10ms | ||
+ | long Ts = 1000; // 1ms | ||
+ | int t_diskr = 0; // nacitavam pocet Ts | ||
+ | // Dvojnásobok ustálenia prechodovej chrakteristiky: | ||
+ | int t_diskr_kon = 100; // ((2 * 5T) = 0,1sek)/ (Ts = 1 ms)) = 100; {2*(5*T) = 1sek} | ||
+ | #endif | ||
+ | |||
+ | |||
+ | void setup() { | ||
+ | // úvodná inicializácia | ||
+ | // Nastavenie PWM signálu | ||
+ | pinMode(PWM, OUTPUT); // sets the pin as output | ||
+ | analogWrite(PWM, 0); // sets to "0.0V" | ||
+ | // počet opakovani je daný časovou konštantou | ||
+ | for(int i = 0; i < ????; i++){ | ||
+ | delay(1000); // 1000ms // Na začiatku vybijem kondenzátor | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | Serial.begin(115200); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | Zac_time = micros(); | ||
+ | // výpis v čase t = 0.0 s | ||
+ | t_0 = Zac_time; | ||
+ | nap = analogRead(0); // Počiatočná hodnota napätia na kondenzátore | ||
+ | |||
+ | Serial.print(1023); // "5,0V" | ||
+ | Serial.print(" "); | ||
+ | Serial.print(w_zel); // "3V/5V*1023" | ||
+ | Serial.print(" "); | ||
+ | Serial.println( nap ); | ||
+ | // Regulácia | ||
+ | do { | ||
+ | Kon_time = micros(); | ||
+ | if((Kon_time - Zac_time) >= Ts ){ | ||
+ | nap = analogRead(0); | ||
+ | |||
+ | P_reg(); | ||
+ | //nap = analogRead(0); | ||
+ | //Zac_time = Kon_time; //Takoto by narastala chyba | ||
+ | Zac_time += Ts; // Začiatok predchádzajúcej periódy vzorkovania | ||
+ | // výpisy | ||
+ | Serial.print(1023); | ||
+ | Serial.print(" "); | ||
+ | Serial.print(w_zel); | ||
+ | Serial.print(" "); | ||
+ | Serial.println( nap ); | ||
+ | t_diskr++; // počet periód vzokovania | ||
+ | } | ||
+ | } | ||
+ | while( t_diskr < t_diskr_kon); | ||
+ | // tu môžem vypočítať | ||
+ | // e_oo = w_zel - nap; | ||
+ | //--------------------- | ||
+ | |||
+ | AAA: goto AAA; | ||
+ | // tu čakam na ďalší RESET a nové meranie | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | // Počítam v takzv. SJ (1SJ = 1023, resp. 5V ) | ||
+ | void P_reg(){ | ||
+ | // doplňte | ||
+ | // regulačná odchýlka | ||
+ | // akc_zas | ||
+ | // Obmedzenia | ||
+ | analogWrite(PWM, akc_zas >> 2); // the duty cycle: between 0 (always off) and 255 (always on). | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | </syntaxhighlight></tab> | ||
+ | </tabs> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | == Datasheety == | ||
+ | |||
+ | * [https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf ATmega328P8-bit AVR Microcontroller] | ||
+ | |||
− | + | [[Category: ELSA]] |
Aktuálna revízia z 21:11, 6. december 2020
Úlohy:
- Identifikujte parametre regulovanej sústavy
- Sústavu predstavuje RC člen, pozostávajúci z rezistora 10 kΩ a kondenzátora 1µF resp. 100 µF. Použite pripravený program: ( → #program1)
- Pre RC člen (10 kΩ a 100 µF) navrhnite P regulátor. Upravte - doplňte pripravený program: ( → #program2)
- Vysvetlite, prečo nedosiahneme dobré výsledky pre časovú konštantu 10ms.
- Navrhnite P (zosilnenie 1, 2 a 3) regulátor pre časovú konštantu 1s a vypočítajte trvalú regulačnú odchýlku pre w_zel = 3V.
- Výsledky porovnajte s nameranými.
- Ako sa mení dynamika uzatvoreného regulačného obvodu?
- Bonus. Doplňte program regulátora o I zložku a navrhnite parametre.
- Najskôr použite celočíselnú aritmetiku. Vysvetlite prečo vznikne trvalá regulačná odchýlka aj pre PI regulator.
- Použite Float aritmetiku. Doplňte program o zmenu záťaže. Vypočítajte a meraním overte veľkosť trvalej regulačnej odchýlky pri skokovej zmene záťaže.
Poznámky:
- Nezabudnite zapojiť na výstup PWM signálu filter.
- Nepoužité OZ v púzdre je v hodné „ošetriť“.
- Nepoužitý vstup A/D prevodníka je vhodné „ošetriť“.
- Nezabudnite, vnútorný odpor zdroja má byť oveľa menší ako je odpor záťaže.
Použijeme:
- Arduino
- Kondenzátory 1 µF a 100 µF. Rezistor 10 kΩ
- Programy ...
Návod viď príloha v classroome a vysvetlivky na cvičení.
// Meranie prechodovej charakteristiky
// Použijeme Serial Plotter
#define C_1uF //
#define SerialPlotter //
//#define C_100uF //
// --------------------------
// Program pre vykreslenie prechodovej charakteristiky RC člena
// Použite 100uF a 1.0 uF kondezátor
// pinA je vždy zapojený cez 10kOhm rezistor ako OUTPUT.
// pinB je najskôr zapojený ako output a následne nastavený do log. nuly.
// pinB a A0 sú skratnuté.
// za cca 1sekundu (delay(1000)) po resete bude kondenzátor určite vybitý. Potom sa
// pinB prepne do stavu input bez pullup a kondenzátor sa začne nabíjať.
// Keď program dosiahne čas 10*T (T - časová konštanta RC člena) vykreslovanie sa zastaví.
// príkaz micros() vracia systémový čas v us od spustenia programu ako "long" číslo.
// Vykreslovanie na Serial Plotter sa deje v diskrétnom čase. Každých n*Ts (n = 0, 1, 2, ...),
// kde Ts je perióda vzorkovania.
// Vykreslovanie je v pomerných jednotkách. 1SJ = 1023 (10b-ový prevodník).
// 1SJ odpovedá napätiu 5V
// Vykreslujú sa tri čiary:
// 1.) Uc, 2.) 1023 (5V) a 3.) 647 = int(0.632*1023)
int pinA = 2;
int pinB = 3;
long t_0_tau = 0;
long Zac_time = 0;
long Kon_time = 0;
long tau = 0; // časová konštanta RC člena
#ifdef C_100uF // T = R*C = 10kOhm*100uF = 1000ms = 1s
// Doplňte
#endif
#ifdef C_1uF // T = R*C = 10kOhm*1uF = 10ms
long Ts = 1000; // 1ms
int t_diskr = 0; // nacitavam pocet Ts
// Dvojnásobok ustálenia prechodovej chrakteristiky:
int t_diskr_kon = 100; // ((2 * 5T) = 0,1sek)/ (Ts = 1 ms)) = 100;
#endif
void setup() {
// úvodná inicializácia
pinMode (pinA, OUTPUT);
digitalWrite(pinA, HIGH);
pinMode (pinB, OUTPUT);
digitalWrite(pinB, LOW);
Serial.begin(115200);
}
void loop() {
int nap = 0;
// počkám na ustálenie sa pomerov na RC
delay(1000); // 1000ms
Zac_time = micros();
// výpis v čase t = 0.0 s
t_0_tau = Zac_time;
nap = analogRead(0); // Počiatočná hodnota napätia na kondenzátore
pinMode (pinB, INPUT); // Od tohto okamžiku sa začne kondenzátor nabíjať
Serial.print(1023); // "5,0V"
Serial.print(" ");
Serial.print(647); // "0,632*5V"
Serial.print(" ");
Serial.println( nap );
// Meranie prechodovej charakteristiky
do {
Kon_time = micros();
nap = analogRead(0);
if((Kon_time - Zac_time) >= Ts ){
//nap = analogRead(0);
//Zac_time = Kon_time; //Takoto by narastala chyba
Zac_time += Ts; // Začiatok predchádzajúcej periódy vzorkovania
// výpisy
Serial.print(1023 );
Serial.print(" ");
Serial.print(647 ); // 0,63% z1023
Serial.print(" ");
Serial.println( nap );
t_diskr++; // počet periód vzokovania
}
if(( nap >= 647 ) && ( !tau )){// Spresnosťou na trvanie A/D prevodu odmeriame tau v mikrosekundach
tau = Kon_time - t_0_tau;
}
}
while( t_diskr < t_diskr_kon);
#ifdef SerialPlotter //
// Vypisujeme na Serial Plotter
#elseif
// vypisujeme na Serial Monitor
delay(1000); // 1000ms
delay(1000); // 1000ms
Serial.print("tau = ");
Serial.print( tau );
Serial.println(" [us] ");
#endif
//---------------------
AAA: goto AAA; // tu čakám na ďalší RESET a nové meranie
}
#define C_1uF //
// #define C_100uF //
// --------------------------
// Regulačný obvod s P regulátorom
// Regulovaná sústava 1. rádu, staticka s prenosovou funkciou S(s) = K/(1+T.s)
// časová konštanta je raz cca 10ms a druhý krát 1s.
// Použite 100uF a 1.0 uF kondezátor a 10kOhm rezistor.
// pin3, resp. pin6 je vždy zapojený cez 10kOhm rezistor ako OUTPUT.
// pin A0 je pripojený na spoj rezistor - kondenzátor.
// Keď program dosiahne čas 10*T (T - časová konštanta RC člena) vykreslovanie sa zastaví.
// príkaz micros() vracia systémový čas v us od spustenia programu ako "long" číslo.
// Vykreslovanie na Serial Plotter sa deje v diskrétnom čase. Každých n*Ts (n = 0, 1, 2, ...),
// kde Ts je perióda vzorkovania.
// Vykreslovanie je v pomerných jednotkách. 1SJ = 1023 (10b-ový prevodník).
// 1SJ odpovedá napätiu 5V
// Vykreslujú sa tri čiary:
// 1.) Uc, 2.) 1023 (5V) a 3.) 614 (3V)
int PWM_3_490 = 3; // PWM
int PWM_6_980 = 6;
int PWM = PWM_6_980;
long t_0 = 0;
long Zac_time = 0;
long Kon_time = 0;
long tau = 0; // časová konštanta RC člena
int nap = 0; // regulovaná veličina
int w_zel = 614; // 3V
int e_wy; // regulačná odchýlka
int e_oo = 0; // trvalá regulačná odchýlka
int akc_zas = 0; // akčný zásah, plnenie PWM signálu
int K_P = 1; // Zosilnenie regulátora
#ifdef C_100uF // T = R*C = 10kOhm*100uF = 1000ms = 1s, Ts = 50ms
// doplňte
#endif
#ifdef C_1uF // T = R*C = 10kOhm*1uF = 10ms
long Ts = 1000; // 1ms
int t_diskr = 0; // nacitavam pocet Ts
// Dvojnásobok ustálenia prechodovej chrakteristiky:
int t_diskr_kon = 100; // ((2 * 5T) = 0,1sek)/ (Ts = 1 ms)) = 100; {2*(5*T) = 1sek}
#endif
void setup() {
// úvodná inicializácia
// Nastavenie PWM signálu
pinMode(PWM, OUTPUT); // sets the pin as output
analogWrite(PWM, 0); // sets to "0.0V"
// počet opakovani je daný časovou konštantou
for(int i = 0; i < ????; i++){
delay(1000); // 1000ms // Na začiatku vybijem kondenzátor
}
Serial.begin(115200);
}
void loop() {
Zac_time = micros();
// výpis v čase t = 0.0 s
t_0 = Zac_time;
nap = analogRead(0); // Počiatočná hodnota napätia na kondenzátore
Serial.print(1023); // "5,0V"
Serial.print(" ");
Serial.print(w_zel); // "3V/5V*1023"
Serial.print(" ");
Serial.println( nap );
// Regulácia
do {
Kon_time = micros();
if((Kon_time - Zac_time) >= Ts ){
nap = analogRead(0);
P_reg();
//nap = analogRead(0);
//Zac_time = Kon_time; //Takoto by narastala chyba
Zac_time += Ts; // Začiatok predchádzajúcej periódy vzorkovania
// výpisy
Serial.print(1023);
Serial.print(" ");
Serial.print(w_zel);
Serial.print(" ");
Serial.println( nap );
t_diskr++; // počet periód vzokovania
}
}
while( t_diskr < t_diskr_kon);
// tu môžem vypočítať
// e_oo = w_zel - nap;
//---------------------
AAA: goto AAA;
// tu čakam na ďalší RESET a nové meranie
}
// Počítam v takzv. SJ (1SJ = 1023, resp. 5V )
void P_reg(){
// doplňte
// regulačná odchýlka
// akc_zas
// Obmedzenia
analogWrite(PWM, akc_zas >> 2); // the duty cycle: between 0 (always off) and 255 (always on).
}