Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. Curtain Control Node.

Curtain Control Node.

Scheduled Pinned Locked Moved My Project
domoticzcurtain controlmysensors node
51 Posts 15 Posters 20.0k Views 22 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Suresh MaliS Offline
    Suresh MaliS Offline
    Suresh Mali
    wrote on last edited by Suresh Mali
    #3

    Its a Geared DC Motor with Voltage Rating of 6-12V and 100 RPM. I am using a L239 to control the motor.
    alt text

    1 Reply Last reply
    1
    • AWIA Offline
      AWIA Offline
      AWI
      Hero Member
      wrote on last edited by
      #4

      Looks good. I am curious to see the details... jealous for the speed :runner: your curtain is moving.

      I have been working on a similar project last week. The mechanics and ´looks´ are the most difficult part for me.

      For now I have used a ´tuned´ cheap & small stepper which makes it slooow but effective ;-) The rail and mounting is standard IKEA. The pro-mini has the jModule attached. Works like a charm (/snail)!

      0_1457980545567_upload-c50fc1e9-f23e-458d-a812-62ad4bf478e0
      0_1457981153586_upload-c7064209-3900-4e4b-b335-8c88721367c0

      TheoLT 1 Reply Last reply
      1
      • Suresh MaliS Offline
        Suresh MaliS Offline
        Suresh Mali
        wrote on last edited by Suresh Mali
        #5

        @AWI Thanks. Why dont you increase the pulley size (larger pulley) that will increase the speed.

        I found driving stepper motor to be bit more complicated than driving a DC motor. I picked the Geared motor basis the calculation using this calculator.

        Since without rails pulling the curtains on a metal pipe needed more torque. Thus I chose 100 RPM to be a suitable fit.

        Will share the Schematics and PCB layout files soon. I have already added the sketch for reference. Since I was testing I did not put the circuit in any housing. But will give some shape soon.

        Also will be adding 3 buttons for Manual Control.

        1 Reply Last reply
        0
        • barduinoB Offline
          barduinoB Offline
          barduino
          wrote on last edited by
          #6

          @Suresh-Mali

          DC Motor, very interesting!

          Do you have end stops? The sketch doesn't open for some reason...

          Cheers

          Suresh MaliS S 2 Replies Last reply
          0
          • barduinoB barduino

            @Suresh-Mali

            DC Motor, very interesting!

            Do you have end stops? The sketch doesn't open for some reason...

            Cheers

            Suresh MaliS Offline
            Suresh MaliS Offline
            Suresh Mali
            wrote on last edited by
            #7

            @barduino I tried downloading the code, it works. Anyways I am pasting the code below.

            For end stops I have not yet decided. I had some Ideas of using Hall effect sensor on both ends and a small piece of magnet in the string to detect ends or Maybe use stop switches. Not sure but will have to try both and see which works the best.

            I am yet to clean the code I have some debugging serial prints in code which will remove once finalized.

            #include <SPI.h>
            #include <MySensor.h>
            
            
            int motor_forward = 5;
            int motor_reverse = 6;
            
            int LDRinput = 1;     //analog pin to which LDR is connected, here we set it to 0 so it means A0
            int LDRValue = 0;      //that�s a variable to store LDR values
            int light_sensitivity = 500;    //This is the approx value of light surrounding your LDR
            
            int stopSwLeft = 4;
            int stopSwRight = 3;
            int stopSwNow = 2;
            
            int CHILD_CURTAIN_ID =1;
            int lastState;
            MySensor gw;
            MyMessage msg_S_COVER_U(CHILD_CURTAIN_ID, V_UP);
            MyMessage msg_S_COVER_D(CHILD_CURTAIN_ID, V_DOWN);
            MyMessage msg_S_COVER_S(CHILD_CURTAIN_ID, V_STOP);
            //MyMessage msg(CHILD_CURTAIN_ID,V_UP);
            // the setup routine runs once when you press reset:
            void setup()
            {
            	Serial.begin(115200);
            	// initialize the digital pin as an output for L239D.
            	pinMode(motor_forward, OUTPUT);
            	pinMode(motor_reverse, OUTPUT);
            	
            	// initialize the digital pin as an output for Stop Switches.
            	pinMode(stopSwLeft, INPUT_PULLUP);
            	pinMode(stopSwRight, INPUT_PULLUP);
            	pinMode(stopSwNow, INPUT_PULLUP);
            	
            	gw.begin(incomingMessage, AUTO, true);
            	// Send the sketch version information to the gateway and Controller
            	gw.sendSketchInfo("Window_Curtain", "1.0");
            	gw.present(CHILD_CURTAIN_ID, S_COVER);
            	
            }
            
            void loop(){
            	
            	gw.process();
            	
            	}
            void cover(int coverVal){
            
            	//int coverVal = gw.loadState(CHILD_CURTAIN_ID);
            
            	Serial.print("Cover is : ");
            	lastState = coverVal;
            	switch (coverVal) {
            	case 0:
            		Serial.println("Opening");
            			while (lastState == coverVal)
            			{
            				m_left();
            				gw.process();
            				checkHWInnputs();
            				coverVal = gw.loadState(CHILD_CURTAIN_ID);
            			}
            			gw.send(msg_S_COVER_U.set(V_UP));
            		break;
            	case 1:
            		Serial.println("Closing");
            			while (lastState == coverVal)
            			{
            				m_right();
            				gw.process();
            				checkHWInnputs();
            				coverVal = gw.loadState(CHILD_CURTAIN_ID);
            			}
            			gw.send(msg_S_COVER_D.set(V_DOWN));
            		break;
            	case 2:
            		Serial.println("Idle");
            			while (lastState == coverVal)
            				{
            					m_stop();
            					gw.process();
            					checkHWInnputs();
            					coverVal = gw.loadState(CHILD_CURTAIN_ID);
            				}
            			gw.send(msg_S_COVER_S.set(V_STOP));
            			break;
            	}
            	return;
            
            }
            void incomingMessage(const MyMessage &message) {
            	// We only expect one type of message from controller. But we better check anyway.
            	Serial.println("recieved incomming message");
            	switch (message.type) {
            	case V_UP:
            		gw.saveState(CHILD_CURTAIN_ID, 0);
            		Serial.print("Incoming change for ID_S_COVER:");
            		Serial.print(message.sensor);
            		Serial.print(", New status: ");
            		Serial.println("V_UP");
            		cover(gw.loadState(CHILD_CURTAIN_ID));
            		Serial.print("Done cover procedure");
            		//m_right();
            		break;
            
            	case V_DOWN:
            		gw.saveState(CHILD_CURTAIN_ID, 1);
            		Serial.print("Incoming change for ID_S_COVER:");
            		Serial.print(message.sensor);
            		Serial.print(", New status: ");
            		Serial.println("V_DOWN");
            		cover(gw.loadState(CHILD_CURTAIN_ID));
            		Serial.print("Done cover procedure");
            		//m_left();
            		break;
            
            	case V_STOP:
            		gw.saveState(CHILD_CURTAIN_ID, 2);
            		Serial.print("Incoming change for ID_S_COVER:");
            		Serial.print(message.sensor);
            		Serial.print(", New status: ");
            		Serial.println("V_STOP");
            		cover(gw.loadState(CHILD_CURTAIN_ID));
            		Serial.print("Done cover procedure");
            		//m_stop();
            		break;
            	}
            	Serial.print("exiting incoming message");
            	return;
            	
            }
            // the loop routine runs over and over again forever:
            void m_right() {
            	digitalWrite(motor_forward, HIGH); //terminal D1 will be HIGH
            	digitalWrite(motor_reverse, LOW); //terminal D2 will be LOW
            	Serial.print("Set For:High and Rev: Low");
            	exit;
            }
            
            void m_left() {
            	digitalWrite(motor_forward, LOW); //terminal D1 will be LOW
            	digitalWrite(motor_reverse, HIGH); //terminal D2 will be HIGH
            	Serial.print("Set For:Low and Rev: High");
            	exit;
            }
            
            void m_stop() {
            	digitalWrite(motor_forward, LOW); //terminal D1 will be LOW
            	digitalWrite(motor_reverse, LOW); //terminal D2 will be HIGH
            	Serial.print("Set For:Low and Rev: Low");
            	exit;
            }
            
            void checkHWInnputs()
            	{
            		if (digitalRead(stopSwNow) == LOW)
            		{
            			Serial.println("Detected stop button push. Stopping");
            			cover(2);
            			Serial.println("Saved stop state to EEPROM");
            		}
            		if (digitalRead(stopSwLeft) == LOW)
            		{
            			Serial.println("Detected stop button push. Stopping");
            			cover(1);
            			Serial.println("Saved stop state to EEPROM");
            		}
            		if (digitalRead(stopSwRight) == LOW)
            		{
            			Serial.println("Detected stop button push. Stopping");
            			cover(0);
            			Serial.println("Saved stop state to EEPROM");
            		}
            	}
            
            
            barduinoB 1 Reply Last reply
            0
            • franzelareF Offline
              franzelareF Offline
              franzelare
              wrote on last edited by
              #8

              Sweet!
              My girl has put this on my todolist...
              But still have to get started, this is some nice reference for my new porject!

              Suresh MaliS 1 Reply Last reply
              1
              • franzelareF franzelare

                Sweet!
                My girl has put this on my todolist...
                But still have to get started, this is some nice reference for my new porject!

                Suresh MaliS Offline
                Suresh MaliS Offline
                Suresh Mali
                wrote on last edited by
                #9

                @franzelare Great. Good Luck with the build.

                I'll be posting my HW design and Code as part of Contest on openhardware.io

                1 Reply Last reply
                1
                • Suresh MaliS Offline
                  Suresh MaliS Offline
                  Suresh Mali
                  wrote on last edited by
                  #10

                  I have published my project with all the files.
                  https://www.openhardware.io/view/45/Curtain-Control-Node

                  1 Reply Last reply
                  0
                  • Suresh MaliS Suresh Mali

                    @barduino I tried downloading the code, it works. Anyways I am pasting the code below.

                    For end stops I have not yet decided. I had some Ideas of using Hall effect sensor on both ends and a small piece of magnet in the string to detect ends or Maybe use stop switches. Not sure but will have to try both and see which works the best.

                    I am yet to clean the code I have some debugging serial prints in code which will remove once finalized.

                    #include <SPI.h>
                    #include <MySensor.h>
                    
                    
                    int motor_forward = 5;
                    int motor_reverse = 6;
                    
                    int LDRinput = 1;     //analog pin to which LDR is connected, here we set it to 0 so it means A0
                    int LDRValue = 0;      //that�s a variable to store LDR values
                    int light_sensitivity = 500;    //This is the approx value of light surrounding your LDR
                    
                    int stopSwLeft = 4;
                    int stopSwRight = 3;
                    int stopSwNow = 2;
                    
                    int CHILD_CURTAIN_ID =1;
                    int lastState;
                    MySensor gw;
                    MyMessage msg_S_COVER_U(CHILD_CURTAIN_ID, V_UP);
                    MyMessage msg_S_COVER_D(CHILD_CURTAIN_ID, V_DOWN);
                    MyMessage msg_S_COVER_S(CHILD_CURTAIN_ID, V_STOP);
                    //MyMessage msg(CHILD_CURTAIN_ID,V_UP);
                    // the setup routine runs once when you press reset:
                    void setup()
                    {
                    	Serial.begin(115200);
                    	// initialize the digital pin as an output for L239D.
                    	pinMode(motor_forward, OUTPUT);
                    	pinMode(motor_reverse, OUTPUT);
                    	
                    	// initialize the digital pin as an output for Stop Switches.
                    	pinMode(stopSwLeft, INPUT_PULLUP);
                    	pinMode(stopSwRight, INPUT_PULLUP);
                    	pinMode(stopSwNow, INPUT_PULLUP);
                    	
                    	gw.begin(incomingMessage, AUTO, true);
                    	// Send the sketch version information to the gateway and Controller
                    	gw.sendSketchInfo("Window_Curtain", "1.0");
                    	gw.present(CHILD_CURTAIN_ID, S_COVER);
                    	
                    }
                    
                    void loop(){
                    	
                    	gw.process();
                    	
                    	}
                    void cover(int coverVal){
                    
                    	//int coverVal = gw.loadState(CHILD_CURTAIN_ID);
                    
                    	Serial.print("Cover is : ");
                    	lastState = coverVal;
                    	switch (coverVal) {
                    	case 0:
                    		Serial.println("Opening");
                    			while (lastState == coverVal)
                    			{
                    				m_left();
                    				gw.process();
                    				checkHWInnputs();
                    				coverVal = gw.loadState(CHILD_CURTAIN_ID);
                    			}
                    			gw.send(msg_S_COVER_U.set(V_UP));
                    		break;
                    	case 1:
                    		Serial.println("Closing");
                    			while (lastState == coverVal)
                    			{
                    				m_right();
                    				gw.process();
                    				checkHWInnputs();
                    				coverVal = gw.loadState(CHILD_CURTAIN_ID);
                    			}
                    			gw.send(msg_S_COVER_D.set(V_DOWN));
                    		break;
                    	case 2:
                    		Serial.println("Idle");
                    			while (lastState == coverVal)
                    				{
                    					m_stop();
                    					gw.process();
                    					checkHWInnputs();
                    					coverVal = gw.loadState(CHILD_CURTAIN_ID);
                    				}
                    			gw.send(msg_S_COVER_S.set(V_STOP));
                    			break;
                    	}
                    	return;
                    
                    }
                    void incomingMessage(const MyMessage &message) {
                    	// We only expect one type of message from controller. But we better check anyway.
                    	Serial.println("recieved incomming message");
                    	switch (message.type) {
                    	case V_UP:
                    		gw.saveState(CHILD_CURTAIN_ID, 0);
                    		Serial.print("Incoming change for ID_S_COVER:");
                    		Serial.print(message.sensor);
                    		Serial.print(", New status: ");
                    		Serial.println("V_UP");
                    		cover(gw.loadState(CHILD_CURTAIN_ID));
                    		Serial.print("Done cover procedure");
                    		//m_right();
                    		break;
                    
                    	case V_DOWN:
                    		gw.saveState(CHILD_CURTAIN_ID, 1);
                    		Serial.print("Incoming change for ID_S_COVER:");
                    		Serial.print(message.sensor);
                    		Serial.print(", New status: ");
                    		Serial.println("V_DOWN");
                    		cover(gw.loadState(CHILD_CURTAIN_ID));
                    		Serial.print("Done cover procedure");
                    		//m_left();
                    		break;
                    
                    	case V_STOP:
                    		gw.saveState(CHILD_CURTAIN_ID, 2);
                    		Serial.print("Incoming change for ID_S_COVER:");
                    		Serial.print(message.sensor);
                    		Serial.print(", New status: ");
                    		Serial.println("V_STOP");
                    		cover(gw.loadState(CHILD_CURTAIN_ID));
                    		Serial.print("Done cover procedure");
                    		//m_stop();
                    		break;
                    	}
                    	Serial.print("exiting incoming message");
                    	return;
                    	
                    }
                    // the loop routine runs over and over again forever:
                    void m_right() {
                    	digitalWrite(motor_forward, HIGH); //terminal D1 will be HIGH
                    	digitalWrite(motor_reverse, LOW); //terminal D2 will be LOW
                    	Serial.print("Set For:High and Rev: Low");
                    	exit;
                    }
                    
                    void m_left() {
                    	digitalWrite(motor_forward, LOW); //terminal D1 will be LOW
                    	digitalWrite(motor_reverse, HIGH); //terminal D2 will be HIGH
                    	Serial.print("Set For:Low and Rev: High");
                    	exit;
                    }
                    
                    void m_stop() {
                    	digitalWrite(motor_forward, LOW); //terminal D1 will be LOW
                    	digitalWrite(motor_reverse, LOW); //terminal D2 will be HIGH
                    	Serial.print("Set For:Low and Rev: Low");
                    	exit;
                    }
                    
                    void checkHWInnputs()
                    	{
                    		if (digitalRead(stopSwNow) == LOW)
                    		{
                    			Serial.println("Detected stop button push. Stopping");
                    			cover(2);
                    			Serial.println("Saved stop state to EEPROM");
                    		}
                    		if (digitalRead(stopSwLeft) == LOW)
                    		{
                    			Serial.println("Detected stop button push. Stopping");
                    			cover(1);
                    			Serial.println("Saved stop state to EEPROM");
                    		}
                    		if (digitalRead(stopSwRight) == LOW)
                    		{
                    			Serial.println("Detected stop button push. Stopping");
                    			cover(0);
                    			Serial.println("Saved stop state to EEPROM");
                    		}
                    	}
                    
                    
                    barduinoB Offline
                    barduinoB Offline
                    barduino
                    wrote on last edited by
                    #11

                    @Suresh-Mali

                    I'm just curious, maybe its the arduino IDE version or something.

                    I'm using 1.6.4 and I get this:

                    0_1458129604092_upload-1364c257-d6a3-46d0-bdec-ff24cf9d2b41

                    However opening with a text editor is fine:

                    0_1458129652911_upload-e1883418-162b-4aba-bacf-d3e85436cca7

                    Cheers

                    Suresh MaliS 1 Reply Last reply
                    0
                    • barduinoB barduino

                      @Suresh-Mali

                      I'm just curious, maybe its the arduino IDE version or something.

                      I'm using 1.6.4 and I get this:

                      0_1458129604092_upload-1364c257-d6a3-46d0-bdec-ff24cf9d2b41

                      However opening with a text editor is fine:

                      0_1458129652911_upload-e1883418-162b-4aba-bacf-d3e85436cca7

                      Cheers

                      Suresh MaliS Offline
                      Suresh MaliS Offline
                      Suresh Mali
                      wrote on last edited by
                      #12

                      @barduino Seems like the IDE. Open any example MySensors Sketch. Delete the contents from sketch and copy paste from my sketch. I guess that should work.

                      Are you able to compile any other sketch in Arduino?

                      1 Reply Last reply
                      0
                      • P Offline
                        P Offline
                        patchmaster
                        wrote on last edited by
                        #13

                        @AWI Are you able to share the sketch you used with the UL2003 driver board? I have tried to combine the MySensors servo sketch with other arduino only sketches utilizing the UL2003, but without luck. Thanks.

                        Suresh MaliS AWIA 2 Replies Last reply
                        0
                        • P patchmaster

                          @AWI Are you able to share the sketch you used with the UL2003 driver board? I have tried to combine the MySensors servo sketch with other arduino only sketches utilizing the UL2003, but without luck. Thanks.

                          Suresh MaliS Offline
                          Suresh MaliS Offline
                          Suresh Mali
                          wrote on last edited by
                          #14

                          @patchmaster I used the relay sketch and modified it to my needs. Sorry but I dont have any sketch for ULN2003. :disappointed:

                          1 Reply Last reply
                          0
                          • P patchmaster

                            @AWI Are you able to share the sketch you used with the UL2003 driver board? I have tried to combine the MySensors servo sketch with other arduino only sketches utilizing the UL2003, but without luck. Thanks.

                            AWIA Offline
                            AWIA Offline
                            AWI
                            Hero Member
                            wrote on last edited by
                            #15

                            @patchmaster This is my current curtain control sketch. I work with the development branch, so the syntax can be a little different.

                            The Accelstepper library gives you all the abilities to slow start/stop with numerous kinds of steppers.
                            My sketch includes a calibration function (stored in EEPROM) so the you don't need end stop detection (a stepper knows where it is)

                            /*
                             PROJECT: MY Sensors curtain controller
                             PROGRAMMER: AWI
                             DATE: march 11, 2016
                             FILE: AWI stepper1.ino
                             LICENSE: Public domain
                            
                             Hardware: ATMega328p board w/ NRF24l01
                            	and MySensors 2.0 (Development)
                            		
                            Special:
                            	uses AccelStepper library
                            	
                            Summary:
                            	Curtain control with stepper motor. 
                            	Manual operation with 1 push button 
                            	Calibration with manual button
                            
                            Remarks:
                            	Fixed node-id
                            	
                            Change log:
                            20160312 - Cleanup
                            */
                            
                            // Enable debug prints to serial monitor
                            #define MY_DEBUG 
                            
                            #define MY_NODE_ID 13											// fixed node number
                            // Enable and select radio type attached
                            #define MY_RADIO_NRF24
                            //#define MY_RADIO_RFM69
                            
                            #include <SPI.h>
                            #include <MySensor.h> 
                            
                            // stepper library
                            #include <AccelStepper.h>										// http://www.airspayce.com/mikem/arduino/AccelStepper/
                            #define HALFSTEP 8  											// Stepper uses "Halfstep" mode
                            
                            // button library
                            // used for:
                            // - manual open close - single click: close/ stop/ open/ stop
                            // - calibration  - after long press: open calibarion- until single press - closed calibration - until single press (stop)
                            #include <Button.h>												// https://github.com/JChristensen/Button
                            
                            #define CHILD_ID 1   											// Id of the sensor child
                            
                            #define SN "Curtain control 13"
                            #define SV "1.0"
                            
                            #define buttonPin1 7  											// Arduino pin connected to buttonPin1
                            #define buttonPin2 A0  											// Arduino pin connected to buttonPin2 (fixed to ground)
                            
                            // Motor pin definitions
                            #define motorPin1  3     										// IN1 on the ULN2003 driver 1
                            #define motorPin2  4     										// IN2 on the ULN2003 driver 1
                            #define motorPin3  5     										// IN3 on the ULN2003 driver 1
                            #define motorPin4  6     										// IN4 on the ULN2003 driver 1
                            
                            const unsigned long heartbeatInterval = 1 * 3600UL * 1000UL ;	// heartbeatinterval
                            unsigned long heartbeatCounter = 0 ;
                            
                            //
                            // helper routines to store and retrieve long in mysensors EEPROM
                            union {															// used to convert long to bytes for EEPROM storage
                            	long longInt;
                            	uint8_t LongByte[4];
                            	} convLongInt ;
                            
                            void saveStateL(int EEposition, long StateL){
                            	convLongInt.longInt = StateL ;
                            	for (int y = 0; y < 4 ; y++){								// convert to bytes
                            		saveState(EEposition + y , convLongInt.LongByte[y]) ;
                            		}
                            	Serial.print("State saved: "); Serial.println(StateL);
                            	}
                            		
                            long loadStateL(int EEposition){
                            	for (int y = 0; y < 4 ; y++){								// convert from bytes
                            		convLongInt.LongByte[y] = loadState(EEposition + y) ;
                            		}
                            	Serial.print("State read: "); Serial.println(convLongInt.longInt);
                            	return convLongInt.longInt ;
                            	}
                            	
                            
                            // Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
                            AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
                            // Initialize button active low, debounce and internal pull-up
                            Button myBtn(buttonPin1, true, true, 40);						// Initiate the button (pin, pull_up, invert, debounce_ms)
                            
                            MyMessage percentageMsg(CHILD_ID, V_PERCENTAGE);				// used to send updates to controller
                            
                            const long maxRun = 4000000L ;									// maximum runway
                            long setPosition = 0 ; 											// remembers set position, need to be saved in EEPROM
                            const int setPositionEE = 4 ;									// eeprom location
                            long openPosition = 0 ; 										// Position at open, need to be saved in EEPROM?
                            const int openPositionEE = setPositionEE + 4 ;					// eeprom location
                            long closedPosition = 120000UL ; 								// Position at full close, need to be saved in EEPROM
                            const int closedPositionEE = openPositionEE + 4 ;				// eeprom location
                            
                            unsigned long idleTimer = millis() ;							// return to idle timer
                            unsigned long idleTime = 100000UL ;								// return to idle after 100 secs
                            
                            unsigned long printTimer = millis() ;							// print timer
                            unsigned long printTime = 1000UL ;								// print after 1 secs
                            
                            enum position_t {Open, Close, Idle, Running} ;
                            position_t lastDirection = Open ; 								// lastDirection only for buttonpress
                            position_t runStatus = Idle ;									// indicates current status for running motor. used for status reporting to controller
                            
                            enum State_t {sIdle, sCalibrateOpen, sCalibrateClose} ;
                            State_t State = sIdle ;
                            
                            
                            void setup() {
                            	// setup buttons
                            	pinMode(buttonPin1, OUTPUT);
                            	stepper1.setMaxSpeed(2000.0);
                            	stepper1.setAcceleration(1000.0);
                            	//saveStateL(closedPositionEE, closedPosition) ; 			// INIT: save closed position in EEPROM
                            	closedPosition = loadStateL(closedPositionEE) ;				// need to get last values from EEPROM and assume the current position is correct
                            	setPosition = loadStateL(setPositionEE) ;
                            	stepper1.setCurrentPosition(setPosition );
                            }//--(end setup )---
                            
                            void presentation() {
                              present(CHILD_ID, S_COVER, "Curtain");						// Window Cover sub-type, commands: V_UP, V_DOWN, V_STOP
                            
                              // Register the LED Dimmable Light with the gateway
                              sendSketchInfo(SN, SV);
                            }
                            
                            
                            void loop() {
                            unsigned int now = millis() ;								// current time for loop
                            // simple state machine for button press
                            	myBtn.read();  
                            	switch (State) {
                                    // Idle state, waiting for some action
                            		// - button press
                            		// - idleTimer
                                    case sIdle:                
                                        if (myBtn.wasReleased()){						// idle
                            				Serial.println("Button release") ;
                            				// if running stop
                            				if (stepper1.isRunning()){
                            					setPosition = stepper1.currentPosition();
                            					stepper1.moveTo(setPosition) ;			// move to current position (was already there..)
                            				} else if (lastDirection == Open) {
                            					stepper1.moveTo(closedPosition) ;
                            					lastDirection = Close ;
                            				} else {									// lastDirection == Close
                            					stepper1.moveTo(openPosition) ;
                            					lastDirection = Open ;
                            				}	
                            			} else if (myBtn.pressedFor(3000)){				// move to calibratete state with long press
                            				Serial.println("Button press long") ;
                            				idleTimer = now ;							// return to idle after ...
                            				State = sCalibrateOpen ;
                            				stepper1.move(-maxRun) ;					// let the stepper open with maximum
                            				}
                            			break ;
                            		// if not running and last action was open close ;  else open
                            		// if longpress Calibrate open
                                    case sCalibrateOpen:           						// calibration going on     
                            			if (myBtn.wasPressed()){
                            				stepper1.setCurrentPosition(0 );		// set new 0 position ??
                            				openPosition = setPosition = 0 ;
                            				State = sCalibrateClose ;					// next is close calibarion
                            				stepper1.move(maxRun) ;						// let the stepper close with maximum
                            			} else if (now > idleTimer + idleTime) {		// timer expired -> abort calibration
                            				State = sIdle ;
                            			}
                            			break ;
                                    case sCalibrateClose:								// calibrate closed position, end with keypress
                            			if (myBtn.wasPressed())	{
                            				closedPosition = setPosition = stepper1.currentPosition() ;
                            				saveStateL(closedPositionEE, closedPosition) ; // save closed position in EEPROM
                            				State = sIdle ;
                            				stepper1.moveTo(openPosition) ;				// return to open after calibration
                            			} else if (now > idleTimer + idleTime) {		// timer expired -> abort calibration
                            				State = sIdle ;
                            			}
                            			break ;
                            		default :
                            			break ;
                            		}
                            	// power off stepper if not running (no need to reenable))
                            	if (!stepper1.isRunning()){
                            		if (runStatus != Idle){								// there was a change in runningstatus, so report to controller
                            			setPosition = stepper1.currentPosition() ;		// store in EEPROM and report ready to controller
                            			saveStateL(setPositionEE, setPosition) ;
                            			send( percentageMsg.set((100 * setPosition)/(closedPosition - openPosition))) ;
                            			runStatus = Idle ;
                            		}
                            		stepper1.disableOutputs();
                            	} else {
                            		runStatus = Running ;
                            	}
                            	stepper1.run();
                            	/*
                            	if (printTimer++ > now + printTime){
                            		printTimer = now ;
                            		Serial.println(stepper1.currentPosition());
                            		}
                            	*/
                            }
                            
                            // This is called when a message is received 
                            void receive(const MyMessage &message) {
                            // We only expect few types of messages from controller, check which
                              switch (message.type) {
                            	case V_PERCENTAGE:
                            	// Curtain should be opened
                            	stepper1.moveTo(message.getInt() * (closedPosition - openPosition)/100);
                            	Serial.print("Message: "); Serial.print(message.sensor); Serial.print(" , value: % "); Serial.println( message.getInt());
                            	Serial.print("Moving to: "); Serial.println(message.getInt() * (closedPosition - openPosition)/100);
                            	break ;
                            	case V_STATUS:
                            	// Curtain should be opened or closed full
                            	stepper1.moveTo((message.getInt() == HIGH)?openPosition:closedPosition);
                            	Serial.print("Message - valid: ");
                            	Serial.print(message.sensor);
                            	Serial.print(" , value: % ");
                            	break ;
                            	default : 
                            	// not recognizable message
                            	Serial.print("Message - valid: ");
                            	Serial.print(message.sensor);
                            	Serial.print(", Unrecognized ");
                            	break ;
                            	}
                              }
                              
                            
                            
                            
                            
                            P Tore André RosanderT A 3 Replies Last reply
                            0
                            • AWIA AWI

                              @patchmaster This is my current curtain control sketch. I work with the development branch, so the syntax can be a little different.

                              The Accelstepper library gives you all the abilities to slow start/stop with numerous kinds of steppers.
                              My sketch includes a calibration function (stored in EEPROM) so the you don't need end stop detection (a stepper knows where it is)

                              /*
                               PROJECT: MY Sensors curtain controller
                               PROGRAMMER: AWI
                               DATE: march 11, 2016
                               FILE: AWI stepper1.ino
                               LICENSE: Public domain
                              
                               Hardware: ATMega328p board w/ NRF24l01
                              	and MySensors 2.0 (Development)
                              		
                              Special:
                              	uses AccelStepper library
                              	
                              Summary:
                              	Curtain control with stepper motor. 
                              	Manual operation with 1 push button 
                              	Calibration with manual button
                              
                              Remarks:
                              	Fixed node-id
                              	
                              Change log:
                              20160312 - Cleanup
                              */
                              
                              // Enable debug prints to serial monitor
                              #define MY_DEBUG 
                              
                              #define MY_NODE_ID 13											// fixed node number
                              // Enable and select radio type attached
                              #define MY_RADIO_NRF24
                              //#define MY_RADIO_RFM69
                              
                              #include <SPI.h>
                              #include <MySensor.h> 
                              
                              // stepper library
                              #include <AccelStepper.h>										// http://www.airspayce.com/mikem/arduino/AccelStepper/
                              #define HALFSTEP 8  											// Stepper uses "Halfstep" mode
                              
                              // button library
                              // used for:
                              // - manual open close - single click: close/ stop/ open/ stop
                              // - calibration  - after long press: open calibarion- until single press - closed calibration - until single press (stop)
                              #include <Button.h>												// https://github.com/JChristensen/Button
                              
                              #define CHILD_ID 1   											// Id of the sensor child
                              
                              #define SN "Curtain control 13"
                              #define SV "1.0"
                              
                              #define buttonPin1 7  											// Arduino pin connected to buttonPin1
                              #define buttonPin2 A0  											// Arduino pin connected to buttonPin2 (fixed to ground)
                              
                              // Motor pin definitions
                              #define motorPin1  3     										// IN1 on the ULN2003 driver 1
                              #define motorPin2  4     										// IN2 on the ULN2003 driver 1
                              #define motorPin3  5     										// IN3 on the ULN2003 driver 1
                              #define motorPin4  6     										// IN4 on the ULN2003 driver 1
                              
                              const unsigned long heartbeatInterval = 1 * 3600UL * 1000UL ;	// heartbeatinterval
                              unsigned long heartbeatCounter = 0 ;
                              
                              //
                              // helper routines to store and retrieve long in mysensors EEPROM
                              union {															// used to convert long to bytes for EEPROM storage
                              	long longInt;
                              	uint8_t LongByte[4];
                              	} convLongInt ;
                              
                              void saveStateL(int EEposition, long StateL){
                              	convLongInt.longInt = StateL ;
                              	for (int y = 0; y < 4 ; y++){								// convert to bytes
                              		saveState(EEposition + y , convLongInt.LongByte[y]) ;
                              		}
                              	Serial.print("State saved: "); Serial.println(StateL);
                              	}
                              		
                              long loadStateL(int EEposition){
                              	for (int y = 0; y < 4 ; y++){								// convert from bytes
                              		convLongInt.LongByte[y] = loadState(EEposition + y) ;
                              		}
                              	Serial.print("State read: "); Serial.println(convLongInt.longInt);
                              	return convLongInt.longInt ;
                              	}
                              	
                              
                              // Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
                              AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
                              // Initialize button active low, debounce and internal pull-up
                              Button myBtn(buttonPin1, true, true, 40);						// Initiate the button (pin, pull_up, invert, debounce_ms)
                              
                              MyMessage percentageMsg(CHILD_ID, V_PERCENTAGE);				// used to send updates to controller
                              
                              const long maxRun = 4000000L ;									// maximum runway
                              long setPosition = 0 ; 											// remembers set position, need to be saved in EEPROM
                              const int setPositionEE = 4 ;									// eeprom location
                              long openPosition = 0 ; 										// Position at open, need to be saved in EEPROM?
                              const int openPositionEE = setPositionEE + 4 ;					// eeprom location
                              long closedPosition = 120000UL ; 								// Position at full close, need to be saved in EEPROM
                              const int closedPositionEE = openPositionEE + 4 ;				// eeprom location
                              
                              unsigned long idleTimer = millis() ;							// return to idle timer
                              unsigned long idleTime = 100000UL ;								// return to idle after 100 secs
                              
                              unsigned long printTimer = millis() ;							// print timer
                              unsigned long printTime = 1000UL ;								// print after 1 secs
                              
                              enum position_t {Open, Close, Idle, Running} ;
                              position_t lastDirection = Open ; 								// lastDirection only for buttonpress
                              position_t runStatus = Idle ;									// indicates current status for running motor. used for status reporting to controller
                              
                              enum State_t {sIdle, sCalibrateOpen, sCalibrateClose} ;
                              State_t State = sIdle ;
                              
                              
                              void setup() {
                              	// setup buttons
                              	pinMode(buttonPin1, OUTPUT);
                              	stepper1.setMaxSpeed(2000.0);
                              	stepper1.setAcceleration(1000.0);
                              	//saveStateL(closedPositionEE, closedPosition) ; 			// INIT: save closed position in EEPROM
                              	closedPosition = loadStateL(closedPositionEE) ;				// need to get last values from EEPROM and assume the current position is correct
                              	setPosition = loadStateL(setPositionEE) ;
                              	stepper1.setCurrentPosition(setPosition );
                              }//--(end setup )---
                              
                              void presentation() {
                                present(CHILD_ID, S_COVER, "Curtain");						// Window Cover sub-type, commands: V_UP, V_DOWN, V_STOP
                              
                                // Register the LED Dimmable Light with the gateway
                                sendSketchInfo(SN, SV);
                              }
                              
                              
                              void loop() {
                              unsigned int now = millis() ;								// current time for loop
                              // simple state machine for button press
                              	myBtn.read();  
                              	switch (State) {
                                      // Idle state, waiting for some action
                              		// - button press
                              		// - idleTimer
                                      case sIdle:                
                                          if (myBtn.wasReleased()){						// idle
                              				Serial.println("Button release") ;
                              				// if running stop
                              				if (stepper1.isRunning()){
                              					setPosition = stepper1.currentPosition();
                              					stepper1.moveTo(setPosition) ;			// move to current position (was already there..)
                              				} else if (lastDirection == Open) {
                              					stepper1.moveTo(closedPosition) ;
                              					lastDirection = Close ;
                              				} else {									// lastDirection == Close
                              					stepper1.moveTo(openPosition) ;
                              					lastDirection = Open ;
                              				}	
                              			} else if (myBtn.pressedFor(3000)){				// move to calibratete state with long press
                              				Serial.println("Button press long") ;
                              				idleTimer = now ;							// return to idle after ...
                              				State = sCalibrateOpen ;
                              				stepper1.move(-maxRun) ;					// let the stepper open with maximum
                              				}
                              			break ;
                              		// if not running and last action was open close ;  else open
                              		// if longpress Calibrate open
                                      case sCalibrateOpen:           						// calibration going on     
                              			if (myBtn.wasPressed()){
                              				stepper1.setCurrentPosition(0 );		// set new 0 position ??
                              				openPosition = setPosition = 0 ;
                              				State = sCalibrateClose ;					// next is close calibarion
                              				stepper1.move(maxRun) ;						// let the stepper close with maximum
                              			} else if (now > idleTimer + idleTime) {		// timer expired -> abort calibration
                              				State = sIdle ;
                              			}
                              			break ;
                                      case sCalibrateClose:								// calibrate closed position, end with keypress
                              			if (myBtn.wasPressed())	{
                              				closedPosition = setPosition = stepper1.currentPosition() ;
                              				saveStateL(closedPositionEE, closedPosition) ; // save closed position in EEPROM
                              				State = sIdle ;
                              				stepper1.moveTo(openPosition) ;				// return to open after calibration
                              			} else if (now > idleTimer + idleTime) {		// timer expired -> abort calibration
                              				State = sIdle ;
                              			}
                              			break ;
                              		default :
                              			break ;
                              		}
                              	// power off stepper if not running (no need to reenable))
                              	if (!stepper1.isRunning()){
                              		if (runStatus != Idle){								// there was a change in runningstatus, so report to controller
                              			setPosition = stepper1.currentPosition() ;		// store in EEPROM and report ready to controller
                              			saveStateL(setPositionEE, setPosition) ;
                              			send( percentageMsg.set((100 * setPosition)/(closedPosition - openPosition))) ;
                              			runStatus = Idle ;
                              		}
                              		stepper1.disableOutputs();
                              	} else {
                              		runStatus = Running ;
                              	}
                              	stepper1.run();
                              	/*
                              	if (printTimer++ > now + printTime){
                              		printTimer = now ;
                              		Serial.println(stepper1.currentPosition());
                              		}
                              	*/
                              }
                              
                              // This is called when a message is received 
                              void receive(const MyMessage &message) {
                              // We only expect few types of messages from controller, check which
                                switch (message.type) {
                              	case V_PERCENTAGE:
                              	// Curtain should be opened
                              	stepper1.moveTo(message.getInt() * (closedPosition - openPosition)/100);
                              	Serial.print("Message: "); Serial.print(message.sensor); Serial.print(" , value: % "); Serial.println( message.getInt());
                              	Serial.print("Moving to: "); Serial.println(message.getInt() * (closedPosition - openPosition)/100);
                              	break ;
                              	case V_STATUS:
                              	// Curtain should be opened or closed full
                              	stepper1.moveTo((message.getInt() == HIGH)?openPosition:closedPosition);
                              	Serial.print("Message - valid: ");
                              	Serial.print(message.sensor);
                              	Serial.print(" , value: % ");
                              	break ;
                              	default : 
                              	// not recognizable message
                              	Serial.print("Message - valid: ");
                              	Serial.print(message.sensor);
                              	Serial.print(", Unrecognized ");
                              	break ;
                              	}
                                }
                                
                              
                              
                              
                              
                              P Offline
                              P Offline
                              patchmaster
                              wrote on last edited by
                              #16

                              @AWI Thanks. I have been using the Accelstepper library, but this has already given me several other ideas.
                              I appreciate the help.

                              1 Reply Last reply
                              0
                              • AWIA AWI

                                @patchmaster This is my current curtain control sketch. I work with the development branch, so the syntax can be a little different.

                                The Accelstepper library gives you all the abilities to slow start/stop with numerous kinds of steppers.
                                My sketch includes a calibration function (stored in EEPROM) so the you don't need end stop detection (a stepper knows where it is)

                                /*
                                 PROJECT: MY Sensors curtain controller
                                 PROGRAMMER: AWI
                                 DATE: march 11, 2016
                                 FILE: AWI stepper1.ino
                                 LICENSE: Public domain
                                
                                 Hardware: ATMega328p board w/ NRF24l01
                                	and MySensors 2.0 (Development)
                                		
                                Special:
                                	uses AccelStepper library
                                	
                                Summary:
                                	Curtain control with stepper motor. 
                                	Manual operation with 1 push button 
                                	Calibration with manual button
                                
                                Remarks:
                                	Fixed node-id
                                	
                                Change log:
                                20160312 - Cleanup
                                */
                                
                                // Enable debug prints to serial monitor
                                #define MY_DEBUG 
                                
                                #define MY_NODE_ID 13											// fixed node number
                                // Enable and select radio type attached
                                #define MY_RADIO_NRF24
                                //#define MY_RADIO_RFM69
                                
                                #include <SPI.h>
                                #include <MySensor.h> 
                                
                                // stepper library
                                #include <AccelStepper.h>										// http://www.airspayce.com/mikem/arduino/AccelStepper/
                                #define HALFSTEP 8  											// Stepper uses "Halfstep" mode
                                
                                // button library
                                // used for:
                                // - manual open close - single click: close/ stop/ open/ stop
                                // - calibration  - after long press: open calibarion- until single press - closed calibration - until single press (stop)
                                #include <Button.h>												// https://github.com/JChristensen/Button
                                
                                #define CHILD_ID 1   											// Id of the sensor child
                                
                                #define SN "Curtain control 13"
                                #define SV "1.0"
                                
                                #define buttonPin1 7  											// Arduino pin connected to buttonPin1
                                #define buttonPin2 A0  											// Arduino pin connected to buttonPin2 (fixed to ground)
                                
                                // Motor pin definitions
                                #define motorPin1  3     										// IN1 on the ULN2003 driver 1
                                #define motorPin2  4     										// IN2 on the ULN2003 driver 1
                                #define motorPin3  5     										// IN3 on the ULN2003 driver 1
                                #define motorPin4  6     										// IN4 on the ULN2003 driver 1
                                
                                const unsigned long heartbeatInterval = 1 * 3600UL * 1000UL ;	// heartbeatinterval
                                unsigned long heartbeatCounter = 0 ;
                                
                                //
                                // helper routines to store and retrieve long in mysensors EEPROM
                                union {															// used to convert long to bytes for EEPROM storage
                                	long longInt;
                                	uint8_t LongByte[4];
                                	} convLongInt ;
                                
                                void saveStateL(int EEposition, long StateL){
                                	convLongInt.longInt = StateL ;
                                	for (int y = 0; y < 4 ; y++){								// convert to bytes
                                		saveState(EEposition + y , convLongInt.LongByte[y]) ;
                                		}
                                	Serial.print("State saved: "); Serial.println(StateL);
                                	}
                                		
                                long loadStateL(int EEposition){
                                	for (int y = 0; y < 4 ; y++){								// convert from bytes
                                		convLongInt.LongByte[y] = loadState(EEposition + y) ;
                                		}
                                	Serial.print("State read: "); Serial.println(convLongInt.longInt);
                                	return convLongInt.longInt ;
                                	}
                                	
                                
                                // Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
                                AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
                                // Initialize button active low, debounce and internal pull-up
                                Button myBtn(buttonPin1, true, true, 40);						// Initiate the button (pin, pull_up, invert, debounce_ms)
                                
                                MyMessage percentageMsg(CHILD_ID, V_PERCENTAGE);				// used to send updates to controller
                                
                                const long maxRun = 4000000L ;									// maximum runway
                                long setPosition = 0 ; 											// remembers set position, need to be saved in EEPROM
                                const int setPositionEE = 4 ;									// eeprom location
                                long openPosition = 0 ; 										// Position at open, need to be saved in EEPROM?
                                const int openPositionEE = setPositionEE + 4 ;					// eeprom location
                                long closedPosition = 120000UL ; 								// Position at full close, need to be saved in EEPROM
                                const int closedPositionEE = openPositionEE + 4 ;				// eeprom location
                                
                                unsigned long idleTimer = millis() ;							// return to idle timer
                                unsigned long idleTime = 100000UL ;								// return to idle after 100 secs
                                
                                unsigned long printTimer = millis() ;							// print timer
                                unsigned long printTime = 1000UL ;								// print after 1 secs
                                
                                enum position_t {Open, Close, Idle, Running} ;
                                position_t lastDirection = Open ; 								// lastDirection only for buttonpress
                                position_t runStatus = Idle ;									// indicates current status for running motor. used for status reporting to controller
                                
                                enum State_t {sIdle, sCalibrateOpen, sCalibrateClose} ;
                                State_t State = sIdle ;
                                
                                
                                void setup() {
                                	// setup buttons
                                	pinMode(buttonPin1, OUTPUT);
                                	stepper1.setMaxSpeed(2000.0);
                                	stepper1.setAcceleration(1000.0);
                                	//saveStateL(closedPositionEE, closedPosition) ; 			// INIT: save closed position in EEPROM
                                	closedPosition = loadStateL(closedPositionEE) ;				// need to get last values from EEPROM and assume the current position is correct
                                	setPosition = loadStateL(setPositionEE) ;
                                	stepper1.setCurrentPosition(setPosition );
                                }//--(end setup )---
                                
                                void presentation() {
                                  present(CHILD_ID, S_COVER, "Curtain");						// Window Cover sub-type, commands: V_UP, V_DOWN, V_STOP
                                
                                  // Register the LED Dimmable Light with the gateway
                                  sendSketchInfo(SN, SV);
                                }
                                
                                
                                void loop() {
                                unsigned int now = millis() ;								// current time for loop
                                // simple state machine for button press
                                	myBtn.read();  
                                	switch (State) {
                                        // Idle state, waiting for some action
                                		// - button press
                                		// - idleTimer
                                        case sIdle:                
                                            if (myBtn.wasReleased()){						// idle
                                				Serial.println("Button release") ;
                                				// if running stop
                                				if (stepper1.isRunning()){
                                					setPosition = stepper1.currentPosition();
                                					stepper1.moveTo(setPosition) ;			// move to current position (was already there..)
                                				} else if (lastDirection == Open) {
                                					stepper1.moveTo(closedPosition) ;
                                					lastDirection = Close ;
                                				} else {									// lastDirection == Close
                                					stepper1.moveTo(openPosition) ;
                                					lastDirection = Open ;
                                				}	
                                			} else if (myBtn.pressedFor(3000)){				// move to calibratete state with long press
                                				Serial.println("Button press long") ;
                                				idleTimer = now ;							// return to idle after ...
                                				State = sCalibrateOpen ;
                                				stepper1.move(-maxRun) ;					// let the stepper open with maximum
                                				}
                                			break ;
                                		// if not running and last action was open close ;  else open
                                		// if longpress Calibrate open
                                        case sCalibrateOpen:           						// calibration going on     
                                			if (myBtn.wasPressed()){
                                				stepper1.setCurrentPosition(0 );		// set new 0 position ??
                                				openPosition = setPosition = 0 ;
                                				State = sCalibrateClose ;					// next is close calibarion
                                				stepper1.move(maxRun) ;						// let the stepper close with maximum
                                			} else if (now > idleTimer + idleTime) {		// timer expired -> abort calibration
                                				State = sIdle ;
                                			}
                                			break ;
                                        case sCalibrateClose:								// calibrate closed position, end with keypress
                                			if (myBtn.wasPressed())	{
                                				closedPosition = setPosition = stepper1.currentPosition() ;
                                				saveStateL(closedPositionEE, closedPosition) ; // save closed position in EEPROM
                                				State = sIdle ;
                                				stepper1.moveTo(openPosition) ;				// return to open after calibration
                                			} else if (now > idleTimer + idleTime) {		// timer expired -> abort calibration
                                				State = sIdle ;
                                			}
                                			break ;
                                		default :
                                			break ;
                                		}
                                	// power off stepper if not running (no need to reenable))
                                	if (!stepper1.isRunning()){
                                		if (runStatus != Idle){								// there was a change in runningstatus, so report to controller
                                			setPosition = stepper1.currentPosition() ;		// store in EEPROM and report ready to controller
                                			saveStateL(setPositionEE, setPosition) ;
                                			send( percentageMsg.set((100 * setPosition)/(closedPosition - openPosition))) ;
                                			runStatus = Idle ;
                                		}
                                		stepper1.disableOutputs();
                                	} else {
                                		runStatus = Running ;
                                	}
                                	stepper1.run();
                                	/*
                                	if (printTimer++ > now + printTime){
                                		printTimer = now ;
                                		Serial.println(stepper1.currentPosition());
                                		}
                                	*/
                                }
                                
                                // This is called when a message is received 
                                void receive(const MyMessage &message) {
                                // We only expect few types of messages from controller, check which
                                  switch (message.type) {
                                	case V_PERCENTAGE:
                                	// Curtain should be opened
                                	stepper1.moveTo(message.getInt() * (closedPosition - openPosition)/100);
                                	Serial.print("Message: "); Serial.print(message.sensor); Serial.print(" , value: % "); Serial.println( message.getInt());
                                	Serial.print("Moving to: "); Serial.println(message.getInt() * (closedPosition - openPosition)/100);
                                	break ;
                                	case V_STATUS:
                                	// Curtain should be opened or closed full
                                	stepper1.moveTo((message.getInt() == HIGH)?openPosition:closedPosition);
                                	Serial.print("Message - valid: ");
                                	Serial.print(message.sensor);
                                	Serial.print(" , value: % ");
                                	break ;
                                	default : 
                                	// not recognizable message
                                	Serial.print("Message - valid: ");
                                	Serial.print(message.sensor);
                                	Serial.print(", Unrecognized ");
                                	break ;
                                	}
                                  }
                                  
                                
                                
                                
                                
                                Tore André RosanderT Offline
                                Tore André RosanderT Offline
                                Tore André Rosander
                                wrote on last edited by
                                #17

                                @AWI
                                I have been searching for something like this for a while, thank you for the code!

                                But i have some problems compiling it :\

                                C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'void saveStateL(int, long int)':
                                
                                stepper_mysensor:74: error: 'saveState' was not declared in this scope
                                
                                         saveState(EEposition + y , convLongInt.LongByte[y]) ;
                                
                                                                                           ^
                                
                                C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'long int loadStateL(int)':
                                
                                stepper_mysensor:81: error: 'loadState' was not declared in this scope
                                
                                         convLongInt.LongByte[y] = loadState(EEposition + y) ;
                                
                                                                                           ^
                                
                                C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'void presentation()':
                                
                                stepper_mysensor:129: error: 'present' was not declared in this scope
                                
                                   present(CHILD_ID, S_COVER, "Curtain");                        // Window Cover sub-type, commands: V_UP, V_DOWN, V_STOP
                                
                                                                       ^
                                
                                stepper_mysensor:132: error: 'sendSketchInfo' was not declared in this scope
                                
                                   sendSketchInfo(SN, SV);
                                
                                                        ^
                                
                                C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'void loop()':
                                
                                stepper_mysensor:195: error: 'send' was not declared in this scope
                                
                                             send( percentageMsg.set((100 * setPosition)/(closedPosition - openPosition))) ;
                                
                                                                                                                         ^
                                
                                exit status 1
                                'saveState' was not declared in this scope```
                                AWIA 1 Reply Last reply
                                0
                                • Tore André RosanderT Tore André Rosander

                                  @AWI
                                  I have been searching for something like this for a while, thank you for the code!

                                  But i have some problems compiling it :\

                                  C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'void saveStateL(int, long int)':
                                  
                                  stepper_mysensor:74: error: 'saveState' was not declared in this scope
                                  
                                           saveState(EEposition + y , convLongInt.LongByte[y]) ;
                                  
                                                                                             ^
                                  
                                  C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'long int loadStateL(int)':
                                  
                                  stepper_mysensor:81: error: 'loadState' was not declared in this scope
                                  
                                           convLongInt.LongByte[y] = loadState(EEposition + y) ;
                                  
                                                                                             ^
                                  
                                  C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'void presentation()':
                                  
                                  stepper_mysensor:129: error: 'present' was not declared in this scope
                                  
                                     present(CHILD_ID, S_COVER, "Curtain");                        // Window Cover sub-type, commands: V_UP, V_DOWN, V_STOP
                                  
                                                                         ^
                                  
                                  stepper_mysensor:132: error: 'sendSketchInfo' was not declared in this scope
                                  
                                     sendSketchInfo(SN, SV);
                                  
                                                          ^
                                  
                                  C:\Users\ToreR\Documents\Arduino\stepper_mysensor\stepper_mysensor.ino: In function 'void loop()':
                                  
                                  stepper_mysensor:195: error: 'send' was not declared in this scope
                                  
                                               send( percentageMsg.set((100 * setPosition)/(closedPosition - openPosition))) ;
                                  
                                                                                                                           ^
                                  
                                  exit status 1
                                  'saveState' was not declared in this scope```
                                  AWIA Offline
                                  AWIA Offline
                                  AWI
                                  Hero Member
                                  wrote on last edited by AWI
                                  #18

                                  @Tore-André-Rosander are you using the development branch? The errors seem to indicate that is the case.

                                  Tore André RosanderT 1 Reply Last reply
                                  0
                                  • AWIA AWI

                                    @Tore-André-Rosander are you using the development branch? The errors seem to indicate that is the case.

                                    Tore André RosanderT Offline
                                    Tore André RosanderT Offline
                                    Tore André Rosander
                                    wrote on last edited by
                                    #19

                                    @AWI Thank you, that helped :)
                                    I now have it up and running.

                                    But how do i connect and use this with a controller (like Domoticz)?

                                    I use an ESP gateway (from the dev branch) and the curtain node is connected and showing up in domoticz.
                                    But how do i make domoticz send commands to the curtain node?

                                    All i get when adding the curtain node both as on/off button and blinds in domoticz is "unreconized" in the curtain serial monoitor.

                                    AWIA 1 Reply Last reply
                                    0
                                    • Tore André RosanderT Tore André Rosander

                                      @AWI Thank you, that helped :)
                                      I now have it up and running.

                                      But how do i connect and use this with a controller (like Domoticz)?

                                      I use an ESP gateway (from the dev branch) and the curtain node is connected and showing up in domoticz.
                                      But how do i make domoticz send commands to the curtain node?

                                      All i get when adding the curtain node both as on/off button and blinds in domoticz is "unreconized" in the curtain serial monoitor.

                                      AWIA Offline
                                      AWIA Offline
                                      AWI
                                      Hero Member
                                      wrote on last edited by
                                      #20

                                      @Tore-André-Rosander I have defined it as "Blinds Percentage" in Domoticz. This send the V_STATUS and V_PERCENTAGE messages where the node should respond to...
                                      0_1458557025507_upload-d16cb932-d511-433f-9488-112b68d308f4

                                      Tore André RosanderT 1 Reply Last reply
                                      0
                                      • AWIA AWI

                                        @Tore-André-Rosander I have defined it as "Blinds Percentage" in Domoticz. This send the V_STATUS and V_PERCENTAGE messages where the node should respond to...
                                        0_1458557025507_upload-d16cb932-d511-433f-9488-112b68d308f4

                                        Tore André RosanderT Offline
                                        Tore André RosanderT Offline
                                        Tore André Rosander
                                        wrote on last edited by
                                        #21

                                        @AWI THanks again for your fast replys!

                                        This is what i get in serial monitor when i use the "up" "down" buttons for blinds percentage in domoticz.

                                        This is my very first MySensor setup so it might be some error with my setup, i will have a deeper look at it later tonight.

                                        Starting sensor (RNNNA-, 2.0.0-beta)
                                        Radio init successful.
                                        State read: -1
                                        State read: -1
                                        send: 13-13-0-0 s=255,c=3,t=15,pt=0,l=2,sg=0,st=ok:
                                        send: 13-13-0-0 s=255,c=0,t=17,pt=0,l=10,sg=0,st=ok:2.0.0-beta
                                        send: 13-13-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,st=ok:0
                                        read: 0-0-13 s=255,c=3,t=15,pt=0,l=2,sg=0:
                                        read: 0-0-13 s=255,c=3,t=6,pt=0,l=1,sg=0:M
                                        send: 13-13-0-0 s=1,c=0,t=5,pt=0,l=7,sg=0,st=ok:Curtain
                                        send: 13-13-0-0 s=255,c=3,t=11,pt=0,l=18,sg=0,st=ok:Curtain control 13
                                        send: 13-13-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,st=ok:1.0
                                        Init complete, id=13, parent=0, distance=1
                                        read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                        Message - valid: 1, Unrecognized```
                                        AWIA 1 Reply Last reply
                                        0
                                        • Tore André RosanderT Tore André Rosander

                                          @AWI THanks again for your fast replys!

                                          This is what i get in serial monitor when i use the "up" "down" buttons for blinds percentage in domoticz.

                                          This is my very first MySensor setup so it might be some error with my setup, i will have a deeper look at it later tonight.

                                          Starting sensor (RNNNA-, 2.0.0-beta)
                                          Radio init successful.
                                          State read: -1
                                          State read: -1
                                          send: 13-13-0-0 s=255,c=3,t=15,pt=0,l=2,sg=0,st=ok:
                                          send: 13-13-0-0 s=255,c=0,t=17,pt=0,l=10,sg=0,st=ok:2.0.0-beta
                                          send: 13-13-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,st=ok:0
                                          read: 0-0-13 s=255,c=3,t=15,pt=0,l=2,sg=0:
                                          read: 0-0-13 s=255,c=3,t=6,pt=0,l=1,sg=0:M
                                          send: 13-13-0-0 s=1,c=0,t=5,pt=0,l=7,sg=0,st=ok:Curtain
                                          send: 13-13-0-0 s=255,c=3,t=11,pt=0,l=18,sg=0,st=ok:Curtain control 13
                                          send: 13-13-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,st=ok:1.0
                                          Init complete, id=13, parent=0, distance=1
                                          read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=29,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized read: 0-0-13 s=1,c=1,t=30,pt=0,l=0,sg=0:
                                          Message - valid: 1, Unrecognized```
                                          AWIA Offline
                                          AWIA Offline
                                          AWI
                                          Hero Member
                                          wrote on last edited by
                                          #22

                                          @Tore-André-Rosander Nothing wrong with you interpretation. I have not written this sketch as a complete S_COVER implementation. Only the V_PERCENTAGE part (not V_UP/V_DOWN). If you define it in Domoticz as "Blinds percentage" (see my previous post) it will work. Sorry for the confusion.

                                          Tore André RosanderT 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          18

                                          Online

                                          11.7k

                                          Users

                                          11.2k

                                          Topics

                                          113.1k

                                          Posts


                                          Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • MySensors
                                          • OpenHardware.io
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular