pa-pa / AskSinPP

104 stars 71 forks source link

AskSin++ for ESP MCU's (ESP32, ESP8266) #26

Closed knopserl closed 5 years ago

knopserl commented 6 years ago

Hello, I urgently need a library to build homematic devices, which are not available by Homematic. I was happy to find AskSin or AskSinPP. I need to work with ESP (Espressif) MCU's preferable ESP32 and unfortunatly AskSinPP does not support it. I have commented out alls avr/... libs, EnableInterrupt.h, LowPower.h, as they are all not compatible with Espressif MCU's. I guess they might also not required (as the ESP32 has featues already in the internal RTOS)? So would it be possible to get a AskSinPP version which supports ESP32/ESP8266 MCU's which are the MCU's my friends and myself are using for mos projects? I'm using boards like: WeMos Lolin32 https://www.aliexpress.com/item/4-MB-Flash-WEMOS-Lolin32-V1-0-0-WIFI-Bluetooth-Card-Based-ESP-32-ESP-WROOM/32823891656.html https://www.aliexpress.com/item/LOLIN32-Wifi-Bluetooth-Development-Board-Antenna-ESP32-ESP-32-REV1-CH340-CH340G-MicroPython-Micro-USB-Lithium/32846143452.html Anything I can do to create motivation (e.g sponsor you boards?) :-)

regards Heinz

jp112sdl commented 6 years ago

What's the need of using an ESP? At the one side you have the 868MHz radio module to communicate with the CCU and on the other side you have connected a sensor or relay etc. to the ATMega328.

Btw: An ESP is more expensive than a Mega328 and has a higher power consumption.

pa-pa commented 6 years ago

There is no plan to add support for ESP MCU. You can try by yourself. The implementation of the STM32 port may give you hints where changes are needed. You can search for the ARDUINO_ARCH_STM32F1 define. It is used to integrate STM32 specific code. You should also look into the examples/stm32 folder, how the basic setup is done to use the STM32 stuff.

ghenne commented 6 years ago

Just for curiosity: What is the state of the stm32 port? Is this work in progress, or have you already used it to build a halfway working homematic device?

pa-pa commented 6 years ago

The Switch example works very well. I plan to use the STM32 for a RGB dimmer, because it has more usable PWM pins. In the master branch there is also support for external EEPROMs (AT24C32) now. So the Flash-Hack for storing settings is no longer needed for STM32.

jp112sdl commented 6 years ago

Can you recommend this board for first steps with an STM32? Or another?

pa-pa commented 6 years ago

This board is fine. I use it with an ST-Link for programming and debugging (inside Eclipse with OpenOCD-Plugin). You can also use the Maple Mini Board. It can be used like an Arduino - uploading the code by using the USB-Connection. It also has more flash memory (128k). There is a STM32duino Webpage with a lot of information.

jp112sdl commented 6 years ago

That's great. Thanks!

Xento commented 6 years ago

Is it maybe possible that asksin++ can run on a STM8? I have 8 window sensors from MAX! and they use a STM8L052 controler.

knopserl commented 6 years ago

Thanks guys for sharing your opinion and giving feedback. Just to answer to the question why I use ESP (32 or 8266, 8285) MCU's. I think they are perfect and very cheap IoT devices (WiFI & BTLE and an RTOS for free). They are fast and cheap (1,90 to 4€), so there is not a reason to talke about the price, they are all between 1,70 to 4,x€. Beside the connectivity (some boards have also 433/868/915 MHz transceivers on it but cost a bit more of course), I also like are three other facts: Power efficiency, as the ESP's are tune for very low power modes like deep sleep works with few uA, some boards have a LiPo battery plug with changer/switch between sources and also if required dual core up to 240MHz (e.g. for speech recognition). Just check the Espressif data sheet. So you see, cheap, flexible, energy (battery) optimized. That to the reason to use ESP.

Back to my request: Since I got the feedback, that ESP will not be supported, I will try first a supported MCU like the STM32. I have order already 10pieces meanwhile before I try to implement the ESP by myself, which I guess is not just easy (not having the background as the lead developer).

