Strange behaviour in ESP8266 AccessPoint was password related

In my previous article, I made a skeleton program for a tutorial about the various ways of WiFi connection of an ESP8266, I ran into an odd problem that turned ourt to be related to the password.
the code aimed to include both STA and AP connection and I set up the credentials like this.

#define WIFI_SSID "YOURSSID"
#define WIFI_PASS "YOURPASSWORD"

// Set AP credentials
#define AP_SSID "YOUR_DESIRED_AP_NAME"
#define AP_PASS "YOUR_DESIRED_AP_PW"

After uploading the acces point ofcourse identified itself as ‘YOUR_DESIRED_AP’ and I quickly set to correct my mistake of not filling out my credentials and I changed it to:

// Set AP credentials
#define AP_SSID "Pond"
#define AP_PASS "1234"

After uploading again, I was surprised to see that instead of the expected AP SSID ‘Pond’, I now saw ESP-859C2F, with the numbers being the last 3 bytes of my ESP’s MAC-number. Chosing that accespoint made me connect to the ESP without asking for a password.
what the heck was going on? I knew the code was allright as on myinitial upload I had seen the SSID of the AP when it was still called “YOUR_DESIRED_AP_NAME”.
To make a long story short: I found out the problem was with the password: apparently there is a problem with a password that is too short, or contains numbers.
1234–> no proper AP_SSID visible
abcd–>works well
abcd1234 –>no proper AP SSID visible
abcd123–> works well.
So initially I thought that perhaps the amount of letters needed to be bigger than the amount of numbers in th epassword.
but ‘1234567’ worked fine….till I tried ‘123456’ which did not work, and then ‘1234567’ did not work either anymore and i had to go to ‘12345678’ to make it work.
Note: I uploaded the sketches with the “Tools-erase all flash content set”.
So I am still not entirely sure the exact problem, but I do know that numbers in the password apparently can cause problems with the AP

ESP8266 WiFiConnections

This article is probably cut and dry for those who have been working with the ESP8266 for more than a week, but every now and then I do get questions on how to connect an ESP8266 to the internet.

The code below shows how to do that in a combined STA and AP mode. It shows various options, including a static IP address. It includes a simple webserver, just to show the AP and STA connections are made. You can also download the code here.

#include <ESP8266WiFi.h> //for the WiFi connection
#include "ESP8266WebServer.h" //for the Server
ESP8266WebServer server(80);

// Set WiFi credentials
#define WIFI_SSID "YOURSSID"
#define WIFI_PASS "YOURPASSWORD"

// Set AP credentials
#define AP_SSID "YOUR_DESIRED_AP_NAME"
#define AP_PASS "YOUR_DESIRED_AP_PW"

//Extra's. these are optional
#define AP_CHANNEL 1   //choose the channel
#define AP_HIDDEN false //SSID broadcasted or not
#define AP_MAX_CON 4 // max nr of connections to the AP

uint8_t macAddr[6];

//for static IP (all not necessary if you choose DHCP)
// Set IP addresses
IPAddress local_IP(192, 168, 1, 70);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
//change the default IP address for the AP (192.168.4.1)
IPAddress AP_IP(192,168,4,5);

