I'm continuing to work on enhancing my laser setup. One item on the list is a warning indicator that the laser is operating and that it is not safe to enter the room. I plan to put it outside the door to my computer room (the access to the workroom with the laser is through the computer room), so one requirement is that the indicator should be remotely controlled via WiFi or Bluetooth. I received an Adafruit 8266 Huzzah board in the latest Element14 goodie bag and that seemed like a good place to start. I've been wanting to use an e-Paper display since I saw the clock that shabaz built a couple of years ago: Experimenting with E-Paper Displays: Building a Clock! I thought e-Paper would work well here because the display does not update very often. I wanted the warning to be in RED letters, so I bought a tricolor (Black/White/Red) 2.9 inch display with SPI interface: https://www.amazon.com/gp/product/B0751JYW36/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1 .
I decided to use the Arduino IDE to program the ESP8266 Huzzah board. I used the Adafruit_GFX, Adafruit_EPD, and ESP8266WiFi libraries. I used an online converter to create a 48 pt Dialog_bold font compatible with the libraries. I decided to add an RGB LED to draw attention to the sign because the e-Paper display is not very bright. I used a simple common cathode direct drive LED which pins out each LED individually. This configuration required 6 GPIO pins - 4 for SPI (Data, Clk, CS, DC) and 1 each for the Red and Green LEDs. I elected not to use the Busy and Reset pins on the display. The prototype breadboard is shown below. I did a quick 3D print to hold the display and LED. I will probably need to modify the case when I mount the controller board.
To test the functionality I set up a simple wifi webserver that receives requests to set the output of the sign to "Laser On" or "Laser Off". When the laser is on the Red LED will flash and when the laser is off the Green LED will be on. The code is shown below.
laser_sign_wifi.ino
/*************************************************** Using Adafruit Graphics and ePaper libraries ****************************************************/ // include required libraries #include <Adafruit_GFX.h> // Core graphics library #include "Adafruit_EPD.h" // e-Paper display library #include <ESP8266WiFi.h> const char* ssid = "xxxxx"; const char* password = "yyyyy"; // include fonts used //#include <Fonts/FreeSansBold24pt7b.h> #include <Fonts/Dialog_bold_48.h> // pin definitions #define EPD_CS 0 // SPI CS #define EPD_DC 2 // SPI DC #define SRAM_CS -1 // no external storage #define EPD_RESET -1 // can set to -1 and share with microcontroller Reset! #define EPD_BUSY -1 // can set to -1 to not use a pin (will wait a fixed delay) #define GREEN_LED 5 // same as SCL #define RED_LED 4 // same as SDA /* Using Waveshare tricolor 2.9" EPD */ Adafruit_IL0373 display(296, 128, EPD_DC, EPD_RESET, EPD_CS, SRAM_CS, EPD_BUSY); // Create an instance of the server // specify the port to listen on as an argument WiFiServer server(80); // initial pass int newClient = 1; void setup(void) { pinMode(GREEN_LED, OUTPUT); pinMode(RED_LED, OUTPUT); digitalWrite(GREEN_LED, LOW); digitalWrite(RED_LED, LOW); Serial.begin(115200); while(!Serial); Serial.print("Laser Warning Sign\n"); // Connect to WiFi network Serial.println(); 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()); // start the server server.begin(); Serial.println(F("Server started")); // setup display display.begin(); // iniitalize display display.setRotation(2); // text upright with connector on left display.clearBuffer(); display.setFont(&Dialog_bold_48); display.setTextSize(1); // text size multiplier display.display(); Serial.println("Display initialized"); } void loop() { // Check if a client has connected WiFiClient client = server.available(); if (!client) { if (!digitalRead(GREEN_LED) && !newClient) { delay(500); digitalWrite(RED_LED, !digitalRead(RED_LED)); return; } } if (client.connected()) { newClient = 0; Serial.println(F("new client")); client.setTimeout(1000); // default is 1000 // Read the first line of the request String req = client.readStringUntil('\r'); Serial.println(F("request: ")); Serial.println(req); // Match the request int val; if (req.indexOf(F("/laser/0")) != -1) { val = 0; } else if (req.indexOf(F("/laser/1")) != -1) { val = 1; } else if (req.indexOf(F("/favicon.ico")) != -1) { val = 2; } else { Serial.println(F("invalid request")); val = digitalRead(RED_LED); } // Set LED according to the request // digitalWrite(LED_BUILTIN, val); // read/ignore the rest of the request // do not client.flush(): it is for output only, see below while (client.available()) { // byte by byte is not very efficient client.read(); // Serial.println(F("client.read")); delay(10); } // Send the response to the client // it is OK for multiple small client.print/write, // because nagle algorithm will group them into one single packet client.print(F("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nLaser is now ")); client.print((val) ? F("on") : F("off")); client.print(F("<br><br>Click <a href='http://")); client.print(WiFi.localIP()); client.print(F("/laser/1'>here</a> to switch Laser on, or <a href='http://")); client.print(WiFi.localIP()); client.print(F("/laser/0'>here</a> to switch Laser off.</html>")); // The client will actually be *flushed* then disconnected // when the function returns and 'client' object is destroyed (out-of-scope) // flush = ensure written data are received by the other side Serial.println(F("Disconnecting from client")); // close the connection: client.stop(); if (val == 1) { digitalWrite(GREEN_LED, LOW); digitalWrite(RED_LED, HIGH); display.clearBuffer(); display.setCursor(20, 80); display.setTextColor(EPD_RED); display.print("Laser On"); display.display(); } else if (val == 0) { digitalWrite(RED_LED, LOW); digitalWrite(GREEN_LED, HIGH); display.clearBuffer(); display.setCursor(20, 80); display.setTextColor(EPD_BLACK); display.print("Laser Off"); display.display(); } else { Serial.println(F("favicon request")); } } }
Here are pictures of the 2 display conditions:
I was a little surprised by the gymnastics that the display controller goes through when writing the e-Paper display. I've seen complaints about it and videos on YouTube but did not realize what it looked like with a tricolor display. The controller first writes an inverse (negative) image then the image that was requested. In the case of Red text it additionally writes the text in Black before writing it in Red. I've attached a video below that demonstrates what it looks like. Maybe this behavior can be overridden. I'll need to check the controller spec. I am making the "Laser On" and "Laser Off" requests directly from the Chrome browser but in the final configuration I'll do that from the program that is controlling the laser.
Top Comments