I have not find any other good BidCos library to start for ESP MCU's.

BTW: Another short question: As far as I have understood, AskSin expects an TI CC1101 transceiver right? I have a couple of RFM69 and RFM95 (868MHz) which are supposed to support better range and more transmission power (20db). How difficult is it to support also RFM transceiver like RFM69/95?

Thanks!

pa-pa commented 6 years ago

STM8 is not possible because there is no C++ compiler available and the library makes heavy use of C++.

pa-pa commented 6 years ago

To replace the C1101 with any other hardware you need to implement the public API of the Radio class. To use your own implementation in a device you have to replace the Radio class in the HAL type def. In the FHEM Forum there are already some information about using RFM69 for Homematic.

knopserl commented 6 years ago

I'm working on a support for ESP32 and have resolved already most of the files. Currently I'm stuck at the AlarmClock class. The ESP32 seem to have quite good timer/internal RTC support but the class is probably to difficult for me to change. BTW: If simebody might ask again, why I'm not using an ATMEGA328p or STM32F1, I have tried both and they worked, but as soon as I add any e-paper, it exceeds the Flash/RAM of the 328p and also the STM32. That is the reason why I need the ESP's with 4+MB Flash and 520k RAM.

pa-pa commented 6 years ago

What is your problem with AlarmClock ? You only need to change Sysclock::init(), enable() and disable(). It generate TICKS_PER_SECOND interrupts. Same for RTC it should interrupt once per second.

TomMajor commented 6 years ago

Why not use the ESP32 for your demanding e-paper application, use the AVR for Bidcos and connect them via SPI or any other interface that suits your needs? Guess that would be much less work than porting AskSinPP to ESP32. Just my opinion :)

knopserl commented 6 years ago

@pa-pa: Since you wrote the Alarmclock, you anderstand it. I have not yet understood it, thus it's not easy for me to change even the few methods. But I will look further if I find something from somebody before I give up using Asksin and switch to LoRa (MySensors has support for ESP32 + RFM95). But I just build a MapleCUN with 4 RF units and it would have been nice to use them for Homematic.

I dont think it's the best solution to use two MCU's just one for the display. At least I don't really want to do it. But thanks for the idea!

knopserl commented 6 years ago

ok guys, I got something working with ESP32! It does a pairing when I press the config button and transmits some values (RSSI level etc....). So I have a least a start and also the AlarmCLock seem to works to some extend. @pa-pa : Mybe you can do me a favour and take a quick look at my AlarClock.h file which I have attached (zipped) is you see obvious mistakes?

I also have complete understanding problems with the RTC class: I see three methods: init, getCounter, overflow, I don't see the generated interrupt, what is done (callback?) and I also don't see a code for an STM32 but rather a "warning, RTC not supported" for non AVR/ATMEGA32. The remaining code is rather "cryptic" to me. Do I need to create an additonal independend second timer for the RTC with one interrupt/second and what should the interrupt do/what shall be called? The ESP32 has two RTC timer/counter groups with two timer per group. Does that help for the RTC. I also get a return code at init storage: Init Storage: CAFE6189 (I have included the required ESP storage class). Does that look good or bad?

I hope you can and are willing to help so that I can successfully complete the AskSinPP ESP32 support. So far it looks already promising!

AlarmClock.h.zip

below is the ESP32 serial monitor output.

AskSin++ V2.1.3 (May 13 2018 20:08:54) Address Space: 32 - 73 00000000 Init Storage: CAFE6189 CC init1 CC Version: 14

-> 13 76 A0 01 FD0001 345678 00 08 02 01 0A FD 0B 00 0C 01 - 22750 <- 0A 76 80 02 345678 FD0001 00 - 22871 -> 0B 77 A0 01 FD0001 345678 00 06 - 22992 <- 0A 77 82 02 345678 FD0001 00 - 23111 -> 10 78 A0 01 FD0001 345678 00 04 00 00 00 00 00 - 23388 <- 14 78 80 10 345678 FD0001 02 02 00 0A 00 0B 00 0C 00 00 00 - 23519 -> 0B 79 A0 01 FD0001 345678 01 03 - 23640 <- 0E 79 80 10 345678 FD0001 01 00 00 00 00 - 23764 debounce released <- 1A 02 84 00 345678 000000 10 00 3F 48 56 54 53 31 38 30 30 30 31 70 01 01 00 - 33181

