Multi-file arduino esp8266 sketch sharing a reference to server - arduino

As my sketches get bigger, the code looks awful as one file and the number of global variables is too high.
For the webconfig part of my sketch the device attempts to get online and if it fails it scans for available wifi networks, goes into Access Point Mode, starts a server, sends the list of ssid's and listens for a response of an ssid/passwd pair. The server is only for the configuration.
Ideally I'd like the cleaned up main.ino file to look like
#include "config.h"
void setup(){
Serial.begin(115200);
Serial.println();
Serial.println("--------------------------");
Serial.println("ESP8266 multifile");
Serial.println("--------------------------");
getOnline();
}
void loop(){
if(IN_CONFIG_MODE){
server.handleClient();
}
}
with a config.h something like..
#ifndef config_h
#define config_h
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server;
void getOnline();
#endif
and then a config.cpp where it does all stuff described above yet gives the main.ino program access to the server instance so it can listen in the main loop.
#include "config.h"
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
char *espssid = "espAPsb";
char *ssid = "street_no_vale2";
char *pwd = "jjjjjjjjx";
char ssids[300];
extern server(80);
void handleRoot(){
server.send(200, "text/html", "<h1>root of espAPsb AP server</h1>");
//send json of available ssids
}
void scan(){
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0)
Serial.println("no networks found");
else
{
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i)
{
// Print SSID and RSSI for each network found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
delay(10);
}
}
Serial.println("");
}
void setupAP(){
WiFi.softAP(espssid);
server.on("/", handleRoot);
server.begin();
Serial.println();
Serial.print("connected as AP ");
Serial.println(espssid);
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
}
void getOnline(){
WiFi.begin(ssid, pwd);
int tries =0;
int success=1;
while (WiFi.status() != WL_CONNECTED ) {
delay(500);
Serial.print(".");
tries++;
if (tries==15){
success=0;
Serial.println("WiFi not connected");
scan();
setupAP();
break;
}
}
if (success){
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
}

You can make an own library from your networking code, which you can easily reuse.
https://www.arduino.cc/en/Hacking/LibraryTutorial
Alternatively, you can use multiple "tabs" in Arduino IDE which works like a standard multi-source project. http://arduino.land/FAQ/content/7/43/en/breaking-a-sketch-into-multiple-files.html
(Btw, StackExchange hosts a dedicated Ardunio microsite here: https://arduino.stackexchange.com/ Have fun there :)

Related

NodeMCU ESP8266 Client-Server communication

I am trying to connect two ESP8266 boards to communicate with each other. The client board first connects to the server and sends a message, the character 'd', after the server receives the message it replies with "Hello from server".
Server
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
char *ssid = "SSID";
char *pass = "PASS";
int stat;
WiFiServer server(8080);
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,pass);
Serial.println("Connecting to wifi ");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
delay(500);
}
Serial.print("SSID :");
Serial.print(ssid);
Serial.println("ip: ");
Serial.print(WiFi.localIP());
server.begin();
}
void loop() {
WiFiClient client = server.available();
if(client){
if(client.connected()){
Serial.println("Client connected");
if(client.available() > 0){
delay(500);
char data = client.read();
Serial.println(data);
delay(500);
}
char d[] = "Hello from server";
client.println(d);
}
client.stop();
}
}
Client
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
char *ssid = "SSID";
char *pass = "PASS";
char *host = "ip";
WiFiClient client;
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,pass);
Serial.println("Connecting to wifi");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
delay(500);
}
//Serial.println("Connecting to wifi network");
Serial.print("SSID: ");
Serial.print(ssid);
Serial.println("Connected");
}
void loop() {
// put your main code here, to run repeatedly:
if(client.connect(host, 8080)) {
Serial.println("Connected to server");
client.println('d');
if(client.available() > 0){
delay(500);
Serial.println(client.read());
delay(500);
}
else{
Serial.println("No data received");
}
}
else{
Serial.println("Cannot connect to server");
}
client.stop();
}
The problem is that the message from client is received by the server. But the reply is not sent. When I try to see the reply from server using serial monitor in the client it gets connected to the server and the message is sent but the reply is not received.
I'm new to this domain and would like to know whether I'm doing it correctly or not. Any suggestions and solutions will help a lot.
Thank you.

Feather Huzzah MQTT

