Moin,
in Anlehung an die "Raumgerät Light"-Variante von Andreas29 (https://forum.fhem.de/index.php/topic,91867.0.html (https://forum.fhem.de/index.php/topic,91867.0.html)) habe ich mir eine Lösung geschaffen, die mit dem BSB-LAN Adapter (https://forum.fhem.de/index.php/topic,29762.0.html) via UDP kommuniziert.
Grundlage ist ein Arduino Uno mit Ethernet Shield, einem 20x4 LCD sowie einem Taster als Präsenztaste.
Aus dem Arduino läuft einen eigenständiger Code; beim BSB-LAN Adapter müssen die "Custom"-Dateien entsprechend erweitert werden.
Code und Fotos stelle ich nachfolgend ein.
Gruß
Fabian
Display mit Standard-Ausgabe
Code RGLU.ino, v0.01
//RaumGerät Light UDP v0.01
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <LiquidCrystal_I2C.h>
//IP adress and port of RG
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 42);
unsigned int port = 28001;
//IP adress and UDP port of BSB-LAN adapter
IPAddress RxIP(192, 168, 0, 88);
unsigned int RxUDPport = 28000;
const int udp_buff_size = 16;
char RxBuffer[udp_buff_size];
unsigned long t_act, t_old;
int maxtry = 5; //maximum tries for connection etc. with BSB-LAN
struct pv_Rx {
int par;
int val;
};
struct pv_RG {
double OT; //outside temperature
double RT; //room temperature
double WT; //water temperature
double RT_t; //room temperature, target
double RT_c; //room temperature, comfort
double RT_r; //room temperature, reduced
boolean presence_state;
boolean presence_error;
boolean water_state;
boolean burner_state;
};
struct pv_RG dat;
struct pv_Rx pv;
unsigned int sep_pos = 5;
unsigned int TM_size = 16;
char ps[5];
char vs[10];
boolean presence_button_pressed;
boolean button_pres_stat_act;
boolean button_pres_stat_old;
boolean isconnected;
boolean wait;
EthernetUDP Udp;
LiquidCrystal_I2C LCD(39, 20,4);
byte degree[8] = {B01110, B01010, B01110, B00000, B00000, B00000, B00000, B00000};
byte sun[8] = {0b00100, 0b10101, 0b01110, 0b11011, 0b01110, 0b10101, 0b00100, 0b00000};
byte moon[8] = {0b00111, 0b01110, 0b11100, 0b11100, 0b11100, 0b01110, 0b00111, 0b00000};
byte snow[8] = {0b01010, 0b00100, 0b10101, 0b01110, 0b10101, 0b00100, 0b01010, 0b00000};
byte flame[8] = {0b00010, 0b00100, 0b01100, 0b01110, 0b01010, 0b01010, 0b00100, 0b11011};
byte water[8] = {0b00000, 0b01110, 0b00101, 0b11111, 0b10001, 0b10000, 0b00000, 0b00000};
void requestBC() {
//sprintf(TxBuffer, "%.7s", "REQBC@1");
Udp.beginPacket(RxIP, RxUDPport);
//Udp.print(TxBuffer);
Udp.print("REQBC@0000000001");
Udp.endPacket();
}
void RxUDP() {
int RxPacket = Udp.parsePacket();
if(RxPacket) {
Udp.read(RxBuffer, udp_buff_size);
isconnected = true;
}
}
//determine presence state
void determine_presence_state() {
if (dat.RT_t == dat.RT_c) {
dat.presence_state = true;
dat.presence_error = false;
}
if (dat.RT_t == dat.RT_r) {
dat.presence_state = false;
dat.presence_error = false;
}
if (dat.RT_t != dat.RT_c && dat.RT_t != dat.RT_r)
dat.presence_error = true;
}
void get_button_state() {
button_pres_stat_act = digitalRead(8);
//Pin uses PULL UP resistance -> "not pressed" means HIGH
if (button_pres_stat_act && button_pres_stat_old) { //not pressed and not pressed before
presence_button_pressed = false; //do not detect as pressed
}
if (!button_pres_stat_act && !button_pres_stat_old) { //pressed and pressed before
presence_button_pressed = false; //do not detect as pressed
}
if (button_pres_stat_act && !button_pres_stat_old) { //not pressed and pressed before
presence_button_pressed = false; //do not detect as pressed
}
if (!button_pres_stat_act && button_pres_stat_old) { //pressed and not pressed before
presence_button_pressed = true; //detect as pressed
delay(100); //debounce
}
button_pres_stat_old = button_pres_stat_act;
}
struct pv_Rx GetParamVal() {
//all TM has to be:
//[5 character]@[10 character]
//5 character = parameter number acc. to RVS43.122, 0 at LSB if needed
//@ = separator
//10 character = value
char ps[5];
char vs[10];
int i, j;
struct pv_Rx pv;
pv.par = 0;
pv.val = 0;
//get parameter
j=0;
for(i=0;i<sep_pos; i++){
ps[j] = RxBuffer[i];
j++;
}
pv.par = atoi(ps);
//get value
j=0;
for(i=sep_pos+1;i<TM_size; i++){
vs[j] = RxBuffer[i];
j++;
}
vs[j]='\0'; //I don't know why this is necessary, maybe some char/pointer thing...
pv.val = atoi(vs);
return pv;
}
void EvalParamVal() {
pv = GetParamVal();
if (pv.par > 0) {
Serial.print(pv.par);
Serial.print("@");
Serial.println(pv.val);
}
if (pv.par == 8700) //outside temperature
dat.OT = 0.1 * pv.val;
if (pv.par == 8740) //room temperature
dat.RT = 0.1 * pv.val;
if (pv.par == 8830) //water temperature
dat.WT = 0.1 * pv.val;
if (pv.par == 8741) //room temperature, target
dat.RT_t = 0.1 * pv.val;
if (pv.par == 710) //room temperature, comfort
dat.RT_c = 0.1 * pv.val;
if (pv.par == 712) //room temperature, reduced
dat.RT_r = 0.1 * pv.val;
if (pv.par == 8300) {//burner state
//evaluate burner state
if (pv.val == 1)
dat.burner_state = true;
else
dat.burner_state = false;
}
if (pv.par == 8003) {//water heating state
//evaluate TWW state
if (pv.val == 69 || (pv.val >= 92 && pv.val <= 97))
dat.water_state = true;
else
dat.water_state = false;
}
}
void UpdateLCD(){
LCD.setCursor(0,0);
LCD.print("Au\xE2");
LCD.print("entemp: ");
LCD.print(dat.OT);
LCD.setCursor(15,0);
LCD.print(char(0));
LCD.print("C");
LCD.setCursor(0,1);
LCD.print("Raumtemp : ");
LCD.print(dat.RT);
LCD.setCursor(15,1);
LCD.print(char(0));
LCD.print("C");
LCD.setCursor(0,2);
LCD.print("TWW Temp : ");
LCD.print(dat.WT);
LCD.setCursor(15,2);
LCD.print(char(0));
LCD.print("C");
//presence state
if (dat.presence_state) {
LCD.setCursor(19,0);
LCD.print(char(1)); //sun enable
LCD.setCursor(19,1);
LCD.print(" "); //moon disable
}
else {
LCD.setCursor(19,0);
LCD.print(" "); //sun disable
LCD.setCursor(19,1);
LCD.print(char(2)); //moon enable
}
//presence error
if (dat.presence_error) {
LCD.setCursor(19,0);
LCD.print("#"); //sun disable
LCD.setCursor(19,1);
LCD.print("#"); //moon disable
}
//burner state
LCD.setCursor(19,3);
if (dat.burner_state)
LCD.print(char(4)); //flame enable
else
LCD.print(" "); //flame disable
//water state
LCD.setCursor(19,2);
if (dat.water_state)
LCD.print(char(5)); //water enable
else
LCD.print(" "); //water disable
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(8, INPUT_PULLUP);
presence_button_pressed = false;
button_pres_stat_act = true;
button_pres_stat_old = true;
isconnected = false;
int i;
Ethernet.begin(mac,ip);
delay(500);
Udp.begin(port);
delay(500);
Serial.begin(115200);
delay(500);
LCD.init();
LCD.clear();
LCD.backlight();
LCD.createChar(0, degree);
LCD.createChar(1, sun);
LCD.createChar(2, moon);
LCD.createChar(3, snow);
LCD.createChar(4, flame);
LCD.createChar(5, water);
LCD.setCursor(0,0);
LCD.print("Connecting...");
delay(500);
for (i=0; i<=maxtry; i++) {
//request first BC to check connection
requestBC();
delay(1000);
RxUDP(); //sets "isconnected" to true if UDP packet received
Serial.println(i);
if (isconnected)
break;
}
//determine_presence_state();
LCD.setCursor(0,0);
if (!isconnected) {
LCD.print("Connection failed! ");
LCD.setCursor(0,3);
LCD.print("Error #503");
delay(2000);
}
else {
LCD.print("Connected! ");
delay(2000);
}
LCD.clear();
UpdateLCD();
t_old=millis();
}
void loop() {
int i;
//check for new UDP packets
RxUDP();
//evaluate what has been received
EvalParamVal();
//determine presence state based on room target temperature
determine_presence_state();
//check if presence button ("Präsenztaste") was pressed on RG
get_button_state();
if (presence_button_pressed) {
double RT_t_old = dat.RT_t;
LCD.setCursor(0,3);
LCD.print("Bitte warten...");
//transmit request to BSB_LAN for change of presence_state
Udp.beginPacket(RxIP, RxUDPport);
Udp.print("!PRES@0000000001");
Udp.endPacket();
wait = true;
for (i=0; i<=maxtry; i++) {
if (RT_t_old == dat.RT_t) {//if no change
//wait for RT_t to be updated
RxUDP(); //sets "isconnected" to true if UDP packet received
EvalParamVal();
delay(2000);
}
else {
wait = false;
LCD.setCursor(0,3);
LCD.print(" ");
break;
}
//Serial.println(i);
}
//invert presence state
if (!wait) {//target room teperature was changed by heating before max try was reached
dat.presence_state = !dat.presence_state;
//update LCD
LCD.clear();
LCD.setCursor(0,0);
if (dat.presence_state && !dat.presence_error) {
LCD.print("Pr\xE1");
LCD.print("senz: EIN");
LCD.setCursor(0,1);
LCD.print("Heizen auf");
LCD.setCursor(0,2);
LCD.print("Komfortsollwert");
}
if (!dat.presence_state && !dat.presence_error) {
LCD.print("Pr\xE1");
LCD.print("senz: AUS");
LCD.setCursor(0,1);
LCD.print("Heizen auf");
LCD.setCursor(0,2);
LCD.print("Reduziersollwert");
}
delay(2000);
//RxUDP(); //check for new values to make sure presence was really changed
//determine_presence_state(); //update presence state
LCD.clear();
UpdateLCD(); //show new presence state
}
else { //no answer received in time from BSB-LAN
LCD.setCursor(0,3);
LCD.print("Error #503 ");
delay(2000);
LCD.setCursor(0,3);
LCD.print(" ");
}
}
t_act = millis();
if (t_act - t_old > 5000) {
UpdateLCD();
t_old = t_act;
}
//reset Rx buffer
sprintf(RxBuffer, "%d", 0);
}
Code BSB_lan_custom.h
//RGLU, custom code for loop function
//for RGLU v0.01
//check for new UDP packets
RxUDP();
//presence state changed in RG
if (!strcmp(RxBuffer, "!PRES@0000000001")) {
Serial.println("Request to change presence status");
pv.RT_t = (int)(atof(query(8741,8741,0))*10);
pv.RT_c = (int)(atof(query(710,710,0))*10);
pv.RT_r = (int)(atof(query(712,712,0))*10);
if (pv.RT_t == pv.RT_c) { //if currently in comfort mode
Serial.println("Currently, RT_t = comfort, change to reduced / 'not present'");
set(701, "1", 1); //set heating to "reduced"
}
if (pv.RT_t == pv.RT_r) { //if currently in reduced mode
Serial.println("Currently, RT_t = reduced, change to comfort / 'present'");
set(701, "0", 1); //set heating to "comfort"
}
//delay (1);
//send new room target temperature
pv.RT_t = (int)(atof(query(8741,8741,0))*10);
//Serial.print("RT_t set to :");
//Serial.println(pv.RT_t);
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 8741, pv.RT_t);
Udp.print(TxBuffer);
Udp.endPacket();
}
//broadcast request by RG
if (!strcmp(RxBuffer, "REQBC@0000000001")) {
Serial.println("BC request ... send BC data");
pv.RT_t = (int)(atof(query(8741,8741,0))*10);
pv.RT_c = (int)(atof(query(710,710,0))*10);
pv.RT_r = (int)(atof(query(712,712,0))*10);
pv.OT = (int)(atof(query(8700,8700,0))*10);
pv.RT = (int)(atof(query(8740,8740,0))*10);
pv.WT = (int)(atof(query(8830,8830,0))*10);
pv.water_state = (atoi)(query(8003,8003,0));
pv.burner_state = (atoi)(query(8300,8300,0));
Serial.println(pv.OT);
//send broadcast
TxBC();
}
//send BC data periodically every ~30 seconds
t_act = millis();
if (t_act - t_old > 30000) {
Serial.println("Send periodic BC data");
pv.RT_t = (int)(atof(query(8741,8741,0))*10);
pv.RT_c = (int)(atof(query(710,710,0))*10);
pv.RT_r = (int)(atof(query(712,712,0))*10);
pv.OT = (int)(atof(query(8700,8700,0))*10);
pv.RT = (int)(atof(query(8740,8740,0))*10);
pv.WT = (int)(atof(query(8830,8830,0))*10);
pv.water_state = (atoi)(query(8003,8003,0));
pv.burner_state = (atoi)(query(8300,8300,0));
//send broadcast
TxBC();
t_old = t_act;
}
//reset Rx buffer
sprintf(RxBuffer, "%d", 0);
Code BSB_lan_custom_global.h
//RGLU, custom code for global section
//for RGLU v0.01
#include <stdlib.h>
//UDP port of BSB-LAN
unsigned int UDPportBSB = 28000;
//IP adress and port of RG
IPAddress RxIP(192, 168, 0, 42);
unsigned int RxPort = 28001;
const int udp_buff_size = 16;
char RxBuffer[udp_buff_size];
char TxBuffer[udp_buff_size];
unsigned long t_act, t_old;
struct pv_BSB {
int OT; //outside temperature
int RT; //room temperature
int WT; //water temperature
int RT_t; //room temperature, target
int RT_c; //room temperature, comfort
int RT_r; //room temperature, reduced
int water_state;
int burner_state;
};
struct pv_BSB pv;
EthernetUDP Udp;
void RxUDP() //read UDP packet
{
int RxPacket = Udp.parsePacket();
if(RxPacket) {
Udp.read(RxBuffer, udp_buff_size);
Serial.print("RxUDP: ");
Serial.println(RxBuffer);
}
}
void TxBC(){
Serial.println("Send UDP data: ");
//send outside temperature
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 8700, pv.OT);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
//send room temperature
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 8740, pv.RT);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
//send water temperature
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 8830, pv.WT);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
//send burner status
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 8300, pv.burner_state);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
//send water status
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 8003, pv.water_state);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
//send room target temperature
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 8741, pv.RT_t);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
//send room comfort temperature
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 710, pv.RT_c);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
//send room reduced temperature
Udp.beginPacket(RxIP, RxPort);
sprintf(TxBuffer, "%.5i@%.10i", 712, pv.RT_r);
Serial.println(TxBuffer);
Udp.print(TxBuffer);
Udp.endPacket();
delay(100);
}
Code BSB_lan_custom_setup.h
//RGLU, custom code for setup function
//for RGLU v0.01
Udp.begin(UDPportBSB);
t_old=millis(); //counter for periodic broadcast
Moin Fabian,
wärst du damit einverstanden, wenn ich das mit als 'Bastel'-Beispiel ins BSB-LAN-Handbuch aufnehme?
Gruß
Gerne.
Super, danke :)
@fabulous
Jetzt fehlt nur noch die ESP-Variante ;)
Schönen Sonntag
Gerd
Moin,
hier noch ein paar erläuternde Worte:
Auf beiden Arduinos (BSB-LAN Adapter und RGLU) läuft ein UDP-Service. Damit ist es möglich, UDP-Pakete sowohl zu versenden als auch zu empfangen. Der BSB-Lan Adapter verwendet dazu Port 28000, das RGLU verwendet Port 28001. Theoretisch sind auch andere Ports möglich; ich habe welche gewählt die durch keine von mir verwendete Software benutzt werden. Siehe auch: https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports#Registrierte_Ports:_1024%E2%80%9349151 (https://de.wikipedia.org/wiki/Liste_der_standardisierten_Ports#Registrierte_Ports:_1024%E2%80%9349151)
Der BSB-LAN Adapter sendet alle ca. 30 Sekunden ein Broadcast-Paket mit folgenden Parametern:
- RT_t = Parameter 8741; derzeitige Raumsolltemperatur
- RT_c = 710; Komforttemperatur
- RT_r = 712; Reduziertemperatur
- OT = 8700; Aussentemperatur
- RT = 8740; Raumtemperatur
- WT = 8830; Wassertemperatur
- water_state = 8003; Trinkwasserstatus
- burner_state = 8300; Brennerstufe 1 aktiv
Darüberhinaus reagiert der BSB-LAN Adapter auf einen Broadcast-Request (REQBC@0000000001) des RGLU sowie ein Drücken der Präsenztaste am RGLU (!PRES@0000000001).
Das RGLU prüft permanent auf empfangene UDP-Pakete und wertet diese aus. Nach der Auswertung werden die entsprechenden Infos auf dem LCD bereitgestellt. Aussentemperatur, Raumtemperatur und Wassertemperatur werden direkt angezeigt.
Der Trinkwasserstatus wird verwendet, um ein entsprechendes Symbol (Wasserhahn) anzuzeigen, wenn das Wasser gerade erwärmt wird.
"Brennerstufe 1" wird verwendet, um ein entsprechendes Symbol (Flamme) anzuzeigen, wenn der Brenner läuft.
Raumsolltemperatur, Komfortemperatur und Rediziertemperatur werden verwendet, um entsprechend das Symbol Sonne/Mond anzuzeigen.
Beim Drücken des Tasters (Präsenztaste) am RGLU wird eine UDP-Nachricht an den BSB-LAN Adapter gesendet. Dieser setzt per set(701, ...) die Heizung in den entsprechenden Modus. Anschließend wird die neue Solltemperatur (im Erfolgsfall wurde diese durch den set(701, ...) in der Heizung geändert) ans RGLU zurückgeschickt. Dort wird der neue Präsenzstatus bestimmt und entsprechend zurückgemeldet.
Es existiert nur eine minimale Fehlerbehandlung; alle Pakete verwenden den Aufbau "ppppp@vvvvvvvvvv"; also 5 Stellen für den Parameter, einen Separator (@) und 10 Stellen für den Wert.
Es werden nur Integerwerte verwendet; daher werden alle Temperaturen vor dem Senden mit dem Faktor 10 multipliziert und nach dem Empfang mit dem Faktor 0,1 multipliziert. Dadurch ist keine Verwendung von Double-Werten für die Übertragung bzw. Erkennung von Kommata etc. nötig.
Das Ganze soll noch in eine Box gepackt werden; diese soll an der Haustür platziert werden. Das Hauptaugemerk liegt in der Präsenztaste; ich habe zwar ein RGT, allerdings befindet sich das RGT im Referenzraum und dieser ist maximal weit von der Haustür entfernt. Es ist zwar möglich, ein zweites RGT zu verwenden; aber an diesem ist dann die Präsenzfunktion (soweit ich weiss) deaktiviert.
Gruß
Fabian
Zitat von: fabulous am 26 April 2020, 14:05:02
Der BSB-LAN Adapter sendet alle ca. 30 Sekunden ein Broadcast-Paket mit folgenden Parametern:
...
Darüberhinaus reagiert der BSB-LAN Adapter auf einen Broadcast-Request (REQBC@0000000001) des RGLU sowie ein Drücken der Präsenztaste am RGLU (!PRES@0000000001).
Das RGLU prüft permanent auf empfangene UDP-Pakete und wertet diese aus.
Vorweg: Ich habe nicht alles verstanden, aber das mit den Broadcasts finde ich prinzipiell interessant und wäre evtl auch für FHEM und andere HA-Systeme nützlich, oder?
Soweit ich weiß, kann BSB-LAN ja bisher keine eigenständigen Broadcasts versenden: https://1coderookie.github.io/BSB-LPB-LAN/kap15.html#1513-kann-bspw-fhem-auf-bestimmte-broadcasts-lauschen
Könntest du das vielleicht auch nochmal im eigentlichen BSB-LAN-Thread posten? Ich könnte mir vorstellen, dass das auch für @freetz und eine etwaige generelle Implementierung in BSB-LAN interessant sein könnte?!
Gruß
Moin,
@Schotty:
Kannst du etwas genauer erläutern, was das Ziel ist? Ich habe noch nicht mit FHEM gearbeitet.
Der Grund, warum ich UDP verwende, ist, dass es ein sehr einfaches Protokoll ist und sich der Sender nicht wirklich darum kümmert, was mit seinem gesendeten Paket passiert - sozusagen "fire and forget".
Ich habe den Begriff "Broadcast" verwendet, weil ich im Hinterkopf habe, noch ein zweites RGLU im Badezimmer zu installieren, allerdings mit einem "TWW Push"-Button - der BSB-LAN Adapter soll nicht übermäßig belastet werden und das Paket mit den ganzen Werten nur einmal an alle Empfänger gleichzeitig senden anstatt an jeden Empfänger separat. UDP beherrscht diesen "Broadcast" theoretisch. Ich habe es aber noch nicht umgesetzt. Es wird derzeit nur an einen einzigen Empfänger gesendet.
@Maista: was meinst du in diesem Zusammenhang mit "ESP"? Hilf mir mal auf die Sprünge ...
Gruß
Fabian
So wie ich es verstanden habe machst du im Grunde das, was auch der Heizungsregler selbst schon von Haus aus macht, nämlich bestimmte Werte/Parameter in bestimmten Intervallen einfach über den Bus schicken. Finde ich gut und ließe sich bestimmt gut nutzen, wenn man die Parameter entspr konfigurieren/definieren kann. Eine gute Lösung, um bspw nicht immer aktiv abfragen zu müssen (ob nun mit FHEM oder einer anderen HA-Lösung ist dabei ja gleichgültig) und wie du jetzt bspw ein Status-Display o.ä. damit zu basteln..
Ein bestimmtes 'Ziel hinsichtlich FHEM' habe ich da nicht im Sinn, mir ging's nur darum, dass eine solche 'broadcast'-Funktion noch nicht in BSB-LAN implementiert ist. Also bisher kann/muss man entweder aktiv pollen oder via MQTT schicken lassen.
Maista meinte mit ESP sicherlich, dass er (und bestimmt auch andere ;) ) sich diesen Code lauffähig für ESP-basierte Plattformen (Wemos D1, nodeMCU etc) wünscht, so dass man eben anstelle eines Uno+LAN-Shield einfach irgendwo im Haus eine WLAN-basierte Lösung einsetzen könnte. Hätte wirklich was.. ;)
Moin,
ich verstehe.
Wenn das Zielsystem UDP-fähig ist, könnte meine Lösung entsprechend angepasst werden.
Gruß
Fabian
Moin,
begzl. ESP: meint ihr sowas hier?
https://www.amazon.de/AZDelivery-NodeMCU-ESP8266-ESP-12E-unverlötet/dp/B07GYW4T5F/ref=pd_aw_sbs_23_3/260-9062909-7202766 (https://www.amazon.de/AZDelivery-NodeMCU-ESP8266-ESP-12E-unverl%C3%B6tet/dp/B07GYW4T5F/ref=pd_aw_sbs_23_3/260-9062909-7202766)
Gruß
Fabian
Yupp,zum beispiel,andere varianten mit micro-usb-port (weils praktisch ist ;) ) wären bspw auch 'wemos d1 mini' (gibts u.a. auch als 'pro' mit optionaler externer antenne)). Is nochmal etwas kleiner als ein nodemcu, aber bietet im grunde gleich viel.
Allen gemein ist,dass darauf ein esp8266 verbaut ist. Ist quasi der wlan-chip mit leistungsfähigem mikrocontroller. Den gibts zwar auch einzeln,is aber m.m.n. nich so praktisch benutzbar (bzgl flashen,strom etc). Die dinger sind mittlerweile in unzähligen komponenten verbaut,bspw sonoff, lampen mit wlan- anbindung und wat nich noch alles..
Haben mehr ram,flash,power etc als jeder arduino.
Werden gerne eingesetzt,wo eine relativ unkomplizierte komponentenanbindung via wlan gewünscht ist. Für nicht-programmierer mit bspw tasmota, espeasy, espurna, esphome auch relativ unkompliziert zu konfigurieren. Für programmierer aber natürlich auch mit arduino-ide o.ä. programmierbar.
Der nachfolger vom esp8266 ist der esp32, hat mehr speicher,power,bluetooth an board und noch etliches mehr. Für die 'normalen' dinge reicht der esp8266 aber i.d.r. dicke.
..fällt mir gerade noch ein: pass auf bei sog. 'v3 lolin' nodemcu's,das sind wohl 'alte' varianten und außerdem sind sie größer als die v2.
Gibt aber wohl im grunde eigtl eh nur zwei 'eigentliche' nodemcu-typen,s.hier: https://www.mikrocontroller.net/topic/412609
Wemos d1 haben noch nen extra 5v-pin zur spannungsversorgung von komponenten,wenn du das modul selbst per mini-usb-buchse mit strom versorgst. Der fehlt bei nodemcu (v2),aber dort kann man afaik in dem fall 'vin' zum abgreifen der 5v nutzen.
Aber achtung: die gpios des esp8266 (und aller darauf basierenden varianten, also auch wemos d1, nodemcu etc) sind laut datenblatt nur 3,3v-kompatibel! Manche vertragen mit glück auch mal 5v,aber das ist bzw kann ein glücksspiel sein. Also für 5v-signale dann lieber sicherheitshalber spannungsteiler o.ä. nutzen oder einen mehr bestellen ;)
..nur für den fall,dass du die noch nicht kennst: es gibt 0.96" oled-displays (spi ssd1306),sind schick und kannst evtl noch mehr drauf darstellen.
Bei pollin gibts kleine gehäuse in unterschiedlichen tiefen, wo alles reinpasst. Bei interesse kann ich morgen nochmal nachgucken und dir nen beispiellink schicken wenn du möchtest..
Moin,
ich glaube verstanden zu haben, auf was ihr abzielt.
Das Raumgerät soll ESP-basiert sein, richtig?
Ihr wollt keine Ethernetkabel verlegen.
Ich kann mir das mal anschauen.
Gruß
Fabian
Moin Fabian,
ja klasse, ich bin gespannt :)
Zitat von: fabulous am 26 April 2020, 15:42:54
weil ich im Hinterkopf habe, noch ein zweites RGLU im Badezimmer zu installieren, allerdings mit einem "TWW Push"-Button
Nur so ein Gedanke: Wieso stattest du die nicht direkt mit zwei Tastern aus, einen für TWW-Push, einen als Präsenztaste (also so wie ein RGT)? Wenn du den Taster nur im Badezimmer hast und dann dort erst bei Bedarf drückst, dauert es ja auch nochmal eine ganze Weile, bis das TWW entsprechend aufgeheizt ist.
Gruß
Moin,
mein Ziel ist es, dass der Code ohne Anpassung auf beiden RGs läuft; der UDP-Request wird ja so gesehen jeweils durch einen Taster ausgelöst. Theoretisch ist dann beides an beiden RGs möglich; praktisch nicht weil ich nur jeweils einen Taster anbringen werde.
Aufgrund der baulichen Situation sehe ich bei mir tatsächlich nur eine XOR- Notwendigkeit für die Taster.
Gruß
Fabian
Moin,
kurze Statusmeldung:
- Der UDP Broadcast (gleichzeitiges Senden der Daten an alle Clients im Subnet mit einem einzigen Aufruf) scheint wie geplant zu funktionieren durch das Ersetzen der RxIP von 192.168.0.42 mit 192.168.0.255.
- Die Kompatibilitätsprüfung bzw. Portierung auf ESP-basierte Lösungen scheitert gerade an meinem WinXP Rechner. Die Arduino IDE scheint sich lt. Internetrecherche nicht mit den Wemos D1 Boardinfos zu vertragen. Die Pfade der Bibliotheken etc. laufen ins Leere. Ich muss mal schauen, wie ich hier weiter mache.
Ich warte ausserdem noch auf ein weiteres Uno-Board, da die Nano-Boards in Verbindung mit einem Ethernet Shield irgendwie nicht so wirklich funktionieren.
Gruß
Fabian
Moin,
auf die Schnelle:
a) hast du die entspr CH340G-Treiber für den USB-Chip des Wemos bei Win installiert und
b) die entspr ESP8266-Board-Lib in der ArduIDE hinzugefügt? (Werkzeuge -> Board -> Boardverwalter -> "esp8266" oder "wemos" eingeben)
U.a. hier ist es (wenn auch nur für Mac) sonst auch nochmal ganz gut beschrieben: https://www.xgadget.de/anleitung/wemos-so-laeuft-die-installation-in-der-arduino-ide-ab/
Gruß
Moin,
ja, kann auch das Board auswählen.
Ich hatte beim Kompilieren erst diese Ausgabe:
fatal error: bits/c++config.h: No such file or directory
#include <bits/c++config.h>
Das konnte ich lösen, ein entsprechendes Kopieren in das bits-Verzeichnis (wie auf diversen Seiten vorgeschlagen) war die Lösung.
Dann gibt es jetzt aber diese Ausgabe:
fatal error: bits/stl_iterator_base_types.h: No such file or directory
#include <bits/stl_iterator_base_types.h>
Und dafür finde ich keine Lösung.
EDIT: siehe Beitrag 1
https://www.roboternetz.de/community/threads/70524-NodeMCU-an-Arduino-IDE-Fehler-beim-Kompilieren (https://www.roboternetz.de/community/threads/70524-NodeMCU-an-Arduino-IDE-Fehler-beim-Kompilieren)
Gruß
Fabian
Hmm,also wenn ich die zweite fehlermeldung google,dann kommen ein paar ergebnisse,die sich dabei größtenteils auf winxp beziehen. Scheint bei xp öfter vorzukommen, habs aber nur kurz quergelesen. Hast du n anderes os zur verfügung?
Wenn du magst,kannst du mir die ino sonst mal schicken (email siehe handbuch, adapter@...) od hier einstellen,dann kann ich mal testen,ob ichs hier unter ubuntu problemlos flashen kann. Wird heute zwar nix mehr,aber asap..
Gruß Ulf
Moin Fabian,
ich sitze gerade an den Handbuchanpassungen für den Due und wollte bei der Gelegenheit auch gleich deine Raumgeräte-Variante mit aufführen. Kann ich dafür dein Foto mit ins Handbuch nehmen?
Bist du bzgl der ESP-Umsetzung schon weitergekommen? (Btw: Den Code zum Test-Flashen hattest du mir nicht geschickt, oder? Zumindest war auch im Spam-Ordner nichts, was danach aussah..)
Gruß Ulf
Moin,
@Schotty: entschuldige bitte die späte Antwort. An meiner Heizung hängt noch ein Haus dran, dessen Renovierung mich relativ viel Zeit kostet.
Natürlich kannst du das Bild verwenden; wenn du noch mehr brauchst, melde dich einfach.
Zum Thema ESP-Portierung:
Ich habe noch keine ESP-speziellen Änderungen am Code vorgenommen. Ich gehe davon aus, das zusätzliche Bibliotheken nötig sind; allerdings kann ich das erst herausfinden, wenn es mir gelingt, den Code zu compilieren - und das funktioniert auf dem XP-Rechner nicht.
Allerdings konnte ich einen Win8 PC auftreiben; ich konnte es allerdings noch nicht ausprobieren.
Das OLED (128x32) habe ich zum Laufen gebracht; mit I2C-Schnittstelle ist es relativ einfach. Ich möchte aber noch ein größeres LCD ausprobieren um mehr darstellen zu können.
Ausserdem habe ich jetzt zwei mögliche Konfigurationen im Code hinterlegt: eine Konfiguration ist für nahe der Haustür mit Präsenzknopf und 20x4 LCD; eine zweite Konfiguration fürs Badezimmer mit TWW Push sowie DHT22-Sensor für Logging von Raumtemperatur und Luftfeuchtigkeit.
Für das OLED möchte ich eine weitere Konfiguration anlegen.
EDIT: Kompilieren auf dem Win8 Rechner läuft ohne Fehler durch. Ich muss aber wohl die Ethernet- und UDP - Aufrufe anpassen.
Gruß
Fabian
Hi Fabian,
gar kein Problem, wir haben schließlich alle noch ein Leben neben Heizung und FHEM - und die Heizsaison ist (für die meisten) ja eh quasi durch ;)
Bzgl Bild(er): Dann wäre es schön, wenn du schlussendlich von deinen verschiedenen Lösungen, die du dann selbst nutzt, jeweils ein Bild machen könntest. Dann würde ich die (evtl in der Gesamtansicht im Gehäuse oder nur von der Display-Ansicht, mal sehen) jeweils mit aufführen. Eilt aber nicht!
Klasse, dass du verschiedene Varianten erstellst, da dürfte dann ja wirklich für jeden was dabei sein! Danke!
Dann noch viel Spaß und Erfolg beim Renovieren :)
Gruß
Moin,
ich kann erste Erfolge vermelden.
Die Portierung auf Nodemcu v2 mit 0.96 OLED funktioniert im Prinzip.
Es gibt allerdings noch Kinderkrankheiten.
Gruß
Fabian
Noch ein Foto.
Whoa wie cool! Das ging jetzt aber fix! :)
Kennst du diese 0.96" OLEDs https://www.amazon.de/AZDelivery-Display-Arduino-Raspberry-gratis/dp/B01L9GC470/
Die meinte ich damals eigtl, die haben 128 x 64 Zeichen, vielleicht wäre das was?
Moin,
ich musste quasi nur die Ethernet- gegen eine Wifi-Lib tauschen; gleiches für die UDP-Lib.
Der größte Aufwand ist die Parallelität von Arduino, ESP, LCD und OLED im gleichen Code.
Ich warte derzeit noch auf ein größeres OLED mit 128x64 Pixeln.
Gruß
Fabian
Moin,
anbei eine überarbeitete Version.
Die BSB_lan...-Dateien müssen mit auf den BSB-LAN-Adapter geflasht werden. Ausserdem muss RGLU_types.h mit dazu.
Alle RGLU...-Dateien werden für das Raumgerät benötigt.
Die wichtigste Datei ist "RGLU_def.h"; hiermit können die einzelnen Konfigurationen ausgewählt ("RG_CONF") werden oder neue selbst definiert werden.
Derzeit sind drei Konfigurationen hinterlegt:
- 0: Arduino Uno mit Ethernet Shield, 20x4 LCD und Präsenztaste
- 1: Arduino Uno mit Ethernet Shield und 16x2 LCD
- 2: NodeMCU v2 mit 128x32 OLED (hierfür müssen SSID und pwd in "RGLU_pass.h" angepasst werden)
Die IP-Adressen bzw. die Netzwerk-Konfiguration ist ebenfalls anzupassen.
Die Funktion "TWW Push" ist nur teilweise implementiert und funktioniert daher noch nicht.
Der DHT22 Sensor ist noch nicht implementiert.
Für die Verwendung der Präsenztaste muss der entsprechende Parameter im BSB-lan schreibbar gesetzt werden.
Verwendung auf eigene Gefahr.
Gruß
Fabian
Klasse, danke! Da ich selbst nur das 128x64er OLED liegen und auch keinen Zeitdruck habe, warte ich mit dem Testen noch, bis du die finale Version einstellst ;)
Moin,
mit welcher Konfiguration könntest du es testen?
Dann würde ich versuchen sie nachzubilden.
Ich habe noch ein Wemos D1; und beim OLED wäre es wichtig den Chipsatz zu kennen. Es gibt da wohl verschiedene.
Gruß
Fabian
Moin,
also zum Testen hätte ich folgende Komponenten da, was hierfür in Frage käme:
- Boards: NodeMCU, WemosD1, Uno+LAN (-> EDIT: Tüddelkram, den habe ich kürzlich gerade verbaut :( )
- Display: besagtes OLED 1306 (128x64) (das ist -glaube ich- sogar auch von az-delivery; auf der Packung steht SPI OLED 1306, laut www ists wohl der SSD1306 Standardtreiber - verwendet dein 128x32er den nicht auch?)
- Gedöns: Mini-Taster hätte ich auch da, u.a. auch noch nen DHT22
Zeitlich ist's bei mir derzeit auch knapp, aber bei entspr. schlechtem Wetter lege ich gerne eine Bastelstunde ein ;)
Gruß
Moin,
hätte zwei Fragen an dich ;D
- Hast du den DHT22 schon mal auf einem ESP-Board zum Laufen gebracht? Offensichtlich ist in der DHT-Bibliothek ein Timingfehler mit dem Resultat, dass der Sensor nur NaN liefert. Auf den Arduino- Boards läuft es mit der gleichen Bibliothek problemlos.
- Wenn du dir eine Darstellung auf dem 128x64 Display aussuchen könntest, wie sähe sie aus? Mir fehlen irgendwie die Ideen, und ich habe einfach die LCD-Darstellung übernommen. Die Schrift ist damit allerdings viel zu klein. Ich überlege daher den Text gegen aussagekräftige Symbole zu tauschen und nur die Zahlen darzustellen, aber doppelt so groß.
Hast du irgendwelche Ideen oder Wünsche?
Gruß
Fabian
Moin Fabian,
a) bzgl DHT22@ESP: Nein, habe ich noch nicht versucht. Ich habe den lediglich rumliegen, damit ich einen zum Testen für BSB-LAN-Setups habe. Da die Teile eh nicht so genau sein sollen und auch noch recht groß sind, habe ich mich damit nie weiter auseinander gesetzt.. :(
Ich frage mich nur gerade, ob das NaN-Problem evtl mit der 3.3V Spannungsversorgung zusammenhängt, da haben nämlich kürzlich bei mir DS18B20er an einem Wemos genau so rumgezickt (es kam nur NaN zurück).
(Btw: Hast du zufällig einen BME280 rumliegen? Die laufen 1a am ESP mit den 3.3V via I2C, sind kleiner und genauer. Müsste man aber dann im Gehäuse vermutlich eine kleine Bohrung vornehmen, wo der Sensor drinsitzen könnte, damit die Werte passen..)
b) bzgl Darstellung: Hmm, das ist ne gute Frage.. Spontan würden mir entweder nur die gängigen Symbole (Sonne, Mond, Wasserhahn etc) und/oder Abkürzungen (AT = Außentemperatur etc) einfallen.
Bei den echten OneWire DS18B20 kann man die Versorgung mit 5V vornehmen und dann den PullUp zwischen DATA und einem 3.3V-Pin klemmen, somit kommt beim GPIO auch nur ein 3.3V Signal an. Soll angeblich beim DHT22 auch funktionieren, habe ich aber noch nie getestet. Kann ich gerne machen, wenns meinen ESP dann brutzelt, dann isses eben so. (Bisher waren meine ESPs auch recht 5V-kompatibel an den GPIOs, laut Datenblatt können sie das aber offiziell nicht, weshalb das also grundsätzlich nicht zu empfehlen ist..)
..an einem zu kurzen Abfrageintervall des DHT22 wird's vermutlich nicht liegen, oder? Die sind wohl eher etwas 'lahm'.. Was hast du da für ein Intervall eingestellt?
Moin,
das Ausleseintervall sind 5s. Sollte also passen.
Ich habe mir aber jetzt auch einen BME280 bestellt. Ich möchte auf jeden Fall einen Sensor mit Feuchtigkeitsmessung, daher passen die DS nicht.
Das OLED läuft zusammen mit dem restlichen Code nicht auf dem Arduino aufgrund Speicherplatzmangels. Die Adafruit GFX Bibliothek verschlingt relativ viel Ressourcen. Vielleicht muss ich eine Alternative ausprobieren.
Ich habe auch eine Darstellung für das OLED gefunden mit der ich ganz zufrieden bin.
EDIT: ich habe einen 4.7kOhm Pull up verwendet. Leider habe ich kein Oszi um der Sache auf den Grund zu gehen.
Gruß
Fabian
Moin,
das sieht doch gut aus! Rechts der Wasserhahn und die Flamme symbolisieren dann den Zustand, ob gerade TWW bereitet wird und/oder ob der Brenner an ist?
Bzgl PullUp:
Falls du das auf mein Geschreibsel bezogen hattest: Bitte beachte, dass ich von Versorgung mit 5V und dann PullUp zwischen DATA und einem 3.3V-Pin sprach! Also beim ESP dann nicht den PullUp zwischen 5V und DATA! Aber wie gesagt - angeblich soll das mit nem DHT22 funktionieren, getestet habe ich es noch nicht.
BME280 ist auf jeden Fall ne gute Wahl.
Bzgl Speicherplatz:
Hmm.. Es gibt für die OLEDs eine 'kleine' speicherplatzoptimierte Version: SSD1306Ascii (ArduinoIDE -> Werkzeuge -> Bibliotheken verwalten), aber das ist text-only, da wirst du wohl keine Wasserhähne finden :( - aber wäre ja evtl eine Option, wenn du Abkürzungen o.ä. nimmst?
Moin,
anbei die neueste Version v0.07.
- das LCD ist rausgeflogen
- OLEDs 128x64 sowohl mit SSD1306 als auch mit SH1106 werden unterstützt
- ich verwende das 1,3 Zoll OLED. Es passt ziemlich gut in eine TAE-Dosenabdeckung. Siehe Fotos.
- TWW Push Button implementiert
- ist ein Sensor angeschlossen, werden die Sensorwerte statt RT_soll und RT_ist angezeigt.
Gruß
Fabian
Danke für die Lösungsvorlage zu meiner ersten IoT-Implementierung, Fabian!
Auch wenn von Deinem Kode nur noch winzige Fragmente (und ein Icon) übrig geblieben sind, hat es mir doch sehr geholfen.
Mein Anliegen war: Protokollierung der jüngsten Aktivitäten unserer Heizung und Anzeige aller für mich interessanter Temperaturen auf einen Blick - ohne FHEM-Server oder so, nur mit BSB-LAN im Brennergehäuse im Keller und einer schlanken Anzeige-Einheit im Hausflur.
Nachgerüstet habe ich dann gleich noch:
- Möglichkeit, den Anzeigeinhalt per HTTP abzurufen
- Präsenzdarstellung für ausgewählte Computer (ok, eher Handys=Personen :) im Netz
Ein Beispiel für die Darstellung (im Zeitraffer) auf dem SSD1306 am ESP32 sowie den Quellkode füge ich unten an, falls es jemanden interessiert.
(Das Beispiel beinhaltet keine Präsenzdarstellung. Die würde mit einer Pixelzeile je Computer unten eingefügt, und die oberen Grafiken würden entsprechend verkleinert werden.)
Grüße,
Christian
P.S. Für die aktuelle Version nicht das *.zip hier nutzen sondern https://github.com/DE-cr/BSBmonCR :)
Freut mich, dass ich helfen konnte.
Ich mag die Wassertropfen ... :-)