P5.js with ESP8266 WiFi

hello, after years I return to the pc and I’m still dazzled by processing.
I wanted to ask if this single schetch for esp8266 where a p5.js sketch is included is a good system and if it can be improved, I searched the net for a long time but I didn’t find anything to be explored.
unfortunately only those with an esp89266 can try it.
it is about sending values from the esp8266 directly to p5.js and then via wifi without being connected to the serial and it works.
Thank you

////////////////////////////////////////////////////////////////////html
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
   <script type="text/javascript">
/////////////////////////////////////////////////////////////////////Processing P5.js
let arduVal1
let arduVal2
let p5
let rot
function setup() {
  createCanvas(700, 700);
  r = random(255);
  g = random(255);
  b = random(255);
textAlign(CENTER);
textSize(width/30);
rot =0;
p5=0;
arduVal1=0;
arduVal2=0;
 }
function draw() {
var source = new EventSource('/events');
source.addEventListener('newVal', function(e) {
const obj = JSON.parse(e.data);
arduVal1 = obj.out1.toFixed(2); // toFixed(2) =  2 decimal
arduVal2 = obj.out2;
});

background(200,50,20);
noStroke();
fill(20,20,255);
text ("from ardu1 (5s)", width/20, width/14);
text (arduVal1, width/20, width/9);
text ("from ardu2 (5s)", width/2.9, width/14);
text (arduVal2, width/2.9, width/9);

strokeWeight(2);
stroke(r, g, b);
fill(r, g, b, 127);
ellipse(width/2, width/2, width/3.6, width/3.6);

push();
translate(width / 2, width / 2);
fill(0,255,0);
rot = rot+1;
rotate(radians(rot));
rect(-26, -26, 52, 52);
pop();

stroke(255,255,0);
text ("clickMe", width/2, width/2);
}

function mousePressed() {
  // Check if mouse is inside the circle
  let d = dist(mouseX, mouseY, width/2, width/2);
  if (d < 100) {
    // Pick new random color values
    r = random(255);
    g = random(255);
    b = random(255);
  }
}
////////////////////////////////////////////////////////////////////////html
</script>
</html>)rawliteral";
////////////////////////////////////////////////////////////////////arduino esp8266

#include <ESP8266WiFi.h>
#include "ESPAsyncWebServer.h"

#include <Arduino_JSON.h>
const char *ssid = "xxxxzzxxxxxx";
const char *password = "xxxzxxxxxxxx";
/////////////////
float ardu1;
int ardu2;
AsyncWebServer server(80);
AsyncEventSource events("/events");

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Setting as a Wi-Fi Station..");
  }
  Serial.print("Station IP Address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Wi-Fi Channel: ");
  Serial.println(WiFi.channel());
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send_P(200, "text/html", index_html);
  });
  server.addHandler(&events);
  server.begin();
  delay(4000);
}

void loop() {
  ardu1 = ardu1 + 0.01;
  ardu2 = random(1, 1234);
  JSONVar myVal;
  myVal["out1"] = ardu1;
  myVal["out2"] = ardu2;
  String jsonStr = JSON.stringify(myVal);
  events.send(jsonStr.c_str(), "newVal", millis(), 5000);
  events.send("ping", NULL, millis(), 5000);
}
1 Like

Hi @camperos. This is interesting, fun, and possibly useful. I’ve loaded it into an ESP8266 (Node MCU 0.9 (ESP-12 Module)). It’s using P5.js from the internet but in my utility projects I’ve always wanted them to be fully functional without the internet. Maybe the whole project uses the internet, then it doesn’t matter. I know the ESP has a filing system and it’s on my todo list to find how to use it. Maybe the .html, p5.js etc can go there.

With your code I saw the two values static for a few seconds, and then update several times rapidly. I put a 2 sec delay at the end of loop, now I have an update every 2 sec. I’ve never used ‘events.send’ before, haven’t yet Googled and understood what they do.

Thanks for posting.

2 Likes

Hi

Maybe this useful

