Din greseala mi-am cumparat un adaptor de ethernet bazat pe circuitul ENC28J60.
Cand l-am primit am constatat ca este pentru Arduino, adica este placa shield care se suprapune peste placa Arduino. Eu as fi vrut sa-l folosesc cu PIC-uri Microchip.
Testat pe Arduino Mega 2560, circuitul cu ENC28J60 merge numai ca in imaginea de mai jos,
pentru ca Arduino Mega 2560 are pinii SPI (MOSI, MISO, SCK) in alta parte decat Arduino Uno, iar placa ENC28J60 v1.1 este numai pentru Arduino Uno.
Pe placa Arduino Uno, programul functioneaza destul de stabil cu UIPEthernet si MQTT PubSub Client - knolleary.
In documentatia clientului de MQTT este specificat ca nu merge cu ENC28J60, dar autorul bibliotecii UIPEthernet a avut grija sa pastreze compatibilitatea cu biblioteca <Ethernet.h>, care este pentru cipul wiznet (w5200 si w5500). Cipul wiznet este solutia ethernet oficial suportata de Arduino, dar cipul wiznet (shieldul Arduino) este de doua-trei ori mai scump decat solutia cu ENC28J60.
Mi-am cumparat doua module ENC28J60, fara sa fie shield Arduino, la 20 RON bucata:
Desi ENC28J60 e mai ieftin, interfatarea necesita memorie RAM mai multa (pentru PIC Microchip trebuie cel putin 32k flash si 2-3k ram) si programul este mai complicat.
Pentru Arduino, aproape orice program care merge cu biblioteca <Ethernet.h>, trebuie sa mearga fara modificari si cu biblioteca <UIPEthernet.h>.
Programul folosit de mine ocupa 75% din memoria de program a lui Arduino Uno:
#include <avr/wdt.h>
//Aproape orice merge cu
//#include <Ethernet.h>
//trebuie sa mearga si cu
#include <UIPEthernet.h>
#include "PubSubClient.h"
// Update these with values suitable for your network.
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 200); //my ip
IPAddress server(192, 168, 1, 1);
EthernetClient ethClient;
PubSubClient client(ethClient);
unsigned long cnt1, cnt2, cnt3, cnt4;
void watchdogSetup(void)
{
cli(); // disable all interrupts
wdt_reset(); // reset the WDT timer
/*
WDTCSR configuration:
WDIE = 1: Interrupt Enable
WDE = 1 :Reset Enable
WDP3 = 0 :For 2000ms Time-out
WDP2 = 1 :For 2000ms Time-out
WDP1 = 1 :For 2000ms Time-out
WDP0 = 1 :For 2000ms Time-out
*/
// Enter Watchdog Configuration mode:
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Set Watchdog settings:
WDTCSR = (1<<WDIE) | (1<<WDE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (1<<WDP0);
sei();
}
void callback(char* topic, byte* payload, unsigned int length) {
wdt_reset();
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
//Serial.print("Primit:");
//for (int i=0;i<length;i++)
}
void sendMQTT_Data(){
int n, v1, v2;
#define LG_BUFF 100
char buff[LG_BUFF];
v1 = analogRead(A0);
v2 = analogRead(A5);
#if 0
n = sprintf(buff, "v1=%d v2=%d",v1,v2); if (n > LG_BUFF) Serial.println("Buffer overflow");
Serial.println("Send mqtt data");
client.publish("test1",buff);
#else
n = sprintf(buff, "%d",v1); if (n > LG_BUFF) Serial.println("Buffer overflow");
client.publish("lumina",buff);
Serial.print("lumina=");Serial.print(buff);
n = sprintf(buff, "%d",v2); if (n > LG_BUFF) Serial.println("Buffer overflow");
client.publish("temp",buff);
Serial.print(", temperatura=");Serial.println(buff);
#endif
}
void setup()
{
cnt1 = 0;
cnt2 = 0;
cnt3 = 0;
cnt4 = 0;
delay(1000);
Serial.begin(9600);
watchdogSetup();
Serial.println("Start arduino. Achizitie + MQTT + ENC28J60");
pinMode(5, OUTPUT); //LED Infrared
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
//digitalWrite(5, HIGH); //LED Infrared
digitalWrite(5, LOW); //LED Infrared
digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
client.setServer(server, 1883);
client.setCallback(callback);
Ethernet.begin(mac, ip);
wdt_reset();
delay(1500);
wdt_reset();
Serial.print("IP=");Serial.println(Ethernet.localIP());
analogReference(DEFAULT); // the default analog reference of 5 volts (on 5V Arduino boards) or 3.3 volts (on 3.3V Arduino boards)
//umax = 4.27;
}
void loop()
{
wdt_reset();
#if 1
//mqtt
if (!client.connected()) {reconnect();}
client.loop();
cnt1++;
if(cnt1 > 10000) {
cnt1=0;
sendMQTT_Data();
}
#endif
#if 1
//aprinde LED=uri
cnt3++;
if (cnt3 > 5000){
cnt3 = 0;
digitalWrite(6, cnt4 == 0);
digitalWrite(7, cnt4 == 1 || cnt4 == 3);
digitalWrite(8, cnt4 == 2);
cnt4 ++;
if(cnt4==4)cnt4=0;
}
#endif
} //end main loop
//MQTT reconnect
void reconnect() {
wdt_reset();
// Loop until we're reconnected
while (!client.connected()) {
wdt_reset();
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("arduinoClient")) {
Serial.println("connected");
// Once connected, publish an announcement...
//client.publish("outTopic","hello world");
// ... and resubscribe
//mqtt2rrdclient.subscribe("test2");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again");
wdt_reset();delay(1000);
wdt_reset();delay(1000);
wdt_reset();delay(1000);
}
}
}
Rezultatul programului se vede in teminalul serial: