Saturday, May 21, 2022

Control multiple ESP webservers

For an index to all my stories click this text

Some time ago there was a question posted on Reddit concerning a topic I was just working on so I answered the question: https://www.reddit.com/r/esp32/comments/uok455/is_it_possible_to_control_two_or_more_esp32/
Then I realised that this might need some explanation.

What is this about

Normally when we talk about a webserver in combination with the ESP8266 or ESP32 a program is discussed that puts up a webpage that ca be accessed from your computer, tablet or phone. So the webpage is send (served) from the ESP.
That webpage might contain buttons and/or sliders that control a led, relay, servo, neopixels etc etc etc attached to that same ESP.

This is however not necessary. You can start a webserver on the ESP (be it ESP8266 or ESP32) that does not put up a website but just uses the webserver framework for controlling the led(s). On your PC, tablet or phone you can the run a webpage with some Javascript code that controls the ESP's led(s).

Even better. The Javascript program can control multiple ESP's. And that is what the original poster wanted.

Hardware setup

This wil work with any ESP8266. I used two Wemos D1 Mini's with on both a led connected to pin D5.



So the actual hardware setup is easy. Just a led with a 220 OHM current delimiting resistor attached to D5.

For this test to be conducted properly you will need to build this two times. Although you can perform the test also with just 1 ESP with a led.

Those that follow this weblog regularly might notice that I normally draw my schematics in Fritzing but this one is made in Cirkit Designer. Cirkit has some advantages: like easily add your own components if they are not already in the included library. And just like Fritzing you download the software and work off-line. Check it out: https://www.cirkitstudio.com/

The ESP software.

Have a look at my story on building a webserver with the ESP8266. That example puts a button on a webpage with which you can control a led. You can find that story here: http://lucstechblog.blogspot.com/2019/07/esp-webserver-tutorial-part-2-button.html

I am going to use that program and leave some things out and put something else in. What I am leaving out is the part where the webpage is build. There will be just minimal HTML code.
I added code to receive a value. So the software will not only be able to set a led on or off but also receive a value.
Remember that this is a demonstration of what is possible. So you can add more leds, use the value to control a servo, add a display etc. etc. etc.

As usual I will give you the complete program first and then discus several parts in details.

// ======================================================
// Webserver program that has no webpage and the program
// only handles a received ON-OFF command by putting a
// led on or off.
// next to that it prints a received value 
// in the Serial Monitor.
//
// command is IPADRESS/?cmd=ON
// command is IPADRESS/?cmd=OFF
//
// value is IPADRESS/?val=anynumber
//
// By Luc Volders: http://lucstechblog.blogspot.com/
// ======================================================

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

// Your routers credentials
const char* ssid = "XXXXXXXXXXXXXXXXX";
const char* password = "YYYYYYYYYYYYYY";

// ==========================================
// initial variables
// ========================================== 

String ledcmd;
String value;

// =========================================
// Here is the HTML page
// =========================================

String getPage()
  {
  String page = "<!DOCTYPE HTML>";
  page += "<html>";
  return page;
  }
  

// ==================================================
// Handle submit form
// ==================================================
void handlecmdreceived()
{  
   if (server.hasArg("cmd"))
      {
      ledcmd = server.arg("cmd");
      Serial.print("Thereceived command is:             ");
      Serial.println(ledcmd);
      if (ledcmd == "ON")
        {
           digitalWrite(D5, HIGH);
        } 
      if (ledcmd == "OFF")
        {
           digitalWrite(D5, LOW);
        }
      }


   if (server.hasArg("val"))
      {
        value = server.arg("val");
        Serial.print("The received value is:             ");
        Serial.println(value);
      }
    
  server.send(200, "text/html", getPage());       //Response to the HTTP request
}  


// ===================================================
// Handle root
// ===================================================
void handleRoot() 
{   
  if (server.args() ) 
    {
    handlecmdreceived();
    } 
}


