The story:
I have two Teensy 4.1 units using the onboard Ethernet to communicate with a MQTT server. They are set up fairly similar in the respect that the code is very similar and that they do the same thing - reporting sensor information via MQTT.
Each and by itself the units apparently performs flawlessly. But when i hook up both units in the network, things start to become a little more mysterious than I have so far been able to wrap my brain around...
Have anyone got any idea what this might come from or where I should start to look...?
Here are some factual information and things I have done so far:
Mentionable things:
I have two Teensy 4.1 units using the onboard Ethernet to communicate with a MQTT server. They are set up fairly similar in the respect that the code is very similar and that they do the same thing - reporting sensor information via MQTT.
Each and by itself the units apparently performs flawlessly. But when i hook up both units in the network, things start to become a little more mysterious than I have so far been able to wrap my brain around...
- The first unit connected stops working (hangs).
- The second unit connected works flawlessly for 2hours - to the second, and then stop working.
- But then the first one starts to work again - and works for, you might guess - two hours.
- And they go on taking their turn doing their own stuff every two hours.
Have anyone got any idea what this might come from or where I should start to look...?
Here are some factual information and things I have done so far:
- The units have different IP-addresses and different MAC-addresses. This is verified by pinging each unit from a Windows PC and then running 'arp -a' to verify MAC-adresses - everything checks out ok.
- I have a genuine Arduino due with a genuine Arduino Ethernet shield running close to the same setup. This unit does not seem to be affected since I can connect/disconnect it at my will without any misbehavior from this or the two Teensys i question.
- I am using Arduino 1.8.13 and Teensyduino 1.53.
- For Ethernet I am using NativeEthernet connected via the onboard interface on the Teensy 4.1
- The sensors are widely different but both uses LOW/HIGH on GPIO-pins to transfer their knowledge - no external libraries are used.
- For MQTT i am using PubSubClient 2.8.0
- MQTT-server is mosquitto running on debian 10 - no authentication or TLS is used.
- The units do not use the same MQTT-topic and only one of them subscribe to a publisher that publishes only 2 to 3 times a month.
- The setup has been tried on the same switch and trough up to three switches (Cisco PoE, HP Procurve) - same result.
- Any type of packet sniffing is not tried - yet (mostly because of the (apparent) hassle of sniffing from a third machine trough a switch)
- What have I forgot to mention...?
Mentionable things:
- The network code is mostly cut and paste between the units - ie. it is close to identical. Only IP- an MAC-addresses are different.
- The overall layout of the program is also identical - down to the "I am Alive" led-stuff at the bottom
- In this particular code there is an obscene amount of Serial.Prints for bugtracking (which might generate a new post in the near future) - but has no effect on the behavior investigated in this post (I guess/think/hope...).
Code:
#include <NativeEthernet.h>
#include <PubSubClient.h>
char mqttSERVER[] = "192.168.10.11";
const char* mqttServer = mqttSERVER;
IPAddress serv(192, 168, 10, 11);
EthernetClient NetClient;
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE3
};
IPAddress ip(192, 168, 10, 165);
void net_setup()
{
Serial.println("Starting Ethernet");
Ethernet.begin(mac, ip);
Serial.println("Checking Ethernet Hardware");
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("**** Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
Serial.println("Checking Ethernet link");
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("**** Ethernet cable is not connected.");
}
Serial.println("Some sort of link...");
}
PubSubClient mqttClient(NetClient);
bool connected = false;
void mqtt_reconnect()
{
while (!mqttClient.connected()) {
Serial.print ("Kobler til MQTT-server... ");
if (mqttClient.connect("teensy")) {
Serial.println ("Koblet til!");
// mqttClient.subscribe("bergen/strom/set");
connected = true;
}
else {
Serial.println ("**** Ikke koblet til!");
connected = false;
delay (1000);
}
}
}
void mqtt_loop()
{
if (!mqttClient.connected()) {
mqtt_reconnect();
} else {
mqttClient.loop();
}
}
int Humidity = 0;
int Temp = 0;
bool DHTError = false; // Checksum Error
void DHT11(int pin) {
// Serial.println ("DHT11 - Read");
long int DataTime = 0;
unsigned long result[45];
int antresult = 0;
byte data[5];
// read the Bits and put them into a Result array (It will count 42 bits. The first two one are useless due my code)
unsigned long prevtime;
elapsedMicros micro = 0;
bool block = false;
//noInterrupts();
do{
if (digitalRead(pin) == 0 && block == false){
result[antresult] = micro - prevtime;
prevtime = micro;
block = true;
antresult++;
}
if (digitalRead(pin) == 1)
block = false;
}while (micro - prevtime < 250);
//interrupts();
// Asign 1 or 0 to Result variable. If more than 80uS Data as "1"
// Starting at Data set 02. First two Datasets are ignored!
for (int i = 2; i < antresult; i++) {
Serial.print (result[i]);
Serial.print (" ");
if (result[i] <= 90)
result[i] = 0;
else
result[i] = 1;
}
Serial.println();
for (int j = 0; j < 5; j++) { // redo it for the 5 Bytes (40 Databits /8 = 5)
data[j] = 0;
for (int i = 0; i < 8; i++) {
bitWrite(data[j], 7 - i, result[i + 2 + (j * 8)]);
} // Create 5 Databytes from the 40 Databits (Ignoring the 2 first Databits)
}
// check checksum }
Serial.print (pin);
Serial.print (" ");
Serial.print (data[0]);
Serial.print (" ");
Serial.print (data[1]);
Serial.print (" ");
Serial.print (data[2]);
Serial.print (" ");
Serial.print (data[3]);
Serial.print (" ");
Serial.print (data[4]);
if (data[4] == (data[0] + data[1] + data[2] + data[3])) {
Humidity = data[0] * 10 + data[1];
Temp = data[2] * 10 + data[3];
DHTError = false;
}
else {
DHTError = true; //If Checksum is worng, Temp=99 (Dataset 0-3 in addition = Dataset 4 = Checksum OK)
Humidity = 990;
Temp = 950;
Serial.print (" Error!");
}
Serial.println();
}
char str[] = "{\"hum\":XX.X,"
"\"temp\":XX.X,"
"\"id\":X,"
"\"error\":X}";
elapsedMillis blk_live;
elapsedMillis intervall = 0;
int DHTPorts[] = {3, 4, 0};
int DHTActive[] = {1, 1, -1};
bool DHTStart = false;
elapsedMicros DHTSeq;
int DHTState = -1;
int DHTPin;
int DHTIndex = -1;
#define LED_LIVE 13
void setup() {
Serial.begin(115200);
pinMode(LED_LIVE, OUTPUT);
digitalWrite(LED_LIVE, HIGH);
delay(2000);
digitalWrite(LED_LIVE, LOW);
Serial.println ("Net Setup");
net_setup();
digitalWrite(LED_LIVE, HIGH);
delay(500);
mqttClient.setServer(serv, 1883);
}
void loop() {
if (intervall > 5050) {
intervall = 0;
if (connected == true) {
DHTStart = true;
DHTIndex++;
if (DHTActive [DHTIndex] == -1)
DHTIndex = 0;
}
Serial.println ("Intervall");
}
if (DHTStart) {
DHTStart = false;
DHTState = 5;
}
if (DHTActive [DHTIndex] == 1 && DHTState == 5) {
DHTState = 0;
DHTSeq = 0;
DHTPin = DHTPorts[DHTIndex];
}
if (DHTState == 0) {
pinMode(DHTPin, OUTPUT);
digitalWrite(DHTPin, HIGH);
DHTState ++;
}
if (DHTState == 1 && DHTSeq > 250000) {
digitalWrite(DHTPin, LOW);
DHTState++;
}
if (DHTState == 2 && DHTSeq > 280000) {
digitalWrite(DHTPin, HIGH);
DHTState++;
}
if (DHTState == 3 && DHTSeq > 280050) {
pinMode(DHTPin, INPUT);
DHTState++;
}
if (DHTState == 4) {
DHTState = 6;
DHT11(DHTPin);
int h, t;
h = Humidity;
t = Temp;
Serial.print ("Hum : ");
Serial.print (h);
Serial.print (" Temp : ");
Serial.println (t);
char ctmp;
ctmp = h / 100;
str[7] = ctmp + 48;
h -= ctmp * 100;
ctmp = h / 10;
str[8] = ctmp + 48;
h -= ctmp * 10;
str[10] = h + 48;
ctmp = t / 100;
str[19] = ctmp + 48;
t -= ctmp * 100;
ctmp = t / 10;
str[20] = ctmp + 48;
t -= ctmp * 10;
str[22] = t + 48;
str[29] = DHTIndex + 48;
if (DHTError)
str[39] = '1';
else
str[39] = '0';
mqttClient.publish ("bergen/fukt/kjeller", str, 29);
// Serial.println("Da er ting sendt avgårde");
}
mqtt_loop();
if (blk_live > 250) {
digitalWrite(LED_LIVE, LOW);
}
if (blk_live > 500) {
digitalWrite(LED_LIVE, HIGH);
blk_live = 0;
}
}