I like to measure things. Temperature, pressure, moisture,
flow, ...
I really like the ESP8266 and ESP32 as I can stick them in zip lock
bags all over the place and they measure and in some cases control.
What to do with the data they gather. I like to create
my own but there are platforms already built. I either use
node red or create a web server in the ESPs or both.
More later.
Hello
World
Or, the micro controller equivalent - flash a LED
We actually have two leds. One on the ESP8266 Development
Board and the external led on the red breadboard.
Code Hello World
// micro controller hello world with 2 leds
// Global variables here
int boardLed = 2;
int externalLed = 5;
digitalWrite(boardLed, LOW);
digitalWrite(externalLed, LOW);
Serial.println("board led on");
delay(500);
}
And by request
- A comparison to the new Raspberry Pi Pico.
Temperature pressure example
Note the temperature measured by the temperature
sensor on the BMP280 is much higher that the temp.
measured by the DS18B20. The BMP280 is in the ziplock
bag and is heated by the ESP8266.
ESP8266 Lolin development board under back deck in its ziplock bag.
The barometric pressure sensor is under the 8266. The DS18B20
temperature
sensor is the black wire on the left. It sensor part is about
a meter away
where rain and sun don't effect it but there is good air flow.
BMP280 and DS18B20
Code Temperature and Barometric Pressure
Rui Santos Complete pr /*******
details at http://randomnerdtutorials.com
Running on ESP8266 12-E LoLin Development Board
Modified by D. Reimer 2017-08-14
Add Temp and Pressure 2020-12-10
************/
// Include the required libraries
#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Red led gpio pin - high during web serving
//int redLed = 5;
int redLed = 14;
// Data wire is connected to D2/GPIO 4
//#define ONE_WIRE_BUS 4
#define ONE_WIRE_BUS 12
// Setup a oneWire instance to communicate with any OneWire
devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire instance reference to the Dallas Temperature
routine
DallasTemperature DS18B20(&oneWire);
// Create variables to hold the temperature measurements
char temperatureCString[8];
char temperatureFString[8];
// Create a Web Server on port 80
WiFiServer server(80);
// *** Functions ***
// Define function to get the Celcius and Farenheit temperature
void getTemperature() {
float tempC;
float tempF;
//Turn on the red led
digitalWrite(redLed, HIGH); // turn the LED
on (HIGH is the voltage level)
// Loop until the temperature is on out of range
do {
DS18B20.requestTemperatures();
tempC = DS18B20.getTempCByIndex(0);
dtostrf(tempC, 6, 2, temperatureCString);
//Serial.println(temperatureCString);
tempF = DS18B20.getTempFByIndex(0);
dtostrf(tempF, 6, 2, temperatureFString);
delay(100);
} while (tempC == (-127.0));
// Turn off the red led.
digitalWrite(redLed, LOW);
}
// Setup
void setup() {
// Set gpio pin 5 to output for red led.
pinMode(redLed, OUTPUT);
// Initialize serial port for debugging
Serial.begin(9600);
delay(10);
// Start the 1wire temperature library
// IC Default 9 bit. If you have troubles consider upping
it 12. This ups the delay giving the IC
// more time to process the temperature measurement
DS18B20.begin();
// Connect to the WiFi network and display the IP.
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(WiFi.localIP());
// Start the web server
server.begin();
Serial.println("Web server running");
delay(2000);
}
// Process
void loop() {
// Listen for a web client
WiFiClient client = server.available();
// If there is a client then:
if (client) {
Serial.println("New client");
// Assume the ending blank line has been
encountered.
boolean blank_line = true;
//
while (client.connected()) {
if (client.available()) {
// Read a request
from the client
char c =
client.read();
// If end of request
get the temperature and display it.
if (c == '\n'
&& blank_line) {
// Send
httpd header.
getTemperature();
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
// Send
the html
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head></head><body>");
client.println("<meta name=viewport
content=\"width=device-width, initial-scale=1.5\">");
client.println("<h1>Temperature</h1><h3>Celsius:
");
client.println(temperatureCString);
client.println("°C</h3><h3>Fahrenheit: ");
client.println(temperatureFString);
client.println("°F</h3>");
client.println("bmpTemp:");
client.println(bmpTempString);
client.println("bmpPress:");
client.println(bmpPressString);
client.println("</body></html>");
break;
}
// If this is an
empty line, then set blank_line true.
if (c == '\n') {
blank_line = true;
// and
not a carriage return, then it is the the empty line indicating
end of http
} else if (c != '\r')
{
blank_line = false;
}
}
}
// close the client connection
delay(1);
client.stop();
Serial.println("Client disconnected.");
}
}
// define pins numbers
const int trigPin = 4; //D2
const int echoPin = 5; //D1
const int alertPin = 14; //D5
const int ledPin = 12; //D6
// Define the approach distances centimetres.
const int alertDistance = 200; // Alarm sounds red led
const int yellowDistance = 280; // Yellow led
// led colours
int red = 0xff0000;
int yellow = 0xff5b00;
int green = 0x00ff00;
// About the leds
#define NUM_LEDS 3
#define LED_PIN ledPin
#define LED_TYPE PL9823
// Tell the library about the number of leds
CRGB led[NUM_LEDS];
// define distance variables
long duration;
int distance;
void setup() {
pinMode(trigPin, OUTPUT); // Set the trigPin as an
Output
pinMode(echoPin, INPUT); // Set the echoPin
as an Input
pinMode(alertPin, OUTPUT); // Set the alert to output.
Serial.begin(9600); // Start the serial communication
// Initialize the fast led library
FastLED.addLeds<LED_TYPE, LED_PIN>(led, NUM_LEDS);
delay(1000);
// Set the initial led colours
led[0] = 0x000000; // pilot light and 5v drop
through diode
led[1] = led[2] = green;
}
void loop() {
// Clear the trigger pin and alert pin
digitalWrite(trigPin, LOW);
digitalWrite(alertPin, LOW);
delayMicroseconds(2);
// Set the trigger pin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read the echoPin, returns the sound wave travel time
in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculate the distance - speed of sound is 343 mps
distance = duration * 0.0343 / 2;
// Set the leds to green
led[1] = led[2] = green;
if (distance < yellowDistance) {
led[1] = led[2] = yellow;
}
if (distance < alertDistance) {
digitalWrite(alertPin, HIGH);
led[1] = led[2] = red;
}
// Display the set led colour.
FastLED.show();
delay(200);
// Display the distance on the Serial Monitor
Serial.print("Distance cm: ");
Serial.println(distance);
}
Leds
Code Addressable Leds
/*
Web and switch control of "addressable" pl9823 controlled
leds.
Deid Reimer 2020-04
deid@drsol.com
*/
//#define FASTLED_ESP8266_RAW_PIN_ORDER
#include <FastLED.h>
// About the leds
#define NUM_LEDS 50
#define LED_PIN 1
#define LED_TYPE WS2811
// Fix ISR problem - not using ISR in this code
// void ICACHE_RAM_ATTR ISR (){ ...}
//ICACHE_RAM_ATTR
// Instantiate and tell the web server to listen on port 80
ESP8266WebServer server(80);
// ID and Password for web control
const char* id = "ws2811";
const char* pw = "neopixel";
// Initialization values for the various led programs.
// Rainbow colours for the rainbow program - this vector
is shifted to move the rainbow
int rainbow[] = {0xff0000, 0xff4800, 0xffff00, 0x00ff00,
0x0000ff, 0x3000ff, 0x9400d3};
// RGB colours for the chase and random programs. These
are incremented
byte cred = 0;
byte cgreen = 0;
byte cblue = 0;
// Variables for the multi pattern
long multiC1 = 0xff0000;
long multiC2 = 0x0000ff;
int multiSp = 20;
int multiSz = 5;
String multiDr = ">";
// Miscellaneous
int rbStart =
0;
// Rainbow start led
int chase =
0;
// chase first led
int chaser = NUM_LEDS - 1; // reverse chase
first led
byte colour[] = {255, 0, 0}; // chasing primaries program
const int webSafe = 51; //
Number of web safe colours
bool dirty =
false;
// Set if the lights need to be changed
int dot =
0;
// moving pixel position
int rc =
0;
// dot colour from rainbow
long colourVal = 0xffffff; // colour value for
several patterns
bool doRefresh = false; //
switch indicate the led array needs to be refreshed or displayed
// Variables for the push button and debouncing.
const int selectButton = 4; // GPIO pin
// Overal Program variables
int lightProgram = 0;
// Current program selected
int maxProgram =
13; // Maximum
program number
// Count millis for timing of random colour/time programs
unsigned long currentTime;
unsigned long loopTime[NUM_LEDS];
// Function to build the select light program web page.
String makePage() {
// Clear all the button colours to offColour and set the
selected to onColour;
for (int i = 0; i <= maxProgram ; i++) {
s[i] = offColour;
}
s[lightProgram] = onColour;
// Display the web page.
void newPage() {
checkCreds();
makePage();
showPage();
}
// Function to get and execute a query to select a program
(pattern)
void execQuery() {
// Check Credentials and Build the new web page.
checkCreds();
// Get the program number. If there is an argument
separate out the value.
if (server.args() >= 1) {
String m = server.arg("s");
int n = m.toInt();
// check the validity of the supplied number.
if (n <2 or n > maxProgram + 2) {
// Got an invalid number just
redisplay the web page and return
makePage();
showPage();
return;
}
// Set the number back to 0 base and set the
new selected program.
// We started at 2 so
that toInt returning 0 on fail can be caught.
lightProgram = n - 2;
makePage();
showPage();
// We need to refresh the pattern
doRefresh = true;
// number of arguments not equal to 1 - just
redisplay the page.
} else {
newPage();
delay(100);
return;
}
}
// Get colour value.
void getColour() {
checkCreds();
char c[] = "0000000";
String m;
if (server.arg("cv") != NULL) {
m = server.arg("cv");
m.remove(0, 1);
m.toCharArray(c, 7);
//Serial.println(c);
colourVal = strtol(c, NULL, 16);
//Serial.println(colourVal);
}
//Serial.println("arg");
//Serial.println(m);
//Serial.println(colourVal);
makePage();
showPage();
}
void getMulti() {
char c[] = "0000000";
// Get first colour from and convert from String to long.
String m = server.arg("cv1");
m.remove(0, 1);
m.toCharArray(c, 7);
multiC1 = strtol(c, NULL, 16);
// Same with second colour.
m = server.arg("cv2");
m.remove(0, 1);
m.toCharArray(c, 7);
multiC2 = strtol(c, NULL, 16);
// And Speed in milliseconds?
m = server.arg("sp");
multiSp = m.toInt();
// Size in pixels
m = server.arg("sz");
multiSz = m.toInt();
// Direction - no conversion
multiDr = server.arg("dr");
doRefresh = true;
makePage();
showPage();
}
// Get the current program number and display it.
void getNumber() {
server.send(200, "text/plain", String(lightProgram));
}
// Invalid request just redisplay the main page.
void handleNotFound() {
newPage();
}
// Initialize the fast led library
FastLED.addLeds<LED_TYPE, LED_PIN>(led, NUM_LEDS);
delay(2000);
//Initialize WiFi
WiFiManager wifiManager;
//reset settings
//wifiManager.resetSettings();
//set timeout until configuration portal gets turned off
//in seconds
wifiManager.setConfigPortalTimeout(300);
wifiManager.autoConnect("GetFrontDeckIP");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (! WiFi.localIP()) {
Serial.println("Continuing without IP");
}
delay(1000);
// Display the last octet of the IP address
Serial.println("IPs");
Serial.println(WiFi.localIP()[3]);
int ipl = WiFi.localIP()[3];
int offOn[] = {0x00ff00, 0xff0000};
for (int i = 0; i < 8; i++) {
led[i] = offOn[ipl % 2];
ipl = ipl >> 1;
}
// Mark the high order bit, show the bits and wait 10
seconds.
led[8] = 0xffffff;
FastLED.show();
delay(10000);
Serial.println("Before first server on");
// Set up the responders for the possible web requests.
// If no command just serve the program select web
page. checkCreds will call the build web page
server.on("/", newPage);
// is a command get the query and set light program to
display
server.on("/program", execQuery);
// Get and display the current light program number.
server.on("/getNumber", getNumber);
// get request for colour
server.on("/get", getColour);
// get info for multi colour
server.on("/get1", getMulti);
// 404
server.onNotFound(handleNotFound);
Serial.println("After last server.on");
// Set up the button interrupt
//pinMode(selectButton, INPUT);
// Setup and enable interrupts.
//attachInterrupt(digitalPinToInterrupt(selectButton),
buttonISR, FALLING);
//sei();
// Clear the random times to 0
for (int i = 0; i < NUM_LEDS; i++) {
loopTime[i] = 0;
}
// Set all the leds to off for one second.
for (int i = 0; i < NUM_LEDS; i++) {
led[i] = CRGB(0, 0, 0);
}
FastLED.show();
delay(1000);
Serial.println("Before server.begin");
// Start the web server
server.begin();
Serial.println("After server.begin");
}
// ***************************************************
void loop() {
// Look for and handle a web request.
//Serial.println("before server.handle Client");
server.handleClient();
//Serial.println("After server.handle Client");
// Find the light program to execute.
// --------------------------
// Chasing primaries
if (lightProgram == 0) {
for (int i = 0; i < NUM_LEDS; i++) {
led[i] = CRGB(colour[i % 3],
colour[(i + 1) % 3], colour[(i + 2) % 3]);
}
dirty = true;
byte s = colour[0];
for (int i = 0 ; i < 3; i++) {
colour[i] = colour[i + 1];
}
colour[2] = s;
delay(200);
delay(200);
// --------------------------
// Random colours and times
} else if (lightProgram == 1) {
currentTime = millis();
for (int i = 0; i < NUM_LEDS; i++) {
if (currentTime >=
loopTime[i]) {
loopTime[i] =
currentTime + random(900, 2000);
byte red = random(0,
256);
byte green =
random(0, 256);
byte blue = random(0,
256);
led[i] = CRGB(red,
green, blue);
dirty = true;
}
}
// --------------------------
// Web safe
} else if (lightProgram == 2) {
currentTime = millis();
for (int i = 0; i < NUM_LEDS; i++) {
if (currentTime >=
loopTime[i]) {
loopTime[i] =
currentTime + random(900, 2000);
byte red = random(0,
5) * webSafe;
byte green =
random(0, 5) * webSafe;
byte blue = random(0,
5) * webSafe;
led[i] = CRGB(red,
green, blue);
dirty = true;
}
}
// --------------------------
// Chasing increasing colour
} else if (lightProgram == 3) {
for ( int i = 0; i < NUM_LEDS; i++) {
led[i] = CRGB(0, 0, 0);
}
cred += 3;
cgreen += 5;
cblue += 7;
int i = 0;
int k = 0;
while (i <= NUM_LEDS - 1) {
led[i++] = rainbow[k++];
if (k > 6) {
k = 0;
}
}
int t = rainbow[6];
for (int i = 6; i > 0; i--) {
rainbow[i] = rainbow[i - 1];
}
rainbow[0] = t;
dirty = true;
delay(500);
delay(500);
// Moving
// --------------------------
} else if (lightProgram == 9) {
if (colourVal == 0) {
led[dot] = CRGB(rainbow[rc]);
} else {
led[dot] = CRGB(colourVal);
}
FastLED.show();
// clear this led for the next time around
the loop
led[dot++] = CRGB(0x000000);
if (dot >= NUM_LEDS) {
dot = 0;
if (rc++ >= 7) {
rc = 0;
}
}
delay(50);
// Set to colourVal
// ---------------------
} else if (lightProgram == 10) {
if (doRefresh) {
Serial.println(colourVal);
for ( int i = 0; i < NUM_LEDS;
i++) {
led[i] =
CRGB(colourVal);
}
doRefresh = false;
dirty = true;
}
// Christmas
// ----------
} else if (lightProgram == 11) {
if (doRefresh) {
int i = 1;
int nr = random(0, 7);
int r = nr;
led[0] = rainbow[nr];
while (i <= NUM_LEDS - 1) {
while (nr == r) {
nr =
random(0, 7);
}
r = nr;
led[i++] =
rainbow[nr];
}
dirty = true;
doRefresh = false;
}
// Rainbow Group
// --------------------------
} else if (lightProgram == 12) {
int i = 0;
int j = 0;
int k = 0;
// Create the group led array only once.
if (doRefresh) {
doRefresh = false;
while (i <= NUM_LEDS - 1) {
while (j <= 7) {
led[i++] = rainbow[k];
if (i
>= NUM_LEDS) {
break;
}
j++;
}
j = 0;
k++;
if (k > 6) {
k = 0;
}
}
}
// Rotate the array right by 1
CRGB t;
t = led[NUM_LEDS - 1];
memmove8( &led[1], &led[0], (NUM_LEDS
- 1) * sizeof( CRGB) );
led[0] = t;
dirty = true;
delay(20);
// Multi Group
// --------------------------
} else if (lightProgram == 13) {
int i = 0; // led count
int j = 0; // group count
int k = 0; // colour count
int a[] = {multiC1, multiC2};
// Create the group led array if time to
refresh.
if (doRefresh) {
doRefresh = false;
while (i < NUM_LEDS) {
while (j <
multiSz) {
led[i++] = a[k];
if (i
>= NUM_LEDS) {
break;
}
j++;
}
j = 0;
k++;
if (k >= 2) {
k = 0;
}
}
}
// Rotate the array by 1 or not.
// dest, source
CRGB t;
if (multiDr == ">") {
t = led[NUM_LEDS - 1];
memmove8(&led[1],
&led[0], (NUM_LEDS - 1) * sizeof(CRGB));
led[0] = t;
dirty = true;
} else if (multiDr == "<") {
t = led[0];
memmove8(&led[0],
&led[1], (NUM_LEDS - 1) * sizeof(CRGB));
led[NUM_LEDS - 1] = t;
dirty = true;
}
delay(multiSp);
}
// Refresh the leds if anything has changed
if (dirty) {
FastLED.show();
dirty = false;
}
// Delay to allow the web pages to work.
delay(1);
}
Node
Red and collection.
back deck
Status Displays.
Each one of the following displays is fed by an ESP8266 with
different types of sensors. Pond
The pond has 2 DS18B20 temperature sensors and a flow sensor on the
make up water. There is an independent level sensor (float
switch) that adds
water if the level drops. The flow sensor ensures that it can
only add a
specified amount in a period of time as sometimes the flow switch
sticks.
Green House
The on off times are watering intervals. There is no closed
loop control. The watering
intervals are set manually.
Kiln
Again no closed loop control. The fall alarm will warn us if
the temperature starts
falling. This will happen if the cone sitter trips and
sometimes it trips sooner than
we would like. Then it can be overridden.
House
The temperature by the thermostat. Some day I will replace the
thermostat.
esp32cam camera
A picture of me -
thinking
Also thinking
My
messy
office
The kiln. It's not on fire inside about 1000C