// ===================================================
// Setup
// ===================================================
void setup()
{
  delay(1000);
  Serial.begin(115200);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid,password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
  server.on("/", handleRoot);

  server.begin();
  delay(500);

  pinMode(D5, OUTPUT);
  digitalWrite(D5,LOW);
}


// ===================================================
// Loop
// ===================================================
void loop()
{  
  server.handleClient(); 
  delay(50);
}


Now let us look at some details.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

// Your routers credentials
const char* ssid = "XXXXXXXXXXXXX";
const char* password = "YYYYYYYYYYYYY";


Nothing special here. The Wifi and Webserver libraries are loaded and a webserver is defined which uses port 80. The port number 80 is important in that way that this is the port used for HTTP communication. Further on we are going to build a webpage with Javascript to command the ESP. Javascript communicates over HTTP and therefore the port is 80.

String getPage()
  {
  String page = "<!DOCTYPE HTML>";
  page += "<html>";
  return page;
  }


A minimalistic webpage is build. This is needed for the webserver to operate. If you want you can expand it to a full webpage just as shown in the original program: http://lucstechblog.blogspot.com/2019/07/esp-webserver-tutorial-part-2-button.html
But more as this is not needed.

Skip some parts and look at the setup first.

void setup()
{
  delay(1000);
  Serial.begin(115200);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid,password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
  server.on("/", handleRoot);

  server.begin();
  delay(500);

  pinMode(D5, OUTPUT);
  digitalWrite(D5,LOW);
}


The first part of the setup contains the normal commands to start the Wifi communication. Nothing special in there. It also prints the IP number of the ESP when a connection with the router is established and that is important.

  server.begin();
  server.on("/", handleRoot);

This is where the webserver is started. When "/"is received the program jumps to the handleRoot routine.

The last part in the setup defines pin D5 as an outpit pin and sets it's value to LOW to make sure that the led is off when the program starts.

void handleRoot()
{   
  if (server.args() )
    {
    handlecmdreceived();
    }
}

In the handleRoot routine the program checks if some information is received. And if the received information is more as just "/" then the webserver received args() and the handlecmdreceived() routine is called.

void handlecmdreceived()
{  
   if (server.hasArg("cmd"))
      {
      ledcmd = server.arg("cmd");
      Serial.print("Thereceived command is:             ");
      Serial.println(ledcmd);
      //Serial.print("If it is an integer its value is:        ");
      //Serial.println(buttonON.toInt());
      if (ledcmd == "ON")
        {
           digitalWrite(D5, HIGH);
        }
      if (ledcmd == "OFF")
        {
           digitalWrite(D5, LOW);
        }
      }


   if (server.hasArg("val"))
      {
        value = server.arg("val");
        Serial.print("The received value is:             ");
        Serial.println(value);
      }


      
  server.send(200, "text/html", getPage());       //Response to the HTTP request
}  


This is the most important part of the program.
If the webserver receives some information the first check is if the received information starts with "cmd". If that is true we store whatever is send with cmd in the variable ledcmd.
Then we check wether ledcmd has the value "ON"or "OFF" and according to that we set the led HIGH or LOW

If the received information does not start with "cmd" but starts with "val" the information contains some value. That value is stored in the variable value and printed in the Serial Monitor.

Adapting for your own purpose.

This can easily be adapted for your own purposes. Just look at:

if (server.hasArg("command"))
  {
     variable = server.arg("command");
  }


Exchange "command" for example for servo or temp or whatever information you want to act upon and adapt the software between the brackets for controlling a servo, a fan or whatever you might need.

How to adress the webserver.

Program your ESP with this software and open the Serial monitor.


As you can see my ESP got the IP number 192.168.1.83

The general command to set the led on is:

IPADRESS/?cmd=ON

and to set the led off:

IPADRESS/?cmd=OFF

To send a value the command is:

IPADRESS/?val=value

in which value can be an integer or a floating point value.

A first test.



