Dnes by som rád predstavil projekt, ktorý som realizoval v dvoch prevedeniach. Projekt využíva 12 posuvných registrov 74HC595 a 96 LED diód, dosku Arduino Uno s Ethernet shieldom Wiznet W5100. Ku každému posuvnému registru je pripojených 8 LED diód. Prestredníctvom LED diód sú reprezentované čísla 0-9. Každý posuvný register je vybavený 8 výstupnými vývodmi.
Každé 4 posuvné registre 74HC595 tvoria logický celok - displej pre výpis 4-ciferného čísla. Celkovo sú teda v projekte 3 logické displeje tvorené 12-timi posuvnými registrami.
Implementácie sú kompatibilné pre Arduino dosky Nano, Mega, Uno a pre Ethernet shieldy a moduly z rodiny Wiznet, konkrétne modely W5100 a W5500 (s využitím Ethernet2 knižnice).
Realizované implementácie v projekte s Arduinom:Webserver - HTTP server bežiaci priamo na Arduine, umožňuje interpretovať HTML kód
WebClient - Klient schopný vykonať HTTP požiadavku na vzdialený server, odoslať / prevziať dáta
Webserver:Poskytuje HTML webovú stránku s formulárom, prostredníctvom ktorého je možné zadať 3 štvormiestne čísla.
Dáta sa po odoslaní formulára spracujú a uložia sa do EEPROM pamäte, používateľ je informovaný o spracovaní dát samostatnou podstránkou.
Po uložení dát je používateľ presmerovaný späť na formulár. EEPROM pamäť je energeticky nezávislá, dáta sú prístupné aj po obnovení napájania, ale aj reštarte dosky.
Všetky čísla sú následne reprezentované na troch displejoch tvorených 12-timi posuvnými registrami 74HC595.
WebClient:Komunikácia s webserverom prebieha každých 5 sekúnd po HTTP protokole.
Na webserveri beží PHP webaplikácia, ktorá umožňuje prostredníctvom formulára zadať 3 štvormiestne čísla.
Dáta z formulára sú uložené v MySQL databáze.
Arduino požiadavkou načítava dáta z tejto databázy prostredníctvom dopytu na server.
Spracované dáta Arduino rozparsuje, následne vykreslí prostredníctvom posuvných registrov 74HC595.
Dáta sú uložené aj do EEPROM pamäte Arduina, využívajú sa v prípade, že vypadne spojenie s webserverom / pri reštarte Arduino dosky sú použité pre prvotné vykreslenie dát na posuvné registre.
Dáta sa v EEPROM prepisujú až pri zmene dát, šetria sa EEPROM bunky pred zbytočnými prepismi.
Kaskádové zapojenie pre posuvné registre 74HC595 (možno rozšíriť o x ďalších) - Export z TinkerCAD-u:Screenshot z prevedenia Arduina ako Webservera - odoslanie dát, spracovanie, presmerovanie: Zo schémy je zrejmé, že na ovládanie posuvný registrov sa využívajú iba 3 dátové vodiče:Dátový vývod - (SER na 74HC595)
Hodinový vývod - (SRCLK na 74HC595)
Latch (klopný) vývod - (RCLK na 74HC595)
Posuvné registre je možné kombinovať do kaskády, pričom je možné ovládať posuvnými registrami aj iné periférie - napríklad relé pre spínanie výkonových prvkov. Jedným dátovým vývodom je možné ovládať aj 500 samostatných relé (s dostatočným počtom shift registrov a napájaním).
Pri ovládaní výstupov registrov je možné modifikovať aj byte order na najvýznamenší bit - MSB FIRST, alebo na LSB - najmenej významený bit. Vo výsledku to invertuje výstupy. V jednom prípade je rozsvietených napríklad 7 diód, v druhom prípade 1 dióda v závisloti od vstupu a byte order.
Obe implementácie využívajú EEPROM pamäť, ktorá dokáže uchovať dáta aj po výpadku napájania, alebo po reštarte dosky. Druhým využitím tejto pamäte je aj možnosť reprezentovať posledné známe dáta v prípade, že nie je možná komunikácia s webserverom (chyba konektivity, servera).
Pamäť je limitovaná na 10-tisíc až 100-tisíc prepisov. Implementácie sú navrhnuté pre čo najmenšiu záťaž pre pamät. Dáta sa prepíšu až pri ich zmene. V prípade načítania rovnakých dát z webservera / klienta sa neprepisujú v EEPROM pamäti.
Arduino vo WebClient móde komunikuje s webovým rozhraním v ktorom je možné modifikovať 3 štvorciferné čísla: https://arduino.php5.sk/led/Programovú implementáciu pre WebClient-a je možné vyskúšať:Kód:
//WebClient - Shift Register 74HC595
//Arduino + Ethernet Wiznet W5100
//Autor: Martin Chlebovec (martinius96)
//Web: https://arduino.php5.sk
//Donate: https://paypal.me/chlebovec
#include <SPI.h>
#include <Ethernet.h>
#include <EEPROM.h>
#define pinData 6
#define pinLatch 7
#define pinClock 8
unsigned long lastDebounceTime = 0;
byte mac[] = { 0xAA, 0xBB, 0xCC, 0x81, 0x7B, 0x4A };
const char * host = "www.arduino.php5.sk"; //PRIPADNE IP ADRESA websevera
IPAddress ip(192, 168, 1, 50);
EthernetClient client;
void ledWrite() {
String line = read_String(10);
String line2 = read_String(100);
String line3 = read_String(200);
String prve_cislo = line.substring(0, 1);
String druhe_cislo = line.substring(1, 2);
String tretie_cislo = line.substring(2, 3);
String stvrte_cislo = line.substring(3, 4);
String piate_cislo = line2.substring(0, 1);
String sieste_cislo = line2.substring(1, 2);
String siedme_cislo = line2.substring(2, 3);
String osme_cislo = line2.substring(3, 4);
String deviate_cislo = line3.substring(0, 1);
String desiate_cislo = line3.substring(1, 2);
String jedenaste_cislo = line3.substring(2, 3);
String dvanaste_cislo = line3.substring(3, 4);
int cislo_1;
int cislo_2;
int cislo_3;
int cislo_4;
int cislo_5;
int cislo_6;
int cislo_7;
int cislo_8;
int cislo_9;
int cislo_10;
int cislo_11;
int cislo_12;
if (prve_cislo == "0") {
cislo_1 = 127;
} else if (prve_cislo == "1") {
cislo_1 = 48;
} else if (prve_cislo == "2") {
cislo_1 = 238;
} else if (prve_cislo == "3") {
cislo_1 = 250;
} else if (prve_cislo == "4") {
cislo_1 = 179;
} else if (prve_cislo == "5") {
cislo_1 = 219;
} else if (prve_cislo == "6") {
cislo_1 = 223;
} else if (prve_cislo == "7") {
cislo_1 = 112;
} else if (prve_cislo == "8") {
cislo_1 = 255;
} else if (prve_cislo == "9") {
cislo_1 = 251;
}
if (druhe_cislo == "0") {
cislo_2 = 127;
} else if (druhe_cislo == "1") {
cislo_2 = 48;
} else if (druhe_cislo == "2") {
cislo_2 = 238;
} else if (druhe_cislo == "3") {
cislo_2 = 250;
} else if (druhe_cislo == "4") {
cislo_2 = 179;
} else if (druhe_cislo == "5") {
cislo_2 = 219;
} else if (druhe_cislo == "6") {
cislo_2 = 223;
} else if (druhe_cislo == "7") {
cislo_2 = 112;
} else if (druhe_cislo == "8") {
cislo_2 = 255;
} else if (druhe_cislo == "9") {
cislo_2 = 251;
}
if (tretie_cislo == "0") {
cislo_3 = 127;
} else if (tretie_cislo == "1") {
cislo_3 = 48;
} else if (tretie_cislo == "2") {
cislo_3 = 238;
} else if (tretie_cislo == "3") {
cislo_3 = 250;
} else if (tretie_cislo == "4") {
cislo_3 = 179;
} else if (tretie_cislo == "5") {
cislo_3 = 219;
} else if (tretie_cislo == "6") {
cislo_3 = 223;
} else if (tretie_cislo == "7") {
cislo_3 = 112;
} else if (tretie_cislo == "8") {
cislo_3 = 255;
} else if (tretie_cislo == "9") {
cislo_3 = 251;
}
if (stvrte_cislo == "0") {
cislo_4 = 127;
} else if (stvrte_cislo == "1") {
cislo_4 = 48;
} else if (stvrte_cislo == "2") {
cislo_4 = 238;
} else if (stvrte_cislo == "3") {
cislo_4 = 250;
} else if (stvrte_cislo == "4") {
cislo_4 = 179;
} else if (stvrte_cislo == "5") {
cislo_4 = 219;
} else if (stvrte_cislo == "6") {
cislo_4 = 223;
} else if (stvrte_cislo == "7") {
cislo_4 = 112;
} else if (stvrte_cislo == "8") {
cislo_4 = 255;
} else if (stvrte_cislo == "9") {
cislo_4 = 251;
}
if (piate_cislo == "0") {
cislo_5 = 127;
} else if (piate_cislo == "1") {
cislo_5 = 48;
} else if (piate_cislo == "2") {
cislo_5 = 238;
} else if (piate_cislo == "3") {
cislo_5 = 250;
} else if (piate_cislo == "4") {
cislo_5 = 179;
} else if (piate_cislo == "5") {
cislo_5 = 219;
} else if (piate_cislo == "6") {
cislo_5 = 223;
} else if (piate_cislo == "7") {
cislo_5 = 112;
} else if (piate_cislo == "8") {
cislo_5 = 255;
} else if (piate_cislo == "9") {
cislo_5 = 251;
}
if (sieste_cislo == "0") {
cislo_6 = 127;
} else if (sieste_cislo == "1") {
cislo_6 = 48;
} else if (sieste_cislo == "2") {
cislo_6 = 238;
} else if (sieste_cislo == "3") {
cislo_6 = 250;
} else if (sieste_cislo == "4") {
cislo_6 = 179;
} else if (sieste_cislo == "5") {
cislo_6 = 219;
} else if (sieste_cislo == "6") {
cislo_6 = 223;
} else if (sieste_cislo == "7") {
cislo_6 = 112;
} else if (sieste_cislo == "8") {
cislo_6 = 255;
} else if (sieste_cislo == "9") {
cislo_6 = 251;
}
if (siedme_cislo == "0") {
cislo_7 = 127;
} else if (siedme_cislo == "1") {
cislo_7 = 48;
} else if (siedme_cislo == "2") {
cislo_7 = 238;
} else if (siedme_cislo == "3") {
cislo_7 = 250;
} else if (siedme_cislo == "4") {
cislo_7 = 179;
} else if (siedme_cislo == "5") {
cislo_7 = 219;
} else if (siedme_cislo == "6") {
cislo_7 = 223;
} else if (siedme_cislo == "7") {
cislo_7 = 112;
} else if (siedme_cislo == "8") {
cislo_7 = 255;
} else if (siedme_cislo == "9") {
cislo_7 = 251;
}
if (osme_cislo == "0") {
cislo_8 = 127;
} else if (osme_cislo == "1") {
cislo_8 = 48;
} else if (osme_cislo == "2") {
cislo_8 = 238;
} else if (osme_cislo == "3") {
cislo_8 = 250;
} else if (osme_cislo == "4") {
cislo_8 = 179;
} else if (osme_cislo == "5") {
cislo_8 = 219;
} else if (osme_cislo == "6") {
cislo_8 = 223;
} else if (osme_cislo == "7") {
cislo_8 = 112;
} else if (osme_cislo == "8") {
cislo_8 = 255;
} else if (osme_cislo == "9") {
cislo_8 = 251;
}
if (deviate_cislo == "0") {
cislo_9 = 127;
} else if (deviate_cislo == "1") {
cislo_9 = 48;
} else if (deviate_cislo == "2") {
cislo_9 = 238;
} else if (deviate_cislo == "3") {
cislo_9 = 250;
} else if (deviate_cislo == "4") {
cislo_9 = 179;
} else if (deviate_cislo == "5") {
cislo_9 = 219;
} else if (deviate_cislo == "6") {
cislo_9 = 223;
} else if (deviate_cislo == "7") {
cislo_9 = 112;
} else if (deviate_cislo == "8") {
cislo_9 = 255;
} else if (deviate_cislo == "9") {
cislo_9 = 251;
}
if (desiate_cislo == "0") {
cislo_10 = 127;
} else if (desiate_cislo == "1") {
cislo_10 = 48;
} else if (desiate_cislo == "2") {
cislo_10 = 238;
} else if (desiate_cislo == "3") {
cislo_10 = 250;
} else if (desiate_cislo == "4") {
cislo_10 = 179;
} else if (desiate_cislo == "5") {
cislo_10 = 219;
} else if (desiate_cislo == "6") {
cislo_10 = 223;
} else if (desiate_cislo == "7") {
cislo_10 = 112;
} else if (desiate_cislo == "8") {
cislo_10 = 255;
} else if (desiate_cislo == "9") {
cislo_10 = 251;
}
if (jedenaste_cislo == "0") {
cislo_11 = 127;
} else if (jedenaste_cislo == "1") {
cislo_11 = 48;
} else if (jedenaste_cislo == "2") {
cislo_11 = 238;
} else if (jedenaste_cislo == "3") {
cislo_11 = 250;
} else if (jedenaste_cislo == "4") {
cislo_11 = 179;
} else if (jedenaste_cislo == "5") {
cislo_11 = 219;
} else if (jedenaste_cislo == "6") {
cislo_11 = 223;
} else if (jedenaste_cislo == "7") {
cislo_11 = 112;
} else if (jedenaste_cislo == "8") {
cislo_11 = 255;
} else if (jedenaste_cislo == "9") {
cislo_11 = 251;
}
if (dvanaste_cislo == "0") {
cislo_12 = 127;
} else if (dvanaste_cislo == "1") {
cislo_12 = 48;
} else if (dvanaste_cislo == "2") {
cislo_12 = 238;
} else if (dvanaste_cislo == "3") {
cislo_12 = 250;
} else if (dvanaste_cislo == "4") {
cislo_12 = 179;
} else if (dvanaste_cislo == "5") {
cislo_12 = 219;
} else if (dvanaste_cislo == "6") {
cislo_12 = 223;
} else if (dvanaste_cislo == "7") {
cislo_12 = 112;
} else if (dvanaste_cislo == "8") {
cislo_12 = 255;
} else if (dvanaste_cislo == "9") {
cislo_12 = 251;
}
shiftOut(pinData, pinClock, LSBFIRST, cislo_1);
shiftOut(pinData, pinClock, LSBFIRST, cislo_2);
shiftOut(pinData, pinClock, LSBFIRST, cislo_3);
shiftOut(pinData, pinClock, LSBFIRST, cislo_4);
shiftOut(pinData, pinClock, LSBFIRST, cislo_5);
shiftOut(pinData, pinClock, LSBFIRST, cislo_6);
shiftOut(pinData, pinClock, LSBFIRST, cislo_7);
shiftOut(pinData, pinClock, LSBFIRST, cislo_8);
shiftOut(pinData, pinClock, LSBFIRST, cislo_9);
shiftOut(pinData, pinClock, LSBFIRST, cislo_10);
shiftOut(pinData, pinClock, LSBFIRST, cislo_11);
shiftOut(pinData, pinClock, LSBFIRST, cislo_12);
digitalWrite(pinLatch, HIGH);
digitalWrite(pinLatch, LOW);
}
void writeString(char add, String data)
{
int _size = data.length();
int i;
for (i = 0; i < _size; i++)
{
EEPROM.write(add + i, data[i]);
}
EEPROM.write(add + _size, '\0'); //Add termination null character for String Data
}
String read_String(char add)
{
int i;
char data[100]; //Max 100 Bytes
int len = 0;
unsigned char k;
k = EEPROM.read(add);
while (k != '\0' && len < 500) //Read until null character
{
k = EEPROM.read(add + len);
data[len] = k;
len++;
}
data[len] = '\0';
return String(data);
}
void setup() {
Serial.begin(115200);
pinMode(pinData, OUTPUT);
pinMode(pinLatch, OUTPUT);
pinMode(pinClock, OUTPUT);
ledWrite();
if (Ethernet.begin(mac) == 0) {
// Ethernet.begin(mac); //DYNAMIC IP
Ethernet.begin(mac, ip); //STATIC IP
}
Serial.print(" DHCP assigned IP ");
Serial.println(Ethernet.localIP());
Serial.println("Ready");
}
void loop() {
if (Ethernet.begin(mac) == 0) {
// Ethernet.begin(mac); //DYNAMIC IP
Ethernet.begin(mac, ip); //STATIC IP
Serial.print(" DHCP assigned IP ");
Serial.println(Ethernet.localIP());
}
if ((millis() - lastDebounceTime) > 5000) {
lastDebounceTime = millis();
client.stop();
String url = "/led/data.php";
if (client.connect(host, 80)) {
Serial.println("Pripojenie na webserver uspesne");
client.print(String("GET ") + url + " HTTP/1.0\r\n" + "Host: " + host + "\r\n" + "User-Agent: WiznetW5100\r\n" + "Connection: close\r\n\r\n");
while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
break;
}
}
String line = client.readStringUntil('\n');
line = line + String("\n");
Serial.println(line);
char str[line.length() + 1];
line.toCharArray(str, line.length());
const char terminator4[2] = "&";
const char terminator5[2] = "=";
char* hodnota1;
char* hodnota2;
char* hodnota3;
hodnota1 = strtok(str, terminator4);
hodnota2 = strtok(NULL, terminator4);
hodnota3 = strtok(NULL, terminator4);
Serial.println(hodnota1);
Serial.println(hodnota2);
Serial.println(hodnota3);
char* H_1;
char* H_2;
char* H_3;
strtok(hodnota1, terminator5);
H_1 = strtok(NULL, terminator5);
strtok(hodnota2, terminator5);
H_2 = strtok(NULL, terminator5);
strtok(hodnota3, terminator5);
H_3 = strtok(NULL, terminator5);
Serial.println(String(H_1));
Serial.println(String(H_2));
Serial.println(String(H_3));
String line_1 = read_String(10);
String line_2 = read_String(100);
String line_3 = read_String(200);
if (String(H_1) != line_1) {
writeString(10, String(H_1));
}
if (String(H_2) != line_2) {
writeString(100, String(H_2));
}
if (String(H_3) != line_3) {
writeString(200, String(H_3));
}
ledWrite();
} else {
Serial.println("Spojenie s webserverom neuspesne");
}
}
}