Closed JacquesBB closed 6 years ago
I have to redirect you to the openv-wiki: https://github.com/openv/openv/wiki/Adressen I don't have this information but there may be some ways to get to the needed info.
First you'll have to find out the type (ID) of your heater. The easiets is to use voIdent (https://github.com/openv/openv/wiki/voIdent). This should give you the ID by which we can look further.
Now probably a lot of the DPs have a similar address so you can always try. By just reading a DP you won't destroy your installation. The worst that can happen is your heater returning an error value or no connection at all.
Thanks, I got the file and extracted the only part that concerns V200KW2 . I will start from there.
By the way. I have the impression that your schematics "circuit.png" is incorrect. The phototransistor has only two pins. The RX of the ESP8266 should be connected to the collector of the SFH309FA, so in your case, between the SFH309FA and the 10 k resistor. as in [https://github.com/openv/openv/wiki/Bauanleitung-ESP8266].
The circuit is wrong, I know. I've drawn the line just a little bit too low :smile:
Anyway, I installed the demo version of the Viessmann diagnostic program. It comes with a large xml file with a lot of datapoints but you'll have to know the ID of your device. I can easily write a sample to have VitoWifi check the ID of your device. From then on it's a fairly simple but tedious task to copy all the DPs. The protocol is simple: if 300 doesn't work you have to chose KW.
Dear Bert,
I think I found most of the codes I need in the link you mentioned above. For a start, I need only two codes :
For the M2 setting (KW2) Room temperature setpoint | | | | 0x3306 | 3..37 | 1 Red. Room temperature setpoint | | | | 0x3307 | 3..37 | 1
My phone app will display these two values and will allow to change them.
In this case, what would be the minimal programming on the ESP8266, using your library that allows to read and write these two values ?
Thanks
Can you help me a bit? Where did you find 0x3306? I assme 3..37 is the allowed range? (I didn't implement this kind of check) What is the 1? Is the datapoint 1 byte long? Is 1 a conversion factor?
Note: I don't think anyone has already tried to write with the KW protocol using VitoWifi. You'll be the first. But I'll be glad to help! Note 2: for ESP8266 I stronly suggest to also use my https://github.com/bertmelis/WifiPrinter lib or https://github.com/JoaoLopesF/RemoteDebug as the ESP only has 1 serial port which will be occupied by the optolink. That way you can print debug messages via telnet/webpage.
I found everything in https://github.com/openv/openv/wiki/Adressen
In the legend (first column), you find Operation (read write) A1M1: 0x23 .. (M2: 0x33 .., M3: 0x43 .., where available)
Room temperature setpoint is written 0x2306, so for M2, it becomes 0x3306 The 3..37 is the range, but I will not put limits in a first try. 1 is the number of bytes that is read or written.
For the debugging, I intend to use some virtual terminal on the Android phone through blynk http://docs.blynk.cc/#widgets-displays-terminal
I will post the results when done.
So the only thing I need on your side is a routine that read a value from an address or write a value to an address.
As I say, I will only start tomorrow, but will try to to it steadily to have rapidly a working device.
OK, I know what to do. Writing will be almost a shot in the dark though.
I've made a TEMP_S branch to test this one out. Be sure to switch to that version!
For the sketch try this (and adapt to your needs offcourse). The functions to write the temperature have to be called somewhere obviously.
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <VitoWifi.h>
#include <WifiPrinter.h>
const char* ssid = "your-ssid";
const char* password = "your-password";
WifiPrinter wifiPrinter;
VitoWifi_setProtocol(KW);
void handleRoomTemp(const char* name, const char* group, uint8_t value) {
// do something with roomtemp
wifiPrinter.printf("room temperature: %d", value);
}
void handleRoomTempRed(const char* name, const char* group, uint8_t value) {
// do something with roomtemp
wifiPrinter.printf("room temperature reduced: %d", value);
}
void setup() {
// setup WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
// setup WifiPrinter
wifiPrinter.begin();
// setup VitoWifi
VitoWifi.addDatapoint("roomtemp", "temp", 0x3306, TEMPS).setCallback(handleRoomTemp);
VitoWifi.addDatapoint("roomtempred", "temp", 0x3307, TEMPS).setCallback(handleRoomTempRed);
VitoWifi.setup(&Serial);
}
void loop() {
static unsigned long lastMillis = 0;
if (millis() - lastMillis > 60 * 1000UL) { // read all values every 60 seconds
lastMillis = millis();
VitoWifi.readAll();
}
VitoWifi.loop();
wifiPrinter.loop();
// to write a value, call VitoWifi.writeDatapoint("roomtemp", 12); for example
// method is VitoWifi.writeDatapoint(const char*, uint8_t);
}
Thanks, I will try this now. First I had to make another optolink, and it took me longer than expected because I put the SFH309FA in the wrong side. The datasheet was not that explicit. Now its working. I can start the programming stage.
Hi Bert,
It is great, it works !! I have even made it OTA, and started to integrate it with blynk ! Still need some polishing, but it is very promising. I have just the output in the terminal on my phone, which is already impressive. Would you be so kind to send me as well the order to change the temperature values ?
Thanks PS: I will post the full code when ready
Writing to DPs (= changing the temp) is done by VitoWifi.writeDatapoint(const char*, uint8_t);
So for instance: VitoWifi.writeDatapoint("roomtemp", 21);
Keep in mind that writing is completely untested!
Right now, I have already set some way to get the desired temp to the ESP and I am testing by displaying the values in the terminal with
void handleRoomTemp(const char* name, const char* group, uint8_t value) {
// do something with roomtemp
TERM.printf("room temperature: Set : %d Actual %d\n", VTemp,value);
Blynk.virtualWrite(V1, value);
}
void handleRoomTempRed(const char* name, const char* group, uint8_t value) {
// do something with roomtemp
TERM.printf("room temperature reduced: Set : %d Actual %d\n", VTempRed,value);
Blynk.virtualWrite(V2, value);
}
Where would you put the
VitoWifi.writeDatapoint("roomtemp", Vtemp);
line. Should I write
void handleRoomTemp(const char* name, const char* group, uint8_t value) {
// do something with roomtemp
VitoWifi.writeDatapoint("roomtemp", Vtemp)
TERM.printf("room temperature: Set : %d Actual %d\n", VTemp,value);
Blynk.virtualWrite(V1, value);
}
I can do that with a security flag as
void handleRoomTemp(const char* name, const char* group, uint8_t value) { // do something with roomtemp if (flag_temp) {VitoWifi.writeDatapoint("roomtemp", Vtemp);} TERM.printf("room temperature: Set : %d Actual %d\n", VTemp,value); Blynk.virtualWrite(V1, value); }
Where flag_temp is set by a button on my phone;
What do you think ?
I don't know anything about Blynk. How does your ESP receives events from Blynk?
Anyway, just put it somewhere in your loop()
. If I understand correctly:
void loop() {
if (flag_temp) {
VitoWifi.writeDatapoint("roomtemp", Vtemp);
}
// here the rest of your loop-code
}
Thanks Bert, but this time it does not work.
Blynk transmits data from the app ( the andoid phone) to the hardware (the ESP8266) with what they call "virtual pins". A virtual pin can contain anything. The transmission is done through a server.
Blynk is quite extraordinary in term of results with respect to programming effort. On the android side, everything is done with widgets, without coding, and on the ESP, the coding is minimal.
Here is my complete code. It handles both the OTA features, and the blynk interface. For blynk, it is better to have a very simple loop, and use a Timer for the different events.
/*
jxl_Vito_OTA
9/3/2018 Communicate with my Vitoladens Vitotronic 200 (KW) with blynk
Thanks for openv (https://github.com/openv/openv/wiki)
and especially to Bert Melis for his ESP VitoWifi library ( https://github.com/bertmelis/VitoWifi)
*/
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ArduinoOTA.h>
#include <VitoWifi.h>
// Go to the Project Settings (nut icon).
char auth[] = "xxxxxxxxxx"; // jxl_Vito_OTA
char ssid[] = "xxxxxxx";
char pass[] = "xxxxxxxx";
// RTC de blynk
#include <Time.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
BlynkTimer timer;
// attach terminal
WidgetTerminal TERM(V20);
// RTC
WidgetRTC rtc;
// temp values
uint8_t Temp, TempRed,VTemp, VTempRed;
// security flag
uint8_t flag_temp;
BLYNK_CONNECTED() {
// Synchronize time on connection
rtc.begin();
}
BLYNK_WRITE(V3) //temp change
{
VTemp = (uint8_t)param.asInt();
}
BLYNK_WRITE(V4) //temp reduite change
{
VTempRed = (uint8_t)param.asInt();
}
// flag de securite
BLYNK_WRITE(V5){
flag_temp=param.asInt();
Blynk.virtualWrite(V6, flag_temp*255); // led de controle
}
VitoWifi_setProtocol(KW);
void handleRoomTemp(const char* name, const char* group, uint8_t Temp) {
// do something with roomtemp
TERM.printf("room temperature: Set : %d Actual %d\n", VTemp,Temp);
Blynk.virtualWrite(V1, Temp);
}
void handleRoomTempRed(const char* name, const char* group, uint8_t TempRed) {
// do something with roomtemp
TERM.printf("room temperature reduced: Set : %d Actual %d\n", VTempRed,TempRed);
Blynk.virtualWrite(V2, TempRed);
}
// the setup function runs once when you press reset or power the board
void setup() {
TERM.flush();
WiFi.mode(WIFI_STA);
Blynk.begin(auth, ssid, pass);
ArduinoOTA.setHostname("jxl_vito");
ArduinoOTA.begin();
setSyncInterval(10 * 60); // RTC Sync interval in seconds (10 minutes)
delay(1000);
//
TERM.println("");
TERM.println(clockDisplay());
TERM.println("Ready - TEST OTA");
TERM.print("IP address: ");
TERM.println(WiFi.localIP());
TERM.println("ça marche !");
TERM.flush();
//vito
// setup VitoWifi
VitoWifi.addDatapoint("roomtemp", "temp", 0x3306, TEMPS).setCallback(handleRoomTemp);
VitoWifi.addDatapoint("roomtempred", "temp", 0x3307, TEMPS).setCallback(handleRoomTempRed);
VitoWifi.setup(&Serial);
timer.setInterval( 10000L, jxl_clock);
timer.setInterval( 10000L, vito);
}
// the loop function
void loop() {
Blynk.run();
timer.run();
VitoWifi.loop();
ArduinoOTA.handle();
}
void vito(){
VitoWifi.readAll();
TERM.flush();
TERM.printf("flag_temp : %d \n", flag_temp);
if (flag_temp==1) {
// update values
VitoWifi.writeDatapoint("roomtemp" , VTemp);
VitoWifi.writeDatapoint("roomtempred", VTempRed);
}
TERM.flush();
}
void jxl_clock(){
TERM.println("");
TERM.println(clockDisplay());
TERM.flush();
}
String clockDisplay()
// Digital clock display of the time
{
String currentTime = "T: "+String(hour()) + ":" + minute() + ":" + second()+" "+ String(day()) + " " + month() + " " + year();
return currentTime;
}
I finally found the way to properly quote the code in Markdown.
```C++
\
```
It will make my posts more easy to read
Thanks for the code. Will look into this (and learn something about Blynk). I might only have some time this evening.
Does is to nothing at all of does it gives som weird errors?
I have nothing in the terminal
I put a write in the loop to verify that I actually call the function. I get the message "passage in the loop" and nothing else. The values are not changed. I have previously verified with the Windows GUI interface that I can change these values with my optolink.
void vito(){
VitoWifi.readAll();
TERM.flush();
TERM.printf("flag_temp : %d \n", flag_temp);
if (flag_temp==1) {
// update values
TERM.printf("passage in the loop %d \n", flag_temp);
VitoWifi.writeDatapoint("roomtemp" , VTemp);
VitoWifi.writeDatapoint("roomtempred", VTempRed);
}
TERM.flush();
}
Hi Bert, Just an update.
I added the reading of two parameters : Burner Starts and Burner Status.
Burner Starts ( 4 bytes)
Burner Status ( 1 bytes)
Contrarily to a previous message, they both work. I had a mistake. With TEMPS for 1 byte, it works.
void handleBurnerstarts(const char* name, const char* group, uint32_t BurnerStarts) {
// do something with roomtemp
TERM.printf("Burner Starts : %d\n", BurnerStarts);
Blynk.virtualWrite(V10, BurnerStarts);
}
void handleBurnerstatus(const char* name, const char* group, uint8_t BurnerStatus) {
// do something with roomtemp
TERM.printf("Burner Status : %d\n", BurnerStatus);
Blynk.virtualWrite(V11, BurnerStatus);
}
void setup() {
.......
//burner
VitoWifi.addDatapoint("burnerstarts","burner", 0x088A, COUNT).setCallback(handleBurnerstarts);
VitoWifi.addDatapoint("burnerstatus","burner", 0x551E, TEMPS).setCallback(handleBurnerstatus);
}
I'm trying to build a Blynk example myself but I can't get it to compile. Using VSCode and platformio on Win10. Blynktimer
is not recognised...
#include <Arduino.h>
#include <VitoWifi.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
const char ssid[] = "xxxx";
const char pass[] = "xxxx";
const char auth[] = "xxxx";
VitoWifi_setProtocol(P300);
bool updateItems = false;
BlynkTimer timer;
WidgetTerminal terminal(V1);
void update() {
updateItems = true;
}
void globalCallbackHandler(const char* name, const char* group, const char* value) {
terminal.printf("Received: %s - %s: %s\n", group, name, value);
}
void sendOutsidetemp(const char* name, const char* group, float value) {
Blynk.virtualWrite(V0, value);
}
void setup() {
// VitoWifi setup
VitoWifi.setLogger(&terminal);
VitoWifi.enableLogger();
VitoWifi.addDatapoint("outsidetemp", "boiler", 0x5525, TEMP).setCallback(sendOutsidetemp);
VitoWifi.setGlobalCallback(globalCallbackHandler);
VitoWifi.setup(&Serial);
Blynk.begin(auth, ssid, pass);
timer.setInterval(30000L, update);
}
void loop() {
VitoWifi.loop();
Blynk.run();
timer.run();
if (updateItems) {
updateItems = false;
VitoWifi.readAll();
}
}
It's for my heating so it may need some modifications. Made a dashboard with a terminal (V1) and a value display (V0)
Maybe You should try with the arduino IDE. The libraries install very easily with the library manager, including the blynk library.
Otherwise, you are not strictly obliged to use the timer library, but I experienced that the less you put in the main loop, the better it is for blynk.
You could try with the update call in the main loop
if (millis() - lastMillis > 30 * 1000UL) { // read all values every 30 seconds
lastMillis = millis();
update();
}
It works now. So if you want to write to your heating you'll have to do something like this:
BLYNK_WRITE(V2) {
int pinValue = param.asInt();
VitoWifi.writeDatapoint("roomtemp", pinValue);
}
As I understand Blynk, this function will be called every time the widget connected to V2 has changed. The received value is then written to the VitoWifi.
FYI: The Arduino-loop in this firmware: https://github.com/bertmelis/esp-boiler takes a little less then 100µs on a Wemos D1 mini @ 80MHz. When people talk about long or blocking operations they usually talk about 10-20ms on these devices. Thats 200 times longer!
As I understand Blynk, this function will be called every time the widget connected to V2 has changed. The received value is then written to the VitoWifi.
Yes, this is the way to communicate from the app on the phone to the hardware.
I am a little bit confused about the types. In my case, am I wrong to assume that the TEMPS type is uint8_t as it is coded on 1 byte ?
I have
uint8_t VTemp, VTempRed;
// in order to have global values
// then
BLYNK_WRITE(V3) //temp change
{
VTemp = (uint8_t)param.asInt();
}
// and in the main loop, called by the timer
void vito(){
VitoWifi.readAll();
VitoWifi.writeDatapoint("roomtemp" , VTemp);
}
}
But it still does not work, although I verify that VTemp is well transmitted ( I print it).
I made an even simpler case
void loop() {
Blynk.run();
timer.run();
VitoWifi.loop();
ArduinoOTA.handle();
}
void vito(){
VitoWifi.readAll();
VitoWifi.writeDatapoint("roomtemp" , 14);
}
But it still does not work. It reads everything, but It does not change the roomtemp value.
This should work. Keep in mind that VitoWifi is sending debug info at a quite fast rate and this may be too fast for over-the-internet transmission. So maybe comment our the setLogger
and enableLogger
lines
/*
V0: step V (set room temp)
V1: labeled value (outside temp)
V2: labeled value (set room temp)
V3: terminal
*/
#include <Arduino.h>
#include <VitoWifi.h> // https://github.com/bertmelis/VitoWifi
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
const char ssid[] = "xxxx";
const char pass[] = "xxxx";
const char auth[] = "xxxx";
VitoWifi_setProtocol(KW);
bool updateItems = false;
BlynkTimer timer;
WidgetTerminal terminal(V3);
// function to run every time BlynkTimer timer fires: just set a flag and handle in main loop
void update() {
updateItems = true;
}
// fallback when no handler has been found, just print received data to Blynk terminal
void globalCallbackHandler(const char* name, const char* group, const char* value) {
terminal.printf("Received: %s - %s: %s\n", group, name, value);
}
// send receive outside temperature to virtual pin V1
void sendOutsidetemp(const char* name, const char* group, float value) {
Blynk.virtualWrite(V1, value);
}
// send receive room temperature (soll) to virtual pin V2
void sendRoomtempSet(const char* name, const char* group, byte value) {
Blynk.virtualWrite(V2, value);
}
// callback for Blynk when widget Step V (on V0) has been changed
// write the receive value to VitoWifi and read back
BLYNK_WRITE(V0) {
int pinValue = param.asInt();
terminal.printf("Blynk update: V0 = %d\n", pinValue);
VitoWifi.writeDatapoint("roomtempset", pinValue);
VitoWifi.readDatapoint("roomtempset");
}
void setup() {
// VitoWifi setup
VitoWifi.setLogger(&terminal); // might be too verbose/fast for Blynk to handle
VitoWifi.enableLogger(); // might be too verbose/fast for Blynk to handle
VitoWifi.addDatapoint("outsidetemp", "boiler", 0x5525, TEMP).setCallback(sendOutsidetemp);
VitoWifi.addDatapoint("roomtempset", "heating", 0x2306, TEMPS).setWriteable().setCallback(sendRoomtempSet);
VitoWifi.setGlobalCallback(globalCallbackHandler);
VitoWifi.setup(&Serial);
// Blynk setup
Blynk.begin(auth, ssid, pass);
timer.setInterval(30000L, update);
}
void loop() {
VitoWifi.loop();
Blynk.run();
timer.run();
// clear flag and read all datapoints
if (updateItems) {
updateItems = false;
terminal.println("Updating items!");
VitoWifi.readAll();
}
}
Thanks a lot for your effort, Bert !
The above changes you propose is to add the "setWriteable()" option in
VitoWifi.addDatapoint("roomtempset", "heating", 0x2306, TEMPS).setWriteable().setCallback(sendRoomtemp);
I will certainly try, but it will not be before next Friday evening, as I am out of my house for the week.
I can program my ESP8266 OTA, but only on the same network.
Meanwhile, I will be able to improve my knowledge of your library.
It certainly is very powerful, and programmed efficiently, but to grasp all the possibilities is not that obvious. Especially at the beginning, as I found only yesterday late evening your reference file
https://github.com/bertmelis/VitoWifi/blob/TEMP_S/REFERENCE.md
It already helps, but what is needed, is a text providing the general structure of your library.
By the way, I hope you are enjoying interfacing with Blynk. It should be my small contribution to this project. When my app will be complete, or nearly, I will post it.
Best Wishes Jacques
Documentation is the Achilles' heel of many projects... Mine is not different :smile:
Please post your working example. You can even make a pull request to add it to the examples. I'll hear when you need more info.
In all these codes, I dont see where one can set up the Heating time program.
Is it possible to have access to this programming as well ?
That's not implemented (yet). I don't use every possibility myself and add feature as they are asked or contributed.
Programming time functions behave like all the rest. It's only a datapoint type that has to be added. Only thing is that the dataponit structure has to be improved to keep up maintainability. When the list of implemented types grows, it is harder to keep an overview. I don't know yet how this has to be done.
Right now, it is not a big issue for me. I will be perfectly happy if I can properly set the temperatures with the app, as I can then schedule anything I want through this app. My question was mostly by simple curiosity, as it was not clear for me.
I see in your doc (https://github.com/bertmelis/VitoWifi/blob/TEMP_S/REFERENCE.md) that there is the option to say
VitoWifi.addDatapoint("roomtempset", "heating", 0x2306, TEMPS, true).setCallback(sendRoomtempSet);
instead of
VitoWifi.addDatapoint("roomtempset", "heating", 0x2306, TEMPS).setWriteable().setCallback(sendRoomtempSet);
Are the two options valid ? equivalent ?
the two options are equal by function. The first one is quicker, it avoids the extra function call.
Hi Bert, I just arrived in my house. Immediately dowloaded my new code, and ...
IT WORKS !!!
Thanks a lot for the help. I will certainly come back to you, as I will now polish my code and interface, and may wish to have at the same time the linux command line interface and the Blynk visual interface. But this will be another story. I am already very happy with the present results.
Glad to hear! Thank you for testing!
I'm looking forward to see your developments.
Closing: "it works". Included the example in the code.
Installation specifics
VitoWifi ESP8266 with Blynk
This thread is to follow the evolution of a project I want to realise, that is be able to monitor my heater remotely with Blynk https://www.blynk.cc/ Bert, If you dont mind, I will ask here all the necessary questions for the implementation of my project and provide the details of its evolution.
First questions :
I see in your example
VitoWifi.addDatapoint("outsidetemp", "boiler", 0x5525, TEMP); VitoWifi.addDatapoint("boilertemp", "boiler", 0x0810, TEMP); But it is not clear to me where is the table of all adresses for the different functions ? for the KW protocol.
I would have expect to see a file with all this information, and I dont find it. DO you have it ?
Thanks