debounce released <- 1A 03 84 00 345678 000000 10 00 3F 48 56 54 53 31 38 30 30 30 31 70 01 01 00 - 34261

debounce pressed released <- 1A 04 84 00 345678 000000 10 00 3F 48 56 54 53 31 38 30 30 30 31 70 01 01 00 - 37378

debounce pressed longpressed longreleased

ignore 0B FC A0 01 FD0001 5540A7 01 0E - 153533 ignore 0B FC A0 01 FD0001 5540A7 01 0E - 153733 ignore 0B FC A0 01 FD0001 5540A7 01 0E - 153933

pa-pa commented 6 years ago

This looks very good. The RTC is only needed for AVR because the "normal" timer is not usable when the CPU is in deep sleep mode. So for ESP you can ignore it. The storage class has to implement some persitent storage. For AVR we use the internal EEPROM. On STM32 there is a "hack" to use the flash as EEPROM od use the external at24c32/64 class to store the data into an external EEPROM. See stm32/HB-DoorBell example.

knopserl commented 6 years ago

@pa-pa : Thanks for your advise. I'll ignore the RTC class. because ESP have a working RTC time in deep sleep (5uA) and wake it up by itself afte every 30seconds or a minute and send the temp/hum/press values. Basically it does a restart after every deep sleep and run though the whole setup again. So then the Activity Class and the LOwPower library is also not usable or required right? Last question: Is the storage init ok with that log entry or do I have a problem? How can I test it if it works? The ESP32 modules have typically 4 to16MB flash. Init Storage: CAFE6189 <-- is this ok or an error code?

jp112sdl commented 6 years ago

@knopserl Great, what you have done so far!

Basically it does a restart after every deep sleep and run though the whole setup again.

That means, that your message counter always starts with 0, when the ESP wakes up ? This could be a problem when using a CCU2, because in some cases, the rfd-Daemon (or ReGaHss process?) ignores messages with the same message counter one after another (to suppress multiple receivings) or to realize long keypress, that uses the same message counter for repeated transmissions.

Maybe you should put the last value of the message counter to EEPROM or a config file in SPIFFS.

Init Storage: CAFE6189 <-- is this ok or an error code?

This is ok. It's a magic with the prefix CAFE. Have a look at L374 in Storage.h

pa-pa commented 6 years ago

As already written the restart will give problems. But the low-power code can wait until the rest of the systems works. The "Init Storage" should only appear during the first start or after changing the lists registers or peer numbers. Please take a look into the InternalEprom class. It has extra code for STM32 which uses a 1k memory array to mirror 1 flash page into RAM. This is used to provide faked EEPROM storage. The store method will use flash routines to write the RAM back into the flash page. You may need similar handling for ESP32. An alternative would be to use an external EEPROM. The library already supports at24c32/64 attached by I2C. See the stm32/HB-DoorBell.ino how to use it.

knopserl commented 6 years ago

@pa-pa thanks again for still helping me further. I admit, that I'm far from understanding a couple of the classes and still need some more hints from you. Hope you don't get bothered - just tell me then I'll stop asking :-) It looks like your doorbell example has some other usefull sample code for my temperature sensor.
it sends the temp/hum/pressure every 180 (3*60) seconds right? But it does not go to sleep to save battery, as it is powered by wire?

@jp112sdl Also thanks for your hints. Were do I get the message counter and how to restore?