I'm attempting to connect my Feather Huzzah to a local MQTT server but the program keeps blowing up and throwing a stack trace. When I attempt to decode the stack trace it's just empty, more frequently I only get part of the stack trace. Here's the code that I'm running, most of it is pretty similar to the pub/sub client example code for Arduino. I've tried erasing the flash on the device, that didn't seem to help.
Even stranger is that it worked once, but as soon as I tried it again adding the callback the code stopped working and blows up. If I try removing the callback nothing changes. I've tried stripping out a lot of the code just to see if I can get a consistent connection to MQTT, but that doesn't seem to be working either. The MQTT server is the latest Mosquitto from Ubuntu 18.04.
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
const char* ssid = "xxxxxxxx";
const char* password = "xxxxxxxxx";
const int hallPin = 14;
const int ledPin = 0;
const char* mqtt_server = "mosquitto.localdomain";
long lastMsg = 0;
char msg[100];
int value = 0;
int hallState = 0;
WiFiClient espClient;
PubSubClient client(espClient);
WiFiUDP ntpUDP;
// By default 'time.nist.gov' is used with 60 seconds update interval and
// no offset
NTPClient timeClient(ntpUDP);
// Setup and connect to the wifi
void setup_wifi() {
delay(100);
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());
Serial.println("Gateway: ");
Serial.println(WiFi.gatewayIP());
}
//Reconnect to the MQTT broker
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("/homeassistant/devices/doorbell", "hello world");
// ... and resubscribe
client.subscribe("/homeassistant/doorbell/receiver");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
//Process messages incoming from the broker
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]);
}
}
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(hallPin, INPUT);
Serial.begin(115200);
setup_wifi();
timeClient.begin();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
setup_wifi();
}
if (!client.connected()) {
reconnect();
}
hallState = digitalRead(hallPin);
if (hallState == LOW) {
digitalWrite(ledPin, HIGH);
generateAndSendMessage();
delay(1000); //Add in a delay so it doesn't send messages extremely rapidly
} else {
digitalWrite(ledPin, LOW);
}
}
void generateAndSendMessage() {
timeClient.update();
StaticJsonBuffer<100> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["sensor"] = "doorbell";
root["time"] = timeClient.getEpochTime();
root["value"] = 1;
root.printTo(msg);
Serial.println(msg);
client.publish("/homeassistant/devices/doorbell", msg);
}
Looking at the generateAndSendMessage function, I believe you are having an issue due to the size of the MQTT buffer.
The MQTT buffer is by default set to 128 bytes. This includes the length of the channel name along with the message.
The length of you channel is 32 bytes, and the json buffer you used to make the message is 100 bytes long. So you might just be exceeding the 128 byte mark.
Just declare this before including the PubSubClient.h
#define MQTT_MAX_PACKET_SIZE 200
This macro defines the buffer size of the PubSubClient to 200. You can change it to whatever you believe is required.
I hope this helps.

ESP32 access point