thanks, I tried quickly for the little time I have now and I couldn’t see the result, it’s very complicated, I’ll try again in 8 hours and study it, the basis of the system seems to be identical

After a while the the browser console started pouring out messages about insufficient resources. (And the browser was laggy on reload.) I moved

var source;

to above setup, and

  source = new EventSource('/events');
    source.addEventListener('newVal', function(e) {
      const obj = JSON.parse(e.data);
      arduVal1 = obj.v0.toFixed(2);
      arduVal2 = obj.v1;
  });

from draw to setup.


Working on Javascript buried in ESP code, in the Arduino IDE is not best. Compiling and loading into the ESP takes 62 seconds. That’s much too difficult and slow. So I moved the Javascript code to a file on a Raspberry Pi. It’s in directory where a node.js server is running. It can be edited with a Javascript editor. Save and reload takes a couple of seconds. This might not be what you want finally, but it’s better for development. The html for this is:

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
  <script src="http://192.168.1.11:8082/sketch_e.js"></script>
</html>)rawliteral";

If you want to try the game of life sketch.js from @jafal’s link it’s very quick to swap the sketch.js for a different one.

1 Like

@camperos

More informations

http://fabacademy.org/2020/labs/barcelona/students/benjamin-scott/week-12.html#using-the-wavemaker-example

thanks for the reply,
insufficient resources (which happens on chrome and mobile) I think I solved it by introducing reception times and improving sending

p5js side:

let interval
let previousMillis
....
function setup() {
...
interval = 5000;
previousMillis = 0;
}
function draw() {
let currentMillis = millis();
.....
if (currentMillis - previousMillis >= interval) {
source = new EventSource('/events');
source.addEventListener('newVal', function(e) {
const obj = JSON.parse(e.data);
arduVal1 = obj.out1.toFixed(2); // toFixed(2) = 2 decimal
arduVal2 = obj.out2;
});
previousMillis = currentMillis;
}
}

arduino side:

unsigned long previousMillis = 0;
const long interval = 5000;
.....
void loop() {
unsigned long currentMillis = millis();

 if (currentMillis - previousMillis >= interval) {
    events.send(jsonStr.c_str(), "newVal", millis(), 1);
    events.send("ping", NULL, millis(), 1);
    previousMillis = currentMillis;
}
}

hi jafal,
i couldn’t get “rwlloyd/p5-javascript-webserver” to work, i try again as soon as possible, but studying it i see that there is nothing sending values from esp8266 to p5js but maybe i saw wrong

hello, now I’m looking for how to P5js in simple mode … for example, turn on and off the led of esp8266 always with the eventsource system, I tried but for the moment I can’t, any ideas?

As I said, this sending events is new to me. Think you need to google for examples. I think I found a page that compared sending events with socket.io. Can’t find it now. Think it said you can’t send events from web-page to server. All my projects with RPi server and P5.js web-pages are based on https://www.youtube.com/watch?v=bjULmG8fqc8&t=450s&pp=ygUXY29kaW5nIHRyYWluIG5vZGUganMgIzE%3D and use socket.io. Haven’t thought how ESP8266 might replace RPi in that scheme.

1 Like

I’ve read and you’re right, it’s only one way, however I keep trying new ways

I succeeded, only one sketch to upload to esp8266 with arduino code and P5js code, it works and is bidirectional.
thanks to jafal for the links and RichardDL, if you want try it maybe the Rasp… clicking inside the circle the led turns on, clicking outside the circle the led turns off. it needs to be improved


//by camper0s

//////////////////////////////////////////////////////////////////////////html
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
   <script type="text/javascript">