I have to explore the deep sleep mode of the ESP32 a little more, but I'm pretty sure that deep sleep or power off will cause a complete restart after wakeup. If something need to survive the restart, it has t be stored in the RTC RAM which is kept durig deep sleep. SO a simple : RTC_DATA_ATTR int wake_count or messagecnt will be stored and can be accessed after wakeup. This is RAM and does not degrade the Flash lifetime. It has 8kB RTC Fast and 8kB RTC SLow memory: Embedded Memory – 448 KB Internal ROM (external 16MB Rom) – 520 KB Internal SRAM – 8 KB RTC FAST Memory – 8 KB RTC SLOW Memory.

knopserl commented 6 years ago

forgot to ask some more questions (in addition to the questions in my last post): 1.) What is the minimum I need (maybe from the door bell) if I only need one value channel for temp/hum/pressure (data types can be also float right and there is no need to predefine the message in any XML file like for the standard Homematic devices?) 2.) can a get the date/time from the controller (I use Homegear) to my sensor when I transmit the "weather" data, as I wanted to show/update the time on my e-paper.

pa-pa commented 6 years ago

The door bell example doesn't use any sleep code. Regarding the deep sleep for ESP32 I see a lot of problems. The code always initialize all data structures during system start. Because the wakeup is not a cold start the code has to handle these two different scenarios. So before go into sleep the current states of the channels and the active alarms needs to stored into the extra memory. During start of the system the current start type needs to recognized and if it is a wakeup the channel data and the alarms needs to be restored. The sysclock needs to corrected by the time of deep sleep. This handling is currently not available. What happend with the interrupt handlers ?

There is a message type for for sending a timestamp. But I have never seen that message. The lib has also no code to handle this. When you sending weather data, you should use the weather message as used in the HM-WDS10-TH-0 example. This can also used to communicate the weather data to other peers. The door bell sends more data and needs special handling on receiver side to decode the send data.

knopserl commented 6 years ago

Ok the key question is now if the Homematic/AskSin protocol/library is still a good choise for my relativly simply use case? It's all about good quality climatic sensors (two: SHT31, BME280) battery usage with thus with an energy efficient display (e-paper). I want to show set temperature, current temp/hum/press and date/time. Should not be rocket sience. The ESP32 is in m.o. an ideal HW, very flexible with a lot of Flash/RAM/RTC/RTC RAM and very energy efficient and cheap.

So what is currently open: If I want to save power, I have to set the ESP in any sleep mode. I have three main options: light sleep (0.8mA = 800uA), deep sleep (5uA) and power off 0.1uA or 800nA). In light sleep, I don't loose any context/RAM, after wakeup, the MCU resumes where it went to sleep but that is 0.8mA. In deep sleep, it wakes up by itself like a warm start and all RAM context is lost. Only the the RTC was running and it's RTC RAM = 8kB is preserved. The time is not lost. SO the system time continues to be correct as the system counter as base for a clock was running at 5uA. Basically the program runs through the setup/initialzation again. I could also place the MCU to power off and have a nano-amp RCT (tpl5110) with external wake-up = cold start. But I'm quite sure, that it does not make a differnce if I do a warm or cold start, it always runs through a fresh as I think the RAM is initialized and for ASkSin it's always a startup. So there is no in-programm trigger but rather a sub-sequent startup (except what was written in the flash memory which is anyhow persistent). So would that be a problem if the system makes a startup every 60 seconds, does a measureing, send the values and goes to a deep sleep (does not really require/use the loop() code)? The only other alternative I see is to use light sleep with 0.8mA (800uA which is 160 times more than deep sleep) and then I guess it is a straight forward implementation but I don't think my 2200mA battery would last for some month.

I'm wondering how e3Q does it with their thermostat and the LCD display (I think they use an STM MCU) and the display is updated at least once a minute.

So what are your hints? Should I go forward with the deep sleep and full init, measure/send and sleep again? Or would you do the light sleep with much higher power consumption, 0,8mA just the MCU. Or use any other solutioon like LoRa or ESPnow (2,4GHz) with MQTT? But then I can forget my mapleCUN's (I have 4 of them with 4 transceiver each).

pa-pa commented 6 years ago

