ESP8266: Ein WLAN-Mikroprozessor für unglaubliche 3 Euro

gabbercopter

Commander
Registriert
Dez. 2014
Beiträge
2.693
Gerade diesen Artikel hier enddeckt :

Klick

(quelle http://t3n.de/ )


schaut doch ganz intressant aus ? ich selbst habe keinen einplatinen computer und brauche auch keinen , habe aber des öfteren am rande mal mit bekommen das dass fehlende wlan immer ein großer diskussionspunkt war... was sagt ihr dazu ?
 
Hab ich seit 9 Monaten im Einsatz. Die Dinger sind klasse. Kommt auch bald nen Nachfolger.
 
Sephe schrieb:


könntest ja vielleicht mal ein paar sätze zum einsatzgebiet nennen und zur allgemeinen erfahrung ? wird sicher den ein oder anderen intressieren
 
Habe den ESP8266 derzeit einen als Temperaturlogger für Luft, einen für das Poolwasser+Wasserfüllstandssensor in unserem Ferienhaus im Einsatz.

Ein weiterer steuert ein Magnetventil, so dass ein zu niedriger Wasserstand im Pool automatisch nachts wieder befüllt wird.

Die Temperaturwerte werden auch direkt auf der Homepage angezeigt.

(Falls "Werbung" erlaubt ist:
https://www.villacalsides.eu/temperaturverlauf/

Und die Rohwerte:
https://www.villacalsides.eu/temperatur/
)

Habe allerdings die ESP8266 nicht direkt programmiert, sondern laufen im AT-Modus und werden von einem Atmega mit Daten versorgt. (Hatte nicht soviel Zeit mich in die ESP8266 komplett einzulesen, daher noch mit dem Atmega)

Die nächste Version kommt aber ohne Zusatzchip aus.
 
Ich hab sowas ähnliches am Laufen direkt auf dem ESP8266 - Logging von Temperatur und Luftfeuchtigkeit.

Was mich interessieren würde, ist deine Messdatenverarbeitung. Speicherst du alle Werte auf dem ESP8266, läuft die Website darüber, wie machst du die Datenberechnung MIN/MAX?
 
Kanibal schrieb:
Ich hab sowas ähnliches am Laufen direkt auf dem ESP8266 - Logging von Temperatur und Luftfeuchtigkeit.

Was mich interessieren würde, ist deine Messdatenverarbeitung. Speicherst du alle Werte auf dem ESP8266, läuft die Website darüber, wie machst du die Datenberechnung MIN/MAX?

Die Teile sind dumm.

Ich habe nen lokalen Webserver mit php und mariadb, der die messwerte per GET entgegen nimmt, in der mariadb speichert, und dann alle 2 Minuten an den Webserver von villacalsides.eu schickt per https.

Dort ist auch die Berechnung mit min/max.
 
Ich hab es direkt auf dem ESP8266 implementiert, samt Webserver (mit Arduino Bootloader auf dem ESP8266).

Code:
#include <Adafruit_HTU21DF.h>

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Wire.h>

#include "NTPClient.h"

#include "data/root.html.h"

const char* ssid = "...";
const char* password = "...";

const char* alternative_ssid = "...";
const char* alternative_password = "...";

float averageTemperature;
float averageHumidity;

ESP8266WebServer server(80);
Adafruit_HTU21DF htu = Adafruit_HTU21DF();

NTPClient ntpclient("pool.ntp.org", 1);
unsigned long unixTime;

unsigned long previousMillisSensor = 0;
unsigned long previousMillisHistoryShort = 0;
unsigned long previousMillisHistoryLong = 0;

const long intervalSensor = 200;
const long intervalHistoryShort = 1000 * 5;
const long intervalHistoryLong = 1000 * 60 * 1;

typedef struct {
  float temperature;
  float humidity;
  uint32_t timestamp;
} SHT21_DataPoint;

#define HISTORY_SHORT_SIZE (5 * 60 * 1000) / intervalHistoryShort // 5 minutes * (1 sample / 5 second) 
#define HISTORY_LONG_SIZE (1 * 24 * 60 * 60 * 1000) / intervalHistoryLong // 1 days * (1 sample / 1 minutes) 

typedef struct {
  SHT21_DataPoint *values; 
  size_t current;
  size_t count;
  size_t capacity;
} history_t;

SHT21_DataPoint bufferShort[HISTORY_SHORT_SIZE];
SHT21_DataPoint bufferLong[HISTORY_LONG_SIZE];

history_t historyShort = {.values = bufferShort, .current = 0, .count = 0, .capacity = HISTORY_SHORT_SIZE};
history_t historyLong = {.values = bufferLong, .current = 0, .count = 0, .capacity = HISTORY_LONG_SIZE};

inline int min(int a, int b) { return ((a)<(b) ? (a) : (b)); }

void historyInit(history_t *history) {
  memset(history->values, 0, history->capacity * sizeof(SHT21_DataPoint));
}

SHT21_DataPoint* historyShift(history_t *history) {
  SHT21_DataPoint *next = &history->values[history->current];
  if(history->count < history->capacity) {
    history->count++;
  }
  history->current = (history->current + 1) % history->capacity;
  return next;
}

SHT21_DataPoint* historyPrev(history_t *history, size_t num) {
  size_t index = (history->current - 1 - num + history->capacity) % history->capacity;
  return &history->values[index];
}

void readSensor();

void sendHistoryShort() {
  String message = "var timeSeries = [";
  for(size_t i = 0; i < min(historyShort.count, 36); i++) {
    SHT21_DataPoint *cur = historyPrev(&historyShort, i);
    message += (i != 0)?",{temperature:":"{temperature:";
    message += cur->temperature;
    message += ",humidity:";
    message += cur->humidity;
    message += ",timestamp:";
    message += cur->timestamp;
    message += "}";
  }
  message += "];";
  server.send(200, "text/javascript", message);
}

void sendHistoryLong() {
  String message = "var timeSeries = [";
  for(size_t i = 0; i < min(historyLong.count, 30); i++) {
    SHT21_DataPoint *cur = historyPrev(&historyLong, i);
    message += (i != 0)?",{temperature:":"{temperature:";
    message += cur->temperature;
    message += ",humidity:";
    message += cur->humidity;
    message += ",timestamp:";
    message += cur->timestamp;
    message += "}";
  }
  message += "];";
  server.send(200, "text/javascript", message);
}

void handleRoot() {
  server.send(200, "text/html", index_html);
}

void setup(void) {
  Serial.begin(115200);
  Wire.pins(0, 2); //on ESP-01.
  WiFi.begin(ssid, password);

  // Wait for connection
  Serial.print("Starting WIFI module");
  unsigned short numTries = 20;
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if(numTries-- <= 0) {
      const char* tmp_ssid = ssid;
      const char* tmp_password = password;
      ssid = alternative_ssid;
      password = alternative_password;
      alternative_ssid = tmp_ssid;
      alternative_password = tmp_password;
      numTries = 20;
      WiFi.begin(ssid, password);
    }
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS responder started");
  }

  if (htu.begin()) {
    Serial.println("Sensor ready");
    averageTemperature = htu.readTemperature();
    averageHumidity = htu.readHumidity();

    historyInit(&historyShort);
    historyInit(&historyLong);
  }

  Serial.print("Request NTP time: ");
  ntpclient.begin();
  unixTime = ntpclient.getRawTime();
  Serial.println(unixTime);

  server.on("/", handleRoot);
  server.on("/history/short.js", sendHistoryShort);
  server.on("/history/long.js", sendHistoryLong);

  server.begin();
  Serial.println("HTTP server started");
}

