connect two ESP8266 to one MQTT broker cause hang - raspberry-pi

I have 2 ESP8266 PubSubClients who are connecting to MQTT broker installed on Raspberry PI3. I'm able to connect them and make a ON/OFF operation and its okay! but when I'm going to use both of them to operating its will be hang and stuck in reconnecting loop, when i turn one of them off, its work fine.
this is my code on ESP8266:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
const char* ssid = "SSID";
const char* password = "PASSWORD";
const char* mqtt_server = "192.168.1.10";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup() {
//pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
//Serial.begin(115200);
Serial.begin(9600);
pinMode(0, OUTPUT);
digitalWrite(0, HIGH);
pinMode(2, OUTPUT);
digitalWrite(2, HIGH);
pinMode(4, OUTPUT);
digitalWrite(4, HIGH);
pinMode(5, OUTPUT);
digitalWrite(5, HIGH);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
//1 ( pin 0 )
if (strcmp(topic,"/home/1/ard1/p1/com")==0) {
if (payload[0] == '0'){
digitalWrite(0, HIGH);
Serial.print("Turning Light ON");
delay(100);
client.publish("/home/1/ard1/p1/state","0");
}
else if (payload[0] == '1')
{
digitalWrite(0, LOW);
Serial.print("Turning Light OFF");
delay(100);
client.publish("/home/1/ard1/p1/state","1");
}
}
//2 ( pin 2 )
if (strcmp(topic,"/home/1/ard1/p2/com")==0) {
if (payload[0] == '0'){
digitalWrite(2, HIGH);
Serial.print("Turning Light ON");
delay(100);
client.publish("/home/1/ard1/p2/state","0");
}
else if (payload[0] == '1')
{
digitalWrite(2, LOW);
Serial.print("Turning Light OFF");
delay(100);
client.publish("/home/1/ard1/p2/state","1");
}
}
//3 ( pin 4 )
if (strcmp(topic,"/home/1/ard1/p3/com")==0) {
if (payload[0] == '0'){
digitalWrite(4, HIGH);
Serial.print("Turning Light ON");
delay(100);
client.publish("/home/1/ard1/p3/state","0");
}
else if (payload[0] == '1')
{
digitalWrite(4, LOW);
Serial.print("Turning Light OFF");
delay(100);
client.publish("/home/1/ard1/p3/state","1");
}
}
//4 ( pin 5 )
if (strcmp(topic,"/home/1/ard1/p4/com")==0) {
if (payload[0] == '0'){
digitalWrite(5, HIGH);
Serial.print("Turning Light ON");
delay(100);
client.publish("/home/1/ard1/p4/state","0");
}
else if (payload[0] == '1')
{
digitalWrite(5, LOW);
Serial.print("Turning Light OFF");
delay(100);
client.publish("/home/1/ard1/p4/state","1");
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP8266Client")) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("outTopic", "hello world");
client.subscribe("/home/1/ard1/#");
// ... and resubscribe
client.subscribe("inTopic");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, 75, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish("outTopic", msg);
}
}
I changed these below lines for one of them but the result is the same.
WiFiClient espClient;
PubSubClient client(espClient);
to:
WiFiClient espClient1;
PubSubClient client(espClient1);
Many Thanks.

Your problem is this line:
if (client.connect("ESP8266Client")) {
Every client needs a unique client id, hard coding it to ESP8266Client means that when the second client connects the broker will kick the first one off, which will then try and reconnect which will kick the second off. This just ends up stuck in a loop.

Related

change an if / else if statement to a switch case in Arduino

I am making a web server with an ESP32D, I am programming it from the Arduino IDE and I have a function with spaghetti code which I want to refactor with switch case,
this is my function, which i am calling in the void loop()
void control(){
if (header.indexOf("GET /2/on") >= 0) {
Serial.println("GPIO 2 on");
output2State = "on";
digitalWrite(output2, HIGH);
} else if (header.indexOf("GET /2/off") >= 0) {
Serial.println("GPIO 2 off");
output2State = "off";
digitalWrite(output2, LOW);
} else if (header.indexOf("GET /15/on") >= 0) {
Serial.println("GPIO 15 on");
output15State = "on";
digitalWrite(output15, HIGH);
} else if (header.indexOf("GET /15/off") >= 0) {
Serial.println("GPIO 15 off");
output15State = "off";
digitalWrite(output15, LOW);
}
}
void function_loop(){
WiFiClient client = server.available(); // Listen for incoming client
// Serial.println(typeOf(client));
if (client) { // If a new client connects,
currentTime = millis();
previousTime = currentTime;
Serial.println("New Client."); // print a message out in the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
control();
}
How could I do to be able to pass it to switch case? I have no idea how to pass the variable to modify (in this case the header.indexOf)
It isn't clear from your example what type your header is, but I'm guessing it is a String.
Send header to control() like this
control(header);
and declare control() like this
void control(String& header) {

Cant seem to figure out how to make the waitBTNPressed Function work, keeps returning invalid operands of types void and bool to binary operator==

void waitBtnPressed() {
while(1) {
if (digitalRead(LP_S1_PIN) == 0) break;
if (digitalRead(LP_S2_PIN) == 0) break;
digitalWrite(LP_RGB_LED_GREEN_PIN, HIGH);
delay(500);
digitalWrite(LP_RGB_LED_GREEN_PIN, LOW);
delay(500); }
}
void driveStraight() {
setMotorDirection(BOTH_MOTORS,MOTOR_DIR_FORWARD);
**Cause the robot to drive forward **
enableMotor(BOTH_MOTORS);
**"Turn on" the motor **
setMotorSpeed(BOTH_MOTORS,WHEELSPEED);
** Set motor speed **
delay(DELAY_MILLI_SECONDS_100CM);
disableMotor(BOTH_MOTORS);
Halt motors
delay(10000);
}
void setup() {
Serial.begin(115200);
delay(500);
setupRSLK();
** Left and right button on LaunchPad **
pinMode(LP_S1_PIN, INPUT_PULLUP);
pinMode(LP_S2_PIN, INPUT_PULLUP);
}
void loop() {
if (waitBtnPressed()==true) {
delay(2000);
driveStraight();
This code is a push button function that is supposed to trigger a drivestraight function in one loop

"No Socket Available" - Wifi Shield on Arduino

I have an LDR/Photocell which sends a value 1 or 0 (depending on the value) to a text file on my web address. The code works for a few seconds then prints out No Socket available.
Any help will be appreciated; code below.
#include <SPI.h>
#include <WiFi.h>
int LDR = A0;
int LED = 11;
char ssid[] = "SSID";
char password[] = "password";
int status = WL_IDLE_STATUS;
char server[] = "www.example.com";
int value;
void setup() {
Serial.begin(9600);
pinMode(LDR, INPUT);
pinMode(LED, OUTPUT);
connectWifi();
printWifiStatus();
// postData();
}
void loop() {
value = analogRead(LDR);
postData();
delay(10000);
}
void connectWifi() {
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to ");
Serial.println(ssid);
status = WiFi.begin(ssid, password);
delay(500);
}
}
void printWifiStatus() {
// Print the SSID of the network you're attached to
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// Print your WiFi shield's IP address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// Print the received signal strength
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void postData() {
WiFiClient client;
if (client.connect(server, 80)) {
Serial.println("Connecting...");
if (value > 350) {
Serial.println("0");
digitalWrite(LED, LOW);
String data = "value=0";
client.print("GET /example/client.php?");
client.print(data);
client.println(" HTTP/1.1");
client.println("Host: www.example.com");
client.println("Connection: close");
client.println(); client.println();
//client.stop();
} else {
Serial.println("1");
digitalWrite(LED, HIGH);
String data = "value=1";
client.print("GET /example/client.php?");
client.print(data);
client.println(" HTTP/1.1");
client.println("Host: www.example.com");
client.println("Connection: close");
client.println(); client.println();
//client.stop();
}
} else {
Serial.println("Connection failed");
client.stop();
}
}
Output:
Attempting to connect to SSID
SSID: SSID
IP Address: 255.255.255.255
signal strength (RSSI):-47 dBm
Connecting...
1
Connecting...
0
Connecting...
0
Connecting...
0
No Socket available
Connection failed
No Socket available
Connection failed
No Socket available
Connection failed
No Socket available
Actual web address omitted.
first of all, try not use "delay()" and your are calling this function "postData()" every 0,5 seconds. Try use the millis() function to do the timer thing, like this:
unsigned long timerBefore = 0;
const int timer = 1000; //1 second
now inside your loop()
unsigned long timerNow=millis();
if((unsigned long)(timerNow-timerBefore)>=timer){
postData();
timerBefore=millis();
}
that code i'll not "pause" your microcontroller and will call that function every one second.

Get Xbee response from Serial and send to a browser

I am trying to do some experiments with Arduino, Ethernet Shield and Xbee Shield.
I demonstrate my set up board like this:
Group 1: Arduino Uno + Xbee shield : broadcast the signal
Group 2: Arduino Uno + Xbee shield + Ethernet shield: receive the signal from
group 1, get the signal strength from AT command and print it into the browser.
The problem here is I can't get the result after sending to the Serial my ATDB command, actually, I am not sure it did worked as I expected.
Here is the code that I used to retrieve the signal strength.
int data;
void setup()
{
Serial.begin(9600);
}
void receiver_checker(){
delay(1200);
Serial.print("+++");
delay(1200);
bool bOK = false;
while (Serial.available() > 0) {
Serial.write(Serial.read());
bOK = true;
}
if(bOK)
{
Serial.println();
Serial.println("ATDB");
delay(100);
while (Serial.available() > 0) {
Serial.write(Serial.read());
}
Serial.println();
}
Serial.println();
}
void loop()
{
while(Serial.available() > 0){
data = Serial.read();
if(data == '1'){
// Broadcaster 1
//Serial.println("1------------------");
receiver_checker();
}
}
}
This part worked as I expected, it printed out in hex number the signal strength of the last package that it received.
Here is the code I combined the previous one and the server part from Web Server tutorial:
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xCA, 0xFE, 0x00, 0x00, 0x00, 0x02
};
IPAddress ip(1, 1, 1, 2);
int data;
int count = 0;
char result;
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
// Serial.print("server is at ");
// Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
// Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
// Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
if (Serial.available() > 0) {
// read the oldest byte in the serial buffer:
data = Serial.read();
// if it's a capital H (ASCII 72), turn on the LED:
if (data == '1') {
count += 1;
client.print("The number of times:");
client.print(count);
result = receiver_checker();
client.print("========================");
client.print(result);
client.print("========================");
}
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
char receiver_checker(){
char signal;
delay(1200);
Serial.print("+++");
delay(1200);
bool bOK = false;
while (Serial.available() > 0) {
Serial.write(Serial.read());
bOK = true;
}
if(bOK)
{
Serial.println();
Serial.println("ATDB");
delay(100);
while (Serial.available() > 0) {
signal = Serial.read();
}
Serial.println();
}
Serial.println();
return signal;
}
If there is another way to interact with the Xbee shield not go through Serial like I ask and get response directly, please let me know!
Your receiver_checker() function is reading characters back from the XBee module, and just returning the last character received, which is likely a carriage return or line feed.
Update the function to return an int, and replace your while (Serial.available() > 0) with the following:
signal = (int) strtoul(Serial.readString().c_str(), 0, 16);
That's for when the XBee returns a hexadecimal value. If it's returning a decimal value, change the 16 parameter to a 10.

Arduino Ethernet Shield connection to socket server

I'm using an ethernet shield for Arduino to connect it to a socket server (different computer) so that I can receive messages from it to activate some routine. Here is my code:
#include <Ethernet.h>
#include <SPI.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x5A, 0x21 };
byte ip[] = { 192,168,1,11 }; //ip shield
byte server[] = { 192,168,1,7 }; // ip server
EthernetClient client;
String readString;
int ledPins[] = {19, 17, 2,3, 5, 6, 7, 8, 9}; // leds pins
int pinCount = 8;// number of leds
int const PINEYES = 9; //pin for different led
int const TIMERLEDS = 1000;
int const TIMERTOOFF= 3000;
//--------------------------------------------------------------------------
void setup() {
turnOffLeds();
Ethernet.begin(mac, ip);
Serial.begin(9600);
delay(1000);
Serial.println("connecting...");
if (client.connect(server, 1400)) {
Serial.println("connected");
client.println();
} else {
Serial.println("connection failed");
}
pinMode(PINEYES, OUTPUT);
int thisPin;
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
pinMode(ledPins[thisPin], OUTPUT);
}
}
//--------------------------------------------------------------------------
void loop() {
if (client.available()) {
char c = client.read();
if (readString.length() < 30) {
if(c!='|')
readString.concat(c);
else {
client.flush();
//if (readString == "START_SENSATIONS") {
if (readString == "on") {
Serial.println("recebi");
client.stop();
turnOnMaya();
}
resetString();
}
}
Serial.println(readString);
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
for(;;)
;
}
}
//--------------------------------------------------------------------------
void turnOnMaya(){
turnOnLeds();
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
delay(TIMERLEDS);
digitalWrite(ledPins[thisPin], LOW);
}
turnOnEyes();
delay(TIMERTOOFF);
turnOffLeds();
digitalWrite(PINEYES, LOW);
client.connect(server, 1400);
}
//--------------------------------------------------------------------------
void turnOnLeds(){
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(ledPins[thisPin], HIGH);
}
}
//--------------------------------------------------------------------------
void turnOffLeds(){
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
digitalWrite(ledPins[thisPin], LOW);
}
}
//--------------------------------------------------------------------------
void turnOnEyes(){
digitalWrite(PINEYES, 255);
}
//--------------------------------------------------------------------------
void resetString() {
readString = "";
}
The problem is, when my server stops or is not available for some moments, I need my Arduino to keep on trying to connect to it until it is available again. But I can't make this work.
I tried this:
while(!client.available()){
Serial.println("connection failed, trying again...");
client.connect(server, 1400);
delay(1000);
}
But it doesn't work. It just prints "connection failed, trying again..." forever. How can I do this?
Thanks!
I'm assuming that the server in your PC is a normal java or c (or any other standard tcp server)
But your arduino client doesn't specify that it is TCP. So either change your server or the client(like in here - this uses wifi connection).
If your server is in java, it could be like this:
int port=9999;
try{
System.out.println("Starting server...");
ServerSocket ss=new ServerSocket(port);
Socket clientSocket=ss.accept();
System.out.println("Connection has been established...");
PrintWriter out=new PrintWriter(clientSocket.getOutputStream(),true);
BufferedReader br=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
System.out.println("Listening.....");
while((inputLine=br.readLine())!=null)
System.out.println(inputLine);
}catch(Exception e){System.out.println(e.getMessage());}