void setup() {
  // Setup serial port
  Serial.begin(115200);

  //begin Acces Point
  WiFi.mode(WIFI_AP_STA);
  //WiFi.mode(WIFI_STA);// for just Station connection
  //WiFi.mode(WIFI_AP);//for just AP connection

  //WiFi.softAP(AP_SSID, AP_PASS); //this makes your Acces point connection
  WiFi.softAPConfig(AP_IP, AP_IP, subnet);// this is optional
  WiFi.softAP(AP_SSID, AP_PASS, AP_CHANNEL, AP_HIDDEN, AP_MAX_CON);

  // Begin WiFi
  WiFi.config(local_IP, gateway, subnet);// optional, for  static connection
  WiFi.begin(WIFI_SSID, WIFI_PASS);// this makes your STA connection

  // Loop continuously while WiFi is not connected
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(100);
    Serial.print(".");
  }

  // Connected to WiFi
  WiFi.setAutoReconnect(true); //For automatic reconnect
  WiFi.persistent(true); // ditto
  Serial.println("Connected");
  Serial.print("Network IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("IP address for network ");
  Serial.print(WIFI_SSID);
  Serial.print(" : ");
  Serial.println(WiFi.localIP());
  Serial.print("IP address for network ");
  Serial.print(AP_SSID);
  Serial.print(" : ");
  Serial.println(WiFi.softAPIP());
  WiFi.softAPmacAddress(macAddr);
  Serial.printf("MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
  Serial.println("");
  //----------------
  server.on("/other", []() {   //Define the handling function for the path

    server.send(200, "text / plain", "Other URL");

  });

  server.on("/", handleRootPath);    //Associate the handler function to the path
  server.begin();                    //Start the server
  Serial.println("Server listening");
}

void loop() {
  server.handleClient();         //Handling of incoming requests
  // put your main code here, to run repeatedly:
  Serial.print("number of clients connected:");
  Serial.println(WiFi.softAPgetStationNum());
delay(3000);
  
}

// for a simple proof of context it would have been enough to just do server.send(200,"text/plain", "Hello World");
// but I added some html to make the content adapt to the size of the viewing device, so it would be properly visible on a phone as well
void handleRootPath() {            //Handler for the rooth path
  server.send(200, "text/html", "<!DOCTYPE HTML><html><head><meta name='viewport' content='width=device-width,initial-scale=1'></head><body>Hello world</body></html>");
}

Also check this post for some strange behaviour of the AccessPointI came across. You may also find this post interesting.

Smoothing

Smoothing of e.g. sensor readings to be displayed in a graph can be done in several ways. A rolling average, sometimes called a moving average, is one way of doing that. The arduino pages contain a program by David Mellis, modified by Tom Igoe that illustrates this: it stores values in a 10 value array and divides the sum by 10. Whenever the array is full it removes one value and adds a new one.

// Define the number of samples to keep track of. The higher the number, the
// more the readings will be smoothed, but the slower the output will respond to
// the input. Using a constant rather than a normal variable lets us use this
// value to determine the size of the readings array.
const int numReadings = 10;

int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average

int inputPin = A0;

void setup() {
// initialize serial communication with computer:
Serial.begin(9600);
// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
}

void loop() {
// subtract the last reading:
total = total - readings[readIndex];
// read from the sensor:
readings[readIndex] = analogRead(inputPin);
// add the reading to the total:
total = total + readings[readIndex];
// advance to the next position in the array:
readIndex = readIndex + 1;

// if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
}

// calculate the average:
average = total / numReadings;
// send it to the computer as ASCII digits
Serial.println(average);
delay(1); // delay in between reads for stability
}

Sadly there is a fundamental flaw in this program:

For the initial 10 readings, the result is simply wrong: when the program starts, the array is empty. A value is read into it, and the sum of the array is then divided by 10. Suppose the analog source is quite stable and always gives a reading of 5. Then the first 10 results of the program will be: 5×9*0=5  ->/10=0.5 (rounded t0 0)
5+5+8*0=10 ->/10=1
5+5+5+7*0=15 ->/10=1.5  (rounded to 1)
etc. etc.
Given the fact that the readings are taken with a 1 microsecond delay, that might not be a huge problem, but in that case there are simpler ways, without the need for an array to smooth the readings. For instance like this:

int ReadSensor(){
  int i;
  int sval = 0;

  for (i = 0; i < 10; i++){
    sval = sval + analogRead(0);
  }

  sval = sval / 10;    // average
 
  return sval;
}

strictly speaking this only gives a moving average during this loop and then 10 completely new values are averaged, but at the 1 microsecond interval of the original program that would virtually be the same.

The results in the original program do become a nuisance when you take readings at say 1 minute intervals and you do not want to wait 10 minutes before you get correct data. Fortunately the program can be simply modified to correct for the mistake: for the first 10 readings we divide by the active indexnumber and only after that we divide by the total number of readings (10). We can simply do that by setting a flag:

 // if we're at the end of the array...
