Overleg:Arduino/Digitale uitvoer: verschil tussen versies

Uit Lab
Naar navigatie springen Naar zoeken springen
 
(33 tussenliggende versies door dezelfde gebruiker niet weergegeven)
Regel 3: Regel 3:
Voor het uitlezen en aansturen van de digitale ingangen en uitgangen gebruikt de Arduino-taal de constanten LOW en HIGH.
Voor het uitlezen en aansturen van de digitale ingangen en uitgangen gebruikt de Arduino-taal de constanten LOW en HIGH.


De beschrijving van deze constanten in de Arduino-documentatie is verwarrend: zie  
De beschrijving van deze constanten in de Arduino-documentatie is verwarrend: zie https://www.arduino.cc/en/Reference/Constants.


Bij deze digitale in- en uitgangen heb je te maken met twee "werelden" die gekoppeld worden: de wereld van de software - waar een digitale ingang of uitgang overeenkomt met een bit, met de waarde 0 of 1; en de wereld van de hardware, waar je werkt met spanningsniveaus.
Bij deze digitale in- en uitgangen heb je te maken met twee werelden die gekoppeld worden: de wereld van de software - waar een digitale ingang of uitgang overeenkomt met een bit, met de waarde 0 of 1; en de wereld van de hardware, waar je werkt met spanningsniveaus.


Door het gebruik van de constanten LOW en HIGH probeert men in de Arduino-taal het niveau van de spanning op de betreffende aansluiting aan te geven. Verschillende systemen werken daar met verschillende spanningsniveaus. Bovendien heb je nog het verschil tussen input en output: een input-spanning kleiner dan 3V wordt (bij de Arduino UNO) gezien als een LOW waarde.
Door het gebruik van de constanten LOW en HIGH probeert men in de Arduino-taal het niveau van de spanning op de betreffende aansluiting aan te geven. Verschillende systemen werken daar met verschillende spanningsniveaus. Bovendien heb je nog het verschil tussen input en output: een input-spanning kleiner dan 3V wordt (bij de Arduino UNO) gezien als een LOW waarde.


Je kunt dit in de volgende tabel zien:
Je kunt dit in de volgende tabel zien:


{| class="wikitable"
{| class="wikitable"
! software !! hardware-1 output !! hardware-1 input !! hardware-2 output !! hardware-2 input  
! software !! hw-1 output !! hw-1 input !! hw-2 output !! hw-2 input  
|-
|-
| LOW || 0V || < 1.5V || 0V || < 0.8V
| LOW || 0V || < 1.5V || 0V || < 0.8V
Regel 20: Regel 19:
|}
|}


De waarden die gegeven worden in de Arduino-documentatie kloppen niet helemaal: zie bijv. https://learn.sparkfun.com/tutorials/logic-levels voor een discussie van de logische (spannings)niveaus in het algemeen, en voor de Arduino hardware in het bijzonder.
De waarden die gegeven worden in de Arduino-documentatie kloppen niet helemaal: zie bijv. https://learn.sparkfun.com/tutorials/logic-levels voor een discussie van de logische (spannings)niveaus in het algemeen, en voor de Arduino hardware in het bijzonder. Er is een gebied waar de waarde (als input) niet gedefinieerd is. Bovendien kan in het geval van een output, de spanning voor LOW iets hoger zijn dan 0V, en voor HIGH iets lager dan 5V.


In principe spreekt de Arduino-documentatie zich er niet over uit wat de waarden van LOW en HIGH zijn aan de software-kant. Het enige wat vastligt is dat het constanten zijn: met andere woorden, je kunt een waarde vergelijken met LOW of HIGH:
In principe spreekt de Arduino-documentatie zich er niet over uit wat de waarden van LOW en HIGH zijn aan de software-kant. Het enige wat vastligt is dat het constanten zijn: met andere woorden, je kunt een waarde vergelijken met LOW of HIGH:
Regel 29: Regel 28:
}
}
</syntaxhighlight>
</syntaxhighlight>
=== LOW en HIGH in software ===


