Arduino

Enc28j60 Ethernet controller met Arduino en EtherCard bibliotheek

Laatst bijgewerkt: 14/03/2021

Arduino's officiële Ethernet board is gebaseerd op Wiznet W5100 microchip en de ethernetbibliotheken in de Arduino's IDE werken ook voor die chip http://arduino.cc/en/Reference/Ethernet

Een veelgebruikte Ethernet-controller is Microchip's enc28j60 op internet kun je breakout-boards voor die chip vinden, meestal goedkoper dan de officiële.

Aansluiten op de arduino

De Ethernet Controller ENC28J60 is een zogenaamd SPI device en gebruikt de SPI pinnen (10, 11, 12, 13) van je Arduino.

Klik op de foto om het aansluitschema en overzicht van de pinnen te zien.

Library

Sommige bedrijven en hobbisten ontwikkelden Arduino bibliotheken voor de controller van Microchip. Voor deze tutorial gaan we de EtherCard bibliotheek van JeeLabs gebruiken.
JeeLabs publiceerde zijn bibliotheek op GitHub. Download eerst de laatste versie in een ZIP-bestand.

Open de map waarin de Arduino bibliotheken zijn geïnstalleerd, gewoonlijk C:\Users\user\Documents\Arduino\libraries en decomprimeer het gedownloade bestand in de submap van de bibliotheken. In het ZIP-archief bevinden alle bibliotheekbestanden zich in de map "jcw-ethercard-xxx" hernoem die map EtherCard.

Start de Arduino IDE en controleer of de bibliotheek beschikbaar is.

Netwerk parameters

Voordat u Ethernet shield op het net aansluit, hebt u enkele parameters nodig.

U moet een MAC adres kiezen dat niet in uw netwerk wordt gebruikt, in de voorbeelden kiezen we meestal MAC adressen met een nog niet toegewezen organisatiecode (DD-DD-DD).

IP parameters (adres, subnet, gateway) moeten consistent zijn met de parameters die zijn geconfigureerd voor andere apparaten in uw lokale netwerk, een uniek IP adres en hetzelfde subnetmasker en dezelfde gateway.

Soms is er een DHCP server beschikbaar die automatisch nieuwe apparaten in het netwerk configureert, in een volgend voorbeeld ga ik laten zien hoe je dit met Arduino kunt gebruiken.

Ping pong!

De eenvoudigste manier om te achterhalen of een apparaat in uw netwerk leeft, is door het te pingen.
Typ gewoon op een computer die op het netwerk is aangesloten de ping opdracht gevolgd door het IP adres van het apparaat dat u moet controleren.

Laten we een eenvoudige schets schrijven om te antwoorden op ping aanvragen.

#include <EtherCard.h>
static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x00,0x01};
static byte myip[] = {192,168,1,10};
byte Ethernet::buffer[700];

void setup () {
Serial.begin(57600);
Serial.println("PING Demo");
if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0)
    Serial.println( "Failed to access Ethernet controller");
if (!ether.staticSetup(myip))
    Serial.println("Failed to set IP address");
}

void loop() {
ether.packetLoop(ether.packetReceive());
}

Verklaring

#include <EtherCard.h>
static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x00,0x01};
static byte myip[] = {192,168,1,10};
byte Ethernet::buffer[700];

Eerst moet u de EtherCard bibliotheek opnemen en enkele variabelen definiëren. MAC-adres, IP adres en een buffer die de bibliotheek zal gebruiken om inkomende en uitgaande gegevens op te slaan;

ether.begin(sizeof Ethernet::buffer, mymac, 10)

Start de bibliotheek met de methode begin (), je moet als parameters de grootte van de buffer, het MAC adres en de Arduino pincode doorgeven die is verbonden met ChipSelect PIN meestal PIN 10, maar controleer de documentatie van je board.

ether.staticSetup(myip)

Complete configuratie met een statische configuratie voor het IP-adres.

ether.packetLoop(ether.packetReceive());

In de loop heb je slechts 2 instructies nodig:

En nu is je Arduino online!

Een DHCP server gebruiken om automatisch netwerkparameters te configureren

Hierboven schreef je een eenvoudige schets waarin alle netwerkparameters werden gedefinieerd als constanten. dit dwingt je om opnieuw te compileren en je schets opnieuw te laden als je het netwerk waar je Arduino mee verbonden is moet veranderen.

