Hi @alowhum why using the SPI variant?
This will require only one digital IO pen for the chip select (CS pin) the rest is shared with the radio SPI interface (MOSI, MISO, SCK, CE and power off course)
Hi @alowhum why using the SPI variant?
This will require only one digital IO pen for the chip select (CS pin) the rest is shared with the radio SPI interface (MOSI, MISO, SCK, CE and power off course)
@dbemowsk yes there is a list available https://www.wunderground.com/weather/api/d/docs?d=resources/phrase-glossary also showing a list of icons
@dbemowsk yes i'm using Weather Underground with my Vera box (http://apps.mios.com/all-reviews.php?id=45)
Not sure if this work with UI7 (i still use UI5), but the plug in is quite simple so it should work.
If you create a free weather underground account a API key will be created, i also use the same key for a virtual rain sensor.
Using this proposed protocol extention : https://forum.mysensors.org/topic/6601/extra-command-message-type-for-local-data-requests will enable you to retrieve information from the Weather plugin, into the MySensors network.
It is something i'd really like to be added to the core functionality...
Just
#define MY_NODE_ID 5
Before the line
#include <MySensors.h>
Should work fine
@Boots33 No i did use a standard Arduino Nano not a low power one.
It is monitoring a caravan mover battery with a 105 Ah capacity, i think it will last during the winter on one load
Does anyone know why the three value are not show in the "data_request?id=lu_sdata" output?
It only outputs default values:
{
"name": "MyMulti",
"altid": "12;1",
"id": 346,
"category": 12,
"subcategory": -1,
"room": 0,
"parent": 64
},
While i would expect
{
"name": "MyMulti",
"altid": "12;1",
"id": 346,
"category": 12,
"subcategory": -1,
"room": 0,
"parent": 64,
"Impedance": 0,
"Current": 0,
"Voltage": 4.89
},
I'm looking for a solution quite some time now, but I somehow miss a problem.
@Boots33 thanks for sharing, this project inspired me to have a monitor for my caravan battery
I have mine up and running now and did run in a small error present in your source code, on this line
present(ID_S_MULTIMETERV,V_VOLTAGE); // Register Sensor to gateway
The present function should contain sensor type (S_xxxx values) and V_VOLTAGE is a payload message type.
So i think the presentation function should look like this.
void presentation()
{
sendSketchInfo("Battery Sensor", "1.1"); // Send the sketch version information to the gateway and Controller
present(ID_S_MULTIMETERV, S_MULTIMETER); // Register Sensor to gateway
}
Up and 'running':
@YFandS for some reason these smartmeters use a inverted implementation of the RS232 serial protocol. While Arduino's etc. use the standardized RS232 implementation.
As far is i known the UART (the "chip" doing the RSR232 decoding fro Arduino) does not supports inverted mode.
So yes a signal inverter is needed..
@knop Fabien tries to explain that the MySensors gateway is a major part of the MySensors-network it not just transmit the messages it actively contributes in, for example assigning node-id's and routing messages.
While the RFLink gateway only receives MySensors messages,
oke some pics..
Queue to get in
The booth
Yes we will be there soon and make some pictures!
@Woodside i think it is wise to bring all modules to same version.
50 07/11/17 13:58:38.725 luup_log:78: Arduino: Warning: Sensor has different library version than GW. Id: 1;255 <0x2e52a680>
i would suggest to start using the stable released version 2.1.1 and try again.
@Dick nice to hear
How it works:
As long as 'blockMotionTimer' is zero the motion debouncer is being monitored for any change.
When a PIR-change is detected the blockMotionTimer gets the value of the Arduino's internal milliseconds timer + the delay in milliseconds one want to wait.
This happes on this line: "blockMotionTimer = (millis() + SLEEP_TIME);"
See more about the millis() here
The blockMotionTimer is set back to zero the when mills() reaches the value set for time-out done with this check "if (blockMotionTimer < millis()) {" , and because the blockMotionTimer is non-zero the PIR value will not be checked during this period.
Expert note: since the milliseconds counter is returned in an unsigned long it will carry over one moment in time. Since Arduino stores it's ulong in 32 bits this means a carry over each 2^32 thus 4294967296 milliseconds. This is approx. every 50 days (49,71 days) So in theory this mechanism could result in a wrong (very short) delay, when timer is started precisely with the SLEEP_TIME period just before these 49,71 days. The result of millis() + SLEEP_TIME will then carry over and is immediate smaller than millis() on the next check. So be aware that this check if (blockMotionTimer > (millis() - SLEEP_TIME)) can result in a death-lock when blockMotionTimer = millis(); was set on the wrong moment in time.
@Dick mm look like a } on the wrong line. The } on line 126 should move up between line 119 and 120
(and there are 2 additional brackets)
The result should look like this
if (blockMotionTimer == 0) {
if (motionsDebouncer.update()) {
int value = motionsDebouncer.read();
Serial.println( "PIR " + (String)value );
gw.send( msgMOTION.set( value ), true ); // Also it might need inverted value
blockMotionTimer = (millis() + SLEEP_TIME);
}
} else {
motionsDebouncer.update(); // dummy update to prevent false trigger after timer expires
if (blockMotionTimer < millis()) {
blockMotionTimer = 0;
}
}
@Dick said in pir trigger must start delay:
Replace this piece of code
if ( motionsDebouncer.update()) {
int value = motionsDebouncer.read();
Serial.println( "PIR " + (String)value );
gw.send( msgMOTION.set( value ), true ); // Also it might need inverted value
// Sleep until interrupt comes in on motion sensor. Send update.
gw.sleep(DIGITAL_MOTION_SENSOR, CHANGE, SLEEP_TIME);
}
with something like this
if (blockMotionTimer == 0) {
{
if (motionsDebouncer.update()) {
int value = motionsDebouncer.read();
Serial.println( "PIR " + (String)value );
gw.send( msgMOTION.set( value ), true ); // Also it might need inverted value
blockMotionTimer = (millis() + SLEEP_TIME);
} else {
motionsDebouncer.update(); // dummy update to prevent false trigger after timer expires
if (blockMotionTimer < millis()) {
blockMotionTimer = 0;
}
}
}
Add this line at the top of your sketch (just below SLEEP_TIME)
unsigned long blockMotionTimer = 0;
Hi @OliverDog , yes this should work
Will it work with a single 4 pin RGB LED common cathode instead of a LED strip?
--> Uncomment this line "#define RGBW 1" to make it three color (RGB) in stead of four (RGBW).
Will it work with Home Assistant Controller like a ordinary RGB Light?
--> Should work with HAC since it presents it self as a RGB module
Could it run on batteries?
--> Yes why not, but please do read some forum posts about what to think about when running mysensors on batteries, there are several of them
@OliverDog here is a link to such a sketch (https://forum.mysensors.org/topic/2160/my-mysensors-rgbw-plug-in-has-an-init-problem)
@daniel.stancu you can do something like this
This examples servers 10 switches with 10 relays
/**
The MySensors Arduino library handles the wireless radio link and protocol
between your home built sensors/actuators and HA controller of choice.
The sensors forms a self healing radio network with optional repeaters. Each
repeater and gateway builds a routing tables in EEPROM which keeps track of the
network topology allowing messages to be routed to nodes.
Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
Copyright (C) 2013-2015 Sensnology AB
Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
Documentation: http://www.mysensors.org
Support Forum: http://forum.mysensors.org
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*******************************
REVISION HISTORY
Version 1.0 - Henrik Ekblad
DESCRIPTION
Example sketch showing how to control physical relays.
This example will remember relay state after power failure.
http://www.mysensors.org/build/relay
*/
// Enable debug prints to serial monitor
#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
// Enable repeater functionality for this node
#define MY_REPEATER_FEATURE
#include <MySensors.h>
#define NUMBER_OF_RELAYS 10 // Total number of attached relays and switches
unsigned int relay_pins[NUMBER_OF_RELAYS] = { 1, 2, 3, 4, 5, 6, 7, 8, A1, A2 };
#define RELAY_ON 1 // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
MyMessage msg(0, V_LIGHT);
#define BUTTON_PIN A0
#define NO_BUTTON 255
// The followinging are interrupt-driven keypad reading functions
// which includes DEBOUNCE ON/OFF mechanism, and continuous pressing detection
#define NUM_BUTTONS NUMBER_OF_RELAYS
//keypad debounce parameter
#define DEBOUNCE_MAX 6
#define DEBOUNCE_ON 4
#define DEBOUNCE_OFF 2
// adc preset value, represent top value,incl. noise & margin,that the adc reads, when a key is pressed
// set noise & margin = 30 (0.15V@5V)
unsigned int adc_key_val[NUM_BUTTONS] = { 50, 150, 200, 250, 300, 450, 500, 550, 600, 650 };
// debounce counters
byte button_count[NUM_BUTTONS];
// button status - pressed/released
byte button_status[NUM_BUTTONS];
// button on flags for user program
byte button_flag[NUM_BUTTONS];
byte lastButtonPressed = NO_BUTTON;
void before()
{
for (int sensor = 0; sensor < NUMBER_OF_RELAYS; sensor++) {
// Then set relay pins in output mode
pinMode(relay_pins[sensor], OUTPUT);
// Set relay to last known state (using eeprom storage)
digitalWrite(relay_pins[sensor], loadState(sensor) ? RELAY_ON : RELAY_OFF);
}
pinMode(BUTTON_PIN, INPUT);
}
void setup()
{
// reset button arrays
for (byte i = 0; i < NUM_BUTTONS; i++)
{
button_count[i] = 0;
button_status[i] = 0;
button_flag[i] = 0;
}
}
void presentation()
{
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Relay 32", "1.0");
for (int sensor = 0; sensor < NUMBER_OF_RELAYS; sensor++) {
// Register all sensors to gw (they will be created as child devices)
present(sensor + 1, S_BINARY);
}
}
void loop()
{
byte button = buttonPressed();
// Check if there was a change of buttons presses
if (button != lastButtonPressed) {
// YES we detected a change, only response when buttons was released
if (button == NO_BUTTON) {
msg.sensor = button + 1;
send(msg.set(loadState(button) ? "0" : "1") );
}
lastButtonPressed = button;
}
wait(10);
}
char buttonPressed()
{
for (byte i = 0; i < NUM_BUTTONS; i++)
{
if (button_flag[i] != 0) {
button_flag[i] = 0;
return i;
}
}
return NO_BUTTON;
}
// Convert ADC value to key number
char get_key(unsigned int input)
{
for (int k = 0; k < NUM_BUTTONS; k++)
{
if (input < adc_key_val[k]) {
return k;
}
}
return -1; // No valid key pressed
}
void update_adc_key()
{
unsigned int adc_key_in;
char key_in;
byte i;
adc_key_in = analogRead(BUTTON_PIN);
Serial.println(adc_key_in); // For debug only
key_in = get_key(adc_key_in);
for (i = 0; i < NUM_BUTTONS; i++)
{
if (key_in == i) {
//one key is pressed
if (button_count[i] < DEBOUNCE_MAX) {
button_count[i]++;
if (button_count[i] > DEBOUNCE_ON) {
if (button_status[i] == 0) {
button_flag[i] = 1;
button_status[i] = 1; //button debounced to 'pressed' status
}
}
}
}
else // no button pressed
{
if (button_count[i] > 0) {
button_flag[i] = 0;
button_count[i]--;
if (button_count[i] < DEBOUNCE_OFF) {
button_status[i] = 0; //button debounced to 'released' status
}
}
}
}
}
void receive(const MyMessage &message)
{
// We only expect one type of message from controller. But we better check anyway.
if (message.type == V_STATUS) {
// Change relay state
digitalWrite(relay_pins[message.sensor - 1], message.getBool() ? RELAY_ON : RELAY_OFF);
// Store state in eeprom
saveState(message.sensor - 1, message.getBool());
// Write some debug info
Serial.print("Incoming change for sensor:");
Serial.print(message.sensor);
Serial.print(", New status: ");
Serial.println(message.getBool());
}
}
You have to connect the switches likes this, the value for R2 - Rx resistors around 100 ohms and 10k for R1.
With the Serial.println debug statement one has to determine the correct analog values for the adc_key_val array (start with the lowest value first) by pressing the keys one by one, add approx 30 to the average values per button you see in the serial monitor too have some margin.
@Yveaux That is more or less in my backyard so i need to visit the booth!
Any help needed?
@mathieu no the shield is not mandatory you can just wire it up yourselves.
But be careful the CC2500 does requires voltage shifting it will brake with TTL level.
Here is the schematic
I'm not familiair with this MD7105 replacement.
One general tip for all user or the Livingcolor controller. It took my 2 broken Arduino Uno's to find out why they stopped working after 2 weeks. The onboard 3v3 power convertor is to weak ans will break. So i added my own 3v3 power regulator.
@Cliff-Karlsson these radio errors normally are the result of no connection with the MySensors gateway.
Please make sure you also remove the #include mysensors.h line when you want to comment out all MySensors stuff
When you connect a Arduino board via USB to your PC no additional power supply is required, so to make sure the power is not causing the problems just disconnect te power.
@tailchopper does your power inverter not have any data interface to read out the measurements?
Most common inteverters do have such interfaces, mine has a RS485 interface for which i made some tools to collect and store the measurements.
Using such an interface is most often more reliable
You might try this piece of code
It only contains the start and stop mechanism for the distance sensor based on the PIR status. The distance measurement code you need to add youself
// Enable debug prints
// #define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
#include <MySensors.h>
#include <Bounce2.h>
#define DIGITAL_INPUT_SENSOR 3
#define CHILD_ID 1 // Id of the sensor child
// Initialize motion message
MyMessage msg(CHILD_ID, V_TRIPPED);
// Instantiate a Bounce object
Bounce debouncer = Bounce();
unsigned long distanceTimer = 0;
#define DISTANCEMEASURETIME (10 * 1000)
void setup()
{
pinMode(DIGITAL_INPUT_SENSOR, INPUT); // sets the motion sensor digital pin as input
// After setting up the button, setup the Bounce instance :
debouncer.attach(DIGITAL_INPUT_SENSOR);
debouncer.interval(5); // interval in ms
}
void presentation()
{
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Motion Sensor", "1.0");
// Register all sensors to gw (they will be created as child devices)
present(CHILD_ID, S_MOTION);
}
void loop()
{
// Check if the PIR sensor has been changed
if (debouncer.update()) {
// Read digital motion value
bool tripped = (debouncer.read() == HIGH);
Serial.println(tripped);
send(msg.set(tripped?"1":"0")); // Send tripped value to gw
if (tripped) {
distanceTimer = millis() + DISTANCEMEASURETIME;
}
}
// Check if we need to measure distance
if (distanceTimer > 0) {
if (millis() > distanceTimer) {
// No times up stop reset the timer
distanceTimer = 0;
} else {
// Loop through all the sensors.
// add the distance measurement code here
///.....
}
}
}
OK i did make a prototype implementation using the V_CUSTOM message type.
This works for Vera only.
I had to change only one file: L_Arduino.lua
The function starting on line 244 has te be extened with this if statement:
-- Handle Local Request variables
if (varType == "CUSTOM") then
local bit = require("bit")
local varReqIndex = bit.band(tonumber(value), 0xFF);
local varVeraId = bit.rshift(tonumber(value), 8);
local varReqType = tVarLookupNumType[varReqIndex]
local varReq = tVarTypes[varReqType]
if (varReq[2] ~= nil) then
log("Local request '" .. varReq[3] .. "' from Device ID: ".. varVeraId .. " sensor type '" .. varReqType .. "'")
local localValue = luup.variable_get(varReq[2], varReq[3], varVeraId)
if (localValue ~= nil) then
-- Send variable value to actuator
sendRequestResponse(nodeId .. ";" .. childId, varReqType, localValue)
end
end
else
The complete function will then look like this:
local function setVariable(incomingData, childId, nodeId)
if (childId ~= nil) then
-- Set variable on child sensor.
local index = tonumber(incomingData[5]);
local varType = tVarLookupNumType[index]
local var = tVarTypes[varType]
local value = incomingData[6]
local timestamp = os.time()
-- Handle Local Request variables
if (varType == "CUSTOM") then
local bit = require("bit")
local varReqIndex = bit.band(tonumber(value), 0xFF);
local varVeraId = bit.rshift(tonumber(value), 8);
local varReqType = tVarLookupNumType[varReqIndex]
local varReq = tVarTypes[varReqType]
if (varReq[2] ~= nil) then
log("Local request '" .. varReq[3] .. "' from Device ID: ".. varVeraId .. " sensor type '" .. varReqType .. "'")
local localValue = luup.variable_get(varReq[2], varReq[3], varVeraId)
if (localValue ~= nil) then
-- Send variable value to actuator
sendRequestResponse(nodeId .. ";" .. childId, varReqType, localValue)
end
end
elseif (var[2] ~= nil) then
log("Setting variable '".. var[3] .. "' to value '".. value.. "'")
setVariableIfChanged(var[2], var[3], value, childId)
-- Handle special variables battery level and tripped which also
-- should update other variables to os.time()
if (varType == "TRIPPED" and value == "1") then
local variable = tVeraTypes["LAST_TRIP"]
setVariableIfChanged(variable[2], variable[3], timestamp, childId)
else
local variable = tVeraTypes["LAST_UPDATE"]
setVariableIfChanged(variable[2], variable[3], timestamp, childId)
end
end
-- Always update LAST_UPDATE for node
if (nodeId ~= nil) then
local nodeDevice = childIdLookupTable[nodeId .. ";" .. NODE_CHILD_ID]
setLastUpdate(nodeDevice)
end
end
end
Now the Vera HA-contoller response on V_CUSTOM messages.
Use the feature in a MySensors node:
void requestValue(byte type, unsigned int id)
{
MyMessage msgRequest(1, V_CUSTOM);
unsigned long msgData;
msgData = type + ((unsigned long)id * 0x100);
send(msgRequest.set(msgData));
}
void loop()
{
// Request the status from Vera Device 4
requestValue(V_STATUS, 4);
// Request the dimn level from Vera Device 20
requestValue(V_LEVEL, 20);
// etc..
}
Make sure you can handle the incoming messages
void receive(const MyMessage &message)
{
if (message.type==V_STATUS) {
Serial.print(" New value: ");
Serial.println(message.getBool());
}
if (message.type==V_LEVEL) {
Serial.print(" New value: ");
Serial.println(message.getByte());
}
if (message.type==V_TEMP) {
Serial.print(" New value: ");
Serial.println(message.getFloat());
}
}
If you need the same value type from different Device a different sensor id can be used, the requestValue will then look like this:
void requestValue(byte type, unsigned int id, byte sensorid)
{
MyMessage msgRequest(sensorid, V_CUSTOM);
unsigned long msgData;
msgData = type + ((unsigned long)id * 0x100);
send(msgRequest.set(msgData));
}
In the receive function "message.sensor" can be used to determine for which device a request was made
@AWI i was actually referring to an additional "command" (third byte) and not a V-type.
The V-type should represent the type of value which is requested from the controller. HA controller like Vera need the message type to be able to retrieve the data.
ControlleRequest is indeed a better name than local request.
Using V_CUSTOM could be an alternative. with the first payload byte the request V-type followed by and HA Controller ID.
I can make a prototype with this implementation.
Every now and then i'd think about sensors which rely on data from other sensors/nodes.
The current way of gathering this data, is request the data direct from the other MySensors-node using the message command type "req" (see api: https://www.mysensors.org/download/serial_api_20) This limits the data gathering to MySensors nodes.
My proposal would be to extend the message API with an additional message command type called "localrequest"
where the payload of this command holds the unique device id as known by the HA-controller (each HA has such ID's)
A localrequest message would look like this:
30;1;5;0;15;215\n
requesting node id (reply-to node);child id (reply-to sensor id);localrequest-command;nack;V_ARMED;HA-unique ID\n
By having this localrequest command and using the unique HA-ID all devices connected to this HA can provide data to the MySensors nodes. At least for Vera this will work fine. (i can provide the correct code for the Vera plugin)
This localrequest will also work for data provided by battery powered nodes which are sleeping most of their time.
@LastSamurai i did found the libraries here http://sylvain.fish.free.fr/kicad_lib/
@gohan did you try running the MRRC522 demo application only?
So eliminating all MySensors stuff. To check the wiring.(make sure the pin 7 an 8 definition are correct.)
@gohan the MIFARE chip needs to be disabled from the SPI bus before the radio is initialized
so put this piece of code in the before() function
void before() {
// Make sure MFRC is disabled from the SPI bus
pinMode(RST_PIN, OUTPUT);
digitalWrite(RST_PIN, LOW);
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, LOW);
}
The MySensors library will iniitialize the MyS before the setup() function but after the before()
these lines
sendSketchInfo("RFID Garage", "1.1"); delay(RF_INIT_DELAY);
// Register all sensors to gw (they will be created as child devices)
present(CHILD_ID_LOCK, S_LOCK); delay(RF_INIT_DELAY);
present(CHILD_ID_ALARM, S_MOTION); delay(RF_INIT_DELAY);
Should be part of
void presentation() {
sendSketchInfo("RFID Garage", "1.1"); delay(RF_INIT_DELAY);
// Register all sensors to gw (they will be created as child devices)
present(CHILD_ID_LOCK, S_LOCK); delay(RF_INIT_DELAY);
present(CHILD_ID_ALARM, S_MOTION); delay(RF_INIT_DELAY);
}
and the function:
void incomingMessage(const MyMessage &message)
should be renamed to
void receive(const MyMessage &message)
@esawyja for getting a value from the controller one can use "request()", i.e. in the relay example like this:
request(CHILD_ID,V_LIGHT);
The answer should be handled by the receive function
@Anduril why do you use a variable?
it is easier to use a define like this, a define is calculated on compile time and does not take any memory space
// Sleep time between reads (in milliseconds)
#define SLEEP_TIME (2 * 60 * 1000)
@Creaky couple of remarks.
@Aron-Sjöberg said in "Choose the Serial Port" error with MySensors and RFXtrx433?:
Add this line
#define MY_BAUD_RATE 38400
above the #include <SPI.h>
@Magnus just a wild guess.
Did you try to compile the MySensors GW with baudrate set to 38400 so they both use the same baudrate?
@Corvl yes you should be able to upgrade.byt you have top upgrade the gateway aswel.
It is quicker to solve the compile errors:
Do note that C in case sensitive so
Since you use the old library you also should change wait to gw.wait on line 30 and 49
That should fix the compiler error.
I think the second gw.wait should also be 5000 iso 500 if you want to wait 5 seconds also.
As a general comment, when programming C it is general practice to use indents for beter readability of the code so please add some whitespace in front of the added lines
@meanmrgreen try to load the "clean eeprom" example sketch of the MySensors library and then load you "final" sketch again
@ramoncarranza you might need to upload all empty files again they should not be empty
And can you be a bit more specific about "the same issue" ? What issue are you referring to?
This sketch has been updated to MySensors 2.0 and added example library https://www.mysensors.org/build/ir
@pettib not sure about the Vera Edge but my Vera3 with MySensors gateway is running for months without the need for a reset.
For what it is worth, i'm using :
@Spanners what hek means, the channel ID is set compile time. So before uploading to your node. So putting it in before() is currently not an option.
What you can do is putting the RF_BASE_RADIO_ID define in a separated include file (.h) and include this file before the other defines in all the sketches. So you only have to update the ID once for all your sketches.
Hi i was browsing AliExpress when i ran into this wall mounted touch screen
It has very nice icons which can be order customized. These panels are meant to interact with other panels. Apparently there is some serial protocol for communicating between two panels. I was thinking to decode this protocol with an Arduino so it can be used as a scene controller within the MySensors network.
But if can not find any protocol description nor a "hacking"-guide for these panels. Does anyone has more information?
About the protocol which is been used ? RC485?
It has to be some kind of serial-bus protocol since up to 8 panels can be connected and they communicate bi-directional
@rayan said:
If i do understand you correctly you want to toggle the relay when the switch is toggled regardless which state it is in?
If so just remove the && state == LOW and the relay whill be toggled each time stateChagened toggles
if ( stateChanged ) {
if ( ledState == LOW ) {
ledState = HIGH;
} else {
ledState = LOW;
}
@TON-RIJNAARD to preset a node id use this define, where 1 can be a number between 1 and 254 (no duplicates allowed within your network)
#define MY_NODE_ID 1
But if there is no gateway you will keep getting errors, since radio messages will fail
@siod this line is missing
#include <SPI.h>
You need to add this line before these includes
#include <Ethernet.h>
#include <MySensors.h>
@thazlett144 can't help to make a few comments on your sketch (sorry)
The led the array start from 0 and prevent the double pin declaration simply subtract one on usage so
this LED_Pin[ledid] becomes this LED_Pin[ledid-1]
please do use wait() instead of delay(), delay is blocking MySensors communication
// hek comment: Is this really nessesary?
send( dimmerMsg.set(currentLevel) );
Answer: Yes, controllers like Vera want feedback about the new dimlevel
@Cliff-Karlsson if you want to dim the strips it requires PWM (pulse width modulation) pens and the nano only has 6 of them (D3, D5, D6, D9, D10 and D11)
D11 and D10 are occupied by the MySensors radio leaving 4 to controll the LED strip.
So you will requires either:
@Cliff-Karlsson it is basically 4 times this https://www.mysensors.org/build/dimmer wiring. These LED strips share the ground
@palande.vaibhav
i think the answer is in the code
// sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
sleep(conversionTime);
Replace sleep(); by wait();
During a sleep the GW does not receives the message acknowledge and thus claims the broadcast did fail.
@Cliff-Karlsson using the search feature and searching for RGB gave me this hit (#8)
https://forum.mysensors.org/topic/4871/fire-pit-rgb-striplight-controller
looking at the examnples gave this link: https://www.mysensors.org/build/dimmer
You can combine the two of them...
And there is a very recent post https://forum.mysensors.org/topic/4938/rgbw-setup
@OliverDog Sorry my (beginners) fault the array's are counting from 0 to 8 and the sensor numbers from 1 till 9
This should work:
#define MY_DEBUG
#define MY_RADIO_NRF24
#include <SPI.h>
#include <MySensors.h>
#include <livolo.h>
#define CHILD_ID 1
Livolo livolo(8);
bool initValSent[] = {false, false, false, false, false, false, false, false, false};
int livoloSensCode[] = {120, 70, 1, 2, 3, 4, 5, 6, 7}; // Set correct livolo codes here
MyMessage msg(CHILD_ID, V_STATUS);
void setup() {
}
void presentation() {
sendSketchInfo("Livolo", "1.0");
for (int sensor=1; sensor<=9; sensor++) {
// (presents each sensor, S_BINARY type)
present(sensor, S_BINARY);
}
}
void loop() {
for (int sensor=1; sensor<=9; sensor++) {
if (!initValSent[sensor-1]) {
msg.setSensor(sensor);
send(msg.set(false));
Serial.print("Requesting initial value for sensor: ");
Serial.println(sensor);
request(sensor, V_STATUS);
wait(2000, C_SET, V_STATUS);
}
}
}
void receive(const MyMessage &message) {
switch (message.type) {
case V_LIGHT:
if (!initValSent[message.sensor-1]) {
Serial.print("Receiving initial value from controller for sensor: ");
initValSent[message.sensor-1] = true;
} else {
Serial.print("Receiving new value for sensor: ");
livolo.sendButton(6400, livoloSensCode[message.sensor-1]); // coded for each sensor
}
Serial.println(message.sensor);
break;
}
}
@OliverDog Maybe this will work for you
#define MY_DEBUG
#define MY_RADIO_NRF24
#include <SPI.h>
#include <MySensors.h>
#include <livolo.h>
#define CHILD_ID 1
Livolo livolo(8);
bool initValSent[] = {false, false, false, false, false, false, false, false, false};
int livoloSensCode[] = {120, 70, 1, 2, 3, 4, 5, 6, 7}; // Set correct livolo codes here
MyMessage msg(CHILD_ID, V_STATUS);
void setup() {
}
void presentation() {
sendSketchInfo("Livolo", "1.0");
for (int sensor=1; sensor<=9; sensor++) {
// (presents each sensor, S_BINARY type)
present(sensor, S_BINARY);
}
}
void loop() {
for (int sensor=1; sensor<=9; sensor++) {
if (!initValSent[sensor]) {
msg.setSensor(sensor);
send(msg.set(false));
Serial.println("Requesting initial value for each sensor");
request(sensor, V_STATUS);
wait(2000, C_SET, V_STATUS);
}
}
}
void receive(const MyMessage &message) {
switch (message.type) {
case V_LIGHT:
if (!initValSent[message.sensor]) {
Serial.println("Receiving initial value from controller");
initValSent[message.sensor] = true;
} else {
Serial.println("Receiving new value");
livolo.sendButton(6400, livoloSensCode[message.sensor]); // coded for each sensor
}
break;
}
}
@Affe No you need too feed with external 3.3 volt OR select LOW power
the repeater mode is used for resending message from one node to the gateway, in case a node is not in reach of the GW.
https://en.wikipedia.org/wiki/Repeater
@Affe when you use MY_RF24_PA_LEVEL HIGH you needs external radio power.
A standard Arduino power regulator is not powerfull enough for high RF24 power.
Disregarding which type of antenna one uses.
The LNA antenna is more sensitive and thus will give a better reception
@thecko said:
You have to add you original setup and incomingMessage function, i just was explaning how to alter the loop function.
void incomingMessage(const MyMessage &message)
{
if (message.type == V_LIGHT)
{
digitalWrite(RELAY_PIN, message.getBool() ? RELAY_ON : RELAY_OFF);
gw.saveState(1, message.getBool());
Serial.print("Incoming change for sensor:");
Serial.print(message.sensor);
Serial.print(", New status: ");
Serial.println(message.getBool());
}
}
@thecko the amount of time you have to wait is the result of this line
delay(dht.getMinimumSamplingPeriod());
Your sketch has to pass 5 times time delay (set by this line debouncer.interval(5);)
before a button press is detected.
Better use a while loop without a delay some something like this
unsigned long lastCheckTimestamp = 0;
// setup stuff
void loop ()
{
gw.process();
if (debouncer.update() && debouncer.read() == 0) {
gw.send(msg.set(gw.loadState(1)?false:true), true); // Send new state and request ack back
}
// Check if the minimal sample period has been passed
if ((lastCheckTimestamp < (millis() - dht.getMinimumSamplingPeriod()) ) || lastCheckTimestamp > millis())
{
lastCheckTimestamp = millis();
// do the normal stuff after the delay
float temperature = dht.getTemperature();
if (isnan(temperature))
{
Serial.println("Failed reading temperature from DHT");
}
else if (temperature != lastTemp)
{
lastTemp = temperature;
if (!metric)
{
temperature = dht.toFahrenheit(temperature);
}
gw.send(msgTemp.set(temperature, 1));
Serial.print("T: ");
Serial.println(temperature);
}
float humidity = dht.getHumidity();
if (isnan(humidity))
{
Serial.println("Failed reading humidity from DHT");
} else if (humidity != lastHum)
{
lastHum = humidity;
gw.send(msgHum.set(humidity, 1));
Serial.print("H: ");
Serial.println(humidity);
}
}
}
@Tias look for suggestions to this post https://forum.mysensors.org/topic/3080/controlling-a-1st-gen-livingcolors-lamp
@thecko the button should connect pin D4 to ground when pressed and there should be no resistor needed since your sketch activates the internal pull up resistor with this line:
digitalWrite(BUTTON_PIN,HIGH);
@thecko said:
The problem is in the "state" variable, you use the state variable to toggle but never save changed value
so change this code snippet
debouncer.update();
int value = debouncer.read();
if (value != oldValue && value==0) {
gw.send(msg.set(state?false:true), true); // Send new state and request ack back
}
oldValue = value;
to
debouncer.update();
int value = debouncer.read();
if (value != oldValue && value==0) {
gw.send(msg.set(gw.loadState(1)?false:true), true); // Send new state and request ack back
}
oldValue = value;
and remove the state variable at all.
Even better also remove the "oldValue" and "value" variables (the bounce2 library keeps the old value for you and debouncer.update(); returns true when the value was toggled )
if (debouncer.update() && debouncer.read() == 0) {
gw.send(msg.set(gw.loadState(1)?false:true), true); // Send new state and request ack back
}
@Marshall I do use a Vera2 and Vera3.
I my case sometimes the USB gateway is not recognized by tVera.
My start up procedure:
@rsaeful
better use gw.wait() i.s.o. of delay. during the gw.wait() you are still receiving and sending MyS messages. delay is blocking
So the function will look like this
void fadeToLevel( int toLevel ) {
int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1;
while ( currentLevel != toLevel ) {
currentLevel += delta;
analogWrite( LED_PIN, (int)(currentLevel * 2.55));
gw.wait( FADE_DELAY );
}
}
@stofakiller no the 8 month old files where OK for me (UI5)
@JahFyahh these relays did use
(Sorry it is a dutch website) Yes i do use a relay with a 230v coil to switch 5v i, if you ask a real electronics guy you might get a cheaper solution with an opto-coupler or so, but this works fine for me (and is safe )
@drock1985 said:
Try this , so add && SEND_FLOW == 0
if (Depth == HIGH_WATER && SEND_FLOW == 0) {
digitalWrite(RELAY_PIN, HIGH);
send(msgRelay.set(1));
SEND_FLOW = 1;
}
@hek andf @martinhjelmare i did some debugging this evening and came to the following findings
My previous comment on start-up behavior was based on a stand alone GW (so disconnected from the Vera Controller)
And i found out that the Library version is NOT pushed by the gateway but requested by the controller on plugin startup.
And this part (on GW side is working) --> Sending "0;0;0;3;0;2;Get Version" to the GW is being answered with "0;255;3;0;2;2.0.0"
So it must be the Vera plugin and then i found this line in my Vera box
02 07/30/16 23:23:43.694 luup_log:64: Arduino: Incoming internal command '0;255;3;0;2;2.0.0' discarded for child: nil <0x6c14>
So the MySensors v2.0.0 GW responses with alt-id 0;255 i.s.o 0;0
By updating this line https://github.com/mysensors/Vera/blob/development/L_Arduino.lua#L370 by... auhm what is already in the current git version it works.
So the final conclusion: just update the Vera plugin with the development branch and it works...
@mfalkvidd a video with cool 8 bit music nice
@rchamp i'm not sure about the DHT's inclucion but you're right about the wrong library version.
This version is NOT updated. If i trace down the debug i notice that the version ID string is not sent to the GW.
Well at least not correct
0;255;3;0;9;Starting gateway (RNNGAS, 2.0.0)
0;255;3;0;9;TSM:INIT
0;255;3;0;9;TSM:RADIO:OK
0;255;3;0;9;TSM:GW MODE
0;255;3;0;9;TSM:READY
0;255;3;0;14;Gateway startup complete.
0;255;0;0;18;2.0.0
0;255;3;0;9;No registration required
0;255;3;0;9;Init complete, id=0, parent=0, distance=0, registration=1
This can be the lirbrary version number but is has 18 as internal message ID (I_HEARTBEAT)
0;255;0;0;18;2.0.0
While i would expect 2 (I_VERSION) so this message
0;255;0;0;2;2.0.0
Here is a reliable delivery discussion with more information
@boozz and @flopp what you check here is that the message successfully was broadcast-ed to the next node.
This can be either the gateway or a repeater node.
With the reception of an acknowledge message you are sure that the original message was delivered at the gateway (and back).
Hi @arraWX
When you set the ack boolean to true while sending a message the gateway will return the message with the ACK bit set.
So you have to handle this message with code like this
setup ()
{
... do stuff
gw.begin(incomingMessage, AUTO, true);
... do more stuff
}
void incomingMessage(const MyMessage &message) {
if (message.isAck()) {
Serial.println("This is an ack from gateway");
if (message.sensor == YOUR_KWH_SENSOR_ID) {
toggleLed();
}
}
}
Hi @pesh000, couple of remarks at your sketch
Did you try the RCSwitch code with out any MySensor stuff so for example the SendDemo sketch with for your garage door the correct ID and pin settings? And did the garage door open/close?
Why declaring 2 debouncer variables but still using digitalRead? Look at the MySensors RelayWithButtonActuator example for debouncer examples
Why using hard coded numbers in the incomingMessage switch to determine which sensor did broadcast the V_LIGHT message while you have CHILD_ID_RELAY1, CHILD_ID_RELAY2 and CHILD_ID_RELAY3 declared?
better use gw.wait(1000); in stead g delay(1000); during gw.wait() MySensors messages keep being processed. Even better do not use wait() functions or very short ones to keep your sketch responsive to triggers
And last but not least it will help if you can post some debug logging from your sketch. I hope these comments will help you to debug , good luck
@Dick Not sure what your approach is but normally i start with prototyping using these wires and when all works fine (software and hardware) i solder everything together on a PCB.
@Dick If there is nothing visible in the log, then you can presume there is a hardware issue.
Some possible issues:
Change these lines
oldValue = value;
gw.wait(HEARTBEAT); //sleep a bit
}
}
to
oldValue = value;
}
gw.wait(HEARTBEAT); //sleep a bit
}
@Dick are you sure it's not a hardware (wire) issue?
What happens if you load the RelayWithButtonActuator example code (with the correct pinning of course) ?
@Dick
laatste:163: error: 'msg' was not declared in this scope
msg should become msgLight
gw.send(msgLight.set(state ? false : true), true); // Send new state and request ack back
and move one } just below this line
gw.wait(HEARTBEAT); //sleep a bit
}
}
to the very end of you sketch
@leeoz said:
@BartE
Tnx for the respose, great.
Also, if i would like to request value from vera?
So i use the gw.request(VeraDeviceID, V_TEMP,??)
Requesting Vera is not possible, there is no request interface between the GW and Vera
Also for solution 2, on the request from arduino2 code,
gw.request(MYSENSOR_TEMP, V_TEMP, 12);
MYSENSOR_TEMP is what?
Just a sensor ID on your arduino1
And why did u type 12? The sensor id is 11...
True, this should have been 11
I think that in general i dont understad the use of gw.request()
gw,request() sends a message to a different node requesting for data, the requested node has to process this message and respond with a second message. Look at this link at the "Requesting data" paragraph
@leeoz there are two ways to achieve this
gw.send(msgTemp.set(((float)temperature / 10.0), 1));
Also send a message to arduino2 something like this:
arduino1 code:
// This can be the sensor ID on arduino2 device #12 (but if you do not check each integer between 1-254 will do)
#define MYSENSOR_TEMP_LCD 1
MyMessage msgTempNode2 (MYSENSOR_TEMP_LCD, V_TEMP);
void loop ()
{
gw.process();
... do stuff
if (oldtemperature != temperature)
{ // inform the gateway we have a new temp.
gw.send(msgTemp.set(((float)temperature / 10.0), 1));
gw.wait(100); // give the gateway some time to process the 1ste message
// inform our LCD slave node also about the temp. change
msgTempNode2.setDestination(12); // This is the node ID on arduino2
gw.send(msgTempNode2.set(((float)temperature / 10.0), 1),;
oldtemperature = temperature;
}
... do some more stuff
}
The LCD arduino should handle the incoming TEMP message, arduino2 code:
void incomingMessage(const MyMessage &message) {
if (message.isAck()) {
Serial.println(F("GW ack"));
}
switch (message.type) {
case V_TEMP:
Serial.print("New temperature received : ");
Serial.println(message.getFloat());
... do some stuff to update your LCD screen
break;
}
}
2)The second more complex way is to request the temperature from arduino2 to arduino1
arduino1 code:
// This can be the sensor ID on arduino2 device #12 (but if you do not check each integer between 1-254 will do)
#define MYSENSOR_TEMP_LCD 1
MyMessage msgTempNode2 (MYSENSOR_TEMP_LCD, V_TEMP);
void loop ()
{
gw.process();
... do stuff
if (oldtemperature != temperature)
{ // inform the gateway we have a new temp.
gw.send(msgTemp.set(((float)temperature / 10.0), 1));
// Store the temp.
oldtemperature = temperature;
}
... do more stuff
}
void incomingMessage(const MyMessage &message) {
if (mGetCommand(message) == C_REQ) {
MyMessage answerMsg;
Serial.print("Incoming request for sensor: ");
Serial.println(message.sensor);
mSetCommand(answerMsg, C_SET);
answerMsg.setSensor(message.sensor);
answerMsg.setDestination(message.sender);
switch (message.sensor) {
case MYSENSOR_TEMP:
answerMsg.setType(V_TEMP);
gw.send(answerMsg.set((float)(oldtemperature/ 10.0), 1));
break;
}
} else {
if (message.isAck()) {
Serial.println(F("GW ack"));
}
switch (message.type) {
... handle other messages
}
}
}
arduino2 code:
void loop ()
{
gw.process();
... do stuff
if (time_to_poll_for_temp())
{ // Request for temperature
gw.request(MYSENSOR_TEMP, V_TEMP, 12); // This is the node ID on arduino2
}
}
void incomingMessage(const MyMessage &message) {
if (message.isAck()) {
Serial.println(F("GW ack"));
}
switch (message.type) {
case V_TEMP:
Serial.print("New temperature received : ");
Serial.println(message.getFloat());
... do some stuff to update your LCD screen
break;
}
}
``
@Dick I think this issue sits here you use Digital port 0 (which is the serial debug port) i.s.o. Analog port 0 (A0).
Change this line
#define LIGHT_SENSOR_ANALOG_PIN 0
to
#define LIGHT_SENSOR_ANALOG_PIN A0
And you better also add this line to the setup function
pinMode(LIGHT_SENSOR_ANALOG_PIN, INPUT);
@Dick
Couple of remarks
This peice of code tries to declare the same variable twice (msg)
MyMessage msg(CHILD_ID,V_LIGHT);
MyMessage msg(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
change to name to msgLight and msgLightLeven
MyMessage msgLight(CHILD_ID,V_LIGHT);
MyMessage msgLightLevel(CHILD_ID_LIGHT, V_LIGHT_LEVEL);
You also have to changethis line:
gw.send(msg.set(state?false:true), true); // Send new state and request ack back
to this
gw.send(msgLight.set(state?false:true), true); // Send new state and request ack back
Also this line
gw.send(msg.set(lightLevel));
needs to be adapted to
gw.send(msgLightLevel.set(lightLevel));
And i think the last } needs to be removed
Oh and please use the code mark up function for posting source code
(by using the </> icon)
@Dick how does relay exactly response to the button?
If you press the button (and keep it down) is the relay turned on?
or is it switched on when you release the button again?
The button can be "reversed" connected (on = off and off - on)
You can play a bit with this line
if (debouncer.update() && debouncer.read() == HIGH) {
or
if (debouncer.update() && debouncer.read() == LOW) {
and how is the button wired? Does is connect to ground or to Vcc (5 volt) ?
This sketch requires connection to ground (with internal PULL-UP)
About the light measuring ?? i just did copy your example from the first post and copied the RelayWithSwitch example in it. (Please notice the message part of sending humidity and temperature are still commented out as in the posted sketch)
The part i did add my self is the timer stuff (so keeping the switched being probed while the DHT sensor is only probed twice a minute)
Cheers BartE
@hek true line 88 of the D_DistanceSensor1.json file:
{
"ControlType": "label",
"Label": {
"lang_tag": "distance_unit",
"text": "cm" <------ line 88
},
"Display": {
"Top": 30,
"Left": 200,
"Width": 25,
"Height": 20
}
}
@signal15 like @hek is writing this requires a "high" freqency update which just works more reliable when calculated inside the sensor and not by the controller also "increasing at a certain rate" can be implemented as a smoke alarm and being triggered with a V_TRIPPED message when "certain rate" is reached
And if you like to show some data sent an update of the actual distance on a much lower frequency
@signal15 just two foods for thought.
@Dick please note: i did not test it on an actual node but this combination should work
#include <SPI.h>
#include <MySensor.h>
#include <DHT.h>
#include <Bounce2.h>
#define CHILD_ID_HUM1 0
#define CHILD_ID_HUM2 1
#define CHILD_ID_TEMP1 3
#define CHILD_ID_TEMP2 4
// RelayWithActuator stuff
#define RELAY_PIN 4 // Arduino Digital I/O pin number for relay
#define BUTTON_PIN 3 // Arduino Digital I/O pin number for button
#define CHILD_ID 5 // Id of the sensor child
#define RELAY_ON 1
#define RELAY_OFF 0
Bounce debouncer = Bounce();
bool state;
MySensor gw;
MyMessage msg(CHILD_ID,V_LIGHT);
#define HEARTBEAT 10
unsigned int timer = 0;
// Sleep time between reads (in milliseconds)
#define SLEEP_TIME 3000
DHT* dht[2];
byte sensorPin[2] = {3, 4};
float lastTemp[2] = {0.0, 0.0};
float lastHum[2] = {0.0, 0.0};
boolean metric = true;
//MyMessage msgHum(CHILD_ID_HUM1, V_HUM);
//MyMessage msgTemp(CHILD_ID_TEMP1, V_TEMP);
void setup()
{
gw.begin(incomingMessage, AUTO, true);
for (int i = 0; i < 2; i++)
{
dht[i] = new DHT;
dht[i]->setup(sensorPin[i]);
}
gw.sendSketchInfo("HumidityAndRelay", "1.0");
gw.present(CHILD_ID_HUM1, S_HUM);
gw.present(CHILD_ID_HUM2, S_HUM);
gw.present(CHILD_ID_TEMP1, S_TEMP);
gw.present(CHILD_ID_TEMP1, S_TEMP);
// Setup the button and Activate internal pull-up
pinMode(BUTTON_PIN,INPUT_PULLUP);
// After setting up the button, setup debouncer
debouncer.attach(BUTTON_PIN);
debouncer.interval(5);
// Register all sensors to gw (they will be created as child devices)
gw.present(CHILD_ID, S_LIGHT);
// Make sure relays are off when starting up
digitalWrite(RELAY_PIN, RELAY_OFF);
// Then set relay pins in output mode
pinMode(RELAY_PIN, OUTPUT);
// Set relay to last known state (using eeprom storage)
state = gw.loadState(CHILD_ID);
digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
timer = 0;
metric = gw.getConfig().isMetric;
}
void loop()
{
gw.process();
timer++;
if (timer > (SLEEP_TIME / HEARTBEAT))
{
// Reset timer again and for the next timed loop
timer = 0;
for (int i = 0; i < 2; i++)
{
delay(dht[i]->getMinimumSamplingPeriod());
float temperature = dht[i]->getTemperature();
if (isnan(temperature))
{
Serial.print(F("Failed reading temperature from DHT"));
Serial.println(i);
}
else if (temperature != lastTemp[i])
{
lastTemp[i] = temperature;
if (!metric)
{
temperature = dht[i]->toFahrenheit(temperature);
}
//gw.send(msgTemp.set(temperature, i));
Serial.print(F("T"));
Serial.print(i);
Serial.print(F("= "));
Serial.println(temperature);
}
float humidity = dht[i]->getHumidity();
if (isnan(humidity))
{
Serial.print("Failed reading humidity from DHT");
Serial.println(i);
}
else if (humidity != lastHum[i])
{
lastHum[i] = humidity;
//gw.send(msgHum.set(humidity, 1));
Serial.print(F("H"));
Serial.print(i);
Serial.print(F("= "));
Serial.println(humidity);
}
}
}
// Get the button update state (true if a change was detected)
if (debouncer.update() && debouncer.read() == 0) {
gw.send(msg.set(state?false:true), true); // Send new state and request ack back
}
gw.wait(HEARTBEAT); //sleep a bit
}
void incomingMessage(const MyMessage &message) {
// We only expect one type of message from controller. But we better check anyway.
if (message.isAck()) {
Serial.println("This is an ack from gateway");
}
if (message.type == V_LIGHT) {
// Change relay state
state = message.getBool();
digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
// Store state in eeprom
gw.saveState(CHILD_ID, state);
// Write some debug info
Serial.print("Incoming change for sensor:");
Serial.print(message.sensor);
Serial.print(", New status: ");
Serial.println(message.getBool());
}
}
@Lior-Rubin What you can do is on your Vera (UI5 but should work on UI7):
luup.call_action("urn:upnp-arduino-cc:serviceId:arduino1", "SendCommand", {radioId="2;255", variableId="VAR_5", value=2}, 98)
There is no such thing as a I_HEARTBEAT (nor a V_HEARTBEAT) look on this page for the available sub-types (skip the V_ in your variableId-string)
Your MySensors node (in the example with ID 2) should handle the incoming message with sub-type V_VAR5
ID 1 (radioID 1) will not work this is reserved for the gateway
@mfalkvidd said:
Add an example that has a complete implementation of end-to-end ack usage. This includes
setting up timer(s) for re-sending
storing sent messages so they can be re-sent
determining which message was acked when an ack message is received (there might be several messages that haven't been acked yet)
removing acked message from the sent message store and clearing the timer(s)
re-sending when the timers expire
Are you referring to this number 1 post?
Does this functionality need to be part of the bool send(MyMessage &msg, bool ack); function or become a layer over the send() function?
Maybe i can have a look one of these days...
@smint I do not have any VeraPlus expecience but i do use a Vera2 and Vera3.
I my case sometime the USB gateway is nog recongised by Vera.
My start up procedure:
@Chakkie sorry for the slow response (i was on a pre summer holiday)
Thx for analyzing this report. The fix you did made is not what i meant with program expired.
The idea is that you start program mode by pressing the program button and holding the master card.
And now one can add one or more new RFID cards and when your oke press the program button for a short period to END the program mode and store the new cards.
If you wait too long the program mode will expire and the new cards are NOT stored. Off course you can change this behavior by adding this line as you suggested.
@codergirl56 Oke i will give it a try:
Basic IO pin set up
void setup() {
Serial.begin(BAUD); // Initialize serial communications with the PC
pinMode(GARAGEPIN, OUTPUT); // Initialise in/output ports
pinMode(SECONDRELAY, OUTPUT); // Initialise in/output ports
This part initializes the SPI I/O pins used by the RFID reader so it release the SPI bus for thr NFR radio
// Make sure MFRC will be disabled on the SPI bus
pinMode(RST_PIN, OUTPUT);
digitalWrite(RST_PIN, LOW);
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, LOW);
Init LED and button I/O-pin
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// Setup the button
pinMode(SWITCH_PIN, INPUT_PULLUP);
// After setting up the button, setup debouncer
debouncer.attach(SWITCH_PIN);
debouncer.interval(5);
Init radion module
// Init mysensors library
gw.begin(incomingMessage, 5);
gw.sendSketchInfo("RFID Garage", "1.2"); delay(RF_INIT_DELAY);
// Register all sensors to gw (they will be created as child devices)
gw.present(CHILD_ID_LOCK, S_LOCK); delay(RF_INIT_DELAY);
gw.present(CHILD_ID_LOCK2, S_LOCK); delay(RF_INIT_DELAY);
gw.present(CHILD_ID_ALARM, S_MOTION); delay(RF_INIT_DELAY);
Read eeprom settings
recallEeprom();
nit SPI bus for MFRC RFID sensor
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522
ShowReaderDetails(); // Show details of PCD - MFRC522 Card Reader details
gw.send(lockArmMsg.set(armed));
Serial.println(F("Init done..."));
}
void loop() {
timer++;
delay(HEARTBEAT);
gw.process();
debouncer.update();
// Get the update value
int switchValue = debouncer.read();
if (switchValue != oldSwitchValue) {
// Send in the new value
Serial.print (F("Switch "));
Serial.println (switchValue);
if (switchValue && programmode) {
lastTime = millis() / 1000;
}
if (!switchValue && programmode && lastTime > 0) {
if ( (millis() / 1000) - lastTime > 3) {
Serial.println(F("Reset all cards"));
countValidCards = 0;
blinkFast(50);
} else {
Serial.println(F("Program off"));
digitalWrite(LED_PIN, LOW);
programmode = false;
storeEeprom();
}
}
if (!switchValue) {
programTimer = 0;
}
oldSwitchValue = switchValue;
}
if (programmode && ((timer % (ONE_SEC / HEARTBEAT)) == 0 )) {
ledon = !ledon;
digitalWrite(LED_PIN, ledon);
programTimer++;
// Stop program mode after 20 sec inactivity
if (programTimer > PROG_WAIT) {
programmode = false;
digitalWrite(LED_PIN, false);
Serial.println(F("Program expired"));
}
}
if ((timer % (200 / HEARTBEAT)) == 0 ) {
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) {
if (releasecnt > 0) {
releasecnt--;
if (!releasecnt) {
olduid.size = 0;
Serial.println(F("release"));
}
}
return;
}
releasecnt = 5;
Check if a RFID card is held at the RFID reader if not: skip the rest and start over with loop()
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
// Dump debug info about the card; PICC_HaltA() is automatically called
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
Check if this card is the same as the previous loop if not enter the IF loop
if (!olduid.size || !sameUid(&(mfrc522.uid), &olduid)) {
ShowCardData(&(mfrc522.uid));
copyUid(&(mfrc522.uid), &olduid);
if ( isValidCard(&olduid) ) {
OpenDoor(programmode);
} else {
Check if the master card was presented and the button was pressed enter program mode
if (sameUid(&(mfrc522.uid), &masterkey)) {
// Only switch in program mode when mastercard is found AND the program button is pressed
if (switchValue) {
Serial.println(F("Program mode"));
programmode = true;
programTimer = 0;
lastTime = 0;
} else {
OpenDoor2(programmode);
}
} else {
If not the master card and this card in not known and we're in program mode add this as a new card
if (programmode) {
Serial.println(F("new card"));
programTimer = 0;
if (countValidCards < MAX_CARDS)
{
// Add card to list...
copyUid(&(mfrc522.uid), &validCards[countValidCards]);
countValidCards++;
blinkFast(15);
}
} else {
Serial.println(F("Invalid card"));
if (armed) {
gw.send(wrongMsg.set(1));
delay(2000);
gw.send(wrongMsg.set(0));
}
}
}
}
}
}
}
These are support functions
void ShowCardData(MFRC522::Uid* uid)
{
Serial.print(F("Card UID:"));
for (byte i = 0; i < uid->size; i++) {
if(uid->uidByte[i] < 0x10) {
Serial.print(F(" 0"));
} else {
Serial.print(F(" "));
}
Serial.print(uid->uidByte[i], HEX);
}
Serial.println();
}
void copyUid(MFRC522::Uid* src, MFRC522::Uid* dest)
{
dest->size = src->size;
dest->sak = src->sak;
for (byte i = 0; i < src->size; i++) {
dest->uidByte[i] = src->uidByte[i];
}
}
bool sameUid(MFRC522::Uid* old, MFRC522::Uid* check)
{
if (old->size != check->size) {
return false;
}
for (byte i = 0; i < old->size; i++) {
if (old->uidByte[i] != check->uidByte[i]) {
return false;
}
}
return true;
}
bool isValidCard(MFRC522::Uid* uid)
{
for (byte i = 0; i < countValidCards; i++) {
if (validCards[i].size != uid->size) {
break;
}
for (int j = 0; j < uid->size; j++) {
if (validCards[i].uidByte[j] != uid->uidByte[j]) {
break;
}
if (j == (uid->size - 1)) {
return true;
}
}
}
return false;
}
void storeEeprom()
{
byte address = 0;
gw.saveState(address++, countValidCards);
for (byte i = 0; i < countValidCards; i++) {
gw.saveState(address++, validCards[i].size);
for (byte j = 0; j < 10; j++) {
gw.saveState(address++, validCards[i].uidByte[j]);
}
}
}
void recallEeprom()
{
byte address = 0;
countValidCards = gw.loadState(address++);
if (countValidCards > MAX_CARDS) {
Serial.println(F("Not a valid EEPROM reading set to default"));
countValidCards = 0;
storeEeprom();
return;
}
for (byte i = 0; i < countValidCards; i++) {
validCards[i].size = gw.loadState(address++);
for (byte j = 0; j < 10; j++) {
validCards[i].uidByte[j] = gw.loadState(address++);
}
}
}
void blinkFast(int times)
{
for (int i = 0; i < times; i++) {
ledon = !ledon;
digitalWrite(LED_PIN, ledon);
delay(100);
}
}
void OpenDoor(bool fakeOpen)
{
Serial.println(F("Open door!"));
gw.send(lockMsg.set(false));
if (!fakeOpen) {
digitalWrite(LED_PIN, HIGH);
digitalWrite(GARAGEPIN, HIGH);
}
delay(1000);
if (!fakeOpen) {
digitalWrite(GARAGEPIN, LOW);
digitalWrite(LED_PIN, LOW);
}
gw.send(lockMsg.set(true));
}
void OpenDoor2(bool fakeOpen)
{
Serial.println(F("Open door 2!"));
gw.send(lock2Msg.set(false));
if (!fakeOpen) {
digitalWrite(LED_PIN, HIGH);
digitalWrite(SECONDRELAY, HIGH);
}
delay(1000);
if (!fakeOpen) {
digitalWrite(SECONDRELAY, LOW);
digitalWrite(LED_PIN, LOW);
}
gw.send(lock2Msg.set(true));
}
void ShowReaderDetails() {
// Get the MFRC522 software version
byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
Serial.print(F("MFRC522 Software Version: 0x"));
Serial.print(v, HEX);
if (v == 0x91) {
Serial.print(F(" = v1.0"));
} else if (v == 0x92) {
Serial.print(F(" = v2.0"));
} else {
Serial.print(F(" (unknown)"));
}
Serial.println("");
// When 0x00 or 0xFF is returned, communication probably failed
if ((v == 0x00) || (v == 0xFF)) {
Serial.println(F("WARNING: Communication failure, is the MFRC522 properly connected?"));
}
}
void incomingMessage(const MyMessage &message)
{
if (message.type == V_LOCK_STATUS) {
// Change relay state
if (!message.getBool()) {
switch (message.sensor)
{
case CHILD_ID_LOCK:
OpenDoor(false);
break;
case CHILD_ID_LOCK2:
OpenDoor2(false);
break;
}
}
// Write some debug info
Serial.print(F("Lock: "));
Serial.print(message.sensor);
Serial.print(F(" status: "));
Serial.println(message.getBool());
}
else
{
if (message.type == V_ARMED) {
// Change relay state
armed = message.getBool();
// Write some debug info
Serial.print(F("Arm status: "));
Serial.println(message.getBool());
}
else
{
// Write some debug info
Serial.print(F("Incoming msg type: "));
Serial.print(message.type);
Serial.print(F(" id: "));
Serial.print(message.sensor);
Serial.print(F(" content: "));
Serial.println(message.getInt());
}
}
}
@Axel yes you can use this sketch stand alone.
In the sketch just:
That should be it, not sure if all compilers are gone now (did not test it)
And of course there is no needs anymore to add the NFR radio module
@codergirl56 there are a number of examples in the MFRC522 library which might help you.
You can find them here: https://github.com/miguelbalboa/rfid
Please feel free to ask questions if the examples does not help you further
@mfalkvidd said:
Very cool, I love the big red button. Where did you find it?
I did found it i my box with electronic parts i once got a number of these switches of a friend of mine.
BTW the clock radio has a led strip connected emulating a Wakeup light, shows the out door temperature on request, since it is MYS connected the alarm can be triggered via my HA controller and the most important feature it switches on my coffee machine upon wake up time.
I will post a detailed description in the comming days,
@mfalkvidd thx for the tip i use the a eds bag with a semi transparent red foil
@niccodemi the bezel shop you suggested does not ship bezel large enough and for the box i did use this box http://www.ebay.com/itm/201180688204
This is the end result of my MySensor based clock radio
(Unfortunately finished to late for the contest)
@jaba yes reed sensors behave like switch this should work.
Hi i'm busy with a larger 7 segment RED LED clock display (like these) and i want to put this in a box and i like to put this segment behind a dark red plastic cover. The stuff once standard to be used for clock radios. But i can not find a supplier.
Does anybody know a supplier for these covers? The segment is 12 by 5 centimeter
Thx
@Lyubomyr This M_ACK_VARIABLE or M_SET_VARIABLE looks like a left over from old releases
but what is meant here:
if (message.type==V_DIMMER) { // can be a new set dimmer value form the Gateway or an acknowledge from a previous send message
In this example there are no message send and thus not acknowledged .
In other examples this line is seen, making the distinguish between new value or ACK
if (message.isAck()) {
Serial.println("This is an ack from gateway");
}
Requesting for an ACK when sending a message is done by setting the third parameter of gw.send() to true
gw.send(msg.set(state?false:true), true);
@dsiee This answer is to explain the basics for node 2 node communications
To respond to node 2 node requests the incomingMessage() function needs to be changed in such a way that it responds to requests
In this example, for the answering node, one can request for temperature, humidity and pressure
void incomingMessage(const MyMessage &message)
{
// Check for incoming node to node request
if (mGetCommand(message) == C_REQ) {
MyMessage msg;
mSetCommand(msg, C_SET);
msg.setType(message.type);
msg.setSensor(message.sensor);
msg.setDestination(message.sender);
bool bHandled = true;
switch (message.sensor) {
case CHILD_ID_HUM:
msg.setType(V_HUM);
msg.set(lastHum, 1);
break;
case CHILD_ID_TEMP:
msg.setType(V_TEMP);
msg.set(lastTemp, 1);
break;
case CHILD_ID_BARO:
msg.setType(V_PRESSURE);
msg.set(lastPressure, 0);
break;
default:
bHandled = false;
break;
}
if (bHandled) {
gw.send(msg);
}
} else {
// do normal message handling stuff
switch (message.type) {
case V_STATUS:
// Do something useful
break;
}
}
With this call one can perform the request
gw.request( TEMP_SENS_ID, V_TEMP, WEATHER_NODE_ID);
And the requesting node should hande incoming data in incomingMessage()
void incomingMessage(const MyMessage &message) {
// We only expect one type of message from controller. But we better check anyway.
if (message.isAck()) {
Serial.println(F("GW ack"));
}
switch (message.type) {
case V_TEMP:
// Write some debug info
Serial.print(F("Temp received: "));
Serial.print(message.sensor);
Serial.print(F(" : "));
Serial.println((int)message.getFloat());
break;
case V_HUM:
// Write some debug info
Serial.print(F("Humidity received: "));
Serial.print(message.sensor);
Serial.print(F(" : "));
Serial.println(message.getInt(), HEX);
break;
case V_PRESSURE:
// Write some debug info
Serial.print(F("Pressure received: "));
Serial.print(message.sensor);
Serial.print(F(" : "));
Serial.println(message.getInt());
break;
}
}
@abrmartin What is the problem?
The Fibaro RGBW module should work without MySensors directly connected to your home automation system.
What is the issue with the wind sensor maybe you can give some more detail.
@mikeg291 Mm sorry must have been a copy/past error when posting the sketch i 've made an update you can try again.