Wat ontbreekt in bovenstaande tabel is welke waarde LOW en HIGH in de software hebben. Dat heb je nodig als je ermee wilt gaan rekenen.
Wat ontbreekt in bovenstaande tabel is welke waarde LOW en HIGH in de software hebben. Dat heb je nodig als je ermee wilt gaan rekenen.
Regel 35: Regel 36:


De Arduino-taal is een variant van C++. Dit betekent dat er geen boolean waarden zijn, of een boolean type. Je kunt een waarde wel gebruiken in een conditie, bijvoorbeeld bij een if- of een while-statement. In dat geval komt de waarde 0 overeen met ''false'', en ''elke andere waarde'' met ''true''.
De Arduino-taal is een variant van C++. Dit betekent dat er geen boolean waarden zijn, of een boolean type. Je kunt een waarde wel gebruiken in een conditie, bijvoorbeeld bij een if- of een while-statement. In dat geval komt de waarde 0 overeen met ''false'', en ''elke andere waarde'' met ''true''.
Binnen de Arduino-taal (library) zijn er overigens wel constanten <code>false</code> en <code>true</code>.
Overigens is BOOL en bool en boolean in C/C++/Arduino niet altijd goed te begrijpen, zie: https://github.com/arduino/Arduino/issues/2147
In C++ is de conversie tussen <code>int</code> en <code>bool</code> goed gedefinieerd: <code> (int)false == 0 </code>, en <code>(int)true == 1 </code>; <code>(bool)0 == false</code>, en <code>(bool)1 == true</code>. Op die manier kun je ook met bool-waarden rekenen. Ook in een taal als Pascal is dat het geval.


=== Rekenen met LOW en HIGH ===
=== Rekenen met LOW en HIGH ===
Regel 51: Regel 58:
Dit kun je eventueel afkorten als: <code>value = (in == HIGH) ? 1 : 0; </code>, maar het blijft omslachtig.
Dit kun je eventueel afkorten als: <code>value = (in == HIGH) ? 1 : 0; </code>, maar het blijft omslachtig.


==== Aanname: LOW en HIGH zijn bits ====
==== Aanname: LOW en HIGH zijn bits (0 of 1) ====


Een veilige aanname is dat LOW en HIGH bits zijn: deze representeren de waarden 0 en 1, hoewel we niet weten of LOW==0 of LOW==1.
Een veilige aanname is dat LOW en HIGH bits zijn: deze representeren de waarden 0 en 1, hoewel we niet weten of LOW==0 of LOW==1.
Regel 57: Regel 64:
In dit geval krijg je de inverse van een LOW/HIGH-waarde <code>x</code>  door middel van <code>1 - x</code>.
In dit geval krijg je de inverse van een LOW/HIGH-waarde <code>x</code>  door middel van <code>1 - x</code>.


Voor andere berekeningen moeten we  
{| class="wikitable"
! <code>x</code> !! <code>1-x</code>
|-
| 0 || 1
|-
| 1 || 0
|}
 
Voor andere berekeningen moeten we de conversie uitvoeren zoals eerder beschreven.