Gewoonlijk vindt u in een lokaal netwerk een DHCP server (Dynamic Host Configuration Protocol), dat is een service die automatisch de apparaten configureert die op het netwerk zijn aangesloten.

Zonder het protocol te diep uit te leggen, werkt het op deze manier.

Gelukkig is wat ik hierboven heb beschreven, al voor ons geïmplementeerd in het bibliotheekbestand dhcp.cpp. Op de volgende pagina ga ik een eenvoudige schets laten zien met behulp van DHCP-services.

Hier is de Arduino-code.

#include <EtherCard.h>
static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x00,0x01};
byte Ethernet::buffer[700];
void setup () {
Serial.begin(57600);
Serial.println("DHCP Demo");
if (!ether.begin(sizeof Ethernet::buffer, mymac, 10))
  Serial.println( "Failed to access Ethernet controller");
else 
  Serial.println("Ethernet controller initialized");
if (!ether.dhcpSetup())
  Serial.println("Failed to get configuration from DHCP");
else
  Serial.println("DHCP configuration done");
  ether.printIp("IP Address:\t", ether.myip);
  ether.printIp("Netmask:\t", ether.mymask);
  ether.printIp("Gateway:\t", ether.gwip);
} 
void loop() {
  ether.packetLoop(ether.packetReceive());
}

Ten eerste heb ik geen vast IP adres meer gedefinieerd, alleen het MAC adres. De initialisatie van de controller wordt nog steeds uitgevoerd met de gebruikelijke methode begin ().

ether.dhcpSetup()

De methode dhcpSetup () voert alle bovenstaande stappen uit, zoekt naar een DHCP server, controleert de antwoorden, kiest een IP adres en vraagt toestemming om het te gebruiken. Die methode wacht 30 seconden, daarna wordt een fout geretourneerd.

ether.printIp()

De methode printIp () is een eenvoudige manier om een IP adres dat is opgeslagen in de Ethernet buffer als een array van uint8_t op een seriële monitor af te drukken.
Als alles goed gaat, zou je je Arduino opnieuw kunnen pingen.

En onze DHCP server toont een nieuw apparaat aangesloten. De EtherCard bibliotheek kiest Arduino-XX als apparaatnaam, met XX het laatste octet van het MAC adres.

Nadat je hebt geleerd om de Arduino met je netwerk te verbinden met behulp van statische IP adressen of met behulp van een DHCP server, zul je leren hoe je gegevens van een website kunt verzenden/ontvangen.

Om het volgende voorbeeld realistischer te maken, gaan we een eenvoudige PHP webpagina die een willekeurig aforisme verzendt telkens als je verbinding maakt (aforismen van Aphorisms Galore) gebruiken.

We gaan een Arduino schets schrijven om die aforismen te krijgen en deze naar de seriële verbinding te printen.

DNS

Meestal neem je contact op met een website door de naam ervan in te typen, je pc kan met behulp van een DNS server die naam in het overeenkomende IP adres omzetten om de verbinding tot stand te brengen.

Het is zo belangrijk om in Arduino het IP adres van de DNS server in uw netwerk te configureren.

#include <EtherCard.h>
static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x00,0x01};
static byte myip[] = {192,168,1,10};
static byte gatewayip[] = {192,168,1,1};
static byte dnsip[] = {151,99,125,2};
ether.staticSetup(myip, gatewayip, dnsip);

U kunt controleren of de naamomzetting werkt met de methode dnsLookup().

char website[] PROGMEM = "www.lucadentella.it";
if (!ether.dnsLookup(website))
  Serial.println("DNS failed");
else
  Serial.println("DNS resolution done");
  ether.printIp("SRV IP:\t", ether.hisip);

Connection

EtherCard bibliotheek heeft een zeer handige methode om verbinding te maken met een website: browseUrl (). Deze methode bereidt de verbinding voor die wordt voltooid in de volgende stappen die worden uitgevoerd tijdens de lus door de twee instructies die je al hebt geleerd.

ether.packetLoop(ether.packetReceive());

Het is heel belangrijk om die instructies te houden als je wilt dat alles werkt.

browseUrl() methode heeft enkele parameters nodig.