To test wether everything works as expected open a webbrowser on your PC or phone and type in the adress bar: 192.168.1.83/?cmd=ON and the led should go on. You need to replace 192.168.1.83 with the IP number your ESP displayed in the serial monitor. Notice that you type this command in your web-browser but no web-page is coming up.

My second ESP8266 has IP number 192.168.1.85 so I set the led ON with 192.168.1.85/?cmd=ON from my phone. This proved that the setup worked from any browser.

Attach one of the ESP's to your computer and open the Arduino IDE. Open the Serial monitor and then type in your web-browser 192.168.1.83/?val=1256 Again: replace 192.168.1.83 by your own ESP's IP number.



And here you can see that the ESP indeed received the command val=1256

Basically that is all.

Control both ESP's with Javascript

As we have a good functioning setup and you know the IP numbers from the ESP's you can now detach the ESP from your computer and attach them to a phone's power supply or power bank.

To control the ESP's I will give you here a webpage with a Javascript program.

The command to send data from Javascript to the ESP's webserver is:

fetch('http://192.168.1.83/?cmd=ON')

As you can see it is just the HTTP line we used in the browser put into a fetch() command.

So here is the full webpage that puts 4 buttons on your screen to set the led's of both ESP's on or off.

<!DOCTYPE html>
<html>
<body>

<h2>Control for ESP webserver</h2>
<button onclick="putledon()">First ESP Led ON</button>
<br>
<br>
<button onclick="putledoff()">First ESP Led Off</button>
<br>
<p>====================================</p>
<br>
<button onclick="putledon2()">Second ESP Led ON</button>
<br>
<br>
<button onclick="putledoff2()">Second ESP Led Off</button>
<br>
<br>


<script>
function putledon() 
  {
     fetch('http://192.168.1.85/?cmd=ON')
  }

function putledoff() 
  {
     fetch('http://192.168.1.85/?cmd=OFF');
  }

function putledon2() 
  {
     fetch('http://192.168.1.83/?cmd=ON')
  };

function putledoff2() 
  {
     fetch('http://192.168.1.83/?cmd=OFF');
  }

</script>
 
</body>
</html>


Just as in the ESP's program you need to alter the IP numbers of both ESP's in the Javascript part of the page's code.

Save this code on your computer as espcontrol.html or any name you want to use. The code will be saved as a webpage.



Click on it and your browser will open with the above screen.

Push the buttons and watch the led's on both ESP's go on and off.

Save this webpage on your Android phone and control both ESP's from your phone.

You can easily convert this webpage into an Android App. Building App's for Android is actually easy with Javascript and I am going to show you how to do that in an upcoming story.

Famous last words

This story demonstrated that you can build a webserver on your ESP which does not produce a webpage. The server is just used as a framework for accepting commands.
The server is then controlled from a webpage that runs on a separate computer, tablet or phone.

This can easily be expanded to send more different commands to the ESP's so they can control led's, relays, servo's motors etc. etc. etc. For that to happen you need to make just minor alterations to the ESP's program and to your HTML page with Javascript.

If you want/need more or different example's drop me a not by email.

Till next time
Have fun

Luc Volders

Friday, May 13, 2022

Gauges and Linecharts in Javascript

For an index to all my stories click this text

As we have seen with cloud based IOT services like Thingspeak it is easy to have a graphical representation of the data of your sensors. With Thingspeak you can create bar-charts and gauges for visualisation of your data. We have been using this in previous stories and adressing them in ESP-Basic. You can find the weblog entry about Thingspeak here:
http://lucstechblog.blogspot.com/2017/11/thingspeak.html

Maybe you do not want to send your data to the cloud for privacy reasons, or you do not need to access the data from all over the world and just want a nice visualisation of the data from within your own network. Well that is possible. I am going to show you how to build a webpage with the ESP32 that has gauges and/or line charts made with data from your sensors. And then you can access that webpage from within your network. To achieve this you need to combine C++ (arduino language) with Javascript.

Javascript.