==== Aanname: LOW==0 en HIGH ==1 ====
==== Aanname: LOW==0 en HIGH ==1 ====
In de Arduino-sofware wordt de volgende definitie gebruikt:
<syntaxhighlight lang=cpp>
#define HIGH 0x1
#define LOW  0x0
</syntaxhighlight>
Met andere woorden:
* LOW en HIGH zijn getallen (<code>int</code>)
* met duidelijk gedefinieerde waarden.
Deze waarden zijn afkomstig vanuit de Wiring software, waar de Arduino software van afgeleid is. Dit betekent dat je rustig kunt aannemen dat deze waarden niet zullen veranderen. Het risico is te groot dat er onderdelen van de software niet meer werken.
(Ik begrijp overigens niet waarom hier een hexadecimale notatie gebruikt wordt. Volgens mijn zijn 0 en 1 dezelfde waarde voor alle talstelsels met grondtal >= 2.)
(Zie op GitHub: Arduino/hardware/arduino/avr/cores/arduino/Arduino.h, en Arduino/hardware/arduino/sam/cores/arduino/wiring_constants.h)
Ook hier kun je een waarde <code>x</code> inverteren als: <code>1 - x</code>. (Controleer dat voor alle mogelijke waarden 0 en 1.)
* een numerieke waarde <code>x</code> inverteer je als <code>0 - x</code> ofwel <code>  -x</code>
* een bit-waarde <code>x</code> inverteer je als <code>1 - x</code>
* een boolean waarde <code>x</code> inverteer je als <code>!x</code> (not x).
Merk op dat de conversie met <code>HIGH - x</code> alleen werkt als <code>HIGH == 1</code>. De formule <code>1 - x</code> is onafhankelijk van de waarde van LOW en HIGH, mits deze (i) verschillen; (ii) 0 of 1 zijn.
==== Geschiedenis: Wiring ====
De Arduino software is afgeleid van Wiring (wiring.
Citaat:
* <code>HIGH</code> Reserved word representing the logical value 1 (ON, 5 volts).
* <code>LOW</code> Reserved word representing the logical value 0 (OFF, 0 volts).
Ik vind de code-voorbeelden op http://wiring.org.co/reference/LOW.html niet echt om aan te zien.
<syntaxhighlight lang=cpp>
boolean b = true;
if (b == true) {
  digitalWrite(WLED, HIGH);  // Turn ON the I/O board LED
} else {
  digitalWrite(WLED, LOW);
}
</syntaxhighlight>
* de conditie <code>(b == true)</code> schrijf je beter als: <code>(b)</code>
** dat hoort bij het leren werken met boolean waarden. Anders is het eind zoek: waarom schrijf je niet <code>b == true == true</code>?
* in plaats van het if-statement kun je beter schrijven:
<syntaxhighlight lang=cpp>
digitalWrite(WLED, b);
</syntaxhighlight>
of in echt C++: <code>digitalWrite(WLED, (int) b);</code>.

Huidige versie van 15 dec 2015 om 09:30

Over LOW, HIGH, en het rekenen met deze waarden

Voor het uitlezen en aansturen van de digitale ingangen en uitgangen gebruikt de Arduino-taal de constanten LOW en HIGH.

De beschrijving van deze constanten in de Arduino-documentatie is verwarrend: zie https://www.arduino.cc/en/Reference/Constants.

Bij deze digitale in- en uitgangen heb je te maken met twee werelden die gekoppeld worden: de wereld van de software - waar een digitale ingang of uitgang overeenkomt met een bit, met de waarde 0 of 1; en de wereld van de hardware, waar je werkt met spanningsniveaus.

Door het gebruik van de constanten LOW en HIGH probeert men in de Arduino-taal het niveau van de spanning op de betreffende aansluiting aan te geven. Verschillende systemen werken daar met verschillende spanningsniveaus. Bovendien heb je nog het verschil tussen input en output: een input-spanning kleiner dan 3V wordt (bij de Arduino UNO) gezien als een LOW waarde.

Je kunt dit in de volgende tabel zien:

software hw-1 output hw-1 input hw-2 output hw-2 input
LOW 0V < 1.5V 0V < 0.8V
HIGH 5V > 3V 3.3V > 2V

De waarden die gegeven worden in de Arduino-documentatie kloppen niet helemaal: zie bijv. https://learn.sparkfun.com/tutorials/logic-levels voor een discussie van de logische (spannings)niveaus in het algemeen, en voor de Arduino hardware in het bijzonder. Er is een gebied waar de waarde (als input) niet gedefinieerd is. Bovendien kan in het geval van een output, de spanning voor LOW iets hoger zijn dan 0V, en voor HIGH iets lager dan 5V.

In principe spreekt de Arduino-documentatie zich er niet over uit wat de waarden van LOW en HIGH zijn aan de software-kant. Het enige wat vastligt is dat het constanten zijn: met andere woorden, je kunt een waarde vergelijken met LOW of HIGH:

if (in == HIGH) {
  someAction();
}

LOW en HIGH in software

Wat ontbreekt in bovenstaande tabel is welke waarde LOW en HIGH in de software hebben. Dat heb je nodig als je ermee wilt gaan rekenen.

LOW en HIGH zijn geen boolean waarden

De Arduino-taal is een variant van C++. Dit betekent dat er geen boolean waarden zijn, of een boolean type. Je kunt een waarde wel gebruiken in een conditie, bijvoorbeeld bij een if- of een while-statement. In dat geval komt de waarde 0 overeen met false, en elke andere waarde met true.

Binnen de Arduino-taal (library) zijn er overigens wel constanten false en true.

Overigens is BOOL en bool en boolean in C/C++/Arduino niet altijd goed te begrijpen, zie: https://github.com/arduino/Arduino/issues/2147

In C++ is de conversie tussen int en bool goed gedefinieerd: (int)false == 0 , en (int)true == 1 ; (bool)0 == false, en (bool)1 == true. Op die manier kun je ook met bool-waarden rekenen. Ook in een taal als Pascal is dat het geval.

Rekenen met LOW en HIGH

Geen enkele aanname

Als je geen enkele aanname wilt doen met betrekking tot LOW en HIGH, dan moet je voor het rekenen met digitale inputs en outputs altijd een omzetting doen, bijvoorbeeld:

if (in == HIGH) {
  value = 1;
} else {
} value = 0;

Dit kun je eventueel afkorten als: value = (in == HIGH) ? 1 : 0; , maar het blijft omslachtig.

Aanname: LOW en HIGH zijn bits (0 of 1)

Een veilige aanname is dat LOW en HIGH bits zijn: deze representeren de waarden 0 en 1, hoewel we niet weten of LOW==0 of LOW==1.

In dit geval krijg je de inverse van een LOW/HIGH-waarde x door middel van 1 - x.

x 1-x
0 1
1 0

Voor andere berekeningen moeten we de conversie uitvoeren zoals eerder beschreven.

Aanname: LOW==0 en HIGH ==1

In de Arduino-sofware wordt de volgende definitie gebruikt:

#define HIGH 0x1
#define LOW  0x0

Met andere woorden:

  • LOW en HIGH zijn getallen (int)
  • met duidelijk gedefinieerde waarden.

Deze waarden zijn afkomstig vanuit de Wiring software, waar de Arduino software van afgeleid is. Dit betekent dat je rustig kunt aannemen dat deze waarden niet zullen veranderen. Het risico is te groot dat er onderdelen van de software niet meer werken.

(Ik begrijp overigens niet waarom hier een hexadecimale notatie gebruikt wordt. Volgens mijn zijn 0 en 1 dezelfde waarde voor alle talstelsels met grondtal >= 2.)

(Zie op GitHub: Arduino/hardware/arduino/avr/cores/arduino/Arduino.h, en Arduino/hardware/arduino/sam/cores/arduino/wiring_constants.h)

Ook hier kun je een waarde x inverteren als: 1 - x. (Controleer dat voor alle mogelijke waarden 0 en 1.)

  • een numerieke waarde x inverteer je als 0 - x ofwel -x
  • een bit-waarde x inverteer je als 1 - x
  • een boolean waarde x inverteer je als !x (not x).

Merk op dat de conversie met HIGH - x alleen werkt als HIGH == 1. De formule 1 - x is onafhankelijk van de waarde van LOW en HIGH, mits deze (i) verschillen; (ii) 0 of 1 zijn.

Geschiedenis: Wiring

De Arduino software is afgeleid van Wiring (wiring.

Citaat:

  • HIGH Reserved word representing the logical value 1 (ON, 5 volts).
  • LOW Reserved word representing the logical value 0 (OFF, 0 volts).

Ik vind de code-voorbeelden op http://wiring.org.co/reference/LOW.html niet echt om aan te zien.

boolean b = true;
if (b == true) {
  digitalWrite(WLED, HIGH);  // Turn ON the I/O board LED 
} else {
  digitalWrite(WLED, LOW); 
}
  • de conditie (b == true) schrijf je beter als: (b)
    • dat hoort bij het leren werken met boolean waarden. Anders is het eind zoek: waarom schrijf je niet b == true == true?
  • in plaats van het if-statement kun je beter schrijven:
digitalWrite(WLED, b);

of in echt C++: digitalWrite(WLED, (int) b);.