if (readIndex >= numReadings) {
// ...wrap around to the beginning:
readIndex = 0;
flag=1;
}

and then calculate results like so:

// calculate the average:
if (flag==0){
average = total / readIndex;
}else{
average=total/numReadings;
}

Now if you really want to smooth things over you could combine the two techniques presented here: take the average of say 50 readings, store the result in an array and calculate the moving average of the array:

// read from the sensor:
readings[readIndex] = ReadSensor();

and ofcourse add the function “ReadSensor”, given bove, to your program

Graphical presentation of Sensordata with ESP8266

In an earlier post I described the use of a graph, showing results of a BME280 and DS18B20 sensor. This was based on an article from siblings Rui anď Sara Santos from randomnerdtutorials, but tailored to my needs. The biggest difference with the original article is that i used a JSON for data transfer in order to display more than one line per graph. The original code as well as my adaptation had some drawbacks, one of them being that after opening the chart, one had to wait the full interval (set to 30 secs) before the first value appeared. That is now fixed (thanks JB): the first value will appear immediately on opening the chart.

As an example I am using an ESP8266-01 that addresses a PCF8591 ADC/DAC. The 4 ADC’s read 4 soil humidity sensors and plot those in a graph. The battery voltage is also plotted. As i use a LiFePO4 battery, there is no need for a regulator and i can simply read the Vcc in order to know the battery voltage. In order to save the soilsensors from electrolysis, i switch them on when i take a measurement and switch them off in between. Rather than using the free gpio1 and gpio3 (Tx and Rx) for that I use the DAC output.

One could argue (and i would agree) that it is quite useless to check soilmoisture every 30 secs where maybe once every 4-6 hrs suffices, but just see it as example of how you could use it say for a slow cooker or your oven or CV.

*These pins hve internal pullup on the ESP01S, but not on the ESP01

You will find the code here.

Another ‘issue’ was that since an external library (highcharts) is called, one needs active connection with internet. This is not always desirable or possible. There are 2 ways around this: download the highcharts library and put it on your own server, or download it and put it in the esp8266 FS and make some small adaptations to your code (solution provided by J. Bredahl). You will find that code here.

Graphical and Table presentation of database info using Googlecharts and PHP

In an earlier post I discussed storing sensor data in a MySQL or MariaDB database (in combo with DeepSleep, which was the focus of the article).
The database part was based on an article by randomnerdtutorials.
Output of the gathered MySQL data was in shape of a table*).

Sometimes though a graph is a more practical way to look at data over a period of time. There are 3 values in the table: temperature, Humidity and Airpressure.
As I wanted one graph, I decided to leave out the Airpressure, as it’s high values  would skew the  Y-axis a bit, so i will be looking at  2 values only: temperature and humidity. The Airpressure is easy to add though.

There are various possibilities of  presenting data in a graph. ‘Highcharts ‘ for example, or jpGraph. This time though I decided for Googlegraphs. Fortunately there is a lot of info available and i found some frameworks at Techjunkgigs that I could rework.

That turned out something like this:

or, with more data:
You will find the program here. There are a few things you need to check. The program expects a database file that is called ‘esp-data’. It checks a table called ‘SensorData’. It looks for fields called ‘value1’, ‘value2’ and ‘reading_time ‘. If you are using different names, you need to adpt tghe program. You also need to insert your database username and password.

You will notice that when time passes by the graph will be condensed more and more.
That is why I added a ‘WHERE’ statement in the query:
$query = “SELECT * from SensorData WHERE id >=1”;

where you can enter a higher ID number (or insert other criteria such as date, or temperatures above a certain value).
However, if you would only be interested in say only the last 100 records, it is better to replace the query by:

$query = "SELECT * FROM(SELECT * from SensorData WHERE id >=1 ORDER BY id DESC LIMIT 100) AS `table` ORDER by id ASC";
_______________

*) The presented table is a bit basic. There are more interactive ways to present data in a table.
espdata-search

You will find the code here.