Ze verdeelden het adres in twee delen om het geheugengebruik te optimaliseren, het statische gedeelte wordt opgeslagen in het programmageheugen met de opdracht PSTR() om geen RAM geheugen te te verspillen.

Callback

De callback functie bevat de "acties" die u wilt uitvoeren aan het einde van de verbinding, in dit voorbeeld alleen de afdruk van wat u via de seriële verbinding hebt gekregen.
U kunt de functienaam kiezen, maar u moet dit declareren met de volgende parameters.

static void response_callback (byte status, word off, word len)

De eerste parameter bevat de verbindingsstatus, de tweede parameter de bufferoffset van waaruit de respons wordt opgeslagen en de derde de reactieafstand.
Om de betekenis van de offset parameter te begrijpen, moet u opmerken dat alle verzonden en ontvangen gegevens van een ethernetverbinding worden opgeslagen in de buffer die we hebben gedefinieerd.

byte Ethernet::buffer[700];

Die buffer bevat, wanneer u gegevens ontvangt, het hele pakket inclusief de velden voor de header, checksum ... Offsetwaarde vertelt u waar de payload begint, dat is waar de reactie van de website is.
Een callback functie om het antwoord af te drukken is.

static void response_callback (byte status, word off, word len) {
  Serial.print((const char*) Ethernet::buffer + off);
}

Als je de sketch uitvoert, je kunt hem hier vinden, krijg je de volgende berichten.

Arduino is correct geconfigureerd door DHCP, het werd verbonden met de website en print de reactie van de website.

Het antwoord bevat niet alleen het aforisme, maar ook enkele rijen die vereist zijn door het HTTP protocol. U hoeft die regels niet af te drukken, dus zoek met behulp van een teksteditor hoeveel tekens erin staan.

Die rijen bevinden zich vóór het aforisme in de ontvangstbuffer, u moet de callback functie wijzigen om 207 tekens later de bufferinhoud af te drukken.

static void response_callback (byte status, word off, word len) {
  Serial.print((const char*) Ethernet::buffer + off + 207);
}

Met de vorige wijziging krijgt u het juiste gedrag.

World Wide Web

Onder de netwerkdiensten, de meest gebruikte is zeker de webservice elke keer dat u op een website surft, maakt de browser die u gebruikt verbinding met de webserver die die site host met behulp van het HTTP protocol en krijgt u de inhoud nl. pagina's, afbeeldingen, video's ...te zien.

Webpagina's zijn samengesteld met behulp van een opmaaktaal met de naam HTML deze taal gebruikt tags om de pagina inhoud te beschrijven. De belangrijkste voordelen van het gebruik van HTTP om met Arduino te communiceren via een netwerkverbinding zijn.

Programma

Met een eenvoudig programma kan je via de seriële verbinding de verzoeken en antwoorden van de browser met een eenvoudige HTML pagina afdrukken.

Dit programma is handig om te begrijpen hoe HTTP functies moeten worden gebruikt en ook om te weten welke informatie een browser binnen het verzoek verzendt en hoe u die informatie in een volgend bericht kunt gebruiken.

De complete schets is hier beschikbaar en dit is de belangrijkste code.

word len = ether.packetReceive();
word pos = ether.packetLoop(len);

In de lus bewaar ik in een variabele de retourwaarde van de methode packetLoop (), deze waarde is de positie binnen de rx buffer, waar het verzoek van de browser begint.

if(pos) {
  Serial.println("---------- NEW PACKET ----------");
  Serial.println((char *)Ethernet::buffer + pos);
  Serial.println("--------------------------------");
  Serial.println();

Als pos groter is dan nul, heb ik echt een correct verzoek ontvangen en kan ik het op seriële poort afdrukken (buffer + pos is de positie om te starten).

BufferFiller bfill = ether.tcpOffset();

Om het antwoord op te slaan dat ik naar de browser van de client ga sturen, gebruik ik een BufferFiller object. Dit object erft van de afdrukklasse en de constructor krijgt als parameter het bufferadres van de ethernet (tcpOffset) waar het antwoord moet worden opgeslagen.

bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\nPragma: no-cache\r\n\r\n"
"<html><body><h1>BasicServer Demo</h1></body></html>"));

Met emit_p () methode kan ik gegevens opslaan in de buffer, voor dit voorbeeld maak ik een eenvoudige HTML pagina die BasicServer Demo tekst toont. Om RAM geheugenruimte te sparen, gebruik ik de PSTR() macro die strings in het PROGRAM opslaat.