Every web-browser has a standard built-in programming language which is Javascript. And almost any modern web-page has Javascript programs running to perform tasks like acting on button-presses etc. The fun part is that anyone with a plain text-editor like Notepad or Wordpad which are standard supplied with Windows can start programming. If you have never paid any attention to Javascript before I urge you to do so, as it is easy to learn and fun to play with.

Javascript is the motor that is going to put the gauges and line-charts on our web-page. Don't worry if you have no Javascript experience. I am going to do this the easy way.

Gauges

Searching the web you will find many Javascript libraries that can put gauges on a web-page. I will show you two different ones that are very easy to use and can easily be adapted for use with the ESP8266 and ESP32 for IOT purposes.



The gauge you see here is made with Google Charts. This is a free to use service from Google which brings you a great many different charts which you can incorporate on your website. To use Google Charts your Javascript program needs to download a library from the web to display the charts. You can find details on Google Charts on their website:
https://developers.google.com/chart

Linecharts

A Gauge just displays a value at a certain moment, like what is the temperature at this moment. When the data changes the Gauges pointer moves and the old value is forgotten. With a line chart you can get a historical view of the data.



The linechart is also made with Google Charts. This is the same library with which the Gauge was made.

Javascript code

Before we are going to bring the Gauges and Linecharts to the ESP8266 and ESP32 I am going to show you how the Javascript code works. Study this code and then porting it to the ESP32 will be easy.

You can learn Javascript by following all kinds of tutorials on the web. Lots of them are free and I give you here two possibilities. If you want to learn it by self-study on your own pace with lots of examples and excercises you can do that at the W3schools website in the Javascript section:
https://www.w3schools.com/js/default.asp
Another option is to study Javascript at EDX. Here you find multiple courses on Javascript. This is a more -school-like approach with a teacher that gives lectures and then you need to do some excercises. You can follow the classes for free. After I had already devellopped some Android Apps myself I decided to follow EDX courses on Mits App-Inventor to build Android Apps and I can recommend it. I learned some neat tricks there. You can find EDX's Javascript courses here: https://www.edx.org/course?search_query=javascript

Javascript Gauge

I am going to show you how to build a HTML page that displays a Gauge and a button. Everytime you press the button the Gauge displays a new random figure which represents the temperature. The Gauge is build with the Google Charts library. The Javascript program generates a new random figure and produces the Gauge.



If you want to try this code copy it and paste it in the notebook editor. Then save it as Gauge.HTML in a folder on your computer.
Opening the folder will show you a webpage with the HTML file Gauge. Click on it and your browser will open displaying the Gauge. Press the button and see the value change.


<html>
 <head>
 </head>
 <body>

  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript">
    google.charts.load('current', {'packages':['gauge']});
    google.charts.setOnLoadCallback(drawGauge);

    var gaugeOptions = {min: -5, max: 50, yellowFrom: 18, yellowTo: 24,
        redFrom: 24, redTo: 50, minorTicks: 10};

    function drawGauge() 
    {
      gaugeData = new google.visualization.DataTable();
      gaugeData.addColumn('number', 'Deg. C');
      gaugeData.addRows(1);
      gaugeData.setCell(0, 0, 19);
      gauge = new google.visualization.Gauge(document.getElementById('gauge_div'));
      gauge.draw(gaugeData, gaugeOptions);
    }

    function changeTemp() 
    {
      gaugeData.setValue(0, 0, Math.round(Math.random()*50));
      gauge.draw(gaugeData, gaugeOptions);
    }
  </script>


  <div id="gauge_div" style="width:560px; height: 240px;"></div>
  <input type="button" value="New Value" onclick="changeTemp()" />
 </body>
</html>

Lets have a look at the program so you'll understand how it works.

<html>
 <head>
 </head>
 <body>

Like all webpages this HTML code starts with a header whic is empty in this case and then opens the <body> part. In this the Javascript program will be placed and the objects we need to put the Gauge on the screen.

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

This line tells your browser where to find andload the Javascript charts library.

<script type="text/javascript">

