diff --git a/NodeManager.cpp b/NodeManager.cpp index 7ca319a0..7a9b56d5 100644 --- a/NodeManager.cpp +++ b/NodeManager.cpp @@ -34,33 +34,33 @@ float getVcc() { */ // set the vcc and ground pin the sensor is connected to -void PowerManager::setPowerPins(int ground_pin, int vcc_pin, long wait) { +void PowerManager::setPowerPins(int ground_pin, int vcc_pin, int wait_time) { #if DEBUG == 1 Serial.print(F("PWR G=")); Serial.print(ground_pin); Serial.print(F(" V=")); Serial.println(vcc_pin); #endif - // configure the vcc pin as output and initialize to low (power off) + // configure the vcc pin as output and initialize to high (power on) _vcc_pin = vcc_pin; pinMode(_vcc_pin, OUTPUT); - digitalWrite(_vcc_pin, LOW); + digitalWrite(_vcc_pin, HIGH); // configure the ground pin as output and initialize to low _ground_pin = ground_pin; pinMode(_ground_pin, OUTPUT); digitalWrite(_ground_pin, LOW); - _wait = wait; + _wait = wait_time; } // return true if power pins have been configured -bool PowerManager::_hasPowerManager() { +bool PowerManager::isConfigured() { if (_vcc_pin != -1 && _ground_pin != -1) return true; return false; } // turn on the sensor by activating its power pins void PowerManager::powerOn() { - if (! _hasPowerManager()) return; + if (! isConfigured()) return; #if DEBUG == 1 Serial.print(F("ON P=")); Serial.println(_vcc_pin); @@ -73,7 +73,7 @@ void PowerManager::powerOn() { // turn off the sensor void PowerManager::powerOff() { - if (! _hasPowerManager()) return; + if (! isConfigured()) return; #if DEBUG == 1 Serial.print(F("OFF P=")); Serial.println(_vcc_pin); @@ -145,8 +145,8 @@ void Sensor::setFloatPrecision(int value) { _float_precision = value; } #if POWER_MANAGER == 1 - void Sensor::setPowerPins(int ground_pin, int vcc_pin, long wait) { - _powerManager.setPowerPins(ground_pin, vcc_pin, wait); + void Sensor::setPowerPins(int ground_pin, int vcc_pin, int wait_time) { + _powerManager.setPowerPins(ground_pin, vcc_pin, wait_time); } void Sensor::setAutoPowerPins(bool value) { _auto_power_pins = value; @@ -1032,6 +1032,8 @@ SensorDs18b20::SensorDs18b20(int child_id, int pin, DallasTemperature* sensors, setValueType(TYPE_FLOAT); _index = index; _sensors = sensors; + // retrieve and store the address from the index + _sensors->getAddress(_device_address, index); } // what do to during before @@ -1045,13 +1047,13 @@ void SensorDs18b20::onSetup() { // what do to during loop void SensorDs18b20::onLoop() { // request the temperature - _sensors->requestTemperaturesByIndex(_index); + _sensors->requestTemperatures(); // read the temperature float temperature = _sensors->getTempCByIndex(_index); // convert it if (! getControllerConfig().isMetric) temperature = temperature * 1.8 + 32; #if DEBUG == 1 - Serial.print(F("DS18 I=")); + Serial.print(F("DS18B20 I=")); Serial.print(_child_id); Serial.print(F(" T=")); Serial.println(temperature); @@ -1064,6 +1066,22 @@ void SensorDs18b20::onLoop() { void SensorDs18b20::onReceive(const MyMessage & message) { onLoop(); } + +// function to print a device address +DeviceAddress* SensorDs18b20::getDeviceAddress() { + return &_device_address; +} + +// returns the sensor's resolution in bits +int SensorDs18b20::getResolution() { + return _sensors->getResolution(_device_address); +} + +// set the sensor's resolution in bits +void SensorDs18b20::setResolution(int value) { + _sensors->setResolution(_device_address, value); +} + #endif /* @@ -1311,8 +1329,8 @@ void NodeManager::setInterrupt(int pin, int mode, int pull) { } } #if POWER_MANAGER == 1 - void NodeManager::setPowerPins(int ground_pin, int vcc_pin, long wait) { - _powerManager.setPowerPins(ground_pin, vcc_pin, wait); + void NodeManager::setPowerPins(int ground_pin, int vcc_pin, int wait_time) { + _powerManager.setPowerPins(ground_pin, vcc_pin, wait_time); } void NodeManager::setAutoPowerPins(bool value) { _auto_power_pins = value; @@ -1380,7 +1398,7 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) { else if (sensor_type == SENSOR_DOOR) index = registerSensor(new SensorDoor(child_id, pin)); else if (sensor_type == SENSOR_MOTION) index = registerSensor(new SensorMotion(child_id, pin)); // set an interrupt on the pin and activate internal pull up - SensorSwitch* sensor = (SensorSwitch*)get(index); + SensorSwitch* sensor = (SensorSwitch*)getSensor(index); setInterrupt(pin,sensor->getMode(),sensor->getInitial()); return index; } @@ -1466,6 +1484,22 @@ Sensor* NodeManager::get(int child_id) { // return a pointer to the sensor from the given child_id return _sensors[child_id]; } +Sensor* NodeManager::getSensor(int child_id) { + return get(child_id); +} + +// assign a different child id to a sensor' +bool NodeManager::renameSensor(int old_child_id, int new_child_id) { + // ensure the old id exists and the new is available + if (_sensors[old_child_id] == 0 || _sensors[new_child_id] != 0) return false; + // assign the sensor to new id + _sensors[new_child_id] = _sensors[old_child_id]; + // set the new child id + _sensors[new_child_id]->setChildId(new_child_id); + // free up the old id + _sensors[old_child_id] = 0; + return true; +} // setup NodeManager void NodeManager::before() { @@ -1525,7 +1559,7 @@ void NodeManager::before() { #endif } #endif - #if POWER_MANAGER == 1 + #if BATTERY_MANAGER == 1 // set analogReference to internal if measuring the battery through a pin if (! _battery_internal_vcc && _battery_pin > -1) analogReference(INTERNAL); #endif @@ -1731,7 +1765,7 @@ void NodeManager::_process(const char * message) { } // VERSION: send back the extension's version else if (strcmp(message, "VERSION") == 0) { - _send(_msg.set(VERSION, 1)); + _send(_msg.set(VERSION)); } #if REMOTE_CONFIGURATION == 1 // IDxxx: change the node id to the provided one. E.g. ID025: change the node id to 25. Requires a reboot/restart diff --git a/NodeManager.h b/NodeManager.h index 917fb42a..aba7f6e4 100644 --- a/NodeManager.h +++ b/NodeManager.h @@ -7,6 +7,8 @@ #include +// define NodeManager version +#define VERSION "1.4-dev1" /*********************************** Constants @@ -40,9 +42,6 @@ #define EEPROM_SLEEP_TIME_MINOR 3 #define EEPROM_SLEEP_UNIT 4 -// define NodeManager version -#define VERSION 1.4 - /************************************ * Include user defined configuration settings */ @@ -247,15 +246,15 @@ class PowerManager { public: PowerManager() {}; // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand - void setPowerPins(int ground_pin, int vcc_pin, long wait = 50); + void setPowerPins(int ground_pin, int vcc_pin, int wait_time = 50); void powerOn(); void powerOff(); float getVcc(); + bool isConfigured(); private: int _vcc_pin = -1; int _ground_pin = -1; long _wait = 0; - bool _hasPowerManager(); }; @@ -295,7 +294,7 @@ class Sensor { void setSleepBetweenSend(int value); #if POWER_MANAGER == 1 // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand - void setPowerPins(int ground_pin, int vcc_pin, long wait = 50); + void setPowerPins(int ground_pin, int vcc_pin, int wait_time = 50); // if enabled the pins will be automatically powered on while awake and off during sleeping (default: true) void setAutoPowerPins(bool value); // manually turn the power on @@ -637,10 +636,17 @@ class SensorDs18b20: public Sensor { void onSetup(); void onLoop(); void onReceive(const MyMessage & message); + // return the sensors' device address + DeviceAddress* getDeviceAddress(); + // returns the sensor's resolution in bits + int getResolution(); + // set the sensor's resolution in bits + void setResolution(int value); protected: float _offset = 0; int _index; DallasTemperature* _sensors; + DeviceAddress _device_address; }; #endif @@ -722,7 +728,7 @@ class NodeManager { void setBatteryPin(int value); // if setBatteryInternalVcc() is set to false, the volts per bit ratio used to calculate the battery voltage (default: 0.003363075) void setBatteryVoltsPerBit(float value); - // If true, wake up by an interrupt counts as a valid cycle for battery reports otherwise only uninterrupted sleep cycles would contribute (default: false) + // If true, wake up by an interrupt counts as a valid cycle for battery reports otherwise only uninterrupted sleep cycles would contribute (default: true) void setBatteryReportWithInterrupt(bool value); #endif #if SLEEP_MANAGER == 1 @@ -746,9 +752,12 @@ class NodeManager { int registerSensor(Sensor* sensor); // return a sensor by its index Sensor* get(int sensor_index); + Sensor* getSensor(int sensor_index); + // assign a different child id to a sensor + bool renameSensor(int old_child_id, int new_child_id); #if POWER_MANAGER == 1 // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand - void setPowerPins(int ground_pin, int vcc_pin, long wait = 50); + void setPowerPins(int ground_pin, int vcc_pin, int wait_time = 50); // if enabled the pins will be automatically powered on while awake and off during sleeping (default: true) void setAutoPowerPins(bool value); // manually turn the power on @@ -773,7 +782,7 @@ class NodeManager { float _battery_min = 2.6; float _battery_max = 3.3; int _battery_report_cycles = 10; - bool _battery_report_with_interrupt = false; + bool _battery_report_with_interrupt = true; bool _battery_internal_vcc = true; int _battery_pin = -1; float _battery_volts_per_bit = 0.003363075; diff --git a/NodeManager.ino b/NodeManager.ino index 1fc03880..a720850d 100644 --- a/NodeManager.ino +++ b/NodeManager.ino @@ -29,7 +29,8 @@ void before() { /* * Register below your sensors */ - nodeManager.registerSensor(SENSOR_ML8511,A1); + + /* * Register above your sensors diff --git a/README.md b/README.md index da1f0fc9..9789909c 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Node Manager comes with a reasonable default configuration. If you want/need to void setBatteryPin(int value); // if setBatteryInternalVcc() is set to false, the volts per bit ratio used to calculate the battery voltage (default: 0.003363075) void setBatteryVoltsPerBit(float value); - // If true, wake up by an interrupt counts as a valid cycle for battery reports otherwise only uninterrupted sleep cycles would contribute (default: false) + // If true, wake up by an interrupt counts as a valid cycle for battery reports otherwise only uninterrupted sleep cycles would contribute (default: true) void setBatteryReportWithInterrupt(bool value); #endif #if SLEEP_MANAGER == 1 @@ -158,6 +158,9 @@ Node Manager comes with a reasonable default configuration. If you want/need to int registerSensor(Sensor* sensor); // return a sensor by its index Sensor* get(int sensor_index); + Sensor* getSensor(int sensor_index); + // assign a different child id to a sensor + bool renameSensor(int old_child_id, int new_child_id); #if POWER_MANAGER == 1 // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand void setPowerPins(int ground_pin, int vcc_pin, long wait = 0); @@ -234,10 +237,10 @@ nodeManager.registerSensor(new SensorCustom(child_id, pin)); ## Configuring the sensors Each built-in sensor class comes with reasonable default settings. In case you want/need to customize any of those settings, after having registered the sensor, you can retrieve it back and call set functions common to all the sensors or specific for a given class. -To do so, use `nodeManager.get(child_id)` which will return a pointer to the sensor. Remeber to cast it to the right class before calling their functions. For example: +To do so, use `nodeManager.getSensor(child_id)` which will return a pointer to the sensor. Remeber to cast it to the right class before calling their functions. For example: ~~~c -((SensorLatchingRelay*)nodeManager.get(2))->setPulseWidth(50); +((SensorLatchingRelay*)nodeManager.getSensor(2))->setPulseWidth(50); ~~~ @@ -359,6 +362,16 @@ Each sensor class can expose additional methods. void setInitial(int value); ~~~ +#### SensorDs18b20 +~~~c + // return the sensors' device address + DeviceAddress* getDeviceAddress(); + // returns the sensor's resolution in bits + int getResolution(); + // set the sensor's resolution in bits + void setResolution(int value); +~~~ + ## Upload your sketch Upload your sketch to your arduino board as you are used to. @@ -507,14 +520,14 @@ Register a LDR sensor attached to pin A1 and send to the gateway the average of ~~~c int sensor_ldr = nodeManager.registerSensor(SENSOR_LDR,A1); - ((SensorLDR*)nodeManager.get(sensor_ldr))->setSamples(3); + ((SensorLDR*)nodeManager.getSensor(sensor_ldr))->setSamples(3); ~~~ Register a rain sensor connected to A0. This will be powered with via pins 4 (ground) and 5 (vcc) just before reading its value at each cycle, it will be presented as S_RAIN. sending V_RAINRATE messages, the output will be a percentage (calculated between 200 and 1024) and the value will be reversed (so that no rain will be 0%): ~~~c int rain = nodeManager.registerSensor(SENSOR_ANALOG_INPUT,A0); - SensorAnalogInput* rainSensor = ((SensorAnalogInput*)nodeManager.get(rain)); + SensorAnalogInput* rainSensor = ((SensorAnalogInput*)nodeManager.getSensor(rain)); rainSensor->setPowerPins(4,5,300); rainSensor->setPresentation(S_RAIN); rainSensor->setType(V_RAINRATE); @@ -765,7 +778,7 @@ void receive(const MyMessage &message) { ## Rain and Soil Moisture Sensor The following sketch can be used to report the rain level and the soil moisture based on two sensors connected to the board's analog pins (A1 and A2). In this case we are customizing the out-of-the-box SENSOR_ANALOG_INPUT sensor type since we just need to measure an analog input but we also want to provide the correct type and presentation for each sensor. -We register the sensors first with registerSensor() which returns the child id assigned to the sensor. We then retrieve the sensor's reference by calling get() so we can invoke the sensor-specific functions, like setPresentation() and setType(). +We register the sensors first with registerSensor() which returns the child id assigned to the sensor. We then retrieve the sensor's reference by calling getSensor() so we can invoke the sensor-specific functions, like setPresentation() and setType(). In this example, the two sensors are not directly connected to the battery's ground and vcc but, to save additional power, are powered through two arduino's pins. By using e.g. setPowerPins(4,5,300), NodeManger will assume pin 4 is ground and pin 5 is vcc for that specific sensor so it will turn on the power just before reading the analog input (and waiting 300ms for the sensor to initialize) and back off before going to sleep. For both the sensors we want a percentage output and with setRangeMin() and setRangeMax() we define the boundaries for calculating the percentage (if we read e.g. 200 when the rain sensor is completely into the water, we know for sure it will not go below this value which will represent the new lower boundary). Finally, since both the sensors reports low when wet and high when dry but we need the opposite, we set setReverse() so to have 0% reported when there is no rain/moisture, 100% on the opposite situation. @@ -809,8 +822,8 @@ void before() { int rain = nodeManager.registerSensor(SENSOR_ANALOG_INPUT,A1); int soil = nodeManager.registerSensor(SENSOR_ANALOG_INPUT,A2); - SensorAnalogInput* rainSensor = ((SensorAnalogInput*)nodeManager.get(rain)); - SensorAnalogInput* soilSensor = ((SensorAnalogInput*)nodeManager.get(soil)); + SensorAnalogInput* rainSensor = ((SensorAnalogInput*)nodeManager.getSensor(rain)); + SensorAnalogInput* soilSensor = ((SensorAnalogInput*)nodeManager.getSensor(soil)); rainSensor->setPresentation(S_RAIN); rainSensor->setType(V_RAINRATE); diff --git a/config.h b/config.h index c5f1c09b..f52ec5d2 100644 --- a/config.h +++ b/config.h @@ -5,8 +5,8 @@ * Sketch configuration */ -#define SKETCH_NAME "NodeManager" -#define SKETCH_VERSION "1.4" +#define SKETCH_NAME "NodeManagerTemplate" +#define SKETCH_VERSION "1.0" /********************************** * MySensors configuration