@nca78 well, after 2 nights of intense trying and failing I've got code to work as expected. And yes, it works with PORT interrupt, its kinda more code for you to write in compare to simply using attachInterrupt function, but I'm okay with that. For me double the price of 52832 compared to 51822 is significant. And for now, for a simple sensor stuff as we do with mysensors I don't really see any advantages except that interrupt bug fixed.
Also I've found that Mysensors sleep function for nrf5 is missing one very important command, I don't know why, maybe it is nrf51822 specific and thus @d00616 missed it but in current version of Mysensors library it doesn't disable UART before sleep, that's why I was getting 120-200uA current during sleep. I still don't really know how to make pull requests on github, so I guess I will just post it here:
line 290 of MyHwNRF5.cpp should contain: NRF_UART0->ENABLE=0;
and line 327: NRF_UART0->ENABLE=1;
respectively. That completely disables UART on nrf51822.
I will post my complete sketch later, when I will finish it, maybe someone who strugles as I did will find it useful. Also I think we need to somehow combine all examples that were posted in this thread or at least put a list of them with links, because looking through 1654 posts is not an easy task, especially if you not sure what you are looking for exactly.
monte
@monte
Best posts made by monte
-
RE: nRF5 action!
-
RE: What did you build today (Pictures) ?
Made a prototype board for writing a software for one of my projects. Goal was to have everything needed on a board no bigger then a 1.54" eink display, and to make it doable at home by my own.
I was gladly surprised that everything worked (after a sleepless night of fighting through-layer connections, and soldering/desoldering FPC connectors) The only I've messed up is order of connector pins, so the display is connected the wrong way...
It also has pads for SHT30 sensor so it may be somehow useful after development is done.
-
RE: Where did everyone go?
I guess the main reason is that mysensors is very stand-alone framework. And it locked itself in purely hobbyist territory. So when there are vast amount of iot devices from various manufacturers that you can combine with your own diy solutions in zigbee-ikea-hue or esp-tasmota-mqtt ecosystem in mysesnsors you have to make all devices yourself if you want some kind of ecosystem, or rely on HA/openhab/nodered/domoticz with its script system to make something connected. Also strict requirement of arduino framework and outdated hardware as the core of the framework alienates the big chunk of iot developers out there. It feels like people come to mysensors, make relay node, temperature sensor and then go forward for more complex solutions to never come back.
@NeverDie said in Where did everyone go?:
not all that long ago Google bought a thermostat company (Nest)
And pretty much broke it for opensource or third-party integrations.
-
RE: What did you build today (Pictures) ?
Build myself a simple temperature sensor with a clock. No RTC, just pulling time from controller and updating every 10 minutes to avoid drift. Also requesting outdoor temperature from controller. Build from what was lying around - DHT22, pro mini clone, nokia screen. I can share the code if someone needs it
-
RE: What did you build today (Pictures) ?
Offtopic in terms of mysensors platform, but somehow tangent to a home automation. I've made a batch of concrete switches/push buttons which are in this case simple buttons with led backlight and all the logic is located centrally in distribution box, based on KNX ABB module. But I am planning on making smarter and more complex version which could use Mysensors as its transport.
and a photo of insides of one of the prototypes at first stages of development
-
RE: What did you build today (Pictures) ?
Today I've finally swapped my outdoor relay node with something descent.
This was my very first mysensors node that I've built when I was only starting to mess with arduino, probably around four years ago.
This board uses cheap 5v power supply and an amplified version of NRF24 module from Ebyte. It supposed to be poured with silicone ore resin, but I am yet to find suitable box, the size of this board appeared to be bigger then most of such cases designed for compound pouring. But I'm planning on making next version, with non-isolated power supply, which will help to achieve smaller size. -
RE: What did you build today (Pictures) ?
From left to right:- Home Assistant server with built-in NRF24 radio and OLED display based on Orange Pi Zero
- MQTT Mysensors gateway with ESP8285
- 4 channel triac dimmer with oled display and UI for operating in standalone mode.
-
Direct pairing of two nodes implementation
I've been looking for some time for implementation of pairing two nodes to each other to be able to send messages directly omitting controller. I've seen some other posts suggesting to add this functionality to mysensors core, and proposing base scheme of how it should look like. After some reading I realized that it is not hard to write such code by myself. So I tried my best and now I have what seems to be a working code for two test nodes and a gateway. One of the nodes is modified sketch for binary button the other one is simple one channel relay. I'm not a professional programmer, so code can be optimized more, I guess, and maybe rewritten in better manner.
It's primarily useful for direct communication between a button node (a light switch, or motion sensor) and some relay or other actuator. The key feature is the ability to avoid necessity of controller presence for some simple usage like light switching. Also it provides better reliability in case of controller failure.
Both nodes must have specific pairing button which also serves as "Clear EEPROM" button if pressed before node is powered on. So basically when pairing button is pressed node enters pairing mode for required amount of time (in my case 10 seconds) and sends special message to controller which collects its node and children id's and then waits for 10 seconds for another node to send request in which case it then sends id's vice versa. My code is written only for single button/relay nodes, but it can be made to pair specific child sensors on every node.
Let me know what do you think of it, and if it's useful to anybody.
Binary button code:
// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 #include <MySensors.h> #define CHILD_ID 3 #define SET_BUTTON_PIN 5// Arduino Digital I/O pin for button/reed switch #define BUTTON_PIN 3 MyMessage msg(CHILD_ID, V_TRIPPED); bool firstLoop = 1; bool pairing = 0; int node_pair=-1; int sensor_pair=-1; bool paired=0; bool lastButState=0; unsigned long timer1 = 0; int debounceTime = 1000; unsigned long timer2 = 0; int pairWaitTime = 10000; unsigned long timer3; int holdTime = 3000; //Time counter function instead of delay boolean isTime(unsigned long *timeMark, unsigned long timeInterval) { if (millis() - *timeMark >= timeInterval) { *timeMark = millis(); return true; } return false; } void before() { Serial.begin(115200); Serial.println("Starting node..."); pinMode(SET_BUTTON_PIN, INPUT_PULLUP); //Eneble button pin for detect request for resetting node's EEPROM bool clr = digitalRead(SET_BUTTON_PIN); if (!clr) { Serial.println("Clearing EEPROM"); for (int i=0; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) { hwWriteConfig(i,0xFF); } //Clearing paired nodes address and paired state for (int i=245; i<=255; i++) { hwWriteConfig(i,0xFF); } Serial.println("EEPROM is clean"); } //Reading pairing state from EEPROM and then reading paired nodes id's if paired paired = loadState(255); Serial.print("Paired state: "); Serial.println(paired); if (paired) { node_pair = loadState(245); sensor_pair = loadState(246); Serial.print("Paired node: "); Serial.print(node_pair); Serial.print("-"); Serial.println(sensor_pair); } } void setup() { // Setup the buttons pinMode(BUTTON_PIN, INPUT_PULLUP); } void presentation() { // Send the sketch version information to the Controller in case node is'nt paired if (!paired) { sendSketchInfo("Binary paired button", "1.0"); present(CHILD_ID, S_MOTION); } } // Loop will iterate on changes on the BUTTON_PINs void loop() { bool butState = !digitalRead(BUTTON_PIN); if (!paired) { if (firstLoop) { timer3 = millis(); //Starting delay for pairing button on first loop } //If pairing button hold for required amount of seconds initiate pairing process if (!digitalRead(SET_BUTTON_PIN)) { if(isTime(&timer3, holdTime)){ Serial.println("Pair button pressed"); pair(); if (!paired) { Serial.println("Pairing timeout"); } } } else { timer3 = millis(); } } //Processing main button press if (butState != lastButState) { if (butState) { lastButState = butState; if (isTime(&timer1, debounceTime)) { Serial.println("Button pressed"); //If node is paired to other node send message directly to paired node omitting controller if (paired) { MyMessage msg(sensor_pair, V_TRIPPED); msg.setDestination(node_pair); Serial.println("Sent message to paired node"); int retry = 0; while(!send(msg.set(1)) || retry == 10) { wait(100); send(msg.set(1)); retry++; } } else { //If not, send message to controller send(msg.set(1)); Serial.println("Sent message to controller"); } } } else { if (!paired) { send(msg.set(0)); } lastButState = butState; } } firstLoop = 0; //Counter for first loop just to know from where to start timer for pairing button hold } //Pairing function void pair() { Serial.println("Entering pairing mode"); pairing = 1; MyMessage pairMsg(244, V_VAR1); //I'm using specific CHILD_ID to be able to filter out pairing requests send(pairMsg.set("Pair me."), true); //Send any message to gateway Serial.println("Pair request sent"); //Then we wait some time to recieve paired node id (in my case 10 seconds) timer2 = millis(); while (!isTime(&timer2, pairWaitTime)) { wait(1); if (paired) { Serial.println("Successfully paired"); break; } } pairing = 0; } void receive(const MyMessage &message) { //While in pairing mode we'll only process pairing messages if (pairing) { if (!message.sender) { if (message.type == V_VAR2) { node_pair = atoi(strtok(message.getString(), ";")); //Deconstructing string from gateway, wich must contain id of paired node Serial.println(node_pair); sensor_pair = atoi(strtok(NULL, ";")); //...and id of specific sensor on that node, in case there are more than one Serial.print("Paired with: "); Serial.println(node_pair); Serial.println(sensor_pair); paired=1; saveState(255, 1); } } } }
Relay actuator code:
// 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 CHILD_ID 1 #define RELAY_PIN 5 // Arduino Digital I/O pin number for relay #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 #define SET_BUTTON_PIN 3 bool relayState; bool firstLoop = 1; bool pairing = 0; int node_pair=-1; int sensor_pair=-1; bool paired=0; bool lastButState=0; unsigned long timer1 = 0; int debounceTime = 100; unsigned long timer2 = 0; int pairWaitTime = 10000; unsigned long timer3; int holdTime = 3000; unsigned long timer4; int resendTime = 1500; MyMessage msg(CHILD_ID,V_LIGHT); //Time counter function instead delay boolean isTime(unsigned long *timeMark, unsigned long timeInterval) { if (millis() - *timeMark >= timeInterval) { *timeMark = millis(); return true; } return false; } void before () { Serial.begin(115200); Serial.println("Starting..."); pinMode(SET_BUTTON_PIN, INPUT_PULLUP); bool clr = digitalRead(SET_BUTTON_PIN); if (!clr) { Serial.println("Clearing EEPROM"); for (int i=0; i<EEPROM_LOCAL_CONFIG_ADDRESS; i++) { hwWriteConfig(i,0xFF); } //Clearing paired nodes address and paired state for (int i=245; i<=255; i++) { hwWriteConfig(i,0xFF); } Serial.println("EEPROM is clean"); } //Reading pairing state from EEPROM and then reading paired nodes id's if paired paired = loadState(255); Serial.print("Paired state: "); Serial.println(paired); if (paired) { node_pair = loadState(245); sensor_pair = loadState(246); Serial.print("Paired node: "); Serial.print(node_pair); Serial.print("-"); Serial.println(sensor_pair); } pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, 1); delay(1000); digitalWrite(RELAY_PIN, 0); // Set relay to last known state (using eeprom storage) relayState = loadState(CHILD_ID); digitalWrite(RELAY_PIN, relayState ? RELAY_ON : RELAY_OFF); } void setup() { } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Relay", "1.0"); present(CHILD_ID, S_LIGHT, "Test light", true); // Send saved state to gateway (using eeprom storage) send(msg.set(relayState),true); } void loop() { if (!paired) { if (firstLoop) { timer3 = millis(); //Starting delay for pairing button on first loop } //If pairing button hold for required amount of seconds initiate pairing process if (!digitalRead(SET_BUTTON_PIN)) { if(isTime(&timer3, holdTime)){ Serial.println("Pair button pressed"); pair(); } } else { timer3 = millis(); } } firstLoop = 0; //Counter for first loop just to know from where to start timer for pairing button hold } void pair() { Serial.println("Entering pairing mode"); pairing = 1; MyMessage pairMsg(244, V_VAR1); //I'm using specific CHILD_ID to be able to filter out pairing requests send(pairMsg.set("Pair me."), true); //Send any message to gateway Serial.println("Pair request sent"); //Then we wait some time to recieve paired node id (in my case 10 seconds) timer2 = millis(); while (!isTime(&timer2, pairWaitTime)) { wait(1); if (paired) { Serial.println("Successfully paired"); break; } } pairing = 0; Serial.println("Pairing timeout"); } void receive(const MyMessage &message) { //While in pairing mode we'll only process pairing messages if (pairing) { if (!message.sender) { if (message.type == V_VAR2) { node_pair = atoi(strtok(message.getString(), ";")); //Deconstructing string from gateway, wich must contain id of paired node Serial.println(node_pair); sensor_pair = atoi(strtok(NULL, ";")); //...and id of specific sensor on that node, in case there are more than one Serial.print("Paired with: "); Serial.println(node_pair); Serial.println(sensor_pair); paired=1; saveState(255, 1); } } } else { //Process mesage from gateway if (message.type == V_LIGHT && !message.sender) { // Change relay state relayState = message.getBool(); digitalWrite(RELAY_PIN, relayState ? RELAY_ON : RELAY_OFF); // Store state in eeprom saveState(CHILD_ID, relayState); // Write some debug info Serial.print("Incoming change. New status:"); Serial.println(relayState); } else if (message.type == V_TRIPPED && message.sender == node_pair) { //Process message sent directly from paired node if(isTime(&timer4, resendTime)) { digitalWrite(RELAY_PIN, relayState ? RELAY_OFF : RELAY_ON); relayState = relayState ? 0 : 1; saveState(CHILD_ID, relayState); send(msg.set(relayState)); //Send changed state to controller, because paired button won't do it } } } }
Gateway code:
// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 // Set LOW transmit power level as default, if you have an amplified NRF-module and // power your radio separately with a good regulator you can turn up PA level. #define MY_RF24_PA_LEVEL RF24_PA_MAX // Enable serial gateway #define MY_GATEWAY_SERIAL // Define a lower baud rate for Arduino's running on 8 MHz (Arduino Pro Mini 3.3V & SenseBender) #if F_CPU == 8000000L #define MY_BAUD_RATE 38400 #endif // Set blinking period #define MY_DEFAULT_LED_BLINK_PERIOD 300 #include <MySensors.h> unsigned long currentTime = 0; int waitTime = 10000; int node1_addr = 0; bool node1_addr_present = 0; int sensor1_addr = 0; char str1[8]; char str2[8]; bool pairing = 0; //Messages for answering pairing requests MyMessage msg(254,V_VAR2); MyMessage msg2(254,V_VAR2); //Time counter function instead delay boolean isTime(unsigned long *timeMark, unsigned long timeInterval) { if (millis() - *timeMark >= timeInterval) { *timeMark = millis(); return true; } return false; } void setup() { // Setup locally attached sensors } void loop() { //We are keeping ids of pairing nodes only for 10 seconds while pairing if(isTime(¤tTime, waitTime)) { node1_addr = 0; node1_addr_present = 0; } } void receive(const MyMessage &message) { //I used specific message type for filtering out pairing request if (message.type == V_VAR1) { Serial.print("Incoming message. Node - "); Serial.print(message.sender); Serial.print(message.sensor); Serial.println(message.getString()); //Check if there was any pairing requests for last 10 seconds, if no begin pairing process if (!node1_addr_present) { currentTime = millis(); node1_addr = message.sender; sensor1_addr = message.sensor; node1_addr_present = 1; } //If there is request from another node send back pairing node ids to each other else if (message.sender != node1_addr && message.sensor != sensor1_addr) { snprintf(str2, 7, "%d;%d", message.sender, message.sensor); //Construct message string with node and sensor ids of second node snprintf(str1, 7, "%d;%d", node1_addr, sensor1_addr); //...and the first one //print some debug info Serial.print("First address: "); Serial.print(str1); Serial.print("Second address: "); Serial.print(str2); //Send answer to nodes msg.setDestination(message.sender); send(msg.set(str1), true); wait(500); Serial.println("Sent message to second address"); msg2.setDestination(node1_addr); send(msg2.set(str2), true); wait(500); Serial.println("Sent message to first address"); node1_addr = 0; sensor1_addr = 0; node1_addr_present = 0; Serial.println("Pairing finished"); } } }
-
RE: Favorite hand solderable radio chip?
@NeverDie stencil would help, for sure. But I am talking bare minimum. You tin the pads a little, so they are like bumps, then apply gel flux, put the IC aligned to the pins and reflow it with hot-air gun. That may be not the best practice, but it works, if you need to solder few IC's.
-
RE: nRF5 action!
I wanted to write that Softdevice and ESB are not compatible for use at the same time, but then decided to fact check myself. Seems like now you can use Softdevice and ESB simultaneously. You can either disable softdevice in program, or use Timeslot API to manage access to radio of different protocols.
https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsds_s140%2FSDS%2Fs1xx%2Fconcurrent_multiprotocol_tsl_api%2Ftsl_usage_examples.html&cp=4_5_3_0_8_2
https://devzone.nordicsemi.com/f/nordic-q-a/55847/priority-level-overlap-between-softdevice-and-esb
https://jimmywongiot.com/2020/06/22/radio-timeslot-api-for-the-multiple-protocols/
If this is doable I can't think of a reason, why mysensors shouldn't use softdevice.
Latest posts made by monte
-
RE: No merge into master in the last 5 years, should we use development?
@kiesel I would look into ZigBee and/or matter. It's an industry standard, so won't be abandoned any time soon. Or you can try ESPHome if you don't mind using WiFi as a carrier.
-
RE: Awesome tip: run LinuxFX instead of Windows!
@NeverDie you can try this https://github.com/cryinkfly/Autodesk-Fusion-360-for-Linux. I've set up bottle container for fusion and it works quite nice.
-
RE: Compile on arm64 Raspi 3
@moses https://github.com/mysensors/MySensors/blob/b9d9cc339659f724aa94d4108fc5289a720d1bcd/configure#L266
This is where you edit it. Just delete-mfpu=neon-fp-armv8 -mfloat-abi=hard
and domake clean ./configure
I'm not sure this will work, but I did compile mysensors for aarch64, just for another board and SoC.
-
RE: Compile on arm64 Raspi 3
@moses said in Compile on arm64 Raspi 3:
unrecognized command-line option β-mfpu=neon-fp-armv8β
unrecognized command-line option β-mfloat-abi=hardβTry removing those flags from make file, apparently they are not needed for arm64.
-
RE: MQTT gateway help!
@Multimax do you send initial states for all children for this multi relay node? HA won't show anything that hasn't sent initial data to show.
https://www.home-assistant.io/integrations/mysensors/#presentation -
RE: Lights on after gateway reboot
@electrik I am using MQTT explorer, but I don't see where is an option to see if message that was sent is retained. There is only box "retain" for a message to be sent from the program.
-
ATMEGA 328 Timer/Counter2 frequency problem
I wonder if anyone else have encountered this problem, and can explain why is it happening.
I was trying to increase frequency of PWM, so the first thing I tried, was lowering the prescaler for Timer2. By default it is set to 1/64 of F_CPU. I am running this particular node at 8MHz.TCCR2B = _BV(CS21);
Setting prescaler to 0 or 8 leads to it being unable to receive any NRF24 messages, though it sends okay.
TCCR2B = _BV(CS21) | _BV(CS20);
Setting prescaler to 32 works normal, as does setting PWM mode to Fast PWM.
I've searched the Mysensors code and haven't found any mentions of use of Timer2 or interrupts connected to it. -
RE: Lights on after gateway reboot
I figured this out. After discovery, gateway sends states found in HA (or MQTT I'm not sure). It sends first - state, second - level. My code was turning light state on on every level change greater than 0, so because the state is sent first and the level second, my nodes got confused and turned lights on.
The question is why this behavior is different from TCP gateway I used before.
It was pretty dumb problem, but at least there is now this thread for someone who might have same problem in the future -
RE: Lights on after gateway reboot
Switching the gateway to 2.3.2 haven't change anything, as expected.
-
Lights on after gateway reboot
I have made myself a new standalone mqtt gateway (before I was only using RPi gateways). Now I see strange behavior with 2 of 3 light nodes I have.
After gateway boots, it sends discovery requests:1296965 TSF:MSG:READ,0-0-255,s=255,c=3,t=20,pt=0,l=0,sg=0: 1296973 TSF:MSG:BC 1297567 TSF:MSG:SEND,3-3-0-0,s=255,c=3,t=21,pt=1,l=1,sg=0,ft=0,st=OK:0 1299177 TSF:MSG:READ,0-0-255,s=43,c=3,t=4,pt=0,l=1,sg=0:1 1299183 TSF:MSG:BC 1299316 TSF:MSG:READ,0-0-255,s=63,c=3,t=4,pt=0,l=1,sg=0:2 1299322 TSF:MSG:BC 1299456 TSF:MSG:READ,0-0-255,s=16,c=3,t=4,pt=0,l=1,sg=0:3 1299462 TSF:MSG:BC 1299595 TSF:MSG:READ,0-0-255,s=30,c=3,t=4,pt=0,l=1,sg=0:4 1299601 TSF:MSG:BC 1299736 TSF:MSG:READ,0-0-255,s=239,c=3,t=4,pt=0,l=1,sg=0:5 1299742 TSF:MSG:BC 1299877 TSF:MSG:READ,0-0-255,s=192,c=3,t=4,pt=0,l=1,sg=0:6 1299884 TSF:MSG:BC 1300019 TSF:MSG:READ,0-0-255,s=145,c=3,t=4,pt=0,l=1,sg=0:7 1300025 TSF:MSG:BC 1300301 TSF:MSG:READ,0-0-255,s=112,c=3,t=4,pt=0,l=1,sg=0:9 1300307 TSF:MSG:BC 1300441 TSF:MSG:READ,0-0-255,s=18,c=3,t=4,pt=0,l=2,sg=0:10 1300447 TSF:MSG:BC 1305182 TSF:MSG:READ,0-0-3,s=255,c=3,t=6,pt=0,l=1,sg=0:M 1305313 TSF:MSG:READ,0-0-3,s=0,c=1,t=2,pt=0,l=1,sg=0:0 1305319 TSF:MSG:ECHO REQ
After this my nodes for some reason send current states:
1305323 TSF:MSG:SEND,3-3-0-0,s=0,c=1,t=2,pt=0,l=1,sg=0,ft=0,st=OK:0 1305333 TSF:MSG:SEND,3-3-0-0,s=1,c=1,t=3,pt=1,l=1,sg=0,ft=0,st=OK:21 1305344 TSF:MSG:SEND,3-3-0-0,s=2,c=1,t=3,pt=1,l=1,sg=0,ft=0,st=OK:100 1305401 TSF:MSG:SEND,3-3-0-0,s=1,c=1,t=2,pt=1,l=1,sg=0,ft=0,st=OK:0 1305446 !TSF:MSG:SEND,3-3-0-0,s=2,c=1,t=2,pt=1,l=1,sg=0,ft=0,st=NACK:0
And after that they recieve it back from gateway, and act as if it was a command to change their state.
Gateway is 2.4 alpha, all 3 nodes are 2.3.2, and only two of them acts like this. I guess I am missing something, but can't grasp what exactly.
Any ideas?