Arduino i potenciometri
S raznim varijantama potenciometara se srećemo svakodnevno. Dovoljno je
da pojačamo zvuk na radiju u kolima (mada je sve više punih digitalaca).
U Arduino svetu potenciometri imaju čestu primenu. Bilo kao regulatori
pozadinskog osvetljenja LCD ekrana, bilo u raznim drugim projektima. U
suštini to su varijabilni otpornici gde se vrednost otpornosti menja po
potrebi. Postoje razne vrste potenciometara ali osnovna podela je na
algoritamske i linearne. Cene se kreću od nekoliko desetina centi do
dolar-dva.
Arduino očitava vrednosti potenciometra preko
analognih pinova i vidi ih u rasponu od 0-1023, što uz početnu nulu čini
1024 digitalnih vrednosti. U pitanju je 10-bitna rezolucija. Očitavanja
sa analognog pina idu u Analogno Digitalni konvertor (ADC) koji
vrednosti prebacuje u digitalni format i koje mi kasnije koristimo u
projektu. To znači da ako potenciometar povežemo na 5V i GND, i ako je
"zavijen" do kraja, na analognom pinu ćemo imati 0 i imaćemo očitanu
digitalnu vrednost 0, ali ako je "odvijen" do kraja (5V) imaćemo 1023.
Takođe je bitno sa koje strane potenciometra dovodimo 5V, zavisiće na
kojoj strani ćemo imati minimalnu otpornost a na kojoj maksimalnu.
Očitavanje Analognog ulaza
Najprostije je da izlaz potenciometra (obično srednja nožica) povežemo na analogni ulaz Arduina.
void setup() {
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
Serial.println(senzorValue);
delay(5);
}
Na
ovaj način ćemo na serial monitoru prikazati očitane digitalne
vrednosti uz 5 milisekundi razmaka. Kako zakrećemo klizač na
potenciometru, tako se i dobijene vrednosti menjaju.
Praktična upotreba očitanih vrednosti
Ako
u blink skeču dobijene vrednosti unesemo u delay() funkciju možemo
kontrolisati vreme treptanja LED po našoj želji. Povezivanje ide po šemi
ispod.
int senzorPin = A0;
int ledPin = 13;
int senzorVrednost = 0;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
senzorVrednost = analogRead(senzorPin);
digitalWrite(ledPin, HIGH);
Serial.println(senzorVrednost);
delay(senzorVrednost);
digitalWrite(ledPin, LOW);
Serial.println(senzorVrednost);
delay(senzorVrednost);
}
Praktična primena - primer
Ako
očitane vrednosti potenciometra koje primi ADC pomnožimo sa 0,00488
dobijamo dosta približne vrednosti napona u Voltima. Ovde je stavljeno
0,00489 iz razloga da nam poslednja LED zasigurno zasvetli na samom
kraju klizača potenciometra. Povezivanje prema šemi ispod. U skeču prvo
označavamo ulazne i izlazne pinove i dajemo početne vrednosti
promenljivima. U loop funkciji pretvaramo očitavanja u napon i u
zavisnosti koliko je Volti palimo određene LED. Potrebno je 6 LED, 6
otpornika 220R, potenciometar 10K, malo žica i Uno.
int senzorPin = A0;
int ledPin1 = 2;
int ledPin2 = 3;
int ledPin3 = 4;
int ledPin4 = 5;
int ledPin5 = 6;
int ledPin6 = 7;
int senzorVrednost = 0;
int napon = 0;
void setup() {
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
pinMode(ledPin5, OUTPUT);
pinMode(ledPin6, OUTPUT);
Serial.begin(9600);
}
void loop() {
senzorVrednost = analogRead(senzorPin);
napon = senzorVrednost*0.00489; //pretvaramo očitane vrednosti u napon u V
if (napon == 0){
digitalWrite(ledPin1, HIGH);
Serial.println("Napona nema");
}else{
digitalWrite(ledPin1, LOW);
}
if (napon >= 1){
digitalWrite(ledPin2, HIGH);
Serial.print("Napon postoji i iznosi ");
Serial.print(napon);
Serial.println("V");
}else{
digitalWrite(ledPin2, LOW);
}
if (napon >= 2){
digitalWrite(ledPin3, HIGH);
Serial.print("Napon postoji i iznosi ");
Serial.print(napon);
Serial.println("V");
}else{
digitalWrite(ledPin3, LOW);
}
if (napon >= 3){
digitalWrite(ledPin4, HIGH);
Serial.print("Napon postoji i iznosi ");
Serial.print(napon);
Serial.println("V");
}else{
digitalWrite(ledPin4, LOW);
}
if (napon >= 4){
digitalWrite(ledPin5, HIGH);
Serial.print("Napon postoji i iznosi ");
Serial.print(napon);
Serial.println("V");
}else{
digitalWrite(ledPin5, LOW);
}
if (napon == 5){
digitalWrite(ledPin6, HIGH);
Serial.print("Napon postoji i iznosi ");
Serial.print(napon);
Serial.println("V");
}else{
digitalWrite(ledPin6, LOW);
}
delay(100);
}
Na
kraju da kažem da se potenciometri razlikuju i po otpornosti.
Najčešće se koriste oni od 10K (kiloma) ali se mogu sresti i razni
drugi. Poređenja radi, 10K potenciometar će prema Omovom zakonu (I=V/R)
na 5V vući maksimalno 0,5mA. Onaj od 10 oma će u tom slučaju vući 500mA.
Iz ovoga vidimo da što je manja otpornost potenciometra on
proporcionalno vuče više struje. Neko će reći zašto onda ne uzmemo
10.000K? Razlog tome je šum. Što veća vrednost potenciometra to je
proporcionalno veći šum. Iz tog razloga se najčešće koristi 10K kao
zlatna sredina. ADC na Arduinu bi trebalo da vuče 0 Volti ali u
stvarnosti on ipak vuče neku minimalnu količinu i taj šum koji se javlja
dovešće do "čudnih" očitavanja.
Kako rešiti šum?
Da bi se
eliminisao šum potrebno je filtriranje. Zatim, treba izbeći projekte
koji direktno zavise od strogo preciznih vrednosti potenciometra. Za
filtriranje se koristi EMA algoritam. EMA je skraćeno od Exponential Moving Average.
int senzorPin = A0;
int senzorVrednost = 0; //promenljiva očitana vrednost potenciometra, jednaka EMA Y
float emaA = 0.6; //EMA alpha
int emaS = 0; //EMA S
void setup(){
Serial.begin(9600);
emaS = analogRead(senzorPin);
}
void loop(){
senzorVrednost = analogRead(senzorPin);
emaS = (emaA*sensorVrednost) + ((1-emaA)*emaS);//filtriranje kroz EMA
Serial.println(emaS);//filtrirana očitana vrednost
delay(50);
}
Do sledećeg skeča...