Arduino - Analog Value Reading

From SPAD-it Wiki
Jump to: navigation, search

Dit project draait helemaal om de analogRead() functie die we al vaker hebben gezien en vormt de opmaat naar het volgende project waar we diverse sensoren zullen behandelen.

De schakeling

Extra benodigdheden:

  • 1 potmeter

Onderstaande schakeling is hetzelfde als de vorige waarbij ook de buzzer nog weggelaten mag worden, maar die zit niet in de weg en mag ook best blijven zitten. Als de vorige schakeling dus nog op je breadboard zit kun je meteen aan de slag, anders moet je even onderstaande schakeling opzetten.

Analog value reading.png
Verbindingen in het breadboard met een bijbehorende schema tekening

Het programma

Bij dit project draait het om het uitlezen van de analoge waarde van pin A0, meer precies willen we de spanning weten die op die pin staat en via de serial monitor in Volt rapporteren. De spanning kan worden gevarieerd via de stand van de potmeter.

int pot_pin = 0;      // A0 is the analog input pin for the potmeter

void setup()
{
  Serial.begin(9600); // start de seriele communicatie met een baud rate van 9600
}

void loop()
{
  int val = digitalRead(pot_pin);       // waarde tussen 0 (=0 Volt) en 1023 (=5 Volt)
  //float volt = val * 5/1023;            // dit werkt NIET!!
  //float volt = 5.0/1023 * val;          // dit werkt WEL!!
  //float volt = (float)val * 5/1023;     // dit werkt OOK!!
  float volt = 0.0488758 * val;         // dit werkt ook en is een ietsie pietsie sneller
  Serial.print(volt,2);                 // 2 cijfers achter de komma is genoeg hier
  Serial.println(" volt uitgelezen");
  delay(500);                           // beperk response tot 2x per seconde
}

Uitleg van het programma

In de setup() hoeft alleen de seriele communicatie te worden gestart. De loop() functie is ook erg eenvoudig. De spanning op pin A0, die door de potmeter kan worden gevarieerd, wordt uitgelezen en als integer tussen 0 (=0 Volt) en 1023 (=5 Volt) opgeslagen in de variabele val. Vervolgens wordt de spanning uitgerekend met:

float volt = 0.0488758 * val;

Het getal 0.0488758 is gelijk aan 5/1023. Als val=0 wordt volt natuurlijk 0 en als val=1023 komt er 5 Volt uit. Dit wordt vervolgens via de seriele lijn doorgestuurd naar de computer.

Nu bevat het programma drie mogelijkheden om uit val de spanning uit te rekenen. De eerste is:

float volt = val * 5/1023;

Zoals het commentaar al zegt werkt dit niet. Om dat te kunnen begrijpen moet je iets meer weten over hoe het programma precies werkt. Zoals je kunt zien is val een int. Dat zijn gehele getallen waarvan de grootte beperkt is tot iets tussen -32768 en 32767. Het type int beschikt over 16 bits (2 bytes) en grotere getallen hebben meer ruimte nodig. Het type float is een getal met een punt. Een variabele van dit type heeft 6 of 7 significante cijfers en een variabele plek voor de punt (een drijvende punt). Door die variabele punt kunnen er hele grote getallen in worden opgeslagen, positief of negatief. Het zal duidelijk zijn dat dit type meer opslagruimte nodig heeft. Het type float gebruikt 32 bits (4 bytes) en werkt van binnen heel anders.

Van de constanten 5 en 1023 denkt de software dat het om ints gaat. Terwijl 5 dus als een int wordt opgevat, is 5.0 vanzelf een float. daar komt bij dat we de variabele val nodig hebben en die is ook van het type int. De software voert daarom de hele berekening uit met int's. In principe wordt dat resultaat-type bepaald door de grootste operand (het getal dat de meeste ruimte vraagt in het geheugen). Een berekening op basis van int's geeft dus ook een int terug. De breuk 5/1023 wordt dan 0, omdat 0 de dichtsbijzijnde int is die lager is 5/1023 kleiner is dan 1 wordt die breuk automatisch 0. Daardoor wordt het resultaat van de berekening altijd 0, wat de waarde van val ook is. Op deze manier krijg je het gekke resultaat dat:

1023*4/10 = 0

Het bovenstaande verklaart waarom de volgende code ook werkt:

float volt = 5.0/1023 * val;

Het getal 5.0 wordt door de software herkent als een float. Daarom zal de hele berekening als float worden uitgevoerd terwijl ook het resultaat een float is. Onderstaande code werkt ook:

float volt = (float)val * 5/1023;

De term (float)val zegt expliciet tegen de software dat van val een float gemaakt moet worden. In feite wordt het type int dus ter plaatse omgezet in het type float. Dit heet een typecast. De code zoals die daadwerkelijk is het programma zit:

float volt = 0.0488758 * val;

Komt op hetzelfde neer, maar is iets sneller omdat de breuk 5.0/1023 niet hoeft te worden uitgevoerd. Wel is dit iets minder begrijpelijk zodat het een goed idee is om in het commentaar uit te leggen waar het getal 0.0488758 vandaan komt.

Beetje spelen

  • Vaak is het zo de spanning niet helemaal 5 Volt wordt. Als je de potmeter naar max draait kun je met een spanningsmeter de echte spanning meten. Stel nu dat die spanning inderdaad geen 5 Volt blijkt te zijn, maar slechts 4.83 Volt, kun je dan het programma aanpassen opdat het toch de juiste spanning weergeeft?
  • Het is natuurlijk leuk om de spanning weer te geven op een LCD scherm. Kun jij dit project met het vorige combineren zodat je de spanning kunt aflezen op het LCD scherm? Je hebt dan een eenvoudige spanningsmeter gemaakt!

Navigatie