ether.httpServerReply(bfill.position());

Eindelijk, met httpServerReply() methode, stuur ik het antwoord naar de browser. Deze methode heeft als parameter het aantal tekens nodig dat moet worden verzonden. Ik kan het aantal tekens dat BufferFiller bevat, met de methode position() bevatten.

Laad de schets, je kunt controleren of het goed is om in de adresbalk van je browser het IP-adres van je Arduino in te typen ... het resultaat zou als volgt moeten zijn.

En op uw seriële monitor.

U kunt zich afvragen waarom de browser twee verzoeken heeft verzonden, één voor de pagina "/" dat is de startpagina van de site en één voor de afbeelding favicon.ico. Dat is het pictogram dat sommige sites naast hun adres weergeven, hier is bijvoorbeeld het pictogram van DangerousPrototypes.

In deze blogpost laat ik je zien hoe je een schets kunt schrijven om een DNS record bij te werken dat wordt gehost door een van de meest bekende Dynamic DNS serviceproviders, no-ip.

Dynamic IP addresses

Als u verbinding maakt met internet via een thuis of mobiele verbinding, heeft u waarschijnlijk een dynamisch openbaar IP adres, dat wil zeggen dat het elke keer dat u verbinding maakt, verandert.Als u met een apparaat op internet wilt praten, moet u in het bericht dat u op internet verzendt het openbare IP adres schrijven: als dit IP adres dynamisch is, weet u dit misschien niet.

Dynamic DNS

Op internet kunt u gratis dynamische DNS (DDNS) services vinden, hiermee kunt u een door u gekozen naam aan een IP adres koppelen en kunt u die koppeling up to date houden.
De update kan op verschillende manieren worden gedaan

No-IP

Een van de meest gebruikte sites met dynamische DNS-service is No-IP.
Als u zich gratis registreert voor de No-IP Free service, kunt u maximaal 5 hosts configureren voor de functie Hosts/Doorverwijzingen.

Voor deze zelfstudie heb ik de volgende host geregistreerd: enc_tutorial.no-ip.info.

DDNS Client

Elke DDNS client voert de volgende stappen uit.

De volledige schets is hier beschikbaar, in de volgende paragrafen zal ik uitleggen hoe het werkt.

Workflow

De workflow van de Sketch is samengevat in het volgende diagram.

De schets is geschreven als een eenvoudige finite state machine (FSM) met 4 toestanden.

Public IP

Om de daadwerkelijke openbare IP te vinden, schreef ik een eenvoudige PHP pagina voor op mijn website.

Arduino sketch krijgt die pagina en ontleedt het IP adres.

DNS record and comparison

Schets roept de dnsLookup() methode op om het daadwerkelijke IP adres voor de DNS record op te lossen, het converteert vervolgens het resultaat in een String object om de methode compareTo() te gebruiken om de twee IP adressen te vergelijken:

if(!ether.dnsLookup(noIP_host)) {
[...]
} else {
for(int i = 0; i < 4; i++) {
  dnsIp = dnsIp + String(ether.hisip[i]);
  if(i < 3) dnsIp = dnsIp + ".";
}
if(actualIp.compareTo(dnsIp) == 0) {
  Serial.println("No update needed :)");
  [...]
} else {  
  Serial.println("Update needed :(");
  actual_status = STATUS_NOIP_NEEDS_UPDATE;

Authentication

U moet zich authenticeren met No-IP voordat u alle records mag bijwerken. In de schets is een constante gedefinieerd.

Je moet aan die constante de base64 gecodeerde waarde van de string gebruikersnaam en wachtwoord toewijzen.
U kunt een online encoder gebruiken.

Test

Om te controleren of de schets werkt, heb ik de DNS record handmatig bijgewerkt met een verkeerd IP adres.

dan heb ik de schets uitgevoerd:

Arduino vond een verschil tussen openbaar IP en DNS record, dus het heeft de No-IP record bijgewerkt. Na een tijdje voerde het nog een controle uit en deze keer waren de twee IP-adressen gelijk, dus er was geen update vereist.
No-IP website bevestigt de update.

Als u een verkeerde verificatiesleutel gebruikt, wordt de fout gedetecteerd en weergegeven in de schets.