In articolul precedent numit Placa de retea cu ENC28J60 si Arduino am prezentat pe scurt cum am conectat eu placa de retea la unArduino Uno... avandu-l ocupat pentru "teste de anduranta", am conectat o alta placa cu ENC28J60 la o placa Arduino Mega si incarcand sketch-ul am avut surpriza sa constat ca nu functioneaza.. chiar daca am schimbat legaturile pe pinii dedicati: MISO la pin 50, MOSI la pin 51, SCK la 52 si SS/CS la 53, cum e prezentat si in articolul How to use enc28j60 ethernet shield with Arduino Mega 2560
Acolo se prezinta o modificare, pentru fortarea pinului CS/SS la pin 53.
Serial.println(P("Failed to access Ethernet controller"));
}
else
{
Serial.println(P("Ethernet is fine and up"));
}
...
Pentru a functiona, in loc de litera P trebuie pus F.
De asemenea, si in libraria Ethercard se mentioneaza acest lucru si prezinta comanda de trecerea a pinului 8 in 53:
VCC - 3.3V
GND - GND
SCK - Pin 52
SO - Pin 50
SI - Pin 51
CS - Pin 53 # Selectable with the ether.begin() function
# The default CS pin defaults to 8, so you have to set it on a mega:
ether.begin(sizeof Ethernet::buffer, mymac, 53)
Inlocuind partea de mutare a comenzii de pe pinul 8 (de la Arduino Uno) pe 53 (la Arduino Mega), sketch-ul din articolul precedent arata asa:
//original sketch from http://www.lucadentella.it/2012/11/10/enc28j60-e-arduino-9/// adapted sketch from http://nicuflorica.blogspot.ro/
#include <EtherCard.h>
#include <avr/wdt.h>
#define RELAY_PIN 2
// ethernet interface mac address, must be unique on the LANstaticbyte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
staticbyte myip[] = { 192,168,0,199 };
byteEthernet::buffer[500];
BufferFiller bfill;
char* on = "ON";
char* off = "OFF";
boolean relayStatus;
char* relayLabel;
char* linkLabel;
voidsetup () {
Serial.begin(9600);
// 1st good version from https://www.youtube.com/watch?v=d2toibPesS4/* if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0) Serial.println(F("Failed to access Ethernet controller")); */// 2nd good version from http://en.code-bude.net/2013/06/22/how-to-use-enc28j60-ethernet-shield-with-arduino-mega-2560/if (ether.begin(sizeof Ethernet::buffer, mymac, 53) == 0)
{
Serial.println(F("Failed to access Ethernet controller"));
}
else
{
Serial.println(F("Ethernet is fine and up"));
}
ether.staticSetup(myip); // put static IP in local networkpinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
relayStatus = false;
relayLabel = off;
linkLabel = on;
wdt_enable(WDTO_1S);//This start the watchdog timer with a 1 second timeout
}
voidloop() {
wdt_reset();//This resets the timerlong t = millis() / 1000;
word h = t / 3600;
byte m = (t / 60) % 60;
byte s = t % 60;
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if(pos) {
if(strstr((char *)Ethernet::buffer + pos, "GET /?ON") != 0) {
relayStatus = true;
relayLabel = on;
linkLabel = off;
} elseif(strstr((char *)Ethernet::buffer + pos, "GET /?OFF") != 0) {
relayStatus = false;
relayLabel = off;
linkLabel = on;
}
digitalWrite(RELAY_PIN, relayStatus);
BufferFiller bfill = ether.tcpOffset();
bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n""Content-Type: text/html\r\nPragma: no-cache\r\n\r\n"// from http://fabiotomio.com.br/blog/2014/05/07/arduino-modulo-ethernet-enc28j60//* "Content-Type: text/html\r\n" "Refresh: 5\r\n" "\r\n" */"<html><head><meta name='viewport' content='width=200px'/></head><body>""<div style='position:absolute;width:200px;height:200px;top:50%;left:50%;margin:-100px 0 0 -100px'>""<div style='font:bold 14px verdana;text-align:center'>Relay is $S</div>""<br><div style='text-align:center'>""<a href='/?$S'><img src='http://www.lucadentella.it/files/bt_$S.png'></a>"
), relayLabel, linkLabel, linkLabel);
bfill.emit_p(PSTR("<p>""<h2>$D$D:$D$D:$D$D</h2>"),
h/10, h%10, m/10, m%10, s/10, s%10);
bfill.emit_p(PSTR("</body></html>"));
ether.httpServerReply(bfill.position());
}
}
// note: for watchdog see https://hackaday.io/project/3731-open-z3zzvw3/log/12362-the-brain-of-the-thingy
In sketch am lasat si varianta din film, doar ca "comentata"... La adresa locala data de mine, 192.168.0.199 gasim 2 situatii:
PS: Pentru a nu avea probleme, trebuie impus IP-ul prin comanda ether.staticSetup(myip);dupa cum se vede in imaginea urmatoare:
PS2: Dupa cateva ore de teste, am observat ca este stabila pagina doar daca se trimit comenzi din reteaua locala, prin cablu, in cazul folosiri unui periferic (laptop, telefon, tableta) conectat prin "uairles" atunci ea se blocheaza. Solutia gasita de mine pentru a elimia aceasta ploblerma, este acea de a folosi pinul 8, ca in cazul placii Arduino Uno si renuntare ala "portarea" pinului 8 la 53...
In montaj eu am mai pus si pinul de RESET...
Sketch-ul devine simplu:
//original sketch from http://www.lucadentella.it/2012/11/10/enc28j60-e-arduino-9/// adapted sketch by niq_ro from http://nicuflorica.blogspot.ro/// direct link: http://nicuflorica.blogspot.ro/2015/03/placa-de-retea-cu-enc28j60-si-arduino_25.html
#include <EtherCard.h>
#include <avr/wdt.h> // for watchdog see https://hackaday.io/project/3731-open-z3zzvw3/log/12362-the-brain-of-the-thingy
#define RELAY_PIN 2
// ethernet interface mac address, must be unique on the LANstaticbyte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
staticbyte myip[] = { 192,168,0,199 };
staticbyte gwip[] = {192,168,0,1};
byteEthernet::buffer[500];
BufferFiller bfill;
char* on = "ON";
char* off = "OFF";
boolean relayStatus;
char* relayLabel;
char* linkLabel;
voidsetup () {
Serial.begin(9600);
if(ether.begin(sizeof Ethernet::buffer, mymac) == 0)
Serial.println( "Failed to access Ethernet controller");
elseSerial.println("Ethernet controller initialized");
if (!ether.dhcpSetup())
Serial.println("Failed to get configuration from DHCP");
if(!ether.staticSetup(myip))
Serial.println("Failed to set IP address");
ether.printIp("My IP: ", ether.myip);
// ether.printIp("Netmask: ", ether.mymask);
ether.printIp("GW IP: ", ether.gwip);
ether.printIp("DNS IP: ", ether.dnsip);
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW);
relayStatus = false;
relayLabel = off;
linkLabel = on;
wdt_enable(WDTO_1S);//This start the watchdog timer with a 1 second timeout
}
voidloop() {
wdt_reset();//This resets the timerlong t = millis() / 1000;
word h = t / 3600;
byte m = (t / 60) % 60;
byte s = t % 60;
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if(pos) {
if(strstr((char *)Ethernet::buffer + pos, "GET /?ON") != 0) {
relayStatus = true;
relayLabel = on;
linkLabel = off;
} elseif(strstr((char *)Ethernet::buffer + pos, "GET /?OFF") != 0) {
relayStatus = false;
relayLabel = off;
linkLabel = on;
}
digitalWrite(RELAY_PIN, relayStatus);
BufferFiller bfill = ether.tcpOffset();
bfill.emit_p(PSTR("HTTP/1.0 200 OK\r\n""Content-Type: text/html\r\nPragma: no-cache\r\n\r\n"// from http://fabiotomio.com.br/blog/2014/05/07/arduino-modulo-ethernet-enc28j60//* "Content-Type: text/html\r\n" "Refresh: 5\r\n" "\r\n" */"<html><head><meta name='viewport' content='width=200px'/></head><body>""<div style='position:absolute;width:200px;height:200px;top:50%;left:50%;margin:-100px 0 0 -100px'>""<div style='font:bold 14px verdana;text-align:center'>Relay is $S</div>""<br><div style='text-align:center'>""<a href='/?$S'><img src='http://www.lucadentella.it/files/bt_$S.png'></a>"
), relayLabel, linkLabel, linkLabel);
bfill.emit_p(PSTR("<p>""<h2>$D$D:$D$D:$D$D</h2>"),
h/10, h%10, m/10, m%10, s/10, s%10);
bfill.emit_p(PSTR("</body></html>"));
ether.httpServerReply(bfill.position());
}
}
Senzorul DTH11 ofera informatii despre temperatura si umiditate, dar nu cu o prea mare precizie, totusi pentru experimente este ok (domeniu de temperatura 0..50oC cu precizie de +2oC, respectiv umiditate 20..90%RH cu o precizie de +5%RH). L-am mai prezentat la inceputurile mele cu Arduino: Ministatie meteo cu senzorul DHT11 si.. Arduino
Exista o varianta mai buna decat DHT11, ca domeniu de masura si precizie, e vorba de DHT22: domeniu de temperatura -40..125oC cu precizie de +0,5oC, respectiv umiditate 0..100%RH cu o precizie de +2%RH.
Revenind la partea de afisare pe ecran grafic color, am folosit montajul de la partea de termometru dublu cu senzori de temperatura DS18B20 (prezentat in articolul anterior), adaptandu-l la modul de conectare al modulului cu senzor DHT11:
/*// original sketch by niq_ro from http://nicuflorica.blogspot.com for analog clock using ucglib library// version for 2.2" TFT with ILI9341 - 2014.07.29, Craiova - Romania// or http://www.tehnic.go.ro// or http://arduinotehniq.blogspot.com/Universal uC Color Graphics Libraryhttps://code.google.com/p/ucglib/ Copyright (c) 2014, olikraus@gmail.com All rights reserved.*/
#include <SPI.h>
#include "Ucglib.h"// Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 13, /*data=*/ 11, /*cd=*/ 6 , /*cs=*/ 5, /*reset=*/ 4); //gordons//Ucglib_ILI9341_18x240x320_SWSPI ucg(/*sclk=*/ 52, /*data=*/ 51, /*cd=*/ 26 , /*cs=*/ 24, /*reset=*/ 22); //at Mega//Ucglib_ILI9341_18x240x320_HWSPI ucg(/*cd=*/ 6 , /*cs=*/ 5, /*reset=*/ 4); // at Uno
Ucglib_ILI9341_18x240x320_HWSPI ucg(/*cd=*/ 26 , /*cs=*/ 24, /*reset=*/ 22); // at Mega/*http://gordonsprojects.blogspot.ro/2014/04/arduino-tft-serial-spi-22-ili9341.htmlMega | Uno | TFT - ILI9341----------------------D22 | D4 | RESETD24 | D5 | CSD26 | D6 | D/C ? | ? | LED (via 220 ohms resistor at 5V)D51 | D11 | MOSID50 | D12 | MISOD52 | D13 | SCK-----------------------------with CD4050 adapter or 10k resistor, power supply and logical levels is 3.3Vschematic: http://nicuflorica.blogspot.ro/2014/07/afisaj-grafic-color-qvga-de-22-cu.html*/
#include "DHT.h"
#define DHTPIN A0 // what pin we're connected to
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
void subrutina(void) {
ucg.setRotate90();
// graphic commands to redraw the complete screen should be placed here // pictez un chenar
ucg.setColor(255, 255, 255); // culoare alba
ucg.drawFrame(0,0,320,240); //
ucg.setFont(ucg_font_courB24); // 20 pixel height
ucg.setColor(255, 0, 0); // culoare rosie
ucg.setPrintPos(60,30);
ucg.print("Ministatie");
ucg.setColor(0, 255, 0); // culoare verde
ucg.setColor(0, 255, 0);
ucg.setColor(0, 0, 255); // culoare albastru
ucg.setPrintPos(20, 60);
ucg.print("meteo cu DHT11");
ucg.setFont(ucg_font_fur17r); // 17 pixel height
ucg.setColor(255, 255, 0); // culoare galbena
ucg.setPrintPos(25,90);
ucg.print("ecran grafic 2,2'' (5,6cm)");
ucg.setFont(ucg_font_courB24); // 20 pixel height
ucg.setColor(0, 255, 255); // culoare bleo
ucg.setPrintPos(10,120);
ucg.print("QVGA cu ILI9341");
ucg.setColor(255, 0, 255); // culoare mov
ucg.setPrintPos(40,150);
ucg.print("versiune 3.0");
ucg.setFont(ucg_font_fur17r); // 17 pixel height
ucg.setColor(255, 255, 255); // culoare alb
ucg.setPrintPos(60,200);
ucg.print("realizat de niq_ro");
}
// variables // variabile int t1, t2;
int t10, t20;
int t11, t21;
int t12, t22;
int t13, t23;
int h11, h12;
voidsetup(void) {
dht.begin();
// Serial.begin(9600); // open the serial port at 9600 bps: delay(1000);
ucg.begin(UCG_FONT_MODE_TRANSPARENT);
//ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
// ucg.clearScreen();
ucg.setFont(ucg_font_ncenR14r);
ucg.setColor(255, 0, 255);
ucg.setColor(1, 255, 0,0);
subrutina(); // unde e mesajul de intampinaredelay(5000);
ucg.clearScreen();
// initial value
t12=40.0;
t12=40.0;
}
voidloop(void) {
// DHT11 partint h11 = dht.readHumidity();
int t11 = dht.readTemperature();
//-------------------------------------------------------if (t11 != t12)
{
texte(t11, t12, 20, 0); // temperature, x, y
termometre(t11, 20);
}
if (h11 != h12)
{
texte(h11, h12, 100, 90); // humidity, x, y
sticla(h11, h12);
}
delay (2000);
// store old value
t12=t11;
h12=h11;
} // final de program, se revine de la inceputvoid texte(int t3, int t4, int ics, int igrec)
{
int t5 = t3;
int t6 = t4;
ucg.setFont(ucg_font_courB24); // 20 pixel height // ucg.clearScreen(); if (t3*t4 < 0)
{ucg.setColor(0, 0, 0);
for (int qy = 39 ; qy < 60; qy++)
{
ucg.drawHLine(ics+7, qy + igrec , 105);
}
}
// sterg semnul ??int t51 = t5/10;
int t61 = t6/10;
ucg.setColor(0, 0, 0);
// sterg zeci daca e cazulif (t51 != t61)
{
//ucg.setColor(255, 255, 0); for (int qy = 39 ; qy < 60; qy++)
{
ucg.drawHLine(ics+28, qy + igrec , 21);
}
}
t5 = t3 - t51*10;
t6 = t4 - t61*10;
// sterg unitati daca e cazul//if ((t5 != t6) || (t5-t6>0.2))if (t5 != t6)
{
//ucg.setColor(0, 255, 255); for (int qy = 39 ; qy < 60; qy++)
{
ucg.drawHLine(ics+49, qy + igrec , 21);
}
}
if (igrec <30)
{
ucg.setColor(255, 255, 0);
ucg.setPrintPos(10 + ics, 30 + igrec);
ucg.print("temperatura:");
}
else
{
ucg.setColor(0, 255, 255);
ucg.setPrintPos(15 + ics, 30 + igrec);
ucg.print("umiditate:");
}
// ucg.setPrintPos(10 + ics, 30 + igrec);// ucg.print("temperatura:"); //ucg.setFont(ucg_font_fub42n); // 20 pixel height
ucg.setPrintPos(10 + ics, 60 + igrec);
if (t3 > 10) ucg.print("+");
else
{
//ucg.setColor(255, 255, 0);
ucg.setColor(0, 0, 0);
for (int qy = 39 ; qy < 60; qy++)
{
ucg.drawHLine(ics+10, qy + igrec , 21);
}
if (igrec <30) ucg.setColor(255, 255, 0);
else ucg.setColor(0, 255, 255);
ucg.setPrintPos(31 + ics, 60 + igrec);
ucg.print("+");
}
//if (t3==0.0) ucg.print(" ");// ucg.print(t12,1);
ucg.print(t3,1);
// ucg.print("23.6"); if (igrec <30)
{
ucg.print(" C");
ucg.setFont(ucg_font_fur17r); // 17 pixel height/* ucg.setPrintPos(30 + ics, 35 + igrec); if (igrec == 0) ucg.print("int"); else ucg.print("ext"); */
ucg.setPrintPos(75 + ics, 50 + igrec);
ucg.print("o");
}
else ucg.print("%");
}
void termometre (int t, int ics1)
{
ucg.setColor(255, 255, 255);
// ucg.setColor(r2, g2, b2);
ucg.drawFrame(ics1-4,10,9,200); // desenez corp termometru// ucg.drawDisc(ics1,220,10,UCG_DRAW_ALL); // desenez partea de jos, cu mercur
ucg.drawCircle(ics1,220,10,UCG_DRAW_ALL); // desenez partea de jos, cu mercurfor (int a = 0; a < 5; a++)
{
ucg.drawLine(ics1-5,15+35*a,ics1-7,15+35*a);
ucg.drawLine(ics1+5,15+35*a,ics1+7,15+35*a);
}
ucg.drawLine(ics1-10,190,ics1+10,190); // zero degree
ucg.setFont(ucg_font_courB24); // 20 pixel height
ucg.setPrintPos(15 + ics1, 199);
ucg.print("0 C");
ucg.setFont(ucg_font_fur17r); // 17 pixel height
ucg.setPrintPos(39 + ics1, 185);
ucg.print("o");
// temperature "lengh"//int lin = 140 - 2*t;int lin = 190-3.5*t;
ucg.setColor(0, 0, 0); // black //ucg.drawBox(ics1-2,20, 5, 190); // erase
ucg.drawBox(ics1-2,21, 5, lin+5);
// temperature gaphicsif (ics1 <30) ucg.setColor(255, 255, 0);
else ucg.setColor(0, 0, 255);
ucg.drawDisc(ics1,220,8,UCG_DRAW_ALL); // desenez partea de jos, cu mercur//ucg.setColor(255, 255, 0); // ucg.drawLine(ics1-10,lin,ics1+10,lin); // just for control
ucg.drawBox(ics1-2,lin, 5, 210-lin);
}
void sticla (int h, int h2)
{
int xmax = 319;
int ymax = 239;
int raza = 98;
// h = 45; // pentru teste
ucg.setColor(255, 255, 255);
ucg.drawCircle(319,239,100,UCG_DRAW_UPPER_LEFT); // desenez arc de cerc in stanga sus
ucg.setColor(0, 0, 255);
ucg.drawHLine(220, 239, 100); // desenez linia de 0% (orizontala)
ucg.setColor(255, 0, 0);
ucg.drawVLine(319, 140, 100); // desenez linia de 100% (verticala)//calculez coordonateint xa=100*cos(2*h2*0.9*3.14/360);
int ya=100*sin(2*h2*0.9*3.14/360);
int xn=100*cos(2*h*3.14*0.9/360);
int yn=100*sin(2*h*3.14*0.9/360);
//sterg indicatia anterioara
ucg.setColor(0, 0, 0);
ucg.drawLine(xmax-xa, ymax-ya, xmax, ymax); // //desenez indicatia noua
ucg.setColor(0, 255, 255);
ucg.drawLine(xmax-xn, ymax-yn, xmax, ymax); //
}
Avand in vedere ca folosesc Arduino Mega nu mai am restrictii la marimea programului, asa ca pana o sa cumpar un senzor performant DHT22, o sa sa masor temperatura cu senzorul DS18B20 si umiditatea cu DHT11. Schema de conectare a celor 2 senzori este combinatia schemelor anterioare:
Ministatiemeteo cu DHT11si DS18B20
Am combinat sketch-ul anterior cu cel de la masurarea cu DS18B20 obtinand:
5.8.2014 Am scos semnul "+" de la umiditate si am schimbat "bateria" cu o barcuta cu vele, care pluteste ce o apa, a carei nivel este proportional cu umiditatea...