@mfalkvidd Thanks for the reply!
Creaky
@Creaky
Best posts made by Creaky
-
RE: PIR node with interrupts
Thanks for all your feedback guys! I really appreciate it!
I now use the following code based on a MySensors example, it does the job but I have the feeling it still uses quite some power. Is this the best we can do code wise to reduce power? My Chinese Nano V3 clone still uses 17.2mA with this code and I have already disabled the power LED...******************************* * * DESCRIPTION * * Interrupt driven binary switch example with dual interrupts * Author: Patrick 'Anticimex' Fallberg * Connect one button or door/window reed switch between * digitial I/O pin 3 (BUTTON_PIN below) and GND and the other * one in similar fashion on digital I/O pin 2. * This example is designed to fit Arduino Nano/Pro Mini * */ #include <MyConfig.h> #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 //#define MY_REPEATER_FEATURE #define MY_NODE_ID 100 #include <MySensors.h> #define SN "PIRnode" #define SV "0.1" #define PRIMARY_CHILD_ID 0 #define PRIMARY_BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch #if (PRIMARY_BUTTON_PIN < 2 || PRIMARY_BUTTON_PIN > 3) #error PRIMARY_BUTTON_PIN must be either 2 or 3 for interrupts to work #endif #if (PRIMARY_BUTTON_PIN == SECONDARY_BUTTON_PIN) #error PRIMARY_BUTTON_PIN and BUTTON_PIN2 cannot be the same #endif // Change to V_LIGHT if you use S_LIGHT in presentation below MyMessage msg(PRIMARY_CHILD_ID, V_TRIPPED); void setup() { // Setup the buttons pinMode(PRIMARY_BUTTON_PIN, INPUT); // Activate internal pull-ups //digitalWrite(PRIMARY_BUTTON_PIN, HIGH); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo(SN, SV); // Register binary input sensor to sensor_node (they will be created as child devices) // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. present(PRIMARY_CHILD_ID, S_MOTION); } // Loop will iterate on changes on the BUTTON_PINs void loop() { uint8_t value; static uint8_t sentValue = 2; static uint8_t sentValue2 = 2; // Short delay to allow buttons to properly settle sleep(5); value = digitalRead(PRIMARY_BUTTON_PIN); if (value != sentValue) { // Value has changed from last transmission, send the updated value send(msg.set(value == HIGH)); sentValue = value; } // Sleep until something happens with the sensor sleep(PRIMARY_BUTTON_PIN - 2, CHANGE, 0); }
-
RE: PIR node with interrupts
@AWI I realize that now and already purchased a Pro mini 3.3v.
Latest posts made by Creaky
-
RE: Recommendations for soldering temperature
Here is a super interesting article about the science of soldering and how soldering affects electronic components.
Fun fact; ICs aren't watertight!https://hackaday.com/2019/05/03/get-to-know-the-physics-behind-soldering-and-the-packaging-of-ics/
-
RE: PIR node with interrupts
@AWI I realize that now and already purchased a Pro mini 3.3v.
-
RE: PIR node with interrupts
@Nca78 Good one! So much for using an example without thouroughly checking the code
-
RE: PIR node with interrupts
Thanks for all your feedback guys! I really appreciate it!
I now use the following code based on a MySensors example, it does the job but I have the feeling it still uses quite some power. Is this the best we can do code wise to reduce power? My Chinese Nano V3 clone still uses 17.2mA with this code and I have already disabled the power LED...******************************* * * DESCRIPTION * * Interrupt driven binary switch example with dual interrupts * Author: Patrick 'Anticimex' Fallberg * Connect one button or door/window reed switch between * digitial I/O pin 3 (BUTTON_PIN below) and GND and the other * one in similar fashion on digital I/O pin 2. * This example is designed to fit Arduino Nano/Pro Mini * */ #include <MyConfig.h> #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 //#define MY_REPEATER_FEATURE #define MY_NODE_ID 100 #include <MySensors.h> #define SN "PIRnode" #define SV "0.1" #define PRIMARY_CHILD_ID 0 #define PRIMARY_BUTTON_PIN 2 // Arduino Digital I/O pin for button/reed switch #if (PRIMARY_BUTTON_PIN < 2 || PRIMARY_BUTTON_PIN > 3) #error PRIMARY_BUTTON_PIN must be either 2 or 3 for interrupts to work #endif #if (PRIMARY_BUTTON_PIN == SECONDARY_BUTTON_PIN) #error PRIMARY_BUTTON_PIN and BUTTON_PIN2 cannot be the same #endif // Change to V_LIGHT if you use S_LIGHT in presentation below MyMessage msg(PRIMARY_CHILD_ID, V_TRIPPED); void setup() { // Setup the buttons pinMode(PRIMARY_BUTTON_PIN, INPUT); // Activate internal pull-ups //digitalWrite(PRIMARY_BUTTON_PIN, HIGH); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo(SN, SV); // Register binary input sensor to sensor_node (they will be created as child devices) // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. present(PRIMARY_CHILD_ID, S_MOTION); } // Loop will iterate on changes on the BUTTON_PINs void loop() { uint8_t value; static uint8_t sentValue = 2; static uint8_t sentValue2 = 2; // Short delay to allow buttons to properly settle sleep(5); value = digitalRead(PRIMARY_BUTTON_PIN); if (value != sentValue) { // Value has changed from last transmission, send the updated value send(msg.set(value == HIGH)); sentValue = value; } // Sleep until something happens with the sensor sleep(PRIMARY_BUTTON_PIN - 2, CHANGE, 0); }
-
RE: PIR node with interrupts
Is there a way to grab that log from Domoticz?
Otherwise I have to grab it directly from the serial interface of my PI, but I have no clue how to do that under Linux...But apart from that, if the radio isn't powered fast enough, I wouldn't get a st=ok message right? I sort of assume you only get a st=ok when the node has received an ack from the gateway, or am I assuming wrong?
-
PIR node with interrupts
Hi guys!
Hopefully someone can help me out...
I'm trying to build a node that uses a PIR to detect motion and report it back to Domoticz.
But I want this node to consume as little power as possible, so I jumped into the world of Arduino interrupts to put my node to sleep between PIR state changes. I cobbled together the code and when I run it it seems to work. The node initializes, registers itself with the gateway and goes to sleep, waiting for a state change from the PIR. When I trigger the PIR, the debug output shows that the node wakes up, determines what state the PIR is in and sends a message to the gateway. The message seems to be received fine by the gateway, since the status of the send is 1. See a debug grab below:wakeup from sleep Awake-1 Motion detected! TSP:MSG:SEND 100-100-0-0 s=0,c=1,t=16,pt=2,l=2,sg=0,ft=0,st=ok:1 wakeup from sleep Sleeping-0 Motion ended! TSP:MSG:SEND 100-100-0-0 s=0,c=1,t=16,pt=2,l=2,sg=0,ft=0,st=ok:0
But I don't see any updates in my controller! Domoticz doesn't register the PIR states at all... When I try a sketch without interrupts, everything works fine and Domoticz registers every PIR state change...
Here is the code that uses interrupts, what am I doing wrong?
// PIR motion detector sensor with Arduino nano in ultimate power saving mode //(reducing power consumption almost by 70% (4.7mA) of normal operation consumption (13mA)) // Current code by Electromania 24th Feb 2016 //https://youtu.be/n-Oiz76aVYs // Thanks to:- http://playground.arduino.cc/Learning/ArduinoSleepCode for information about sleep.h library and modes // http://www.kevindarrah.com/download/arduino_code/LowPowerVideo.ino // for useful explanation of "Low Power Arduino! Deep Sleep Tutorial" for bare arduino uno chip // http://www.atmel.com/images/atmel-8271-8-bit-avr-microcontroller-atmega48a-48pa-88a-88pa-168a-168pa-328-328p_datasheet_complete.pdf // datasheet #include <MyConfig.h> #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 //#define MY_REPEATER_FEATURE #define MY_NODE_ID 100 #include <MySensors.h> #define SN "PIRnode" #define SV "0.1" #define PRIMARY_CHILD_ID 0 #include <avr/interrupt.h> // Library to use interrupt #include <avr/sleep.h> // Library for putting our arduino into sleep modes const int PIRsensorInterrupt = 0; //interrupt 0 at arduino nano pin D2 const int LedPin = 13; // external LED or relay connected to pin 13 int inputPin = 2; // choose the input pin (for PIR sensor) int val = 0; // variable for reading the pin status long lastUpdate = 0; MyMessage PIRMsg(PRIMARY_CHILD_ID, V_TRIPPED); volatile int lastPIRsensorState = 1; // previous sensor state volatile int PIRsensorState = 0; // current state of the button void wakeUpNow(){ // Interrupt service routine or ISR PIRsensorState = !lastPIRsensorState; // we negate previous state and assign to current state } void setup() { pinMode(LedPin, OUTPUT); // initialize pin 13 as an output pin for LED or relay etc. Serial.begin(115200); // initialize serial communication only for debugging purpose //Serial.println("Warming up... wait for a min..."); //// delay execution of sketch for a min, to allow PIR sensor get stabilized //for (int i = 1; i <= 120; i++){ // LED at pin 13 blinks until PIR sensor is stabilized // digitalWrite(LedPin, HIGH); // delay(100); // digitalWrite(LedPin, LOW); // delay(100); //} Serial.println("Ready"); // enable only for debugging purpose pinMode(PIRsensorInterrupt, INPUT); // define interrupt pin D2 as input to read interrupt received by PIR sensor } void presentation() { // Register sensor to sensor_node (they will be created as child devices) // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. present(PRIMARY_CHILD_ID, S_MOTION); sendSketchInfo(SN, SV); } void Hibernate() // here arduino is put to sleep/hibernation { set_sleep_mode(SLEEP_MODE_PWR_DOWN); // lowest power consumption mode //"The Power-down mode saves the register contents but freezes the Oscillator, disabling all other chip functions // until the next interrupt or hardware reset." text from ATMEGA328P datasheet ADCSRA &= ~(1 << 7); // Disable ADC - don't forget to flip back after waking up if you need ADC in your application ADCSRA |= (1 << 7); (From Kevin's sketch) sleep_enable(); // enable the sleep mode function sleep_bod_disable(); //to disable the Brown Out Detector (BOD) before going to sleep. attachInterrupt(PIRsensorInterrupt, wakeUpNow, CHANGE); // Attach interrupt at pin D2 (int 0 is at pin D2 for nano, UNO) // here since PIR sensor has inbuilt timer to swtich its state from OFF to ON, we are detecting its CHANGE IN STATE to control our LED/relay at pin 13. // therefore, we will not need to use arduino delay timer to Set "ON time" of our LED/relay, it can be adjusted physically using potentiometer provided on PIR sensor board. // This further helps in using SLEEP_MODE_PWR_DOWN which is ultimate lowest power consumption mode for ATMEGA8328P chip //(please note - because of onboard power regulators of arduino boards, power consumption cannot be reduced to predicted few microAmps level of bare chips. //To achieve further reduction in current consumption, we will need bare ATMEGA328P chip) for (int i = 0; i < 20; i++) { if (i != 13)// because the LED/Relay is connected to digital pin 13 pinMode(i, INPUT); } sleep_mode(); // calls function to put arduino in sleep mode Serial.println("wakeup from sleep"); sleep_disable(); // when interrupt is received, sleep mode is disabled and program execution resumes from here detachInterrupt(PIRsensorInterrupt); // we detach interrupt from pin D2, to avoid further interrupts until our ISR is finished } void loop() { interrupts(); // enable interrupts for Due and Nano V3 if (PIRsensorState != lastPIRsensorState){ if (PIRsensorState == 0) { digitalWrite(LedPin, LOW); Serial.print("Sleeping-"); // enable for debugging Serial.println(PIRsensorState); // read status of interrupt pin Serial.println("Motion ended!"); send(PIRMsg.set(0)); } else { digitalWrite(LedPin, HIGH); Serial.print("Awake-"); // enable for debugging Serial.println(PIRsensorState); // read status of interrupt pin enable for debugging Serial.println("Motion detected!"); send(PIRMsg.set(1)); delay(50); } } lastPIRsensorState = PIRsensorState; // reset lastinterrupt state delay(50); Hibernate(); // go to sleep - calling sleeping function }
-
RE: Interrupt conflict newremoteswitch and MySensors receive() function?
@Alexander, does your node use the receive() function to receive commands from controller?
-
RE: Interrupt conflict newremoteswitch and MySensors receive() function?
Hi Hek,
Thank you for the feedback! I'll get rid of the String class and have another go.
-
Interrupt conflict newremoteswitch and MySensors receive() function?
Hi all,
I'm trying to make a node that functions as a dimmer for a LED strip as well as a RF receiver for nearby KlikAanKlikUit RF switches.
Pressing a KaKu RF switch sets a MySensors switch to let the controller know the switch was flipped and execute some stuff in Domoticz.I've managed to combine everything codewise, but when I run the sketch it works initially but seizes up after a while.
I'm pretty sure it has to do with the receiver() function and interrupts somehow, but I'm not experienced enough in C or the MySensors framework to fix this.
Can one of you have a look at my code and help me fix the problem? (With interruptchain perhaps???)Here's the code:
// Enable debug prints to serial monitor #include <NewRemoteReceiver.h> #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 #define MY_REPEATER_FEATURE #include <MySensors.h> #include <Bounce2.h> #define SN "DimmableLED" #define SV "1.1" #define PRIMARY_CHILD_ID 1 #define SECONDARY_CHILD_ID 2 #define LED_PIN 3 // Arduino pin attached to MOSFET Gate pin #define FADE_DELAY 10 // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim) static int16_t currentLevel = 0; // Current dim level... static int16_t currentButtonState = 0; // Current state for button 1 static int16_t currentButton2State = 0; // Current state for button 2 int lastLevel; MyMessage dimmerMsg(0, V_DIMMER); MyMessage lightMsg(0, V_LIGHT); MyMessage buttonMsg(PRIMARY_CHILD_ID, V_LIGHT); MyMessage buttonMsg2(SECONDARY_CHILD_ID, V_LIGHT); /*** * Dimmable LED initialization method */ void setup() { // Pull the gateway's current dim level - restore light level upon sendor node power-up request( 0, V_DIMMER ); // Setup the RF receiver NewRemoteReceiver::init(0, 2, showCode); } void presentation() { // Register the LED Dimmable Light with the gateway present( 0, S_DIMMER ); // Register binary input sensor to sensor_node (they will be created as child devices) // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage. // If S_LIGHT is used, remember to update variable type you send in. See "msg" above. present(PRIMARY_CHILD_ID, S_LIGHT); present(SECONDARY_CHILD_ID, S_LIGHT); sendSketchInfo(SN, SV); } /*** * Dimmable LED main processing loop */ void loop() { } void receive(const MyMessage &message) { if ((message.type == V_LIGHT || message.type == V_DIMMER) && message.sensor == 0) { // Retrieve the power or dim level from the incoming request message int requestedLevel = atoi( message.data ); // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on] //requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 ); // Als we van OFF naar ON gaan, dan laatst bekende niveau toepassen requestedLevel *= (message.type == V_LIGHT ? lastLevel : 1); // Clip incoming level to valid range of 0 to 100 requestedLevel = requestedLevel > 100 ? 100 : requestedLevel; requestedLevel = requestedLevel < 0 ? 0 : requestedLevel; Serial.print( "Changing level to " ); Serial.print( requestedLevel ); Serial.print( ", from " ); Serial.println( currentLevel ); fadeToLevel( requestedLevel ); // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value... send(lightMsg.set(currentLevel > 0)); // hek comment: Is this really nessesary? send( dimmerMsg.set(currentLevel) ); if (currentLevel != 0) { lastLevel = currentLevel; } } } /*** * This method provides a graceful fade up/down effect */ void fadeToLevel( int toLevel ) { int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1; while ( currentLevel != toLevel ) { currentLevel += delta; analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) ); delay( FADE_DELAY ); } } // Callback function is called only when a valid code is received. void showCode(NewRemoteCode receivedCode) { // Note: interrupts are disabled. You can re-enable them if needed. // Print the received code. //Serial.print("Addr "); //Serial.print(receivedCode.address); //if (receivedCode.groupBit) { // Serial.print(" group"); //} //else { // Serial.print(" unit "); // Serial.print(receivedCode.unit); //} //switch (receivedCode.switchType) { //case NewRemoteCode::off: // Serial.print(" off"); // break; //case NewRemoteCode::on: // Serial.print(" on"); // break; //case NewRemoteCode::dim: // Serial.print(" dim"); // break; //} //if (receivedCode.dimLevelPresent) { // Serial.print(", dim level: "); // Serial.print(receivedCode.dimLevel); //} //Serial.print(", period: "); //Serial.print(receivedCode.period); //Serial.println("us."); String str(receivedCode.switchType); if (receivedCode.unit == 10 && str == "1") { Serial.println("Send nr 1 ON"); send(buttonMsg.set(1)); Serial.println("Send nr 1 ON done"); } if (receivedCode.unit == 10 && str == "0") { Serial.println("send nr 1 OFF"); send(buttonMsg.set(0)); Serial.println("send nr 1 OFF done"); } if (receivedCode.unit == 11 && str == "1") { Serial.println("Send nr 2 ON"); send(buttonMsg2.set(1)); Serial.println("Send nr 2 ON done"); } if (receivedCode.unit == 11 && str == "0") { Serial.println("Send nr 2 OFF"); send(buttonMsg2.set(0)); Serial.println("Send nr 2 OFF done"); } }
-
RE: 💬 Dimmable LED Actuator
@mfalkvidd Yikes, you're right! I drew my conclusion too soon and only by watching the LED strip at max brightness. At max brightness the switching frequency is so high it is no longer perceptible by the eye. Mea culpa...