You have two simple options. Use a supported hardware or port the library. That the ESP32 boots after deep sleep is not the failure of the library. It is the hardware. I will not investigate in code to do this handling. This is the reason why the STM32 has also no deep sleep support. e3Q will uses different hardware for different devices. If I'm not totally wrong they uses two CPUs in the thermostat - one for the communication and one for display control.

TomMajor commented 6 years ago

e3Q will uses different hardware for different devices. If I'm not totally wrong they uses two CPUs in the thermostat - one for the communication and one for display control.

Something like that I was suggesting earlier, using ESP32 for e-paper and AVR for Bidcos. This will cost you maybe 1-2h more in interface communication design and testing etc, but will save you many days for porting the lib :)

knopserl commented 6 years ago

@pa-pa before I switch to another transmission protocoll(not using AskSin): I kindly ask for a further hint: I have now the display connected to another SPI port (2) and I'm using currently the ESP32 light_sleep = 0.8mA instead of deep_sleep = 5uA (light sleep does no warm start and keeps the status): How can I call the trigger(...) method of the WeatherChannel after the wakeup from sleep (as I don't have the RTC and Activity class which does it on the Arduino? I only have the sdev instance right?

I should call the tigger(..) method before I go to light sleep. // read sensors and send message -> here I need the hint

Heer is my setup and loop // device setup // void setup () { DINIT(115200, ASKSIN_PLUS_PLUS_IDENTIFIER); bool first = sdev.init(hal); // this will also trigger powerUpAction handling bool low = sdev.getConfigByte(CFG_LOWACTIVE_BYTE); buttonISR(cfgBtn, CONFIG_BUTTON_PIN); initPeerings(first);

initDisplay();

const GFXfont* f = &FreeMonoBold12pt7b; display.setFont(f); display.setCursor(0, 16); display.println("Homematic THI"); display.update();

sdev.initDone(); DPRINT("init completed\n"); }

//---------------------------------------------------------------------------------- // device loop // void loop() { DPRINT("in loop\n"); bool worked = hal.runready(); bool poll = sdev.pollRadio(); if ( worked == false && poll == false ) { // read sensors and send message esp_sleep_enable_timer_wakeup(MSG_INTERVAL * 1000000); // 60 seconds int ret = esp_light_sleep_start(); DPRINT("light_sleep\n");
} }

pa-pa commented 6 years ago

You can simply use the sysclock and convert the seconds to ticks. Then the trigger will called by the sysclock. For the sleep code take a look into the Sleep class in the Activity.h file. You can simply replace the doSleep() method with the correct code for the esp. This class will also correct the sysclock by the value returned from doSleep(). So if the timer are stopped during sleep, you can correct this after wakeup. With your ESPSlleep class you can use the "normal" loop.

if( worked==false && poll==false) { hal.activity.savePower<ESPSleep<>>(hal); }

knopserl commented 6 years ago

Thanks for your patience and your further hints. The Activity class is the most difficult for me to understand as it's based on the Arduino only LowPower lib and has also a couple of other very HW related parts.

I'm trying to follow your hints but I#m not sure if I can follwo you. I have copied the code of the Sleep class. I get compile errors as I most likeky do the declaration wrong. I only have changed the ESP wakeup code in the doSleep method. I guess I can ignore the ENABLETIMER2 definition in the doSleep code. The ESP32 has two timer groups with two timer each. There counter does not get lost during light or deep sleep. In deep sleep all program variables get lost and only the 8k RAM in the RTC are kept. Thus the ESP32 would do a warm start and runs through the Setup() part of the sketch and of course all peripherals like SPI, I2C etc have to be reinitialized (deep sleep keeps only the RTC/RAM/counter running = 5uA).

So here is the Sleep class and I have only changed/partially understood the doSleep part.

ifdef ARDUINO_ARCH_ESP32