void loop(void) {
  unsigned long currentMillis = millis();

  // periodic sensor read
  if (currentMillis - previousMillisSensor >= intervalSensor) {
    previousMillisSensor = currentMillis;
    readSensor();
  }

  // short term history
  currentMillis = millis();
  if (currentMillis - previousMillisHistoryShort >= intervalHistoryShort) {
    previousMillisHistoryShort = currentMillis;

    SHT21_DataPoint *sample = historyShift(&historyShort);
    sample->temperature = averageTemperature;
    sample->humidity = averageHumidity;
    // TODO: sample timestamp as unixtime
    sample->timestamp = unixTime + currentMillis / 1000;
  }

  // long term history
  currentMillis = millis();
  if (currentMillis - previousMillisHistoryLong >= intervalHistoryLong) {
    previousMillisHistoryLong = currentMillis;

    SHT21_DataPoint *sample = historyShift(&historyLong);
    const size_t num_samples = min((intervalHistoryLong / intervalHistoryShort), historyShort.count);
    for(int i = 0; i < num_samples; i++) {
      SHT21_DataPoint *cur = historyPrev(&historyShort, i);
      sample->temperature += cur->temperature;
      sample->humidity += cur->humidity;
    }
    sample->temperature /= num_samples;
    sample->humidity /= num_samples;
    // TODO: sample timestamp as unixtime
    sample->timestamp = unixTime + currentMillis / 1000;
  }

  // client requests
  server.handleClient();
}