This line tells the browser that the following lines will be another script (Javascript program).

    google.charts.load('current', {'packages':['gauge']});
    google.charts.setOnLoadCallback(drawGauge);

Here we start the library and tell it that we want to use the Gauge function. The second line starts the drawGauge function in which the Gauge is drawn initially on the webpage.

       var gaugeOptions = {min: -5, max: 50, yellowFrom: 18, yellowTo: 24,
        redFrom: 24, redTo: 50, minorTicks: 10}; var gaugeOptions = {min: -5, max: 50, yellowFrom: 18, yellowTo: 24,

This line tells the library that the gauge's scale starts at -5 and ands at 50. This will be the range of degrees Celsius we want to use. Next there will be a yellow marking from 18 to 24 degrees which I consider as a safe zone in which I am comfortable to work in. The red zone goed from 25 to 50 degrees and that is what I definitely consider as to warm. The scale is divided in small steps of 5 after which a larger indicator follows. Alter these to your own liking.

Then the drawGauge() function starts in which the gauge is actually put on the screen.

The Gauge library gets its data out of a table. The table can have many rows and colums and these could be used for pre-defined values. In reality this is part of the overall library and the colums can be filled with multiple data for displaying a line or bar-chart.
in this case only 1 row is used.

      gaugeData.addColumn('number', 'Deg. C');
The first row is filled with initial data. The first column is for numbers (the actual temperature) and the second column is used for the legend which I defined as 'Deg. C'

      gaugeData.addRows(1);
      gaugeData.setCell(0, 0, 19);

A row is added and that row is actually row 0. Row 0 column 9 (first column) is filled with the value 19. The setCell command is the important command that allows us to put or own data in the table. We can achieve that also with setValue which we will use further on in the program.

      gauge = new google.visualization.Gauge(document.getElementById('gauge_div'));
      gauge.draw(gaugeData, gaugeOptions);

These lines make sure that the Gauge is intialised with the Data list we choose (in this case there is only one) and put on the webpage in the pre-defined div (gauge div) using the options for the scale defined in gaugeOptions.

The next function is the changeTemp() function. This will be activated when we press the button which is defined further on.

gaugeData.setValue(0, 0, Math.round(Math.random()*50));

In the changeTemp function the first cell in the table which contains the value of the temperature is changed.

Math.round(Math.random()*50))

This part of that line calculates a new random temperature. Math.random() gives a figure between 0 and 1. So we multiply it by 50 and then round it to an integer.

And that ends the Javascript code.

  <div id="gauge_div" style="width:560px; height: 240px;"></div>
  <input type="button" value="New Value" onclick="changeTemp()" />

The last two things we have to do is to create a place on the webpage where the Gauge will be displayed and this is inside the <div> In this <div> we also define the width and height of the Gauge.
And we need to define a button which calls the function to re-draw the Gauge with a new random value.

That's it.
Just copy the code into your notebook editor. Save it as a non-txt file with the extention html like for example gauge.html and it will turn into a webpage. Click on that and the Gauge will appear in a new browser tab or window.

To port this to an ESP you will need to put this in a webserver and make sure that the formula Math.round(Math.random()*50) is altered in a real sensor reading. This is what we are going to cover in an upcoming story.

Javascript Linechart

As stated above a Gauge only displays the current or last supplied value. Sometimes we want to see some history. That is when a linechart comes in handy.



The linecharts are build by using the same Google Charts library as the Gauge does. So the basics are the same. I'll give you the complete code first.

<html>
<head>
</head>
<body style='background-color:powderblue;'>

    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      google.charts.load('current', {'packages':['corechart']});
      google.charts.setOnLoadCallback(drawChart);

      function drawChart() 
      {
        var data = google.visualization.arrayToDataTable([
          ['Time' , 'Temp'],
          ['19.00', 15],
          ['19.30', 17],
          ['20.00', 19],
          ['20.30', 19.5],
          ['21.00', 19.5],
          ['21.30', 19.5],
          ['22.00', 19.5],
          ['22.30', 19.5],
          ['23.00', 18],
          ['23.30', 10],
        ]);

        var options = 
        {
          title: 'Mancave temperature',
          legend: { position: 'bottom' },
          width: 600,
          height: 400,
          chartArea: {width: '90%', height: '75%'}
        };
        var chart = new google.visualization.LineChart(document.getElementById('temp_chart'));
        chart.draw(data, options);
      }
    </script>
