Hey,
in the last two month i have spend some time in the rollershutter node. Maybe some of you can use the sketch (it`s an upgrade from depressles sketch).
Some Points to the Sketch:
-send periodically the position and the temperature of the node
-two button (when the shutter ist moving any button stops)
-two times for moving (my Shutters are faster, when they moving down)
-sending up&down time from pimatic
-sending the wantet position from pimatic
If you have any idea to improve it, please tell me!
// Enable debug prints to serial monitor
//
//#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
#define MY_RF24_PA_LEVEL RF24_PA_HIGH // _LOW _MAX empfindlichkeit und sendestärke des Funkmoduls
#define MY_RF24_IRQ_PIN (2) // zwischenspeichern von empfangenen Informationen
#define MY_RX_MESSAGE_BUFFER_FEATURE
#define MY_RX_MESSAGE_BUFFER_SIZE (10)
#define MY_REPEATER_FEATURE //Repeaterfunktion eingeschaltet
#define USE_TEMP_SENSOR //Auskommentieren, wenn keine Temperatur übertragen werden soll.
#define MY_TRANSPORT_WAIT_READY_MS 3000 //set how long to wait for transport ready.
// uncomment if we want to manually assign an ID
//#define MY_NODE_ID 1 /
#include <Bounce2.h>
#include <MySensors.h>
#include <SPI.h>
// Temperature sensor definitions
#ifdef USE_TEMP_SENSOR
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 8 //Dallas Sensor
#define CHILD_DSB_ID 13 // Id of the sensor child for temperature sensor
#define TEMPERATURE_ROUNDING 10.f // Change value to change rounding of temperature value: 10.f for 0.1°C change, 5.f for 0.2°C change, 2.f for 0.5°C change
#define TEMPERATURE_THRESHOLD 2.0 // If threshold is reached, new temperature value will be sent
#define TEMPERATURE_INTERVAL_MS 900000 // Temperature will be sent every 15 minutes
#endif
#define BUTTON_UP_PIN 5 // Arduino Digital I/O pin number for up button
#define BUTTON_DOWN_PIN 3 // Arduino Digital I/O pin number for down button
#define RELAY_DIR_PIN 6 // Arduino Digital I/O pin number for direction relay
#define RELAY_POWER_PIN 7 // Arduino Digital I/O pin number for power relay
#define RELAY_ON 1
#define RELAY_OFF 0
#define DIRECTION_DOWN 1
#define DIRECTION_UP 0
#define SKETCH_NAME "roller shutter"
#define SKETCH_VER "2.1"
#define CHILD_ID 1 // sensor Id of the sensor child
#define CHILD_ID_SET_UP 2 // sensor Id of the sensor child to init the roll time up
#define CHILD_ID_SET_DOWN 3 // sensor Id of the sensor child to init the roll time down
#define PRESENT_MESSAGE "sensor for roller shutter"
const int LEVELS = 100; //the number of levels
float rollTimeUp = 39.0; //the overall rolling time of the shutter for going up -> changed by V_VAR1
float rollTimeDown = 36.0; //the overall rolling time of the shutter for going down -> changed by V_VAR2
const bool IS_ACK = false; //is to acknowlage
#define CHILD_ID_LIGHT 6 //Child ID for sending level
// debouncing parameters
int value = 0;
int oldValueUp = 0;
int oldValueDown = 0;
int oldValueStop = 0;
static unsigned long last_interrupt_time_up = 0;
static unsigned long last_interrupt_time_down = 0;
static unsigned long debounce_time = 200;
Bounce debouncerUp = Bounce();
Bounce debouncerDown = Bounce();
Bounce debouncerStop = Bounce();
// shutter position parameters
float timeOneLevelUp = rollTimeUp / LEVELS; //time for one level up
float timeOneLevelDown = rollTimeDown / LEVELS; //time for one level down
int requestedShutterLevel = 0;
int currentShutterLevel = 0;
int currentShutterLevelold = 0;
unsigned long lastLevelTime = 0;
bool isMoving = false;
int directionUpDown;
#ifdef USE_TEMP_SENSOR
MyMessage msgTemp(CHILD_DSB_ID, V_TEMP);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
#endif
MyMessage msgUp(CHILD_ID, V_UP);
MyMessage msgDown(CHILD_ID, V_DOWN);
MyMessage msgStop(CHILD_ID, V_STOP);
MyMessage msgPercentage(CHILD_ID, V_PERCENTAGE);
MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
void print_debug(String message) {
#ifdef MY_DEBUG
Serial.println(message);
#endif
}
// moves shutters up
void shuttersUp(void) {
print_debug("Shutters going up.");
directionUpDown = DIRECTION_UP;
isMoving = true;
digitalWrite(RELAY_DIR_PIN, RELAY_OFF);
//wait(100);
digitalWrite(RELAY_POWER_PIN, RELAY_ON);
send(msgUp, IS_ACK);
//wait(100);
}
// moves shutters down
void shuttersDown(void) {
print_debug("Shutters going down.");
directionUpDown = DIRECTION_DOWN;
isMoving = true;
digitalWrite(RELAY_DIR_PIN, RELAY_ON);
wait(200);
digitalWrite(RELAY_POWER_PIN, RELAY_ON);
send(msgDown, IS_ACK);
//wait(100);
}
// stops shutters at current position and saves it to currentShutterLevel
void shuttersHalt(void) {
isMoving = false;
directionUpDown = DIRECTION_UP;
digitalWrite(RELAY_POWER_PIN, RELAY_OFF);
wait(200);
digitalWrite(RELAY_DIR_PIN, RELAY_OFF);
print_debug("Shutters halted.");
saveState(CHILD_ID, currentShutterLevel);
print_debug("saving level to: ");
print_debug(String(currentShutterLevel));
requestedShutterLevel = currentShutterLevel;
//wait(100);
}
void changeShuttersLevel(int LEVELS) {
if ((LEVELS < 0) || (LEVELS > 100))
{
print_debug("level is out of range calling InitShutters: ");
print_debug(String(LEVELS));
InitShutters();
LEVELS = 0;
}
else
{
int dir = (LEVELS > currentShutterLevel) ? DIRECTION_DOWN : DIRECTION_UP;
if ((isMoving == true) && (dir != directionUpDown))
{
shuttersHalt();
}
else {
print_debug("setting requested level to:");
print_debug(String(LEVELS));
requestedShutterLevel = LEVELS;
}
}
}
void InitShutters() {
if (LEVELS < 0 || LEVELS > 100)
{
print_debug("Current level unsure, calibrating...");
print_debug("Init Shutters");
shuttersUp();
print_debug("delaying for: ");
print_debug(String((rollTimeUp + timeOneLevelUp * LEVELS) * 1000));
delay((rollTimeUp + timeOneLevelUp * LEVELS) * 1000);
print_debug("ended delay rolltime");
currentShutterLevel = 0;
requestedShutterLevel = currentShutterLevel;
return true;
}
else
{
print_debug("No clibration needed. setting to: ");
print_debug(String(LEVELS));
currentShutterLevel = LEVELS;
changeShuttersLevel(currentShutterLevel);
return false;
}
}
void receive(const MyMessage &message) {
print_debug("recieved incomming message");
print_debug("Recieved message for sensor: ");
print_debug(String(message.sensor));
switch (message.sensor) {
case CHILD_ID:
switch (message.type) {
case V_UP:
print_debug(", New status: V_UP");
changeShuttersLevel(0);
print_debug("Done shutterAction procedure");
send(msgUp, IS_ACK);
break;
case V_DOWN:
print_debug(", New status: V_DOWN");
changeShuttersLevel(100);
print_debug("Done shutterAction procedure");
send(msgDown, IS_ACK);
break;
case V_STOP:
print_debug(", New status: V_STOP");
shuttersHalt();
print_debug("Done shutterAction procedure");
send(msgStop, IS_ACK);
send(msg.set(currentShutterLevel));
currentShutterLevelold = currentShutterLevel;
requestedShutterLevel = currentShutterLevel;
saveState(CHILD_ID, currentShutterLevel);
break;
case V_PERCENTAGE:
print_debug(", New status: V_PERCENTAGE");
changeShuttersLevel(message.getInt());
//InitShutters(message.getInt());//send value < 0 or > 100 to calibrate
print_debug("Done shutterAction procedure");
send(msgPercentage, IS_ACK);
break;
}
case CHILD_ID_SET_UP:
switch (message.type) {
case V_VAR1:
print_debug(", New status: V_VAR1, with payload: ");
rollTimeUp = message.getFloat();
print_debug("rolltimeUp value: ");
print_debug(String(rollTimeUp));
saveState(CHILD_ID_SET_UP, rollTimeUp);
timeOneLevelUp = rollTimeUp / LEVELS;
break;
case V_VAR3:
print_debug(", New status: ");
print_debug("V_VAR3, with payload: ");
print_debug(String(message.getInt()));
InitShutters();
break;
}
case CHILD_ID_SET_DOWN:
switch (message.type) {
case V_VAR2:
print_debug(", New status: V_VAR2, with payload: ");
rollTimeDown = message.getFloat();
print_debug("rolltimeDown value: ");
print_debug(String(rollTimeDown));
saveState(CHILD_ID_SET_DOWN, rollTimeDown);
timeOneLevelDown = rollTimeDown / LEVELS;
break;
}
}
print_debug("exiting incoming message");
return;
}
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo(SKETCH_NAME, SKETCH_VER);
// Register all sensors to gw (they will be created as child devices)
present(CHILD_ID, S_COVER, PRESENT_MESSAGE, IS_ACK);
present(CHILD_ID_SET_UP, S_CUSTOM, PRESENT_MESSAGE, IS_ACK);
present(CHILD_ID_LIGHT, S_LIGHT_LEVEL);
#ifdef USE_TEMP_SENSOR
present(CHILD_DSB_ID, S_TEMP);
#endif
}
void before() {
// Setup the button
pinMode(BUTTON_UP_PIN, INPUT_PULLUP);
//Activate internal pull-up
digitalWrite(BUTTON_UP_PIN, HIGH);
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP);
//Activate internal pull-up
digitalWrite(BUTTON_DOWN_PIN, HIGH);
/*pinMode(BUTTON_STOP_PIN, INPUT_PULLUP);
//Activate internal pull-up
digitalWrite(BUTTON_STOP_PIN, HIGH);
*/
// After setting up the button, setup debouncer
debouncerUp.attach(BUTTON_UP_PIN);
debouncerUp.interval(10);
// After setting up the button, setup debouncer
debouncerDown.attach(BUTTON_DOWN_PIN);
debouncerDown.interval(10);
/*
// After setting up the button, setup debouncer
debouncerStop.attach(BUTTON_STOP_PIN);
debouncerStop.interval(10);
*/
// Make sure relays are off when starting up
digitalWrite(RELAY_DIR_PIN, RELAY_OFF);
// Then set relay pins in output mode
pinMode(RELAY_DIR_PIN, OUTPUT);
// Make sure relays are off when starting up
digitalWrite(RELAY_POWER_PIN, RELAY_OFF);
// Then set relay pins in output mode
pinMode(RELAY_POWER_PIN, OUTPUT);
}
void setup(void) {
Serial.begin(115200);
Serial.println("StartUP");
//set up roll time up if the saved value is not 255
print_debug("getting rolltime from eeprom: ");
int tmpRollTimeUp = loadState(CHILD_ID_SET_UP);
if (tmpRollTimeUp < 255) {
rollTimeUp = tmpRollTimeUp;
timeOneLevelUp = rollTimeUp / LEVELS;
}
print_debug(String(rollTimeUp));
//set up roll time down if the saved value is not 255
print_debug("getting rolltime from eeprom: ");
int tmpRollTimeDown = loadState(CHILD_ID_SET_DOWN);
if (tmpRollTimeDown < 255) {
rollTimeDown = tmpRollTimeDown;
timeOneLevelDown = rollTimeDown / LEVELS;
}
print_debug(String(rollTimeDown));
print_debug("getting state from eeprom: ");
int state = loadState(CHILD_ID);
print_debug(String(state));
currentShutterLevel = state;
requestedShutterLevel = state;
//changeShuttersLevel(state);
#ifdef USE_TEMP_SENSOR
sensors.begin();
sensors.setWaitForConversion(false);
#endif
}
void loop(void) {
#ifdef USE_TEMP_SENSOR
static float prevTemp = 0;
static unsigned long lastSentTimestamp = 0;
#endif
#ifdef USE_TEMP_SENSOR
sensors.requestTemperatures();
// Fetch and round temperature to one decimal
float temperature = static_cast<float>(static_cast<int>(sensors.getTempCByIndex(0) * TEMPERATURE_ROUNDING)) / TEMPERATURE_ROUNDING;
// Check if temperature is valid
if (temperature != -127.00f && temperature != 85.00f) {
// Check threshold
if (((temperature >= (prevTemp + TEMPERATURE_THRESHOLD)) || (temperature <= (prevTemp - TEMPERATURE_THRESHOLD)))) {
// Send in the new temperature
send(msgTemp.set(temperature, true));
#ifdef MY_DEBUG
Serial.print("Sent temperature: ");
Serial.println(temperature);
#endif
prevTemp = temperature;
}
// Check interval
if ((millis() - lastSentTimestamp) > TEMPERATURE_INTERVAL_MS) {
// Send in the new temperature
send(msgTemp.set(temperature, true));
send(msg.set(currentShutterLevel, true));
lastSentTimestamp = millis();
#ifdef MY_DEBUG
Serial.print("Sent temperature: ");
Serial.println(temperature);
#endif
}
}
#endif
debouncerUp.update();
value = debouncerUp.read();
if ((value == 0) && (value != oldValueUp) && (isMoving == false)) {
changeShuttersLevel(0);
}
else if ((value == 0) && (value != oldValueUp) && (isMoving == true)) {
requestedShutterLevel = currentShutterLevel;
}
oldValueUp = value;
debouncerDown.update();
value = debouncerDown.read();
if ((value == 0) && (value != oldValueDown) && (isMoving == false)) {
changeShuttersLevel(100);
}
else if ((value == 0) && (value != oldValueDown) && (isMoving == true)) {
requestedShutterLevel = currentShutterLevel;
}
oldValueDown = value;
if ((currentShutterLevel == requestedShutterLevel) && (isMoving == true))
{
shuttersHalt();
send(msg.set(currentShutterLevel));
currentShutterLevelold = currentShutterLevel;
//send(msgStop, IS_ACK);
saveState(CHILD_ID, currentShutterLevel);
}
else if ((currentShutterLevel != requestedShutterLevel) && (isMoving == true))
{
unsigned long _now = millis();
if ((directionUpDown == DIRECTION_DOWN))
{
if (_now - lastLevelTime >= timeOneLevelDown * 1000)
{
//print_debug("3");
currentShutterLevel += 1;
lastLevelTime = millis();
}
}
else
{
if (_now - lastLevelTime >= timeOneLevelUp * 1000)
{
//print_debug("4");
currentShutterLevel -= 1;
lastLevelTime = millis();
}
}
}
else if ((requestedShutterLevel != currentShutterLevel) && (isMoving == false))
{
//print_debug("6");
if (requestedShutterLevel < currentShutterLevel)
{
//print_debug("7");
shuttersUp();
}
else
{
// print_debug("8");
shuttersDown();
}
lastLevelTime = millis();
}
// Statusposition in 5% Schritten senden, falls sich der Wert vom alten unterscheidet
if ((currentShutterLevel != currentShutterLevelold) && ((currentShutterLevel % 5) == 0))
{
send(msg.set(currentShutterLevel), false);
currentShutterLevelold = currentShutterLevel;
}
}