template class Sleep : public Idle { public: static uint32_t doSleep (uint32_t ticks) { uint32_t offset = 0; period_t sleeptime = SLEEP_FOREVER;

if( ticks > seconds2ticks(8) ) { offset = seconds2ticks(8); sleeptime = SLEEP_8S; }
else if( ticks > seconds2ticks(4) )  { offset = seconds2ticks(4);  sleeptime = SLEEP_4S; }
else if( ticks > seconds2ticks(2) )  { offset = seconds2ticks(2);  sleeptime = SLEEP_2S; }
else if( ticks > seconds2ticks(1) )  { offset = seconds2ticks(1);  sleeptime = SLEEP_1S; }
else if( ticks > millis2ticks(500) ) { offset = millis2ticks(500); sleeptime = SLEEP_500MS; }
else if( ticks > millis2ticks(250) ) { offset = millis2ticks(250); sleeptime = SLEEP_250MS; }
else if( ticks > millis2ticks(120) ) { offset = millis2ticks(120); sleeptime = SLEEP_120MS; }
else if( ticks > millis2ticks(60)  ) { offset = millis2ticks(60);  sleeptime = SLEEP_60MS; }
else if( ticks > millis2ticks(30)  ) { offset = millis2ticks(30);  sleeptime = SLEEP_30MS; }
else if( ticks > millis2ticks(15)  ) { offset = millis2ticks(15);  sleeptime = SLEEP_15MS; }

if( ENABLETIMER2 == false ) {
  esp_sleep_enable_timer_wakeup(sleeptime * 1000000);
}
else {
  esp_sleep_enable_timer_wakeup(sleeptime * 1000000);
}
return offset;

}

template static void powerSave (Hal& hal) { sysclock.disable(); uint32_t ticks = sysclock.next(); if( sysclock.isready() == false ) { if( ticks == 0 || ticks > millis2ticks(15) ) { hal.radio.setIdle(); uint32_t offset = doSleep(ticks); sysclock.correct(offset); sysclock.enable(); } else{ sysclock.enable(); Idle::powerSave(hal); } } else { sysclock.enable(); } } };

endif

pa-pa commented 6 years ago

doSleep should pause the CPU as long as possible. It gets the ticks until the next timer is ready to work. For ESP it may look like this:

public: static uint32_t doSleep (uint32_t ticks) {
  uint32_t sleeptime = ticks2millis(ticks);
  esp_sleep_enable_timer_wakeup(sleeptime * 1000);
  return ticks;
}
knopserl commented 6 years ago

the question was more on the Sleep class declaration which gives compile errors:

ifdef ARDUINO_ARCH_ESP32

