Jullie beginnen intussen een idee te krijgen van de mogelijkheden van de pins op een Arduino.
Digital IN/OUT > onze pins staan aan (5V) of uit (0V)
Analog IN/OUT > onze pins hebben een spanning tussen 0V en 5V
Een derde mogelijkheid is dat we spanning op onze pins gaan gebruiken om onze Arduino te laten communiceren met bijvoorbeeld een sensor of een scherm of zelfs een andere Arduino.
Jullie zijn intussen al gewoon om de Arduino te laten communiceren met andere toestellen. Je computer stuurt immers het programma door via de USB-kabel, en je hebt ook al gegevens van je Arduino naar de Serial Monitor op de computer gestuurd.
Communicatie: Je hebt vroeger vast al wel proberen communiceren met Morse, lichtsignalen, WalkieTalkie... Ook daar waren telkens afspraken nodig. Zender en ontvanger kregen een exemplaar van het Morse-alfabet, of je wist dat je moest wachten op 'over' op het einde van een zin, voor je kon beginnen spreken. Ook bij computers zijn afspraken tussen zender en ontvanger erg belangrijk om ervoor te zorgen dat vlotte communicatie mogelijk is.
Belangrijke afspraken: Wie mag er wanneer communiceren? Wie is zender, wie is ontvanger? Hoe snel loopt de communicatie? Welke signalen gebruiken we? Wat betekenen de signalen? Wanneer is een boodschap afgerond? Welk kanaal/welke draad gebruiken we waarvoor?
Zo'n reeks afspraken noemen we het 'protocol'. Afhankelijk van de boodschap die je wil verzenden zal de ene vorm van communicatie veel efficiënter zijn dan de andere. Wanneer je een beeld wil verzenden ga je een andere vorm van communicatie kiezen dan wanneer je een korte geschreven boodschap wil sturen. In dit deel maken we kennis met enkele manieren van communiceren die we kunnen gebruiken bij onze Arduino.
We hebben het hier telkens over 'seriële communicatie' omdat alle informatie over één draad gaat. Soms gaat er informatie over één draad in de ene richting en één draad in de andere richting, maar nooit gaat er informatie over meerdere draden in dezelfde richting. Wanneer er informatie over meerder draden in dezelfde richting gaat, dan spreken we over parallele communicatie.
Hiernaast zie je een eenvoudig voorbeeld van een signaal dat naar de Serial Monitor gestuurd wordt.
Aangezien onze potmeter signalen van 0 tot 1023 kan lezen worden er getallen doorgestuurd. Met de Serial.print functie worden deze getallen al 'gecodeerd' via ASCII-code.
Wanneer je de functie Serial.print veranderd door Serial.write, dan wordt er geen ASCII meer doorgestuurd, maar dan worden de getallen van de potmeter als pure bytes doorgestuurd.
Onze Serial Monitor zal alle getallen die binnenkomen altijd lezen en weergeven als ASCII-code.
Wanneer onze potmeter bij Serial.print de waarde 84 doorgaf, dan werd dat gewoon weergegeven als 84.
Bij Serial.Write wordt de waarde 84 niet gecodeerd maar als zuivere bytes doorgestuurd. Onze serial monitor zal die toch nog omzetten naar ASCII. Zo zal een doorgestuurde 84 nu bijvoorbeeld weergegeven worden als een T
We gebruiken het niet vaak, maar we kunnen ook signalen sturen van de Serial Monitor naar onze Arduino.
Hiernaast zie je een eenvoudig voorbeeld. Wanneer je bovenaan in de Serial Monitor een letter of cijfer ingeeft, dan kan je dat teken verzenden naar je Arduino. Wanneer je een hoofdletter 'H' doorstuurt, dan zal in dit geval de LED verbonden met pin 5 even aan gaan.
Een veelgebruikte manier van communiceren is I2C of TWI. Meestal wordt er gesproken over I2C, spreek uit ‘I squared C’. Het is dan misschien niet de snelste maar het is een vrij eenvoudige manier en je kan op één Arduino meerdere (tot 127) toestellen aansluiten. Onze Arduino is dan de ‘master’ en de andere toestellen zijn dan de ‘slaves’.
Eén verbinding zorgt voor de spanning (5V).
Eén verbinding gaat naar de GND.
Eén verbinding is de SCL (Serial Clock) : dit is het clock signaal dat er voor zorgt dat master en slaves op dezelfde snelheid communiceren.
Eén verbinding is de SDA (Serial Data) : dit is de datalijn tussen de Arduino en één of meerdere extra toestellen.
Schema voor de verbinding van één toestel (zie fiches)
Bij I2C wordt voor elke slave een adres gebruikt. Bij een LCD is dat bijvoorbeeld meestal 0x27 of 0x3F.
Indien je arduino je toestel niet meteen vindt of je het I2C-adrens niet vindt, dan kan het zijn dat je even een I2C scanner moet gebruiken. Dat is een sketch die even voor je kijkt wat de adressen zijn van de aangesloten toestellen. Een voorbeeld van zo'n scanner vind je op Github: I2C-adress scanner
Onze Arduino zelf kan geen tijd weergeven. Wanneer het voor een project belangrijk is om de tijd te meten dan moeten we gebruik maken van een clock-module. Dit is een module met een klok en een batterij die de tijd doorstuurt naar onze Arduino. De clock-module geeft: jaar, maand, dag, uur, minuut, seconde.
Om de klok-module te gebruiken zal je een library moeten installeren. Je kan bvb Makuna RTC Library gebruiken (github.com/makuna/RTC). Wanneer je de library geïnstalleerd hebt, dan kan je de voorbeeldsketch van deze library als vertrekpunt gebruiken voor eigen projecten.
I2C gebruiken met meerdere toestellen: Via I2C laten we onze Arduino communiceren met een ander toestel via twee draden. Via SDA wordt de data verzonden en via SCL wordt de timing waarmee de data verstuurd wordt opgevolgd. Maar onze Arduino kan zoals gezegd via I2C ook communiceren met meerdere toestellen. Zowel bij de SDA als bij de SCL verbinding kunnen we gewoon telkens de draad verder doortrekken naar het volgende toestel. Ook GND kan gedeeld worden. Bij de spanning moet je wel even controleren of je toestel op 5V werkt. Eventueel moet je een extra draad verbinden met de 3,3V uitgang van de Arduino.
De aansluiting voor de clock-module: die kan je vinden in het schema hierboven. Op de meeste Arduino Uno's kan je voor I2C pin A4 en A5 gebruiken en vind je ook een SCL en SDA pin (vlakbij de reset-knop).
De code voor de DS3231: Zoals hierboven al gezegd kan je best de eerste keer de voorbeeldcode van de Makuna RTC library gebruiken. Zo kan je testen of je clock-module werkt zoals het hoort en meteen worden ook de juiste tijd en datum geïnstalleerd. De voorbeeldcode daar wordt wel wat te ingewikkeld om met andere code te combineren en zo in eigen projecten te gebruiken. Daarom vind je hiernaast een heel erg vereenvoudigde versie van de code die je wel makkelijk kan gebruiken in eigen projecten.
Let op: Deze code kan je niet gebruiken als je niet eerst al met andere code de datum en tijd geïnstalleerde hebt.
Nog wat extra informatie over clock-modules vind je op de pagina hierover op de site.
Meer informatie over de DS3231 en de DS1302 clock-module, (dat is de module van je Arduino Uno box) vind je op de pagina over de clock-module
In dit voorbeeld gaan we meteen al eens I2C gebruiken om twee onderdelen op onze Arduino aan te sluiten. De BME280 is een sensor die temperatuur, vochtigheid en luchtdruk kan meten. De data van deze sensor willen we nu tonen op een LCD-scherm.
De schakeling: De schakeling is erg eenvoudig, je kan gewoon de vier draden die naar de BME-280 gaan, verbinden met de vier pins van je LCD-scherm.
De code: Je zal merken dat er wel wat libraries geïnstalleerd moeten worden. Niet elk LCD-scherm heeft hetzelfde I2C-adres. Als je niet weet wat het I2C-adres is van je scherm kan je best een I2C-scanner gebruiken (hieronder vind je daarvoor de code).
Verder wordt in de commentaren steeds wat uitleg gegeven bij alle stappen in de code. Probeer alle stappen zo goed mogelijk te begrijpen en vraag uitleg als er iets niet duidelijk is.
De code hierboven zal je waarschijnlijk nog moeten aanpassen. Zo kan het zijn dat je LCD een ander I2C-adres heeft dat je op regel 6 zal moeten invullen.
Het kan zijn dat je nog libraries moet installeren. De library <Adafruit_Sensor.h> kan je opzoeken als 'Adafruit Unified Sensor' in je bibliotheekbeheer.
Ook de waarde in regel 3 zal je even moeten opzoeken als je nauwkeurig de hoogte wil bepalen.
Let op, de library hierboven werkt vlot met een Arduino Uno. Bij de ESP32 kan het zijn dat je afhankelijk van je backpack een andere library moet gebruiken. Je kan dan eventueel LCD_I2C.h gebruiken.
Met deze code verschijnen de resultaten op je scherm zoals in het voorbeeld hieronder.
Let op:
De tekst correct plaatsen: Om de tekst te plaatsen maak je gebruik van de functie: lcd.setCursor( , );
Hier geef je altijd eerst de kolom en dan de rij in. Let wel op, je begint te tellen van 0.
Het vakje helemaal linksboven is dus het vak (0,0);
Getallen achter de komma beperken:
Soms heb je door een omzetting teveel getallen na de komma om die op een scherm te krijgen.
Bij de functie lcd.print() mag je na de waarde die je wil weergeven aangeven hoeveel cijfers na de komma je nog wil vermelden. In het voorbeeld hieronder is dat dus één cijfer na de komma.
lcd.print(bme.readTemperature(),1);
Zoals hierboven al vermeld heeft niet elk LCD-scherm hetzelfde I2C-adres. Ook voor andere onderdelen zal je soms op zoek moeten gaan naar dit adres. Zo'n adres ziet eruit als 0x3F of 0x27 of 0x76.
Je vindt verschillende van die scanners op het internet, hiernaast vindt je de code van zo'n scanner.
Je sluit het onderdeel waarvan je het adres wil weten aan op je Arduino en stuurt de code naar je Arduino. Het I2C-adres van je LCD-scherm (of andere aangesloten onderdeel) verschijnt dan in de Serial Monitor.
SPI staat voor ‘Serial Peripheral Interface bus’. Het is net als I2C een systeem om je Arduino te laten communiceren met andere onderdelen/toestellen.
Bij SPI kan de communicatie in twee richtingen gaan (bij I2C kon dat maar in één richting) en de communicatie verloopt ook veel sneller dan bij I2C.
Naast een pin voor je voeding (best 5,5V) en GND heb je ook nog vier pins die zorgen voor de communicatie:
- CS (of SS) staat voor chip select of slave select. In je sketch moet je aangeven welke digitale pin je hiervoor gebruikt.
- SCK staat voor serial clock
- MOSI staat voor master out, slave in
- MISO staat voor master in, slave out
De pins voor SPI op de Brainbox. Reset wordt voorlopig niet gebruikt. Je moet wel nog een digitale pin gebruiken die je moet aanduiden in je code.
Data-logging: Op een Arduino kan maar erg weinig informatie bewaard worden. Die ruimte wordt vooral gebruikt voor je programma en de inhoud van de variabelen. Soms wil je graag extra informatie kunnen opslaan, bijvoorbeeld wanneer je informatie van sensoren over een langere periode wil meten. Dit noemen we data-logging.
Hiervoor is een SD-kaart module erg handig. Het model dat we gebruiken maakt gebruik van een micro-SD kaart, maar je vindt ook modules voor gewone SD-kaarten.
De SD-kaart module verwerken in je code: Bij de Arduino voorbeelden kan je al een een voorbeeld vinden hoe je SD-kaart module in een sketch kan gebruiken. Omdat deze module zoveel mogelijkheden heeft is de kans groot dat je zelf ook wat zal moeten zoeken naar een geschikte voorbeeld-sketch die je nadien zelf kan gaan bewerken.
Data loggen van de BME280 naar de SD-kaart module: Indien je nog niet gewerkt hebt met de BME280 kan je best even gaan kijken naar de info hierover in het deel over sensoren. In de Map van het vak STEM-projecten vind je alvast een voorbeeld-sketch waarmee je je SD-kaart module kan gebruiken om de data te loggen van de BME280 sensor. Die sketch gebruiken we hier als voorbeeld.
Werken met de SD-kaart module: Zodra je code is doorgestuurd naar je Arduino kan je de Arduino met sensor en data-module gaan gebruiken zonder dat deze verbonden is met de computer. Wanneer je je Arduino aansluit op een voeding begint je code opnieuw. Er wordt nu een nieuw bestand aangemaakt op je SD-kaart en de data worden daar verzameld. Zodra de voeding wegvalt wordt de meting gestopt.
De data lezen: Na je meting kan je je micro-SD kaart in een SD-kaart adapter plaatsen en deze in je comuter steken. Als alles goed is gelopen zou je een TXT-bestand op de SD-kaart moeten vinden.
Wanneer je dit bestand opent krijg je een overzicht van de metingen. Op zich lijkt dit niet zo overzichtelijk, maar dit kunnen we nu wel gaan gebruiken in Excel.
In het schema hiernaast wordt I2C gebruikt voor de BME280 en SPI voor de data-module.
CS wordt hier verbonden met pin 7, dat moet ook in de code aangegeven worden (zie regel 16).
Wanneer je je bestand met de metingen van de SD-kaart opent op je computer, dan zie je zoiets:
UART (Universal Asynchronous Receiver/Transmitter) is net als I2C en SPI een manier om je Arduino te laten communiceren met een ander toestel. UART is niet de snelste manier om twee toestellen te verbinden en je kan hier maar één slave aansluiten. Toch wordt UART nog vaak gebruikt.
Op de Arduino Uno zie je pins TX/1 en RX/0. Deze pins worden gebruikt om te communiceren met de computer via USB. We kunnen ze daardoor vaak niet gebruiken. Onze Arduino kan wel een virtuele RX- en TX-pin maken. Bij de Uno kan dat op bijna alle digitale pins. Je moet dan wel de library <SoftwareSerial.h> gebruiken in je code. Bij de Brainbox (Leonardo) zijn er minder mogelijkheden. We gebruiken op de Brainbox D8 als RX en D4 als TX.
De Pins:
5V (eventueel soms 3,3V)
GND
TX (transmitter) zender
RX (receiver) ontvanger
Goed opletten, de RX van je Arduino moet dus naar de TX van het andere toestel en de TX van de Arduino moet naar de RX van het andere toestel!
De SenseAir S8 CO2-sensor: Deze sensor meet het CO2 gehalte in de lucht (±3%). Dit wordt wordt weergegeven in ppm (parts per million). Voorzie steeds voldoende ruimte boven en onder voor luchtcirculatie. De sensor moet steeds even opwarmen en geeft pas na 5 weken echt correcte metingen.
Let op: deze sensor is erg gevoelig! Je mag nooit de sensor aanraken met je blote handen of met een voorwerp. Je mag enkel het uiteinde met de pins boven en onder aanraken. Zelfs dan mag je de sensor enkel vastnemen met ESD-handschoenen (die statische elektriciteit vermijden). De sensor mag niet op geleidend materiaal liggen en moet bewaard worden in een ESD-zak.
Hoewel dit een erg nauwkeurige sensor is lijkt hij in Arduino projecten niet zo vaak gebruikt te worden. Op het internet is het wat zoeken naar de library of code om hier mee te werken. Via deze link: www.co2meters.com kan je de library 'kSeries.h' en 'SoftwareSerial.h' meteen downloaden.
Bij de libraries zitten ook twee voorbeelden van code. De voorbeeldcode 'K30_example_2' nemen we als basis om op verder te werken. Hiernaast wordt ze nog wat vereenvoudigd gegeven.
De SenseAir S8 CO2-sensor aansluiten op de Brainbox Arduino. De schakeling:
Op de site van de vlaamse overheid vind je een hele reeks tips over een geschikte CO2-meter voor een klaslokaal. Daarin lezen we dat onze sensor alvast geschikt is als basis voor een toestel.
Hier worden ook de drempelwaarden vermeld die je kan gebruiken voor je LEDs:
< 900 ppm = groen (perfecte luchtkwaliteit)
> 900 ppm = oranje (matige luchtkwaliteit)
> 1500 ppm = rood (slechte luchtkwaliteit)
Meer weten?
Wil je meer weten over het verschil tussen seriële en parallele communicatie, over hoe die verschillende systemen precies communiceren? In het korte filmpje hiernaast vind je al heel wat informatie.
Het leuke van Processing en Arduino is dat je ze ook perfect kan laten samenwerken. Je zou dus een sketch in Processing kunnen aansturen met sensoren of een joystick op je Arduino. Of je zou een sketch in Processing kunnen maken en afhankelijk van de gebeurtenissen de lampjes, motoren of een buzzer op je Arduino kunnen activeren.
Een blokje in een Processing sketch aansturen met een potmeter op de Arduino.
We beginnen met een eenvoudig voorbeeld. We sluiten eerst een potmeter aan op onze Arduino.
De Arduino code: De code is erg eenvoudig. We gebruiken de input van de potmeter, houden die bij in de variabele 'val'. We delen die wel door 4 zodat het getal in een byte past. We sturen onze data hier immers als bytes door (zie ook het deel over ASCII hierboven). Het doorsturen is net hetzelfde als iets naar de Serial Monitor sturen.
De Processing code: In Processing hebben we wel een library nodig: 'processing.serial'. Indien je code niet meteen werkt, kijk dan even naar regel 7 en 8. In regel 8 wordt automatisch gekozen voor poort 0. Indien dit niet de juiste poort blijkt, dan kan je regel 7 activeren. Je krijgt dan een lijst met de poorten in je console, waaruit je de juiste poort kan kiezen. In regel 19 zien we dat de waarde gebruikt wordt om onze rect van plaats te veranderen.
Zoals we bij het begin van dit deel al aangaven, is het bij communicatie belangrijk dat vooraf afspraken worden gemaakt, tussen zender en ontvanger, hoe de communicatie verloopt. In het vorige voorbeeld was de communicatie erg eenvoudig. Er werd gewoon een reeks bytes doorgestuurd en die werd doorgegeven aan Processing, waar ze gebruikt werden om de plaats van de rect te bepalen.
Wanneer we bijvoorbeeld een joystick willen gebruiken, dan moeten we al minstens twee waarden (onze x en onze y) kunnen doorgeven. Vanaf dan beginnen we getallen als een 'reeks' door te sturen. We verpakken ze eerst en in een 'string', dat is ons pakje. In die string komt tussen elk getal een komma en println geeft aan dat ons pakje klaar is en dat we aan een nieuw pakje beginnen.
De Arduino code: Bekijk eerst nog even de pagina over de joystick, als je daar nog niet mee gewerkt hebt. Hier zijn ook verder weinig verrassingen. De snelheid van de Serial Monitor (hier 38400) moet wel overeenkomen met die bij Processing. We moeten enkel zien dat we onze data netjes doorsturen met de Serial.print functie. Tussen elke variabele plaats je een komma, en op het einde sluit je af met Serial.println.
De Processing code: Het begin hier is wat vergelijkbaar met wat er in het vorige voorbeeld bij a) stond. In void draw zie je dan dat we een string gaan lezen, die hier bestaat uit 3 variabelen: [0], [1] en [2]. Om te kijken wat er binnenkomt, worden ze hier ook nog eens in de console weergegeven. Ons blokje wordt nu verplaats door onze joystick. Onze boolean komt nog niet aan zoals hij verstuurd werd. Dat gaan we later nog bekijken.