Enable Javascript


Last Arduino/ESP8266 project (click to open)

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 


Arduinos (Barebone) aan een I²C lijntje
Verveelvoudigd het aantal I/O-poorten
Verdeel je toepassing over meerder processoren (parallel computing)
Master & Slave(s) of Muli-Masters (& Slave(s))

Voor als dit artikel je interesse wekt:
Dan vindt je hier alle Arduino Barebone projecten en andere Arduino artikelen.
Downloads voor Fritzing-bestanden, sketches (programma code) en andere Arduino projecten vindt je op mijn Download pagina

Wat zouden Arduinos aan een I²C lijntje voor je kunnen betekenen:
In ieder geval meer I/O poorten, maar dat is niet alles. Ook meer geheugen (Flash, SRAM en EEPROM). En niet te vergeten; meer processoren welke parallel werken en dus gelijktijdig verschillende taken kunnen uitvoeren. In een Master & Slave(s) configuratie kan de Master aan derden opdrachten geven en gegevens opvragen. In een Multi-Master configuratie kan elke Master aan derden opdrachten geven en gegevens opvragen.
Bij gebruik van mijn Arduino UNO Barebones (2013- € 10,87) krijg je twee maal zoveel als met een standaard Arduino UNO maar dan voor minder dan de prijs van één standaard Arduino UNO(2013- € 23,95). De Barebone Shields maken het je ook gemakkelijk en kosten bijna niets (2013- € 1,92).

Alleen wat extra digitale-poorten nodig? PIN expander in plaats van Master/Slave:
Een I²C 16 Bit, parallel I/O Expander kost ongeveer € 4,-.
MCP23016 1 + weerstand 3K9 Ohm + Condensator 33 pF
Indien er geen extra analoog- en/of PWM-poorten nodig zijn dan is dit de oplossing en heb je geen Slave nodig, maar ik zou toch maar verder lezen.

Is het moeilijk uit te voeren:
Nee, het is net zo simpel als alle ander Arduino I/O-vormen. I²C, Serial, LCD, SD-card, Ethernet, WiFi of ander data I/O. Alle I/O is op Arduinos Streaming gebaseerd en men heeft de functies van deze verschillende I/O vormen behoorlijk aan elkaar gelijk gemaakt. Met slechts een paar regeltjes code zet je op een Slave een Pin of vraag de waarde van een Pin op. En natuurlijk kun je ook andere gegevens als die van een Pin uitwisselen.

I²C:
De specificaties van I²C geeft aan dat het 7 bit (128 = 0-127) adressen aan kan, maar er zijn 16 gereserveerde adressen dus blijven er "slechts" 112 voor je over ;-) Je kunt een Slave(s) en de Multi-Masters als adres een nummer geven. Als je ook andere I²C componenten gebruikt dan moet je die adressen natuurlijk wel vrij houden (zoek je op in de documentatie van het product). Op de afbeelding zie je hoe te bedraden. De twee pull-up doorverbindingen (gele jumpers) pas je maar op één Arduino toe. SCL is het clock-draadje welke door de Master wordt beheerd. De clock bepaald wanneer data stabiel is en kan worden gelezen. SDA is het draadje waarover de data wordt verstuurd.
LET OP: Er is nog een derde draadje nodig GND of 0V. Als de Master(s) & Slave(s) niet aan de zelfde voeding hangen dan komt er tussen elk nog een GND-draadje bij.

Master & Slave(s):
De Master is de baas, beheerd de clock en heeft geen adres nodig. Elke Slave wordt een uniek adres toegewezen. De Master stuurt data naar een adres of vraagt een adres om data. Slaves kunnen onderling geen gegevens uitwisselen, indien dat wel is gewenst moet dat via de Master lopen.

Multi-Masters:
Meer dan één baas, dat kan nooit goed gaan of toch. I²C is een Multi-Master-bus waarbij de clock en het dataverkeer, bij Multi-Masters-verkeer, arbitraal wordt beheerd. Elke Master wordt door de ander Master(s) als "Slave" gezien dus krijgt elke Masters een uniek adres toegewezen. Zo kunnen de Masters onderling data versturen en/of opvragen en dat maakt van setje Arduinos een prima parallelsysteem (parallel computing). In de programmacode is het enigste verschil dat aan alle Master een adres wordt toegewezen, want als je een adres aanroept dan is dat per definitie, ondanks het Master zijn, een "Slave".

Multi-Masters & Slave(s):
Dit is een combinatie van de twee vorige items. Elk apparaat heeft een uniek adres en is door elke Master te zien en te benaderen.

Wat te kiezen:
Aangezien elke Multi-Master als Slave is te benaderen zet ik geen Arduino als Slave op de bus. In de programmacode bepaal je dan zelf wel wie de echte BIG BOSS is.