void readSensor(void) {
  const float alpha = 0.3;
  averageTemperature = alpha * htu.readTemperature() + (1 - alpha) * averageTemperature;
  averageHumidity = alpha * htu.readHumidity() + (1 - alpha) * averageHumidity;
}

root.html.h
Code:
#pragma once

const char index_html[] PROGMEM = R"=====(
	<head>
	  <!-- Plotly.js -->
	  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
	  <!-- lodash -->
	  <script src="https://cdn.jsdelivr.net/lodash/latest/lodash.min.js"></script>
	  <!-- momentjs -->
	  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.11.2/moment.min.js"></script>
	  <!-- Dataset -->
	  <script src="/history/short.js"></script>
	</head>

	<body>
	  
	  <div id="myDiv" style="width: 480px; height: 400px;"><!-- Plotly chart will be drawn inside this DIV --></div>
	  <script>
		var data = [
		  {
			x: _.map(timeSeries, sample => moment.unix(sample.timestamp).format('YYYY-MM-DD h:mm:ss')),
			y: _.map(timeSeries, sample => sample.temperature),
			type: 'scatter',
			name: 'Temperature',
			showlegend: false
		  },
		  {
			x: _.map(timeSeries, sample => moment.unix(sample.timestamp).format('YYYY-MM-DD h:mm:ss')),
			y: _.map(timeSeries, sample => sample.humidity),
			type: 'scatter',
			name: 'Humidity',
			yaxis: 'y2',
			showlegend: false
		  }
		];
		var layout = {
			title: 'ESP8266 sensor data',
			yaxis: {
				title: 'Temperature',
				titlefont: {
					color: 'rgb(31, 119, 180)'
				},
				tickfont: {
					color: 'rgb(31, 119, 180)'
				}
			},
			yaxis2: {
				title: 'Humidity',
				titlefont: {
					color: 'rgb(255, 127, 14)'
				},
				tickfont: {
					color: 'rgb(255, 127, 14)'
				},
				overlaying: 'y',
				side: 'right'
			}
		};

		Plotly.newPlot('myDiv', data, layout);
	  </script>
	</body>
)=====";
 
Da ich auch bereits ein paar dieser Teile rumfliegen habe, aber bisher noch nicht zur Umsetzung gekommen bin werde ich bei dem Thema natürlich auch gleich hellhörig :)

@Kannibal:
Gibt es die inkludierten Header irgendwo zum Download oder hast du die selbst geschrieben? Schließlich müsste man ja irgendwie das HTTP-Protokoll implementieren. Bisher war mein Plan die benötigten Teile davon einfach selbst zu coden, aber wenn es da bereits etwas fertiges gibt wäre das natürlich wesentlich einfacher :)
 
Könnte man mit dem Ding einen günstigen WLAN-Bewegungssensor bauen? Gibt es dafür passende PIR-Sensoren zu kaufen?
Ergänzung ()

Habe zu dem Thema gerade einen englischen Artikel gefunden. Erster Treffer bei google, steht nicht auf der Whitelist und darf hier nicht verlinkt werden.

Ziemlich cool. Das ganze noch Batteriebetrieben wäre genau das, was ich gesucht habe. Die Gesamtkosten für so ein Projekt würden mich interessieren. Ob man am Ende wirklich noch günster als z.B. Homematic-Bewegungsmelder kommt.
 
Zuletzt bearbeitet:
Zurück
Oben