/////////////////////////////////////////////////////////////////////Processing P5.js
let source
let arduVal1
let arduVal2
let p5
let rot
let interval
let previousMillis
let adc
let stat
let xhr
 
 function setup() {
  createCanvas(700, 700);
  r = random(255);
  g = random(255);
  b = random(255);
textAlign(CENTER);
textSize(width/30);
rot = 0;
p5 = 0;
arduVal1 = 0;
arduVal2 = 0;
interval = 4000;
previousMillis = 0;
source = 0
adc=0;
stat=0;
let xhr = 0; 
}
 function draw() {
let currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
source = new EventSource('/events');
source.addEventListener('newVal', function(e) {
const obj = JSON.parse(e.data);
arduVal1 = obj.out1.toFixed(2); // toFixed(2) = 2 decimal
arduVal2 = obj.out2;
});
previousMillis = currentMillis;
}
background(200,50,20);
noStroke();
fill(20,20,255);
text ("from ardu1 (5s)", width/4, width/14);
text (arduVal1, width/4, width/9);
text ("from ardu2 (5s)", width/1.5, width/14);
text (arduVal2, width/1.5, width/9);

strokeWeight(2);
stroke(r, g, b);
fill(r, g, b, 127);
ellipse(width/2, width/2, width/3.6, width/3.6);

push();
translate(width / 2, width / 2);
fill(0,255,0);
rot = rot+1;
rotate(radians(rot));
rect(-26, -26, 52, 52);
pop();

stroke(255,255,0);
text ("clickMe", width/2, width/2);
}
function mousePressed() {
  // Check if mouse is inside the circle
  let d = dist(mouseX, mouseY, width/2, width/2);
  if (d < 100) {
    // Pick new random color values
    r = random(255);
    g = random(255);
    b = random(255);
stat=1;
}
else if(d > 100 )
{
stat=0;
}
  if (stat == 1) {
  adc=1;
  xhr = new XMLHttpRequest();
  xhr.open("GET", "/update?output="+adc+"&state=0", true);
  xhr.send();
}
else if(stat == 0)
{
 adc=0;
  xhr = new XMLHttpRequest();
  xhr.open("GET", "/update?output="+adc+"&state=0", true);
  xhr.send();
  }
}
////////////////////////////////////////////////////////////////////////html
</script>
</html>)rawliteral";
////////////////////////////////////////////////////////////////////arduino esp826
#include <ESP8266WiFi.h>
#include "ESPAsyncWebServer.h"
#include "ESPAsyncTCP.h"
#include <Arduino_JSON.h>
const char *ssid = "xxxxxdfffvxxx";
const char *password = "xxxxxxxxcxfx";
float ardu1;
int ardu2;
unsigned long previousMillis = 0;
const long interval = 5000;
const char *in1 = "output";
const char *in2 = "state";
String inputMessage1;
String inputMessage2;
AsyncWebServer server(80);
AsyncEventSource events("/events");

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
 WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Setting as a Wi-Fi Station..");
  }
  Serial.print("Station IP Address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Wi-Fi Channel: ");
  Serial.println(WiFi.channel());
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send_P(200, "text/html", index_html);
  });
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request) {
    inputMessage1 = request->getParam(in1)->value();
    inputMessage2 = request->getParam(in2)->value();
    Serial.print("GPIO: ");
    Serial.print(inputMessage1);
    Serial.print(" - Set to: ");
    Serial.println(inputMessage2);
    request->send(200, "text/plain", "OK");
  });
  server.addHandler(&events);
  server.begin();
  delay(4000);
}
void loop() {
  unsigned long currentMillis = millis();
  ardu1 = ardu1 + 0.01;
  ardu2 = random(1, 1234);
  JSONVar myVal;
  myVal["out1"] = ardu1;
  myVal["out2"] = ardu2;
  String jsonStr = JSON.stringify(myVal);

  if (currentMillis - previousMillis >= interval) {
    events.send(jsonStr.c_str(), "newVal", millis(), 1);
    events.send("ping", NULL, millis(), 1);
    previousMillis = currentMillis;
  }
  if (inputMessage1.toInt() == 0) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else if (inputMessage1.toInt() == 1) {
    digitalWrite(LED_BUILTIN, LOW);
  }
}
2 Likes

hello, I noticed that remotely on mobile that if I interact from chrome after 5 minutes it crashes, while from firefox it always works, sorry for the translated language