ELSA Online: 11. Regulačné obvody
Zo stránky SensorWiki
Téma: Inkrementálne snímače (IRC), regulácia napätia na kondenzátore.
Použijeme:
- Arduino
- Kondenzátory 0,1 uF, 1,0 uF a 2x 100nF.
- Programy z prílohy
Úlohy:
- Zmerajte pomocou kondenzátora 0.1uF a 1.0uF hodnotu pullup rezistora. ( → #program1)
- Zistite priemernú hodnotu trvania A/D prevodu a porovnajte s katalógovým údajom.
- Upravte program zo stránky https://www.handsontec.com/dataspecs/module/Rotary%20Encoder.pdf a odskúšajte ako je citlivý na zákmity kontaktov.
- Ošetrite Pin2 a Pin3 proti zákmitom kondenzátormi 100nF.
- Vypočítajte akú frekvenciu spínania kontaktov dokážeme teoreticky takýmto spôsobom sledovať. Predpokladáme, že „pohyb“ je rovnomerný.
- Bonus. Pripravili sme pre Vás základ programu využívajúci prerušenia ( → #program2). Doplňte, dorobte program tak, aby načítal, resp. odčítal pri prechode z jedného stavu do druhého len jeden impulz.
...11 01 00 10 11... resp. naopak ...11 10 00 01 11...
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.
Návod:
Meranie hodnoty Pullup rezistora pomocou ARDUINO „ “. Najskôr som pomocou osciloskopu zmeral skutočné hodnoty kondenzátorov. Použil som dva elektrolity 0,1uF a 1uF. Zmeral som prechodové charakteristiky (nabíjanie na 5V cez presný rezistor 12kOhm). 0,1 uF kondenzátor ma zanedbateľný zvodový odpor. 1uF kondenzátor má tiež zanedbateľný zvodový odpor pri tvrdom zdroji napätia. V ustálenom stave v oboch prípadoch nameriam 5,0V. Prepočítané hodnoty: 0,1uF => 0,095 uF (skut.); 1,0uF => 0,97 uF (skut.). Zapojenie merania vnútorného odporu viď. pptx. Meriam čas nábehu napätia na kondezátore v us . Časovej konštante odpovedá napätie na kondenzátore U_C (τ)=U(∞)/5,0*1023*0,63 = (celé číslo). τ=R*C . Program nám určí čas v us. Odmeriame aj hodnotu ustálenú U(∞). Vstupný pin zapojený s pullup rezistorom je mäkký zdroj prúdu. Program dokolečka odmeriava napätie na kondenzátore. Trvanie časovej konštanty prakticky odpovedá n A/D prevodovov. Ak podelíme τ počtom A/D prevodov získame trvanie jedného prevodu. Vypočítajte a porovnajte s kat. listom. Upravte zapojenie pre vyhodnotenie IRC. Doplňte kondenzátory. Modifikujte program a overte funkčnosť. Podrobnejšie viď. pptx.
// Program pre meranie hodnoty pullup rezistoru pomocou nabíjania kondenzátora
// Použite 0.1uF a 1.0 uF kondezátor
// pinA je vždy zapojený s pullup-om ako input.
// pinB je najskôr zapojený ako output a nastavený do log. nuly.
// pinA , pinB a A0 sú skratnuté.
// za cca 1sekundu (delay(1000))po resete bude kondenzátor určite vybytý. Potom sa
// pinB prepne do stavu input bez pullup a kondenzátor sa začne nabíjať.
// Keď dosiahne hodnotu odpovedajúcu Uc(tau) vypíše sa na seriovú linku hodnota
// tau v [us].
// !!!!! Podľa KL-ov je pullup udávaný v 10-kach kOhm
// príkaz mikros() vracia systémový čas v us od spustenia programu ako "long" číslo.
int pinA = 2;
int pinB = 3;
int Poc_A_D_prevodov = 0;
long Zac_time = 0;
long Kon_time = 0;
void setup() {
// úvodná inicializácia
pinMode (pinA, INPUT_PULLUP);
pinMode (pinB, OUTPUT);
digitalWrite(pinB, LOW);
Serial.begin(19200);
}
void loop() {
// Ak treba, doplňte si/upravte deklaráciu premennných
// !!!!! ZAČNITE menším KONDENZÁTOROM, je to jednoduchšie. Aspoň niečo Vám bude fungovať. !!!!!
int pom = 0;
int nap = 0;
int tau = 0;
int Trvanie_A_D = 0;
int konst_tau = 622; // (int)(0,632 * (984))= 622 ====> napr. (4.8/5)*1023 * 0.63 = 618
delay(1000); // 1000ms
pinMode (pinB, INPUT); // od tohto okamžiku sa začne kondenzátor nabíjať
Zac_time = micros();
while(analogRead(0)< konst_tau){Poc_A_D_prevodov++;}
// vtomto okamžiku je Uc(tau) rovné 0,63*U(oo)
Kon_time = micros();
Serial.print("Tau = ");
tau = Kon_time - Zac_time;
Serial.print(tau);
Serial.println(" [us] ");
Serial.println(" "); // nový riadok
Serial.print("Poc A/D prevodov = ");
Serial.println(Poc_A_D_prevodov);
Serial.println(" "); // nový riadok
Trvanie_A_D = tau / Poc_A_D_prevodov;
Serial.print("Trvanie A/D prevodu = ");
Serial.print(Trvanie_A_D);
Serial.println(" [us] ");
Serial.println(" "); // nový riadok
delay(1000); // 1000ms// počkám na ustálenie a odmeriam ustálenú hodnotu
// vypočítajte priemer 10-tich hodnôt ustáleného napätia na kondenzátore
// a vypíšte cez sériovú linku podobne ako to vidíte na priloženom obrázku
// číslo v zátvorke predstavuje hodnotu 10-bitového prevodníka
//pomocou čísla z A/D prevodníka upresnite,vypočítajte vašu konst_tau, napr.:konst_tau = 618;
// niečo ako (4.8V/5.0V)*1023 * 0.63 = 618
// 4.8V je ustálená hodnota na kondenzátore a 5.0V je napätie zdroja a v našom prípade aj
// Uref A/D prevodníka.
//---------------------
// vypočítajte hodnotu pullup rezistoru a zobrazte
// raz pre C = 0,1uF
// a druhý krát pre C = 1,0uF
AAA: goto AAA;
// tu čakam na ďalší RESET a nové meranie
}
<div id="program2"></div>
// Vyhodnocujem smer a jeden impulz na otacku
// využíva prerušenia, nevyuživa Gray-ov kod
const byte interruptPin0 = 2; // A
const byte interruptPin1 = 3; // B
volatile int counter = 0;
volatile int poc_prechodov = 0;
volatile int old = 0;
volatile int Pin_3;
void setup() {
Serial.begin(115200);
pinMode(interruptPin0, INPUT_PULLUP);
pinMode(interruptPin1, INPUT_PULLUP);
// CHANGE, RISING, FALLING, ...
attachInterrupt(digitalPinToInterrupt(interruptPin0), IntUP, RISING);
attachInterrupt(digitalPinToInterrupt(interruptPin0), IntDOWN, FALLING);
Serial.println(" Start ");
}
void loop() {
if(old != counter ){
Serial.print("Poc Prech = ");
Serial.print(poc_prechodov);
Serial.print(" ");
Serial.print("Counter = ");
Serial.println(counter);
old = counter;
}
}
void IntUP() { // KANAL A
poc_prechodov++;
Pin_3 = digitalRead(interruptPin1);
if ( Pin_3 == LOW ) counter++; else counter--;
}
void IntDOWN() { // KANAL A
poc_prechodov++;
Pin_3 = digitalRead(interruptPin1);
if ( Pin_3 == HIGH ) counter++; else counter--;
}