Software library Wire.h:
Arduino Wire Reference, dit is gewoon Streaming dus net zoiets als Arduinos Serial, LCD, SD-card, Ethernet, WiFi of ander data I/O en in principe nogal eenvoudig mee te werken. Met deze kleine functieset knoop je alles aan elkaar. In de verderop staande voorbeelden zie je dat bij Multi-Masters alleen de groengekleurde functies zijn gebruikt om beiden met elkaar te laten communiceren. Bij Master Slave gebruik je ook de roodgekleurde functies.

  • Wire.begin()
  • Wire.begin(address)
  • Wire.requestFrom(address, count)
  • Wire.requestFrom(address, quantity, stop)
  • Wire.available()
  • Wire.read()
  • Wire.beginTransmission(address)
  • Wire.write()
  • Wire.endTransmission()
  • Wire.onReceive(handler)
  • Wire.onRequest(handler)

Omgang met I/O-pinnen:
Om verwarring te voorkomen kun je pinnen een van het apparaat-nr afhankelijke offset geven:
Multi-Master/Slave #1: D-pinnen 0-13 ⇒ 100-113, A-pinnen 0-5 ⇒ 120-125
Multi-Master/Slave #2: D-pinnen 0-13 ⇒ 200-213, A-pinnen 0-5 ⇒ 220-225
Multi-Master/Slave #3: D-pinnen 0-13 ⇒ 300-313, A-pinnen 0-5 ⇒ 320-325
Bij de Multi-Master/Slave pas je het weer aan.
Als voorbeeld de code van Multi-Master/Slave #3:
    const offsetD = 300;  // offset D-pinnen op Multi-Master/Slave #3 = 3x100
    const offsetA = 320;  // offset A-pinnen op Multi-Master/Slave #3 = 3x100+20
    Wire.read(pinD - offsetD);   // ontvangen
    Wire.read(pinA - offsetA);   // ontvangen
    Wire.write(pinD + offsetD);  // verzenden
    Wire.write(pinA + offsetA);  // verzenden

Het versturen en opvragen van gegevens:
Op een Multi-Master/Slave heb je bijvoorbeeld niet alleen D- en A-pinnen, maar ook sensoren, knopjes en andere (I²C-) componenten staan. Zowel de verzender als de ontvanger moeten dus weten om welk onderdeel het gaat. Geef elk een letter als code, groeperen kun je met een letter plus cijfer zoals code T0 en T1 voor temp-sensor-binnen en temp-sensor-buiten. Verstuur eerst de code en daar direct achteraan de gegevens. Een andere oplossing is om om alles in één keer, verpakt in een array, te versturen. Dat laatste is erg makkelijk en heel overzichtelijk te programmeren.

Voorbeeld code met Multi-Master #1 en Multi-Master #2:
Even Googelen en je vindt tal van voorbeelden om aan je eigen wensen aan te passen. Hieronder staat een heel simpel, maar perfect werkend, Multi-Master voorbeeld. De verschillen tussen de twee programma´s zijn rood gemerkt.
Multi-Master #1 op COM10

/***** Multi-Master #1 *****/

#include <Wire.h>

const byte arduino_Me = 1; // Multi-Master #1, Me, ben ik zelf!
const byte arduino_2 = 2;  // Multi-Master #2, die andere baas

void setup() {
Serial.begin(9600);
Wire.begin(arduino_Me); // Me aanmelden op bus
Wire.onReceive(receiveVanArduino_2); // data van Multi-Master #2 als Slave
delay(5000); // I2C even de tijd
}

void loop() {
Wire.beginTransmission(arduino_2);
Wire.write("Hallo ik ben Master #1");
Wire.endTransmission();
delay(500);
}

void receiveVanArduino_2(int howMany) {
while (Wire.available() > 0) {
char c = Wire.read();
Serial.print(c);
}
Serial.println();
}

Multi_Master #2 op COM3

/***** Multi-Master #2 *****/

#include <Wire.h>

const byte arduino_1 = 1;  // Multi-Master #1, die andere baas
const byte arduino_Me = 2; // Multi-Master #2, Me, ben ik zelf!

void setup() {
Serial.begin(9600);
Wire.begin(arduino_Me); // Me aanmelden op bus
Wire.onReceive(receiveVanArduino_1); // data van Multi-Master #1 als Slave
delay(5000); // I2C even de tijd
}

void loop() {
Wire.beginTransmission(arduino_1);
Wire.write("Hallo ik ben Master #2");
Wire.endTransmission();
delay(500);
}

void receiveVanArduino_1(int howMany) {
while (Wire.available() > 0) {
char c = Wire.read();
Serial.print(c);
}
Serial.println();
}

Zo eenvoudig is dat?

Opmerking: als je Arduinos op verschillend poorten wil draaien dan moet
je voor ieder een verse IDE opstarten, dus niet vanuit menu-bestand