NodeManager: plugin for a rapid development of battery-powered sensors
-
I love the look of this setup. I am making my own slim nodes running at 8MHz with a basic 328P chip.
I am starting with a basic Thermistor which is fine but when I try to compile the code I get the following error.
exit status 1
default argument given for parameter 3 of 'void PowerManager::setPowerPins(int, int, long int)' [-fpermissive]My code is as follows:
// load user settings #include "config.h" // load MySensors library #include <MySensors.h> // load NodeManager library #include "NodeManager.h" // create a NodeManager instance NodeManager nodeManager; // before void before() { // setup the serial port baud rate Serial.begin(9600); // instruct the board to sleep for 10 minutes for each cycle // nodeManager.setSleep(SLEEP,10,MINUTES); // register the sensors nodeManager.registerSensor(SENSOR_THERMISTOR,A1); // nodeManager.registerSensor(SENSOR_LDR,A2); /* * Register below your sensors */ /* * Register above your sensors */ nodeManager.before(); } // presentation void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Battery Temp Sensor","1.0"); // call NodeManager presentation routine nodeManager.presentation(); } // setup void setup() { // call NodeManager setup routine nodeManager.setup(); } // loop void loop() { // call NodeManager loop routine nodeManager.loop(); } // receive void receive(const MyMessage &message) { // call NodeManager receive routine nodeManager.receive(message); }Any help with sorting this out will be great.
Cheers,Ben
-
Thanks for your comment @Ben-Coton! The error message tells me that I'm doing something wrong in the code (http://stackoverflow.com/questions/2545720/error-default-argument-given-for-parameter-1) but I wonder why it compiles without error or warning on my system.
Meanwhile I'll fix the problem (tracking it with https://github.com/mysensors/NodeManager/issues/30), in case you want to try a workaround, I share below my platform.txt file since I'm sure there must be some flag in mine which is somehow ignoring the error when I compile it:
# Arduino AVR Core and platform. # ------------------------------ # # For more info: # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification name=Arduino AVR Boards version=1.6.17 # AVR compile variables # --------------------- compiler.warning_flags=-w compiler.warning_flags.none=-w compiler.warning_flags.default= compiler.warning_flags.more=-Wall compiler.warning_flags.all=-Wall -Wextra # Default "compiler.path" is correct, change only if you want to override the initial value compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects compiler.c.elf.flags={compiler.warning_flags} -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections compiler.c.elf.cmd=avr-gcc compiler.S.flags=-c -g -x assembler-with-cpp -flto -MMD compiler.cpp.cmd=avr-g++ compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto compiler.ar.cmd=avr-gcc-ar compiler.ar.flags=rcs compiler.objcopy.cmd=avr-objcopy compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 compiler.elf2hex.flags=-O ihex -R .eeprom compiler.elf2hex.cmd=avr-objcopy compiler.ldflags= compiler.size.cmd=avr-size # This can be overridden in boards.txt build.extra_flags= # These can be overridden in platform.local.txt compiler.c.extra_flags= compiler.c.elf.extra_flags= compiler.S.extra_flags= compiler.cpp.extra_flags= compiler.ar.extra_flags= compiler.objcopy.eep.extra_flags= compiler.elf2hex.extra_flags= # AVR compile patterns # -------------------- ## Compile c files recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Compile c++ files recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Compile S files recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Create archives # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value archive_file_path={build.path}/{archive_file} recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm ## Create output files (.eep and .hex) recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" ## Save hex recipe.output.tmp_file={build.project_name}.hex recipe.output.save_file={build.project_name}.{build.variant}.hex ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* ## Preprocessor preproc.includes.flags=-w -x c++ -M -MG -MP recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.includes.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" preproc.macros.flags=-w -x c++ -E -CC recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.macros.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{preprocessed_file_path}" # AVR Uploader/Programmers tools # ------------------------------ tools.avrdude.path={runtime.tools.avrdude.path} tools.avrdude.cmd.path={path}/bin/avrdude tools.avrdude.config.path={path}/etc/avrdude.conf tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q # tools.avrdude.upload.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value tools.avrdude.upload.verify= tools.avrdude.upload.params.noverify=-V tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} {upload.verify} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" tools.avrdude.program.params.verbose=-v tools.avrdude.program.params.quiet=-q -q # tools.avrdude.program.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value tools.avrdude.program.verify= tools.avrdude.program.params.noverify=-V tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" tools.avrdude.erase.params.verbose=-v tools.avrdude.erase.params.quiet=-q -q tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m tools.avrdude.bootloader.params.verbose=-v tools.avrdude.bootloader.params.quiet=-q -q tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu} tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port {upload.network.port} -sketch "{build.path}/{build.project_name}.hex" -upload {upload.network.endpoint_upload} -sync {upload.network.endpoint_sync} -reset {upload.network.endpoint_reset} -sync_exp {upload.network.sync_return} # USB Default Flags # Default blank usb manufacturer will be filled in at compile time # - from numeric vendor ID, set to Unknown otherwise build.usb_manufacturer="Unknown" build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'Thanks!
-
Thanks for the reply.
I have no idea about the platform.txt file so I will wait to see if someone much smarter than me can figure it out :)
If it helps, I am using the Arduino IDE V.1.81, compiling with a custom atmega328p board running at 8MHz with BOD disabled.
Ben
-
Oh I see, when you have custom hardware sometimes you have different options set for the compiler, this is why with the default settings works here. Nevertheless it is an easy fix on my side, just wait for v1.3 to be out very soon and it should compile without issues.
Thanks!
-
Hi, I've updated NodeManager to its 1.3 version. This should also solve your issue @Ben-Coton. Short changelog:
- Added support for BME280 temperature/humudity/pressure sensor
- Added option to measure battery level via a pin in addition to internal Vcc
- Added example sketches to the documentation
- Fixed a few bugs
Code and updated documentation (now with with four comprehensive examples including the full sketches at the end) on https://github.com/mysensors/NodeManager
-
@user2684 , Thanks for the new version.
Are you planning to include Virtual Button and IOExpander(MCP23017) support too? Thst would really help especially adding consistent child-ids for the expander pins, just like multiple temp sensors on the SPI bus...
-
@user2684 , Thanks for the new version.
Are you planning to include Virtual Button and IOExpander(MCP23017) support too? Thst would really help especially adding consistent child-ids for the expander pins, just like multiple temp sensors on the SPI bus...
@vikasjee I'm very open to whatever can make the life of an average user easier, so far I've just pitched what were common requirements for me as a new user but I'm sure there is a lot more that I'm missing. Give me some more info or pointers regarding Virtual Button and IOExpander and how you are using it right now, I couldn't find much here on the forum and my knowledge is limited and I'll look into it for sure!
Thanks -
I just started playing with this and must say FANTASTIC! This makes things almost too simple.
I found a few small things´(bugs?)
- You refer to the sourforge page for the latest releases (nit pick)
- Baud in the config.h is default set to 9800, shouldn't this be 9600? However, setting it to whatever doesn't help, only 4800 outputs anything, this could be something on my setup as well ...
Again, thanks!
-
It sounds absolutely terrific ! :+1:
Thank you very much !
-
I just started playing with this and must say FANTASTIC! This makes things almost too simple.
I found a few small things´(bugs?)
- You refer to the sourforge page for the latest releases (nit pick)
- Baud in the config.h is default set to 9800, shouldn't this be 9600? However, setting it to whatever doesn't help, only 4800 outputs anything, this could be something on my setup as well ...
Again, thanks!
@Efflon thanks for reporting these two issues, I'll track them down with https://github.com/mysensors/NodeManager/issues/34 and https://github.com/mysensors/NodeManager/issues/33 and fix asap!
Thank you all for your comments! -
@Efflon thanks for reporting these two issues, I'll track them down with https://github.com/mysensors/NodeManager/issues/34 and https://github.com/mysensors/NodeManager/issues/33 and fix asap!
Thank you all for your comments!@user2684 Excellent!
A question, I'm doing a simple door sensornodeManager.setBatteryMin(1.8); nodeManager.setBatteryMax(3.2); nodeManager.setBatteryReportCycles(1); int door = nodeManager.registerSensor(SENSOR_DOOR,3); ((SensorDoor*)nodeManager.get(door))->setDebounce(500); nodeManager.setSleep(SLEEP,1,HOURS);Now, the node is constantly sending. It seems as if every wake-up triggers a sending, and a wakeup from the debounce sleep, then battery reporting etc.. Removing the debounce helps and lets the node sleep.
AWAKE SEND D=0 I=200 C=1 T=48 S=AWAKE I=0 F=0.00 BATT V=3.16 P=97 SEND D=0 I=201 C=0 T=38 S= I=0 F=3.16 SWITCH I=1 P=3 V=0 SEND D=0 I=1 C=1 T=16 S= N=0 F=0.00 SLEEP 60s SEND D=0 I=200 C=1 T=48 S=SLEEPING I=0 F=0.00 [here i "open" the door] WAKE P=3, M=1 AWAKE SEND D=0 I=200 C=1 T=48 S=AWAKE I=0 F=0.00 BATT V=3.16 P=97 SEND D=0 I=201 C=0 T=38 S= I=0 F=3.16 SWITCH I=1 P=3 V=1 SEND D=0 I=1 C=1 T=16 S= N=1 F=0.00 SLEEP 60s SEND D=0 I=200 C=1 T=48 S=SLEEPING I=0 F=0.00 [just a second wait] WAKE P=3, M=1 AWAKE SEND D=0 I=200 C=1 T=48 S=AWAKE I=0 F=0.00 BATT V=3.16 P=97 SEND D=0 I=201 C=0 T=38 S= I=0 F=3.16 SWITCH I=1 P=3 V=1 SEND D=0 I=1 C=1 T=16 S= N=1 F=0.00 SLEEP 60s [repeated until closing "door"]Edit:
I changed the sleep to a wait and now the behavior is correct (this line).
// what do to during loop void SensorSwitch::onLoop() { // wait to ensure the the input is not floating if (_debounce > 0) wait(_debounce); // read the value of the pin int value = digitalRead(_pin);MY I=8 M=1 SEND D=0 I=200 C=0 T=48 S=STARTED I=0 F=0.00 SWITCH I=1 P=3 V=0 SEND D=0 I=1 C=0 T=16 S= N=0 F=0.00 SLEEP 60s SEND D=0 I=200 C=1 T=48 S=SLEEPING I=0 F=0.00 [open] WAKE P=3, M=1 AWAKE SEND D=0 I=200 C=1 T=48 S=AWAKE I=0 F=0.00 BATT V=3.16 P=97 SEND D=0 I=201 C=0 T=38 S= I=0 F=3.16 SWITCH I=1 P=3 V=1 SEND D=0 I=1 C=1 T=16 S= N=1 F=0.00 SLEEP 60s SEND D=0 I=200 C=1 T=48 S=SLEEPING I=0 F=0.00 [close] WAKE P=3, M=1 AWAKE SEND D=0 I=200 C=1 T=48 S=AWAKE I=0 F=0.00 BATT V=3.16 P=97 SEND D=0 I=201 C=0 T=38 S= I=0 F=3.16 SWITCH I=1 P=3 V=0 SEND D=0 I=1 C=1 T=16 S= N=0 F=0.00 SLEEP 60s SEND D=0 I=200 C=1 T=48 S=SLEEPING I=0 F=0.00 -
Thanks for the hit @Efflon! I accidentally fixed that sleep() in the v1.4 dev branch this afternoon because of another issue. Is everything else now behaving correctly?
I have a concern regarding battery level reports when operating with interrupts: right now I do not distinguish between a cycle because a full sleep has completed from a cycle interrupted by an interrupt like in this case. This may cause a lot more battery reports, depending on how often the sensor triggers. To avoid this unexpected behavior, in the dev branch the default behavior is now the opposite: waking up from an interrupt does not count as a cycle. The drawback though is that if the sensor triggers continuously, it will never report the battery to the controller since unable to complete a full sleeping cycle. This is why I've added the following so allow the user to pick up the policy he likes the most:
// If true, wake up by an interrupt counts as a valid cycle for battery reports otherwise only uninterrupted sleep cycles would contribute (default: false) void setBatteryReportWithInterrupt(bool value);In case you want to give this a try, the dev branch is available at https://github.com/mysensors/NodeManager/tree/v1.4-dev. You just need to replace the existing NodeManager.cpp and NodeManager.h files, you can keep both your sketch and your config.h.
Thanks -
Thanks for the hit @Efflon! I accidentally fixed that sleep() in the v1.4 dev branch this afternoon because of another issue. Is everything else now behaving correctly?
I have a concern regarding battery level reports when operating with interrupts: right now I do not distinguish between a cycle because a full sleep has completed from a cycle interrupted by an interrupt like in this case. This may cause a lot more battery reports, depending on how often the sensor triggers. To avoid this unexpected behavior, in the dev branch the default behavior is now the opposite: waking up from an interrupt does not count as a cycle. The drawback though is that if the sensor triggers continuously, it will never report the battery to the controller since unable to complete a full sleeping cycle. This is why I've added the following so allow the user to pick up the policy he likes the most:
// If true, wake up by an interrupt counts as a valid cycle for battery reports otherwise only uninterrupted sleep cycles would contribute (default: false) void setBatteryReportWithInterrupt(bool value);In case you want to give this a try, the dev branch is available at https://github.com/mysensors/NodeManager/tree/v1.4-dev. You just need to replace the existing NodeManager.cpp and NodeManager.h files, you can keep both your sketch and your config.h.
Thanks@user2684 said in NodeManager: plugin for a rapid development of battery-powered sensors:
behavior, in the dev branch the default behavior is now the opposite: waking up from an interrupt does not count as a cycle. The drawback though is that if the sensor triggers continuously, it will never report the battery to the controller since unable to complete a full sleep
This is tricky. Myself uses the battery report as a heartbeat on top of checking the battery level, thus I only need the info once or twice a day. Not sending on wake-up is good since it will preserve battery. I guess a combination the right sleeping time and cycle count could end up quite ok. For a front door sensor, 4h sleep and 2 cycle count would report battery level after the night and then maybe one more time, max 3 times per day, which is more than enough. I'll test the dev branch after some sleep :smile:
Btw, great work!! and yes, using wait works just fine, no other issues so far.
-
Hello everyone, you can send commands to the node by domoticz even if the node is in sleep forever? Or the node must always have a sleep delay?
@mar.conte if it's sleeping, it will not receive anything until wake-up. If you change the sleep mode to wait,
nodeManager.setSleepMode(WAIT); [or] nodeManager.setSleep(WAIT,1,HOURS);the sensor will be awake all the time (and drain your battery).
-
@user2684 said in NodeManager: plugin for a rapid development of battery-powered sensors:
behavior, in the dev branch the default behavior is now the opposite: waking up from an interrupt does not count as a cycle. The drawback though is that if the sensor triggers continuously, it will never report the battery to the controller since unable to complete a full sleep
This is tricky. Myself uses the battery report as a heartbeat on top of checking the battery level, thus I only need the info once or twice a day. Not sending on wake-up is good since it will preserve battery. I guess a combination the right sleeping time and cycle count could end up quite ok. For a front door sensor, 4h sleep and 2 cycle count would report battery level after the night and then maybe one more time, max 3 times per day, which is more than enough. I'll test the dev branch after some sleep :smile:
Btw, great work!! and yes, using wait works just fine, no other issues so far.
@Efflon glad to see you found out the right balance for you needs. Based on what you are saying I probably want change the default value of setBatteryReportWithInterrupt() back to true, in this way the new version will present the same behavior as the old one but can be changed at any time by the user. Of course if anybody has a different view, please let me know.
-
@mar.conte if it's sleeping, it will not receive anything until wake-up. If you change the sleep mode to wait,
nodeManager.setSleepMode(WAIT); [or] nodeManager.setSleep(WAIT,1,HOURS);the sensor will be awake all the time (and drain your battery).
@Efflon @mar-conte, if the sensor is powered by batteries, I'll leverage smart sleep which NodeManager is using by default. Smart sleep is btw the reason why I moved into MySensors: since all of my sensors are battery powered, I needed a way to send commands also in this situation.
There is no overhead for the sensor in terms of code (it just needs to wake up periodically to receive commands) and on the controller side the implementation is very simple: once the controller knows the node is a sleeping one, it will queue the commands and send them once the node is awake next (when using smart sleep, a heartbeat is reported once the node is awake and just before going to sleep again).
I'm using this since a while for my boiler controller without issue: the node controls a (latching) relay and goes through a 5 minutes sleeping cycle with the controller (I'm using my https://www.mysensors.org/controller/myhouse) queuing the on/off command. This will introduce a little delay (1-5 minutes in my case) but can be adapted with a shorter/longer sleeping cycle.
-
@Efflon @mar-conte, if the sensor is powered by batteries, I'll leverage smart sleep which NodeManager is using by default. Smart sleep is btw the reason why I moved into MySensors: since all of my sensors are battery powered, I needed a way to send commands also in this situation.
There is no overhead for the sensor in terms of code (it just needs to wake up periodically to receive commands) and on the controller side the implementation is very simple: once the controller knows the node is a sleeping one, it will queue the commands and send them once the node is awake next (when using smart sleep, a heartbeat is reported once the node is awake and just before going to sleep again).
I'm using this since a while for my boiler controller without issue: the node controls a (latching) relay and goes through a 5 minutes sleeping cycle with the controller (I'm using my https://www.mysensors.org/controller/myhouse) queuing the on/off command. This will introduce a little delay (1-5 minutes in my case) but can be adapted with a shorter/longer sleeping cycle.