<br>
<br>
    <div id="temp_chart"></div>
  </body>
</html>

For those that are not familiar with Javascript I'll do an analyses for the most important lines.

<html>
<head>
</head>
<body style='background-color:powderblue;'>

These are the starting lines of almost any webpage. We define that it is build on HTML code. The heading of the page stays empty although you may fill in the ususla credentials. Next the body of the webpage's background color is defined. As ususla I use my favorite which is powderblue.

<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>

This line tells your browser where to find andload the Javascript charts library.

<script type="text/javascript">

This line tells the browser that the following lines will be another script (Javascript program).

      google.charts.load('current', {'packages':['corechart']});
      google.charts.setOnLoadCallback(drawChart);

Here we start the library and tell it that we want to use the Gauge function. The second line starts the drawGauge function in which the Gauge is drawn on the webpage.

      function drawChart() 
      {
        var data = google.visualization.arrayToDataTable([
          ['Time' , 'Temp'],
          ['19.00', 15],
          ['19.30', 17],
          ['20.00', 19],
          ['20.30', 19.5],
          ['21.00', 19.5],
          ['21.30', 19.5],
          ['22.00', 19.5],
          ['22.30', 19.5],
          ['23.00', 18],
          ['23.30', 10],
        ]);

Then follows the function drawChart() which puts all data we want to display in a table. The first entries called Time and Temp are to be displayed as the legend of the chart. The next entries all define a timestamp and the measured temperature at that time.

As you can see I defined 10 entries (0 to 9). You may add or delete entries as you like. By adding more entries the time indication at the bottom of the chart may get cramped. Widening the screen eand the width of the chart may bring relief but remember that will have an impact on displayi8ng the chart on a mobile phone or tablet.

        var options = 
        {
          title: 'Mancave temperature',
          legend: { position: 'bottom' },
          width: 600,
          height: 400,
          chartArea: {width: '90%', height: '75%'}
        };

I splitted the options out in multiple lines for clarity.
The title of the chart will be "Mancave Temperature" and the name of what we measured (temp) will be placed at the bottom of the chart.
Next the width and height of the chart are defined.
The last line defines how much space the chart will use within the defined area. I used 90% for width and 75% for height. If you do not specify these percentages there will be a lot of whitespace next to the chart.

        var chart = new google.visualization.LineChart(document.getElementById('temp_chart'));
        chart.draw(data, options);

These 2 lines actually put the chart on the webpage and in the <div> with the name "temp_chart"

That concludes the Javascript program.

    <div id="temp_chart"></div>

This last line defines some space on the webpage with the name "temp_chart" in which the chart will be drawn.

That's it.

Again like with the Gauge code, copy this code paste it into a texteditor like Notepad and save it as a non-text file with a name like charts.html
locate the file on your computer and click on it. Your preferred web-browser wil open and a webpage with the line chart will appear.

Altering the charts.

Both the Gauges and the Linechart code have a variable with options in the name (or as the name). Altering this variable can modify the charts in all kinds of ways. You can alter the background, line colors, texts, width and height etc etc etc.
There ate tons of options to play with.

Next to that there are many more types of charts available. Their basic Javascript code for these is the same as the charts I presented you here so altering the code for making barcharts, column charts, donuts, piecharts, histograms etc etc etc should not prove to be all that difficult.

You can find all details here:
https://developers.google.com/chart/interactive/docs/gallery/histogram

Nerxt steps

First I urge you to play around with Javascript. Look for examples on the web and you will be amazed at how much information, tutorials and programs are available. Javascript is easy to learn and you only need a simple text editor and a browser to start building amazing projects. Next to that Javascript web-programs work on your computer, phone and tablet without alterations.

I have done a complete tutorial on building webpages on the ESP line of micro-controllers. Now lets bring the Gauges and charts to the ESP !!! so keep on coming back to see how it's done.

Till tnext time.
Have fun

Luc

Friday, May 6, 2022

Interrupts: WTF happened

For an index to all my stories click this text.

Some of you pointed out that there was a problem with my code in the "More buttons on fewer pins" story. Now I must admid that I wrote that story some time ago, published it and forgot about it.
When some readers however mailed me that there was a problem with the software I had to dive into this again. And indeed WTF happened.

Well what happened was that a new version of the Arduino software had some alterations in the interrupt routine. That made the ESP series (ESP8266 and ESP32) microcontrollers run berserk.

What's behind it.

Sometimes programs are loaded from flash memory when run. That works fine for a lot of programs but poses a problem when fast processing is involved.
The Arduino IDE therefore changed the way it handles interrupts. It wants the interrupt handling routine to run in RAM so it is always available when needed, and needs not to get loaded first during execution of a program.

Next to that it is recommended that no delay() command is used in the interrupt routine. As a matter of fact that makes sense. Interrupts generally need to be handled as fast as possible because it may happen that when the interrupt routine is being handled at the same time a new interrupt is initiated.

However in my program that handles a button press speed is not the issue. The interrupt routine is processed a lot faster then you would press another button. But my endeavours in my little corner of the universe is of course of no concern to the developers of the Arduino IDE.

It made however an impact on some of my programs and of course the chapter on interrupts in my book ESP32 Simplified. You can find details on my book here: http://lucstechblog.blogspot.com/2020/06/esp32-simplified-my-book-in-english-now.html

The solution

Luckily the alterations to get things working again are small.

attachInterrupt(digitalPinToInterrupt(D5), buttonpress, FALLING);


In the setup() routine the interrupts are initiated with this line. And that stays the same. The interrupt is attached to pin D5 and when that button is pressed it calls the "buttonpress" routine.

void buttonpress()
{
  // button 1 ==> 011
  if (digitalRead(D5)== LOW && digitalRead(D6)== HIGH && digitalRead(D7)== HIGH)
  {
    strip.setPixelColor(0, 0,255,0);
    strip.setPixelColor(1, 0,0,0);
    strip.setPixelColor(2, 0,0,0);
    strip.setPixelColor(3, 0,0,0);
    strip.setPixelColor(4, 0,0,0);
    strip.setPixelColor(5, 0,0,0);
    strip.setPixelColor(6, 0,0,0);
    strip.show();
    delay(500);
  }


This is part of the "buttonpress" interrupt routine. This is where we need to make the changes. First we need to alter void buttonpress() in ICACHE_RAM_ATTR void buttonpress() So a command is put in front of void buttonpress(). That command is ICACHE_RAM_ATTR and that makes sure that this part of the program is loaded into RAM before the program starts.

Next the delay(500) line must be left out.

So the new first part of the program is:

ICACHE_RAM_ATTR void buttonpress()
{
  // button 1 ==> 011
  if (digitalRead(D5)== LOW && digitalRead(D6)== HIGH && digitalRead(D7)== HIGH)
  {
    strip.setPixelColor(0, 0,255,0);
    strip.setPixelColor(1, 0,0,0);
    strip.setPixelColor(2, 0,0,0);
    strip.setPixelColor(3, 0,0,0);
    strip.setPixelColor(4, 0,0,0);
    strip.setPixelColor(5, 0,0,0);
    strip.setPixelColor(6, 0,0,0);
    strip.show();
  }


Famous last words.

So to get your programs that use an interrupt routine working again put ICACHE_RAM_ATTR in front of the line that defines the start of the routine and remove all delay() statements from your interrupt routines.

PHEW !!!
Easier as I thought.

Till next time.

Luc Volders