I have 2 ESP32 boards, and I want to make them server/client in Arduino IDE. Just two boards, no router in between.
So far I have followed tutorials, and I have been able to connect to the ESP32 from my phone.
#include <WiFi.h>
WiFiServer server;
const char *ssid = "Zupa";
const char *password = "12345678";
void setup() {
Serial.begin(115200);
Serial.println();
Serial.print("Configuring access point...");
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
}
void loop() {
}
However, I cannot connect from other ESP32. Code as follows:
#include <WiFi.h>
#include <WiFiMulti.h>
WiFiMulti WiFiMulti;
void setup()
{
Serial.begin(115200);
delay(10);
enter code here
// We start by connecting to a WiFi network
WiFiMulti.addAP("Zupa", "12345678");
Serial.println();
Serial.println();
Serial.print("Wait for WiFi... ");
while(WiFiMulti.run() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(500);
}
void loop()
{
const uint16_t port = 80;
const char * host = "192.168.1.4"; // ip
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
Serial.println("wait 5 sec...");
delay(5000);
return;
}
// This will send the request to the server
client.print("Send this data to server");
//read back one line from server
String line = client.readStringUntil('\r');
client.println(line);
Serial.println("closing connection");
client.stop();
Serial.println("wait 5 sec...");
delay(5000);
}
What happens is it just says it cannot connect. The IP address is default, and I double checked it on the server side! How come I can connect from phone and not from ESP32?
Furthermore, how would I communicate between the two? I tried reading online, but everyone seems to do phone to ESP communication, not ESP to ESP. I also tried reading Mr. Kolbans book on ESP32, but with no success. I am quite new at this, and feel stuck.
All I had to change was the WiFi library from the ESP8266wifi.h to the Wifi.h which is compatible with ESP32.
(Source)
From the code examples is just a matter of changing the code to fit your specific needs.
#include <WiFi.h>
#include <WiFiClient.h>
void setup()
{
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
WiFi.mode(WIFI_STA); //Set wifi mode as station
WiFi.begin("Zupa", "12345678");//Connect to other ESP32
Serial.println();
Serial.println();
Serial.print("Wait for WiFi... ");
//Wait for WiFi to connect
while(WiFi.waitForConnectResult() != WL_CONNECTED){
Serial.print(".");
delay(1000);
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
delay(500);
}
void loop()
{
const uint16_t port = 80;
const char * host = "192.168.1.4"; // ip
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
Serial.println("wait 5 sec...");
delay(5000);
return;
}
// This will send the request to the server
client.print("Send this data to server");
//read back one line from server
String line = client.readStringUntil('\r');
client.println(line);
Serial.println("closing connection");
client.stop();
Serial.println("wait 5 sec...");
delay(5000);
}
Try change the IP of client code to:
const char * host = "192.168.4.1"
Tip: I use the Finger app in Android or iOS to scan the network,
its very good to see the IP of each device connected.
(In your case, You need connect the mobile device into your Esp32's hot spot before use the Finger)

NodeMCU gets strange IP address

Today I got my NodeMCU and I instantly started with coding. I wanted to connect to my WiFi and to my MQTT server.
I used the PubSub example for this.
In the serial monitor I get the message that I connected successfully with the WiFi, but I get the IP 172.20.10.6. However we have a 192.168... network.
Then when I try to reach my MQTT server it doesn't find it. When I try to give the NodeMCU a static IP it also says connected successfully and shows up the static IP I gave it, but I still can't connect to my MQTT server.
I can't ping the NodeMCU and don't find it in my Smartphone app "Fing".
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "myssid";
const char* password = "mypw";
const char* mqtt_server = "192.168.42.131";
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);
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();
// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW);
// Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is active low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH);
// Turn the LED off by making the voltage HIGH
}
}
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");
// ... and resubscribe
client.subscribe("mathistest");
} 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);
}
}
You are most likely having a DHCP failure.
A 172.20.x.x address is a non-routable IP address (see: https://www.lifewire.com/what-is-a-private-ip-address-2625970) and the DHCP code is (likely) using that address when the address assignment fails.
Stepping back, DHCP is most likely failing because you are failing to connect to the Wifi network with the correct SSID and password.

Can't commute a relay with Arduino wifi shield + Xively

I’m trying to turn on and off an LED light bulb connected to a Tinterkit Relay.
I’m using an Arduino UNO r3 connected to internet thanks to an official Arduino Wifi shield.
I’ve done a simple website with two buttons to send a 1 (on) or a 0 (off) to my Xively account.
I’ve written a code to detect the last posted channel value. The code is working fine and I’m able to detect a 1 or a 0 every 3 seconds approximately. The problem is that the relay doesn’t commute.
Please please, I would appreciate a lot your help to solve this problem.
Here is the code:
#include <SPI.h>
#include <WiFi.h>
#include <HttpClient.h>
#include <Xively.h>
#include <TinkerKit.h>
char ssid[] = "XXXXXX";
char pass[] = "XXXXXX";
int state;
int status = WL_IDLE_STATUS;
char myIntStream[]="LED";
char xivelyKey[] = "XXXXXX";
#define FEED_ID XXXXXX
TKMosFet relay(O0);
XivelyDatastream datastreams[] = {
XivelyDatastream(myIntStream, strlen(myIntStream), DATASTREAM_INT),
};
XivelyFeed feed(FEED_ID,datastreams,1);
WiFiClient client;
XivelyClient xivelyclient(client);
void printWifiStatus() {
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void setup() {
Serial.begin(9600);
Serial.println("LED light bulb");
Serial.println();
while ( status != WL_CONNECTED) {
Serial.println("Connecting to internet ...");
status = WiFi.begin(ssid, pass);
Serial.println("");
delay(5000);
}
Serial.println("Connected to wifi");
printWifiStatus();
}
void loop() {
Serial.println();
Serial.print("Datastream is:");
Serial.println(datastreams[0]);
Serial.print("LED value = ");
state = datastreams[0].getInt();
Serial.print(state);
if(state == 0){
relay.off();
Serial.println(" => Light is on.");
}
else if(state == 1){
relay.on();
Serial.println(" => Light is off.");
}
xivelyclient.get(feed, xivelyKey);
}

Resources