template class Sleep : public Idle { public: static uint32_t doSleep (uint32_t ticks) { uint32_t offset = 0; period_t sleeptime = SLEEP_FOREVER; ....

I get this error: D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/Activity.h:143:26: error: expected template-name before '<' token

class Sleep : public Idle { ^ D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/Activity.h:143:26: error: expected '{' before '<' token D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/Activity.h:143:26: error: expected unqualified-id before '<' token

so it look to me, that the "idle" is not known and that comes from the the LowPower class (which is not ESP compatible) or from the Activity class itself?

pa-pa commented 6 years ago

Ah, you don't need to inherit Idle. So you also don't need to use a template. The following should work:

class ESPSleep {
public:
  static uint32_t doSleep (uint32_t ticks) { ... }
  template <class Hal> static void powerSave (Hal& hal) { ... }
};
knopserl commented 6 years ago

Hey pa-pa, that was helpful and what I was looking for. The full declararion of the sleep class inclusing the uint32_t sleeptime = ticks2millis(ticks) because otherwise I would have required the redefinition of the period_t from the LowPower.h (which I actually don't need anymore).

The class has now compiled without errors but when I use it the the main program I get still a few errors

D:\mcdev\arduino\portable\sketchbook_ESP32\ESP32_HM-WDS10_ePaper\ESP32_HM-WDS10_ePaper.ino: In function 'void loop()':

ESP32_HM-WDS10_ePaper:334: error: 'as::Sleep' is not a template hal.activity.savePower<Sleep<>>(hal);
^ In file included from D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/AskSinPP.h:37:0, from D:\mcdev\arduino\portable\sketchbook_ESP32\ESP32_HM-WDS10_ePaper\ESP32_HM-WDS10_ePaper.ino:38: D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/Activity.h: In instantiation of 'void as::Activity::savePower(Hal&) [with Saver = as::Sleep; Hal = Hal]': D:\mcdev\arduino\portable\sketchbook_ESP32\ESP32_HM-WDS10_ePaper\ESP32_HM-WDS10_ePaper.ino:334:40: required from here D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/Activity.h:213:24: error: 'waitSerial' is not a member of 'as::Sleep' Saver::waitSerial(); ^

here is what the class Sleep() looks like, but I'm sure I have also remove some code from the powerSave method (like dealing with offset and correct millis2ticks or so)

ifdef ARDUINO_ARCH_ESP32

class Sleep { public: static uint32_t doSleep (uint32_t ticks) { uint32_t sleeptime = ticks2millis(ticks);

esp_sleep_enable_timer_wakeup(sleeptime * 1000);
esp_light_sleep_start();

return ticks;

}

template static void powerSave (Hal& hal) { sysclock.disable(); uint32_t ticks = sysclock.next(); if( sysclock.isready() == false ) { if( ticks == 0 || ticks > millis2ticks(15) ) { hal.radio.setIdle(); uint32_t offset = doSleep(ticks); sysclock.correct(offset); sysclock.enable(); } else{ sysclock.enable(); // Idle::powerSave(hal); <-- this would not compile powerSave(hal); } } else { sysclock.enable(); } } };

endif

pa-pa commented 6 years ago

The Sleep class is no longer a template. Simply change the loop call to

hal.activity.savePower<Sleep<>>(hal);

Please add also a empty method

static void waitSerial () {}

to your Sleep class. This is on AVR for waiting that the serial buffer is empty before got to sleep. May be not needed on ESP.

knopserl commented 6 years ago

I added the empty wait serial and one error is gone. I had already the statement you have given to me: hal.activity.savePower<Sleep<>>(hal); but I think this is what requires a template. And removing the < <>> did not work.

ESP32_HM-WDS10_ePaper:334: error: 'as::Sleep' is not a template hal.activity.savePower<Sleep<>>(hal);
^ BTW: You're right I did investigations on the wait serial logic (wait for completing the serial transmition) and the ESP32 should not require the effort as it expected that it automatically takes care on that. Many things are stated to be much easier (as ESP are more capeable) than on the older AVR's or STM32 architectures. However, your code i quite advanced and requires good skills to port it, even using better HW.

AI added a picture of my prototype I'm using for this testing. As you see, I use a second/seperate SPI bus just for the E-Paper to have no negative impact on the RF module communication. The ESP32 has 16MB Flash (pretty standard for every ESP32 Wroom module) and 520kb RAM. So Flash/RAM issues are not forseeable in near future.

esp32-pilot-rf-e-paper-sensor-button

I'm also working with ransey (he is doing a couple of very good PCB's for e.g. MapleCUL/CUN and mySensors) to get a PCB for the ESP32 using this kind of small boards to build Homematic, ESPnow or LoRa solutions with a single PCB layout.

https://de.aliexpress.com/item/-/32829367382.html?uttaskid=42008&utcontentid=1396&utalgorithmid=4&tracelog=rowan&rowan_id1=eclc_en_1_1_en_US_2018-05-23&rowan_msg_id=heinUTT_42008_7992937_%2437c5d41f7e4b4a3686bbe5145b3bb715&ck=in_edm_other

pa-pa commented 6 years ago

Sorry Cut&Paste error. It has to be

hal.activity.savePower< Sleep >(hal);

knopserl commented 6 years ago

Ok, done. There are still some things which do not fit. Something around the Saver template class in hal:

D:\mcdev\arduino\portable\sketchbook_ESP32\ESP32_HM-WDS10_ePaper\ESP32_HM-WDS10_ePaper.ino: In function 'void loop()':

ESP32_HM-WDS10_ePaper:334: error: no matching function for call to 'as::Activity::savePower(Hal&)' hal.activity.savePower(hal);
^ In file included from D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/AskSinPP.h:37:0, from D:\mcdev\arduino\portable\sketchbook_ESP32\ESP32_HM-WDS10_ePaper\ESP32_HM-WDS10_ePaper.ino:38:

D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/Activity.h:212:8: note: candidate: template<class Saver, class Hal> void as::Activity::savePower(Hal&) void savePower (Hal& hal) { ^ D:\mcdev\arduino\portable\sketchbook\libraries\AskSinPP/Activity.h:212:8: note: template argument deduction/substitution failed: D:\mcdev\arduino\portable\sketchbook_ESP32\ESP32_HM-WDS10_ePaper\ESP32_HM-WDS10_ePaper.ino:334:31: note: couldn't deduce template parameter 'Saver' hal.activity.savePower(hal);
^

pa-pa commented 6 years ago

Sleep is needed as template argument to the savePower() method. hal.activity.savePower< Sleep >(hal);

knopserl commented 6 years ago

that compiles without error! thanks. Now the solution behaves as follows: after successful start it sleeps for about 20secs and then it continues and loop indefinitly with no break/sleep. It does not enter the trigger method of the WeatherChannel class to measure and does not reinitialize the sleep timer. We have not ported/implemented the RTC class right? And where is the ticks set back to set the proper sleeptime? And why is the trigger method not called and thus no measure?

One reason might be, that I have to replace the rtc.add by sysclock.add(this) here:? // reactivate for next measure HMID id; device().getDeviceID(id); uint32_t nextsend = delay(id,msgcnt); tick = nextsend / 1000; // seconds to wait millis = nextsend % 1000; // millis to wait rtc.add(this); <-- this need to be replaced by sysclock?

But since I don't see trigger gets called, it might not change/solve the problem? Where is the interval for the subsequent sleep/breaks set?

Is it that setting in the sketch? I have not seen this interval been followed. //seconds between sending messages

define MSG_INTERVAL 10

Attached the startup log (with some loop log lines with no sleep) and I have also attched my Activity.h and my sketch if you're willing to take a look. It is derived from the HM-WDS10-TH-O sketch.

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:812 load:0x40078000,len:0 load:0x40078000,len:11572 entry 0x40078a5c AskSin++ V2.1.3 (May 23 2018 20:14:57) Address Space: 32 - 73 00000000 Init Storage: CAFE6189 CC init1 CC Version: 14

ESP32_HM-WDS10_ePaper.zip

pa-pa commented 6 years ago

I had a short look into the code. You need to replace the rtc with the sysclock, because the RTC is not implemented. See also the HM-WDS100-C6-O-2 example. It doesn't use the RTC.

knopserl commented 6 years ago

should I then rather use then the HM-WDS100-C6-O-2 as template rather then already used HM-WDS10-TH-O? Or just go ahead and exchange the RTC with sysclock? And I hope the trigger() is then called. BTW: Is there any example which transmitts float values (I have seen only uint8_ and uint16)

pa-pa commented 6 years ago

May be switching the example is more easy.

knopserl commented 6 years ago

Ok, I'll try it with the HM-WDS100-C6-O-2. Any answer to the transmissing of float values? I have so far seen only values from type int. Is there something to consider as I looks like its avoided in the samples?

jp112sdl commented 6 years ago

You only can transmit int values. If you want to transmit e.g. 1.2 you have to multiply it by 10 and send 12. The CCU divides it, as described in the XML file. For the HM-WDS100-C6-O-2 you can find it when you're looking for <conversion type="float_integer_scale" factor="10.0"/>

knopserl commented 6 years ago

@jp112sdl thanks! I have already assumed something like that and was considering a multiplier by 10, but was wondering how to tell the typical receiver I'm using (e.g. HomeGear, RedNode, OpenHAB) ,that the values are float/decimals and have to be divided by 10. I gues it's even wors, you can only transmit byte values and have to spread e.g. 16bit int over two bytes: pload[1] = ((raincounter >> 8) & 0xff) | (raining << 7); pload[2] = raincounter & 0xff; But thanks, now I know how to deal with the transmissing constraints. So I have to provide XML definitions for the receiver.