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. General Discussion
  3. void receive(const MyMessage &message)

void receive(const MyMessage &message)

Scheduled Pinned Locked Moved General Discussion
40 Posts 6 Posters 1.9k Views 5 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.
  • skywatchS skywatch

    @pjr Thanks for the hint.

    I believe I have what I need now, will be testing tomorrow I hope.

    Essentially I have reduced void loop() and void receive() down to minimum so the program loops very fast. This way it only calls other void () routines as needed.

    skywatchS Offline
    skywatchS Offline
    skywatch
    wrote on last edited by skywatch
    #10

    @skywatch Hmmmm....It didn't work as I expected.

    So if I have a loop with a 'while' routine running, what do I need to do in the 'while' code to check if any messages have arrived?

    something ike.....

    while (MOVING_UP == true && stepcount < BLIND_UP) {
    Do code to turn stepper motor.
    Check for radio message.
    Act on radio message (if there is one)
    Check for button press.
    Act on button press (if there is one)
    update step count
    }

    The buttons and motor I have working, its just that radio messages are currently 'blocked' during the while loop and this isn't good if an emergency stop call is required.

    mfalkviddM 1 Reply Last reply
    0
    • skywatchS skywatch

      @skywatch Hmmmm....It didn't work as I expected.

      So if I have a loop with a 'while' routine running, what do I need to do in the 'while' code to check if any messages have arrived?

      something ike.....

      while (MOVING_UP == true && stepcount < BLIND_UP) {
      Do code to turn stepper motor.
      Check for radio message.
      Act on radio message (if there is one)
      Check for button press.
      Act on button press (if there is one)
      update step count
      }

      The buttons and motor I have working, its just that radio messages are currently 'blocked' during the while loop and this isn't good if an emergency stop call is required.

      mfalkviddM Offline
      mfalkviddM Offline
      mfalkvidd
      Mod
      wrote on last edited by
      #11

      @skywatch I think you're looking for the wait() function. https://www.mysensors.org/download/sensor_api_20#waiting

      Or _process() but that's an internal function so it might not be as well documented and might undergo changes that aren't mentioned in release notes in future releases.

      skywatchS 1 Reply Last reply
      1
      • mfalkviddM mfalkvidd

        @skywatch I think you're looking for the wait() function. https://www.mysensors.org/download/sensor_api_20#waiting

        Or _process() but that's an internal function so it might not be as well documented and might undergo changes that aren't mentioned in release notes in future releases.

        skywatchS Offline
        skywatchS Offline
        skywatch
        wrote on last edited by
        #12

        @mfalkvidd I was just about to say something on that! - you just beat me too it! ;)

        I understand the wait(), but what I have no clue of is how long should a wait() be to get incomming messages? -- Would wait(25); be enough?

        mfalkviddM YveauxY 2 Replies Last reply
        0
        • skywatchS skywatch

          @mfalkvidd I was just about to say something on that! - you just beat me too it! ;)

          I understand the wait(), but what I have no clue of is how long should a wait() be to get incomming messages? -- Would wait(25); be enough?

          mfalkviddM Offline
          mfalkviddM Offline
          mfalkvidd
          Mod
          wrote on last edited by
          #13

          @skywatch it depends a bit on which platform you are using, the clock speed you are using, how often wait is called, how busy your network is, which transport you are using and how much packet loss you are willing to accept. But 25 should work.

          I found transportProcess() which is called without any parameters. You can use that instead.

          skywatchS 1 Reply Last reply
          1
          • mfalkviddM mfalkvidd

            @skywatch it depends a bit on which platform you are using, the clock speed you are using, how often wait is called, how busy your network is, which transport you are using and how much packet loss you are willing to accept. But 25 should work.

            I found transportProcess() which is called without any parameters. You can use that instead.

            skywatchS Offline
            skywatchS Offline
            skywatch
            wrote on last edited by
            #14

            @mfalkvidd pro mini @ 16MHz - I didn't mention that as I was looking at it as purely a programming issue....doh!

            So are you saying that if I simply put transportProcess() in the while statement it will pause the while loop, check for any messages from the nrf24 and then resume the while loop? Of so, that should work if it is quick.

            1 Reply Last reply
            0
            • skywatchS skywatch

              @mfalkvidd I was just about to say something on that! - you just beat me too it! ;)

              I understand the wait(), but what I have no clue of is how long should a wait() be to get incomming messages? -- Would wait(25); be enough?

              YveauxY Offline
              YveauxY Offline
              Yveaux
              Mod
              wrote on last edited by
              #15

              @skywatch said in void receive(const MyMessage &message):

              I understand the wait(), but what I have no clue of is how long should a wait() be to get incomming messages? -- Would wait(25); be enough?

              Just wait as short as possible, 1ms or even 0 (not sure if that is supported).
              It allows the stack to process any queued messages and returns as quickly as possible.
              There is no need to wait for a longer time, as radios will queue incoming messages in hardware. The actual number of messages that can be queued depends on the radio used; for nrf24 it is 3.

              http://yveaux.blogspot.nl

              mfalkviddM 1 Reply Last reply
              1
              • skywatchS Offline
                skywatchS Offline
                skywatch
                wrote on last edited by
                #16

                @mfalkvidd I tried with transportProcess() and it seemed to work well initially, but then something happened (probably HW related) so it is looking promising.

                @Yveaux Thank you for the tip :)

                I will try this next and see how much of a difference it makes -would wait(1); be better in any way to calling transportProcess()?

                But at least it looks like the system might operate as I had intended, hurrah! ;)

                YveauxY 1 Reply Last reply
                0
                • skywatchS skywatch

                  @mfalkvidd I tried with transportProcess() and it seemed to work well initially, but then something happened (probably HW related) so it is looking promising.

                  @Yveaux Thank you for the tip :)

                  I will try this next and see how much of a difference it makes -would wait(1); be better in any way to calling transportProcess()?

                  But at least it looks like the system might operate as I had intended, hurrah! ;)

                  YveauxY Offline
                  YveauxY Offline
                  Yveaux
                  Mod
                  wrote on last edited by
                  #17

                  @skywatch said in void receive(const MyMessage &message):

                  would wait(1); be better in any way to calling transportProcess()?

                  Definately! transportProcess() is a library internal call, which might change without notice or has side effects one cannot oversee. Wait() is an external api call, which won't change without notice, and is documented.

                  http://yveaux.blogspot.nl

                  skywatchS 1 Reply Last reply
                  1
                  • YveauxY Yveaux

                    @skywatch said in void receive(const MyMessage &message):

                    would wait(1); be better in any way to calling transportProcess()?

                    Definately! transportProcess() is a library internal call, which might change without notice or has side effects one cannot oversee. Wait() is an external api call, which won't change without notice, and is documented.

                    skywatchS Offline
                    skywatchS Offline
                    skywatch
                    wrote on last edited by
                    #18

                    @yveaux Thank you for the fast response and explaination. I'll go with what you said! ;)

                    1 Reply Last reply
                    0
                    • YveauxY Yveaux

                      @skywatch said in void receive(const MyMessage &message):

                      I understand the wait(), but what I have no clue of is how long should a wait() be to get incomming messages? -- Would wait(25); be enough?

                      Just wait as short as possible, 1ms or even 0 (not sure if that is supported).
                      It allows the stack to process any queued messages and returns as quickly as possible.
                      There is no need to wait for a longer time, as radios will queue incoming messages in hardware. The actual number of messages that can be queued depends on the radio used; for nrf24 it is 3.

                      mfalkviddM Offline
                      mfalkviddM Offline
                      mfalkvidd
                      Mod
                      wrote on last edited by
                      #19

                      There is a slight risk that wait() will return immediately without processing messages, if the parameter is lower than the increment of millis(). The increment of millis() depends on platform and clock speed. I am not sure if this risk is big enough that it needs to be considered.

                      1 Reply Last reply
                      0
                      • skywatchS Offline
                        skywatchS Offline
                        skywatch
                        wrote on last edited by
                        #20

                        Thank you both for the help - much appreciated.

                        So I went with wait(1); and then only called it every 250 steps as otherwise it was slowing things down too much. It seems pretty reliable at the moment, but I do have dodgy duponts so have to sort them out next!

                        One thing I do see is this......

                        352968 !MCO:WAI:RC=3
                        352971 !MCO:WAI:RC=3
                        352974 !MCO:WAI:RC=3
                        352977 !MCO:WAI:RC=3
                        352980 !MCO:WAI:RC=3
                        352984 !MCO:WAI:RC=3
                        352987 !MCO:WAI:RC=3
                        352990 !MCO:WAI:RC=3
                        

                        Not always, but sometimes.....what is this trying to tell me and where do I look to fix it - I can post full code if you like, but it's not for the faint of heart;)

                        mfalkviddM 1 Reply Last reply
                        0
                        • skywatchS skywatch

                          Thank you both for the help - much appreciated.

                          So I went with wait(1); and then only called it every 250 steps as otherwise it was slowing things down too much. It seems pretty reliable at the moment, but I do have dodgy duponts so have to sort them out next!

                          One thing I do see is this......

                          352968 !MCO:WAI:RC=3
                          352971 !MCO:WAI:RC=3
                          352974 !MCO:WAI:RC=3
                          352977 !MCO:WAI:RC=3
                          352980 !MCO:WAI:RC=3
                          352984 !MCO:WAI:RC=3
                          352987 !MCO:WAI:RC=3
                          352990 !MCO:WAI:RC=3
                          

                          Not always, but sometimes.....what is this trying to tell me and where do I look to fix it - I can post full code if you like, but it's not for the faint of heart;)

                          mfalkviddM Offline
                          mfalkviddM Offline
                          mfalkvidd
                          Mod
                          wrote on last edited by
                          #21

                          @skywatch those messages mean that wait is being called from within wait. That is usually bad, so MySensors prints a warning message. Could you post your code?

                          skywatchS 1 Reply Last reply
                          0
                          • mfalkviddM mfalkvidd

                            @skywatch those messages mean that wait is being called from within wait. That is usually bad, so MySensors prints a warning message. Could you post your code?

                            skywatchS Offline
                            skywatchS Offline
                            skywatch
                            wrote on last edited by skywatch
                            #22

                            @mfalkvidd Here is the code - remember it is in development and some things are currently commented out to concentrate on the places where I have issues.

                            /*
                               Solar Powered Roller Blind - Landing
                            
                               Pin Assignments..... 5V pro mini
                            
                               D2 Down Button.
                               D3 Up Button.
                               D4,D5,D6,D7 for stepper motor. 12V
                               D8 Power fail detect? -and write stepcount to eeprom
                               D9,D10,D11,D12,D13 for NRF24L01+. 3.3V
                               A0 UP LIMIT magnet sensor.
                               A1 DOWN LIMIT magnet sensor.
                               A2 Window Sensor.
                               A3 FREE
                               A4 ATSHA204a.
                               A5 Battery Voltage Sensor.
                               A6 FREE - input only
                               A7 FREE - input only
                            
                            */
                            
                            #define MY_DEBUG
                            #define MY_RADIO_RF24
                            #define MY_RF24_PA_LEVEL   RF24_PA_HIGH
                            #define MY_NODE_ID 181
                            #define MY_RF24_CHANNEL (97)
                            #define MY_PARENT_NODE_ID 0
                            #define MY_PARENT_NODE_IS_STATIC
                            //#define MY_REPEATER_FEATURE
                            //#define MY_SIGNING_ATSHA204
                            //#define MY_SIGNING_REQUEST_SIGNATURES
                            //#define MY_SIGNING_SOFT
                            //#define MY_SIGNING_SIMPLE_PASSWD
                            
                            #include <MySensors.h>
                            #include <Stepper.h>
                            #include <Bounce2.h>
                            // define number of steps per revolution
                            #define STEPS 32
                            
                            // define stepper motor control pins
                            #define IN1   7
                            #define IN2   6
                            #define IN3   5
                            #define IN4   4
                            #define EEPROM_STEPCOUNT_ADDRESS 0
                            #define BLIND_UP 39500  //********
                            #define BLIND_DOWN 100  //********
                            //#define LIMIT_UP A0
                            //#define LIMIT_DOWN A1
                            #define DOWN_BUTTON 2
                            #define UP_BUTTON 3
                            #define WINDOW_SENSOR A2
                            //#define VOLTMETER A5
                            #define CHILD_ID_LANDING_BLIND 0
                            //#define CHILD_ID_BATTERY 1
                            #define CHILD_ID_LANDING_WINDOW 2
                            #define CHILD_ID_LANDING_ALARM 3
                            
                            //float battery = 0.0;
                            //unsigned long BattSendDelay = 10800000;
                            unsigned long previousMillis = 0;
                            unsigned long previousButtonMillis = 0;
                            unsigned long ButtonMillis = 5000;
                            unsigned long stepcount = BLIND_UP;  //******Blind UP for CAL....
                            unsigned long laststepcount = BLIND_UP;
                            unsigned long upspeed = 900;
                            int upstep = 5;
                            int downstep = -1;
                            int oldValue=-1;
                            bool MOVING_UP = false;
                            bool MOVING_DOWN = false;
                            bool ALARM_ARMED = false;
                            bool ALARM_TRIPPED = false;
                            
                            Bounce debouncerUP = Bounce();
                            Bounce debouncerDOWN = Bounce();
                            Bounce debouncerWINDOW = Bounce();
                            
                            // initialize stepper library
                            Stepper stepper(STEPS, IN4, IN2, IN3, IN1);
                            
                            MyMessage msgB_UP(CHILD_ID_LANDING_BLIND, V_UP);
                            MyMessage msgB_DOWN(CHILD_ID_LANDING_BLIND, V_DOWN);
                            MyMessage msgB_STOP(CHILD_ID_LANDING_BLIND, V_STOP);
                            //MyMessage msgBBattery(CHILD_ID_LANDING_BLIND, V_VOLTAGE);
                            //MyMessage msgB_PERCENTAGE(CHILD_ID_LANDING_BLIND, V_PERCENTAGE);
                            MyMessage msgB_ALARM(CHILD_ID_LANDING_WINDOW, V_TRIPPED);
                            MyMessage msgB_WINDOW(CHILD_ID_LANDING_WINDOW, V_TRIPPED);
                            
                            
                            void setup()
                            {
                              Serial.begin(115200);
                              pinMode(DOWN_BUTTON, INPUT_PULLUP);
                              pinMode(UP_BUTTON, INPUT_PULLUP);
                              //pinMode(LIMIT_UP, INPUT_PULLUP);
                              //pinMode(LIMIT_DOWN, INPUT_PULLUP);
                              pinMode(WINDOW_SENSOR, INPUT_PULLUP);
                              //pinMode(VOLTMETER, INPUT);
                              debouncerUP.attach(UP_BUTTON);
                              debouncerUP.interval(25);
                              debouncerDOWN.attach(DOWN_BUTTON);
                              debouncerDOWN.interval(25);
                              debouncerWINDOW.attach(WINDOW_SENSOR);
                              debouncerWINDOW.interval(25);
                              //**** Comment next line after first upload - inital calibration only....
                              hwWriteConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4); //saveStepcount - Use once to set 'memory'. Then reflash with this commented out.
                              hwReadConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4); // Get from EEPROM last position.
                              digitalWrite(IN1, LOW);
                              digitalWrite(IN2, LOW);
                              digitalWrite(IN3, LOW);
                              digitalWrite(IN4, LOW);
                            }
                            
                            
                            void presentation()  {
                              sendSketchInfo("MYS-Landing Blind", "0.4");
                              wait(150);
                              present(CHILD_ID_LANDING_BLIND, S_COVER, "Landing-Blind", true);
                              // present(CHILD_ID_BATTERY, S_MULTIMETER, "Battery", true);
                               wait(200);
                               present(CHILD_ID_LANDING_ALARM, S_BINARY, "Landing-Alarm", true);
                               wait(200);
                               present(CHILD_ID_LANDING_WINDOW, S_BINARY, "Landing-Window", true);
                              
                                //long batterytemp = (readVcc());
                              //float batteryf = (float) batterytemp;
                              //battery = batteryf/1000.0;
                              //send(msgBBattery.set(battery,2),true);
                            }
                            
                            void loop()
                            {
                            
                              // move the blind UP
                              debouncerUP.update();
                              if (debouncerUP.fell() || MOVING_UP == true) {
                                MOVING_UP = true;
                                UP();
                              }
                            
                              // move the blind DOWN
                              debouncerDOWN.update();
                              if (debouncerDOWN.fell() || MOVING_DOWN == true) {
                                MOVING_DOWN = true;
                                DOWN();
                              }
                              
                              //Manual calibration call
                              if (debouncerUP.fell() && debouncerDOWN.fell()){
                                previousButtonMillis = millis();
                                while (millis() - previousButtonMillis < ButtonMillis){
                                  debouncerUP.update();
                                  debouncerDOWN.update();
                                  if (debouncerUP.rose() || debouncerDOWN.rose()){
                                    break;
                                  }
                                }
                              }
                                else calibrate();
                                
                              debouncerWINDOW.update();
                              if (debouncerWINDOW.rose() && ALARM_ARMED == true){
                                send(msgB_ALARM.set(ALARM_TRIPPED = 0), true);
                                }
                                if (debouncerWINDOW.fell() && ALARM_ARMED == true){
                                send(msgB_ALARM.set(ALARM_TRIPPED = 1), true);
                                }
                            //    debouncer.update();
                              
                              // Send window update...
                              int value = debouncerWINDOW.read();
                              if (value != oldValue) {
                                 // Send in the new value
                                 send(msgB_WINDOW.set(value==HIGH ? 1 : 0));
                                 oldValue = value;
                              }
                            
                              //Read and send battery every 3 hours
                              /* if (millis() - previousMillis >= BattSendDelay) {
                                 previousMillis = millis();
                                 long batterytemp = (readVcc());
                                 float batteryf = (float) batterytemp;
                                 battery = batteryf/1000.0;
                                 //float batteryraw = digitalRead(VOLTMETER);
                                 //add calibration here.....
                                 send(msgBBattery.set(battery,2),true);
                                }*/
                              //!!!!!  NO SLEEPING !!!!!  ;)
                            
                            }
                            
                            void receive(const MyMessage &message) {
                            
                              // STOP - if message == V_STOP, stop blinds immediately.
                              if (message.type == V_STOP) {
                                stop();
                              }
                            
                              // UP - if message == V_UP call void UP()
                              if (message.type == V_UP) {
                                MOVING_UP = true;
                                UP();
                              }
                            
                              // DOWN - if message == V_DOWN call void DOWN()
                              if (message.type == V_DOWN) {
                                MOVING_DOWN = true;
                                DOWN();
                              }
                            
                              //Add if (message.type==V_PERCENTAGE); and add calculation....maybe?
                              // for reference 1% == 395 steps....
                            }
                            
                            void stop()
                            {
                              digitalWrite(IN1, LOW);
                              digitalWrite(IN2, LOW);
                              digitalWrite(IN3, LOW);
                              digitalWrite(IN4, LOW);
                              send(msgB_STOP.set(stepcount), true);
                              MOVING_UP = false;
                              MOVING_DOWN = false;
                              hwWriteConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4);
                              wait(100);
                            }
                            
                            void UP()
                            {
                              //If already in motion then stop and reverse direction.
                              if (MOVING_DOWN == true) {
                                stop();
                                MOVING_UP = true;
                              }
                            
                               // test if already up here!!!! - if not recall stepcount and calulate number of steps required.
                              while (MOVING_UP == true && stepcount < BLIND_UP) { //&& LIMIT_UP == HIGH)
                                // set motor speed 
                                if (stepcount >= 20000) {
                                   upspeed = 1000;
                                }
                                if (stepcount >= (BLIND_UP - 50)) {
                                   upstep = 1;
                                }
                                stepper.setSpeed(upspeed); //higher speed = lower torque...
                                // move the motor (x steps)
                                stepper.step(upstep);
                                stepcount = stepcount + upstep;
                               // Serial.println("UP-StepCount = " + (String)stepcount);
                                // }
                            
                                //Test if manual stop.
                                debouncerDOWN.update();
                                if (debouncerDOWN.fell()) {
                                  stop();
                                }
                            
                                //Add time limit for safety?
                                //up timeout message?
                            
                                //Test if at end of travel.
                                if (stepcount == BLIND_UP) {   // || digitalRead(LIMIT_UP) == LOW)
                                  stop();
                                  downstep = -1;
                                  break;
                                }
                            
                                //Check for incomming radio message at frequent intervals.
                                if(stepcount > laststepcount + 500){
                                  laststepcount = stepcount;
                                  wait(1); //allows RX function.
                               }
                             }
                            }
                            
                            void DOWN()
                            {
                              //If already in motion then stop and reverse direction.
                              if (MOVING_UP == true) {
                                stop();
                                MOVING_DOWN = true;
                              }
                            
                               //Check if window open
                               debouncerWINDOW.update();
                                
                              //Do not close if window is open or already closed.
                              while (MOVING_DOWN == true && stepcount > BLIND_DOWN && debouncerWINDOW.read() == LOW)// && digitalRead(WINDOW_SENSOR) == LOW && LIMIT_DOWN == HIGH)
                              {
                                stepper.setSpeed(1200); //higher speed = lower torque...
                                if (stepcount <= (BLIND_UP-500) && stepcount > 150) {
                                   downstep = -5;
                                }
                                if (stepcount <= 150) {
                                   downstep = -1;
                                }
                                // move the motor (x steps)
                                stepper.step(downstep);
                                stepcount = stepcount + downstep;
                                //Serial.println("DOWN-StepCount = " + (String)stepcount);
                                //}
                            
                                //Test if manual stop.
                                debouncerUP.update();
                                if (debouncerUP.fell()) {
                                stop();
                                }
                            
                                //Test if at end of travel.
                                if (stepcount == BLIND_DOWN) { // || digitalRead(LIMIT_DOWN) == LOW) -- maybe add timer as well?
                                  stop();
                                  upstep = 5;
                                  upspeed = 900;
                                  break;
                                 }
                                 
                                 //Check for incomming radio message at frequent intervals.
                                 if(stepcount < laststepcount - 500){
                                  laststepcount = stepcount;
                                  wait(1); //allows RX function.
                                 }
                              }
                                debouncerWINDOW.update();
                            }
                            
                            void calibrate()
                            {
                              //Move fully up or down and set stepcounter. - From controller, buttons or if position is unknown.....
                            }
                            /*
                              long readVcc() {
                              // Read 1.1V reference against AVcc
                              // set the reference to Vcc and the measurement to the internal 1.1V reference
                              ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
                              wait(5); // Wait for Vref to settle
                              ADCSRA |= _BV(ADSC); // Start conversion
                              while (bit_is_set(ADCSRA,ADSC)); // measuring
                            
                              uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
                              uint8_t high = ADCH; // unlocks both
                            
                              long result = (high<<8) | low;
                            
                              result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
                              return result; // Vcc in millivolts
                              }*/
                            

                            It works like this......

                            Pressing up or down button will move the blind up or down depending on window sensor status (I don't want blinds to close with the window open)......

                            Whilst blind is in motion pressing button corresponding to the opposite direction will stop the blind and save position to eeprom.

                            Pressing both buttons at the same time for more than 5 seconds will call a self calibration routine.

                            At any point the controller should be able to send a message to the blinds to move or stop. This now happens even whilst the blind is in motion, which is what I thought to be the best option.

                            Every time the stop is called the position is saved to eeprom so that in the event of power interruption it will know where it last was.

                            Maybe I need to re-think the whole approach to this, but it is annoyingly close to what I would like now ;)

                            mfalkviddM 2 Replies Last reply
                            1
                            • skywatchS skywatch

                              @mfalkvidd Here is the code - remember it is in development and some things are currently commented out to concentrate on the places where I have issues.

                              /*
                                 Solar Powered Roller Blind - Landing
                              
                                 Pin Assignments..... 5V pro mini
                              
                                 D2 Down Button.
                                 D3 Up Button.
                                 D4,D5,D6,D7 for stepper motor. 12V
                                 D8 Power fail detect? -and write stepcount to eeprom
                                 D9,D10,D11,D12,D13 for NRF24L01+. 3.3V
                                 A0 UP LIMIT magnet sensor.
                                 A1 DOWN LIMIT magnet sensor.
                                 A2 Window Sensor.
                                 A3 FREE
                                 A4 ATSHA204a.
                                 A5 Battery Voltage Sensor.
                                 A6 FREE - input only
                                 A7 FREE - input only
                              
                              */
                              
                              #define MY_DEBUG
                              #define MY_RADIO_RF24
                              #define MY_RF24_PA_LEVEL   RF24_PA_HIGH
                              #define MY_NODE_ID 181
                              #define MY_RF24_CHANNEL (97)
                              #define MY_PARENT_NODE_ID 0
                              #define MY_PARENT_NODE_IS_STATIC
                              //#define MY_REPEATER_FEATURE
                              //#define MY_SIGNING_ATSHA204
                              //#define MY_SIGNING_REQUEST_SIGNATURES
                              //#define MY_SIGNING_SOFT
                              //#define MY_SIGNING_SIMPLE_PASSWD
                              
                              #include <MySensors.h>
                              #include <Stepper.h>
                              #include <Bounce2.h>
                              // define number of steps per revolution
                              #define STEPS 32
                              
                              // define stepper motor control pins
                              #define IN1   7
                              #define IN2   6
                              #define IN3   5
                              #define IN4   4
                              #define EEPROM_STEPCOUNT_ADDRESS 0
                              #define BLIND_UP 39500  //********
                              #define BLIND_DOWN 100  //********
                              //#define LIMIT_UP A0
                              //#define LIMIT_DOWN A1
                              #define DOWN_BUTTON 2
                              #define UP_BUTTON 3
                              #define WINDOW_SENSOR A2
                              //#define VOLTMETER A5
                              #define CHILD_ID_LANDING_BLIND 0
                              //#define CHILD_ID_BATTERY 1
                              #define CHILD_ID_LANDING_WINDOW 2
                              #define CHILD_ID_LANDING_ALARM 3
                              
                              //float battery = 0.0;
                              //unsigned long BattSendDelay = 10800000;
                              unsigned long previousMillis = 0;
                              unsigned long previousButtonMillis = 0;
                              unsigned long ButtonMillis = 5000;
                              unsigned long stepcount = BLIND_UP;  //******Blind UP for CAL....
                              unsigned long laststepcount = BLIND_UP;
                              unsigned long upspeed = 900;
                              int upstep = 5;
                              int downstep = -1;
                              int oldValue=-1;
                              bool MOVING_UP = false;
                              bool MOVING_DOWN = false;
                              bool ALARM_ARMED = false;
                              bool ALARM_TRIPPED = false;
                              
                              Bounce debouncerUP = Bounce();
                              Bounce debouncerDOWN = Bounce();
                              Bounce debouncerWINDOW = Bounce();
                              
                              // initialize stepper library
                              Stepper stepper(STEPS, IN4, IN2, IN3, IN1);
                              
                              MyMessage msgB_UP(CHILD_ID_LANDING_BLIND, V_UP);
                              MyMessage msgB_DOWN(CHILD_ID_LANDING_BLIND, V_DOWN);
                              MyMessage msgB_STOP(CHILD_ID_LANDING_BLIND, V_STOP);
                              //MyMessage msgBBattery(CHILD_ID_LANDING_BLIND, V_VOLTAGE);
                              //MyMessage msgB_PERCENTAGE(CHILD_ID_LANDING_BLIND, V_PERCENTAGE);
                              MyMessage msgB_ALARM(CHILD_ID_LANDING_WINDOW, V_TRIPPED);
                              MyMessage msgB_WINDOW(CHILD_ID_LANDING_WINDOW, V_TRIPPED);
                              
                              
                              void setup()
                              {
                                Serial.begin(115200);
                                pinMode(DOWN_BUTTON, INPUT_PULLUP);
                                pinMode(UP_BUTTON, INPUT_PULLUP);
                                //pinMode(LIMIT_UP, INPUT_PULLUP);
                                //pinMode(LIMIT_DOWN, INPUT_PULLUP);
                                pinMode(WINDOW_SENSOR, INPUT_PULLUP);
                                //pinMode(VOLTMETER, INPUT);
                                debouncerUP.attach(UP_BUTTON);
                                debouncerUP.interval(25);
                                debouncerDOWN.attach(DOWN_BUTTON);
                                debouncerDOWN.interval(25);
                                debouncerWINDOW.attach(WINDOW_SENSOR);
                                debouncerWINDOW.interval(25);
                                //**** Comment next line after first upload - inital calibration only....
                                hwWriteConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4); //saveStepcount - Use once to set 'memory'. Then reflash with this commented out.
                                hwReadConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4); // Get from EEPROM last position.
                                digitalWrite(IN1, LOW);
                                digitalWrite(IN2, LOW);
                                digitalWrite(IN3, LOW);
                                digitalWrite(IN4, LOW);
                              }
                              
                              
                              void presentation()  {
                                sendSketchInfo("MYS-Landing Blind", "0.4");
                                wait(150);
                                present(CHILD_ID_LANDING_BLIND, S_COVER, "Landing-Blind", true);
                                // present(CHILD_ID_BATTERY, S_MULTIMETER, "Battery", true);
                                 wait(200);
                                 present(CHILD_ID_LANDING_ALARM, S_BINARY, "Landing-Alarm", true);
                                 wait(200);
                                 present(CHILD_ID_LANDING_WINDOW, S_BINARY, "Landing-Window", true);
                                
                                  //long batterytemp = (readVcc());
                                //float batteryf = (float) batterytemp;
                                //battery = batteryf/1000.0;
                                //send(msgBBattery.set(battery,2),true);
                              }
                              
                              void loop()
                              {
                              
                                // move the blind UP
                                debouncerUP.update();
                                if (debouncerUP.fell() || MOVING_UP == true) {
                                  MOVING_UP = true;
                                  UP();
                                }
                              
                                // move the blind DOWN
                                debouncerDOWN.update();
                                if (debouncerDOWN.fell() || MOVING_DOWN == true) {
                                  MOVING_DOWN = true;
                                  DOWN();
                                }
                                
                                //Manual calibration call
                                if (debouncerUP.fell() && debouncerDOWN.fell()){
                                  previousButtonMillis = millis();
                                  while (millis() - previousButtonMillis < ButtonMillis){
                                    debouncerUP.update();
                                    debouncerDOWN.update();
                                    if (debouncerUP.rose() || debouncerDOWN.rose()){
                                      break;
                                    }
                                  }
                                }
                                  else calibrate();
                                  
                                debouncerWINDOW.update();
                                if (debouncerWINDOW.rose() && ALARM_ARMED == true){
                                  send(msgB_ALARM.set(ALARM_TRIPPED = 0), true);
                                  }
                                  if (debouncerWINDOW.fell() && ALARM_ARMED == true){
                                  send(msgB_ALARM.set(ALARM_TRIPPED = 1), true);
                                  }
                              //    debouncer.update();
                                
                                // Send window update...
                                int value = debouncerWINDOW.read();
                                if (value != oldValue) {
                                   // Send in the new value
                                   send(msgB_WINDOW.set(value==HIGH ? 1 : 0));
                                   oldValue = value;
                                }
                              
                                //Read and send battery every 3 hours
                                /* if (millis() - previousMillis >= BattSendDelay) {
                                   previousMillis = millis();
                                   long batterytemp = (readVcc());
                                   float batteryf = (float) batterytemp;
                                   battery = batteryf/1000.0;
                                   //float batteryraw = digitalRead(VOLTMETER);
                                   //add calibration here.....
                                   send(msgBBattery.set(battery,2),true);
                                  }*/
                                //!!!!!  NO SLEEPING !!!!!  ;)
                              
                              }
                              
                              void receive(const MyMessage &message) {
                              
                                // STOP - if message == V_STOP, stop blinds immediately.
                                if (message.type == V_STOP) {
                                  stop();
                                }
                              
                                // UP - if message == V_UP call void UP()
                                if (message.type == V_UP) {
                                  MOVING_UP = true;
                                  UP();
                                }
                              
                                // DOWN - if message == V_DOWN call void DOWN()
                                if (message.type == V_DOWN) {
                                  MOVING_DOWN = true;
                                  DOWN();
                                }
                              
                                //Add if (message.type==V_PERCENTAGE); and add calculation....maybe?
                                // for reference 1% == 395 steps....
                              }
                              
                              void stop()
                              {
                                digitalWrite(IN1, LOW);
                                digitalWrite(IN2, LOW);
                                digitalWrite(IN3, LOW);
                                digitalWrite(IN4, LOW);
                                send(msgB_STOP.set(stepcount), true);
                                MOVING_UP = false;
                                MOVING_DOWN = false;
                                hwWriteConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4);
                                wait(100);
                              }
                              
                              void UP()
                              {
                                //If already in motion then stop and reverse direction.
                                if (MOVING_DOWN == true) {
                                  stop();
                                  MOVING_UP = true;
                                }
                              
                                 // test if already up here!!!! - if not recall stepcount and calulate number of steps required.
                                while (MOVING_UP == true && stepcount < BLIND_UP) { //&& LIMIT_UP == HIGH)
                                  // set motor speed 
                                  if (stepcount >= 20000) {
                                     upspeed = 1000;
                                  }
                                  if (stepcount >= (BLIND_UP - 50)) {
                                     upstep = 1;
                                  }
                                  stepper.setSpeed(upspeed); //higher speed = lower torque...
                                  // move the motor (x steps)
                                  stepper.step(upstep);
                                  stepcount = stepcount + upstep;
                                 // Serial.println("UP-StepCount = " + (String)stepcount);
                                  // }
                              
                                  //Test if manual stop.
                                  debouncerDOWN.update();
                                  if (debouncerDOWN.fell()) {
                                    stop();
                                  }
                              
                                  //Add time limit for safety?
                                  //up timeout message?
                              
                                  //Test if at end of travel.
                                  if (stepcount == BLIND_UP) {   // || digitalRead(LIMIT_UP) == LOW)
                                    stop();
                                    downstep = -1;
                                    break;
                                  }
                              
                                  //Check for incomming radio message at frequent intervals.
                                  if(stepcount > laststepcount + 500){
                                    laststepcount = stepcount;
                                    wait(1); //allows RX function.
                                 }
                               }
                              }
                              
                              void DOWN()
                              {
                                //If already in motion then stop and reverse direction.
                                if (MOVING_UP == true) {
                                  stop();
                                  MOVING_DOWN = true;
                                }
                              
                                 //Check if window open
                                 debouncerWINDOW.update();
                                  
                                //Do not close if window is open or already closed.
                                while (MOVING_DOWN == true && stepcount > BLIND_DOWN && debouncerWINDOW.read() == LOW)// && digitalRead(WINDOW_SENSOR) == LOW && LIMIT_DOWN == HIGH)
                                {
                                  stepper.setSpeed(1200); //higher speed = lower torque...
                                  if (stepcount <= (BLIND_UP-500) && stepcount > 150) {
                                     downstep = -5;
                                  }
                                  if (stepcount <= 150) {
                                     downstep = -1;
                                  }
                                  // move the motor (x steps)
                                  stepper.step(downstep);
                                  stepcount = stepcount + downstep;
                                  //Serial.println("DOWN-StepCount = " + (String)stepcount);
                                  //}
                              
                                  //Test if manual stop.
                                  debouncerUP.update();
                                  if (debouncerUP.fell()) {
                                  stop();
                                  }
                              
                                  //Test if at end of travel.
                                  if (stepcount == BLIND_DOWN) { // || digitalRead(LIMIT_DOWN) == LOW) -- maybe add timer as well?
                                    stop();
                                    upstep = 5;
                                    upspeed = 900;
                                    break;
                                   }
                                   
                                   //Check for incomming radio message at frequent intervals.
                                   if(stepcount < laststepcount - 500){
                                    laststepcount = stepcount;
                                    wait(1); //allows RX function.
                                   }
                                }
                                  debouncerWINDOW.update();
                              }
                              
                              void calibrate()
                              {
                                //Move fully up or down and set stepcounter. - From controller, buttons or if position is unknown.....
                              }
                              /*
                                long readVcc() {
                                // Read 1.1V reference against AVcc
                                // set the reference to Vcc and the measurement to the internal 1.1V reference
                                ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
                                wait(5); // Wait for Vref to settle
                                ADCSRA |= _BV(ADSC); // Start conversion
                                while (bit_is_set(ADCSRA,ADSC)); // measuring
                              
                                uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
                                uint8_t high = ADCH; // unlocks both
                              
                                long result = (high<<8) | low;
                              
                                result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
                                return result; // Vcc in millivolts
                                }*/
                              

                              It works like this......

                              Pressing up or down button will move the blind up or down depending on window sensor status (I don't want blinds to close with the window open)......

                              Whilst blind is in motion pressing button corresponding to the opposite direction will stop the blind and save position to eeprom.

                              Pressing both buttons at the same time for more than 5 seconds will call a self calibration routine.

                              At any point the controller should be able to send a message to the blinds to move or stop. This now happens even whilst the blind is in motion, which is what I thought to be the best option.

                              Every time the stop is called the position is saved to eeprom so that in the event of power interruption it will know where it last was.

                              Maybe I need to re-think the whole approach to this, but it is annoyingly close to what I would like now ;)

                              mfalkviddM Offline
                              mfalkviddM Offline
                              mfalkvidd
                              Mod
                              wrote on last edited by
                              #23

                              @skywatch the reason you're getting the wait warning messages (and probably the reason why your code behaves in strage ways sometimes) is that you're calling send and wait from within receive. Doing so can have very strange side effects.

                              skywatchS 1 Reply Last reply
                              1
                              • skywatchS skywatch

                                @mfalkvidd Here is the code - remember it is in development and some things are currently commented out to concentrate on the places where I have issues.

                                /*
                                   Solar Powered Roller Blind - Landing
                                
                                   Pin Assignments..... 5V pro mini
                                
                                   D2 Down Button.
                                   D3 Up Button.
                                   D4,D5,D6,D7 for stepper motor. 12V
                                   D8 Power fail detect? -and write stepcount to eeprom
                                   D9,D10,D11,D12,D13 for NRF24L01+. 3.3V
                                   A0 UP LIMIT magnet sensor.
                                   A1 DOWN LIMIT magnet sensor.
                                   A2 Window Sensor.
                                   A3 FREE
                                   A4 ATSHA204a.
                                   A5 Battery Voltage Sensor.
                                   A6 FREE - input only
                                   A7 FREE - input only
                                
                                */
                                
                                #define MY_DEBUG
                                #define MY_RADIO_RF24
                                #define MY_RF24_PA_LEVEL   RF24_PA_HIGH
                                #define MY_NODE_ID 181
                                #define MY_RF24_CHANNEL (97)
                                #define MY_PARENT_NODE_ID 0
                                #define MY_PARENT_NODE_IS_STATIC
                                //#define MY_REPEATER_FEATURE
                                //#define MY_SIGNING_ATSHA204
                                //#define MY_SIGNING_REQUEST_SIGNATURES
                                //#define MY_SIGNING_SOFT
                                //#define MY_SIGNING_SIMPLE_PASSWD
                                
                                #include <MySensors.h>
                                #include <Stepper.h>
                                #include <Bounce2.h>
                                // define number of steps per revolution
                                #define STEPS 32
                                
                                // define stepper motor control pins
                                #define IN1   7
                                #define IN2   6
                                #define IN3   5
                                #define IN4   4
                                #define EEPROM_STEPCOUNT_ADDRESS 0
                                #define BLIND_UP 39500  //********
                                #define BLIND_DOWN 100  //********
                                //#define LIMIT_UP A0
                                //#define LIMIT_DOWN A1
                                #define DOWN_BUTTON 2
                                #define UP_BUTTON 3
                                #define WINDOW_SENSOR A2
                                //#define VOLTMETER A5
                                #define CHILD_ID_LANDING_BLIND 0
                                //#define CHILD_ID_BATTERY 1
                                #define CHILD_ID_LANDING_WINDOW 2
                                #define CHILD_ID_LANDING_ALARM 3
                                
                                //float battery = 0.0;
                                //unsigned long BattSendDelay = 10800000;
                                unsigned long previousMillis = 0;
                                unsigned long previousButtonMillis = 0;
                                unsigned long ButtonMillis = 5000;
                                unsigned long stepcount = BLIND_UP;  //******Blind UP for CAL....
                                unsigned long laststepcount = BLIND_UP;
                                unsigned long upspeed = 900;
                                int upstep = 5;
                                int downstep = -1;
                                int oldValue=-1;
                                bool MOVING_UP = false;
                                bool MOVING_DOWN = false;
                                bool ALARM_ARMED = false;
                                bool ALARM_TRIPPED = false;
                                
                                Bounce debouncerUP = Bounce();
                                Bounce debouncerDOWN = Bounce();
                                Bounce debouncerWINDOW = Bounce();
                                
                                // initialize stepper library
                                Stepper stepper(STEPS, IN4, IN2, IN3, IN1);
                                
                                MyMessage msgB_UP(CHILD_ID_LANDING_BLIND, V_UP);
                                MyMessage msgB_DOWN(CHILD_ID_LANDING_BLIND, V_DOWN);
                                MyMessage msgB_STOP(CHILD_ID_LANDING_BLIND, V_STOP);
                                //MyMessage msgBBattery(CHILD_ID_LANDING_BLIND, V_VOLTAGE);
                                //MyMessage msgB_PERCENTAGE(CHILD_ID_LANDING_BLIND, V_PERCENTAGE);
                                MyMessage msgB_ALARM(CHILD_ID_LANDING_WINDOW, V_TRIPPED);
                                MyMessage msgB_WINDOW(CHILD_ID_LANDING_WINDOW, V_TRIPPED);
                                
                                
                                void setup()
                                {
                                  Serial.begin(115200);
                                  pinMode(DOWN_BUTTON, INPUT_PULLUP);
                                  pinMode(UP_BUTTON, INPUT_PULLUP);
                                  //pinMode(LIMIT_UP, INPUT_PULLUP);
                                  //pinMode(LIMIT_DOWN, INPUT_PULLUP);
                                  pinMode(WINDOW_SENSOR, INPUT_PULLUP);
                                  //pinMode(VOLTMETER, INPUT);
                                  debouncerUP.attach(UP_BUTTON);
                                  debouncerUP.interval(25);
                                  debouncerDOWN.attach(DOWN_BUTTON);
                                  debouncerDOWN.interval(25);
                                  debouncerWINDOW.attach(WINDOW_SENSOR);
                                  debouncerWINDOW.interval(25);
                                  //**** Comment next line after first upload - inital calibration only....
                                  hwWriteConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4); //saveStepcount - Use once to set 'memory'. Then reflash with this commented out.
                                  hwReadConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4); // Get from EEPROM last position.
                                  digitalWrite(IN1, LOW);
                                  digitalWrite(IN2, LOW);
                                  digitalWrite(IN3, LOW);
                                  digitalWrite(IN4, LOW);
                                }
                                
                                
                                void presentation()  {
                                  sendSketchInfo("MYS-Landing Blind", "0.4");
                                  wait(150);
                                  present(CHILD_ID_LANDING_BLIND, S_COVER, "Landing-Blind", true);
                                  // present(CHILD_ID_BATTERY, S_MULTIMETER, "Battery", true);
                                   wait(200);
                                   present(CHILD_ID_LANDING_ALARM, S_BINARY, "Landing-Alarm", true);
                                   wait(200);
                                   present(CHILD_ID_LANDING_WINDOW, S_BINARY, "Landing-Window", true);
                                  
                                    //long batterytemp = (readVcc());
                                  //float batteryf = (float) batterytemp;
                                  //battery = batteryf/1000.0;
                                  //send(msgBBattery.set(battery,2),true);
                                }
                                
                                void loop()
                                {
                                
                                  // move the blind UP
                                  debouncerUP.update();
                                  if (debouncerUP.fell() || MOVING_UP == true) {
                                    MOVING_UP = true;
                                    UP();
                                  }
                                
                                  // move the blind DOWN
                                  debouncerDOWN.update();
                                  if (debouncerDOWN.fell() || MOVING_DOWN == true) {
                                    MOVING_DOWN = true;
                                    DOWN();
                                  }
                                  
                                  //Manual calibration call
                                  if (debouncerUP.fell() && debouncerDOWN.fell()){
                                    previousButtonMillis = millis();
                                    while (millis() - previousButtonMillis < ButtonMillis){
                                      debouncerUP.update();
                                      debouncerDOWN.update();
                                      if (debouncerUP.rose() || debouncerDOWN.rose()){
                                        break;
                                      }
                                    }
                                  }
                                    else calibrate();
                                    
                                  debouncerWINDOW.update();
                                  if (debouncerWINDOW.rose() && ALARM_ARMED == true){
                                    send(msgB_ALARM.set(ALARM_TRIPPED = 0), true);
                                    }
                                    if (debouncerWINDOW.fell() && ALARM_ARMED == true){
                                    send(msgB_ALARM.set(ALARM_TRIPPED = 1), true);
                                    }
                                //    debouncer.update();
                                  
                                  // Send window update...
                                  int value = debouncerWINDOW.read();
                                  if (value != oldValue) {
                                     // Send in the new value
                                     send(msgB_WINDOW.set(value==HIGH ? 1 : 0));
                                     oldValue = value;
                                  }
                                
                                  //Read and send battery every 3 hours
                                  /* if (millis() - previousMillis >= BattSendDelay) {
                                     previousMillis = millis();
                                     long batterytemp = (readVcc());
                                     float batteryf = (float) batterytemp;
                                     battery = batteryf/1000.0;
                                     //float batteryraw = digitalRead(VOLTMETER);
                                     //add calibration here.....
                                     send(msgBBattery.set(battery,2),true);
                                    }*/
                                  //!!!!!  NO SLEEPING !!!!!  ;)
                                
                                }
                                
                                void receive(const MyMessage &message) {
                                
                                  // STOP - if message == V_STOP, stop blinds immediately.
                                  if (message.type == V_STOP) {
                                    stop();
                                  }
                                
                                  // UP - if message == V_UP call void UP()
                                  if (message.type == V_UP) {
                                    MOVING_UP = true;
                                    UP();
                                  }
                                
                                  // DOWN - if message == V_DOWN call void DOWN()
                                  if (message.type == V_DOWN) {
                                    MOVING_DOWN = true;
                                    DOWN();
                                  }
                                
                                  //Add if (message.type==V_PERCENTAGE); and add calculation....maybe?
                                  // for reference 1% == 395 steps....
                                }
                                
                                void stop()
                                {
                                  digitalWrite(IN1, LOW);
                                  digitalWrite(IN2, LOW);
                                  digitalWrite(IN3, LOW);
                                  digitalWrite(IN4, LOW);
                                  send(msgB_STOP.set(stepcount), true);
                                  MOVING_UP = false;
                                  MOVING_DOWN = false;
                                  hwWriteConfigBlock((void*)&stepcount, (void*)(EEPROM_LOCAL_CONFIG_ADDRESS + EEPROM_STEPCOUNT_ADDRESS), 4);
                                  wait(100);
                                }
                                
                                void UP()
                                {
                                  //If already in motion then stop and reverse direction.
                                  if (MOVING_DOWN == true) {
                                    stop();
                                    MOVING_UP = true;
                                  }
                                
                                   // test if already up here!!!! - if not recall stepcount and calulate number of steps required.
                                  while (MOVING_UP == true && stepcount < BLIND_UP) { //&& LIMIT_UP == HIGH)
                                    // set motor speed 
                                    if (stepcount >= 20000) {
                                       upspeed = 1000;
                                    }
                                    if (stepcount >= (BLIND_UP - 50)) {
                                       upstep = 1;
                                    }
                                    stepper.setSpeed(upspeed); //higher speed = lower torque...
                                    // move the motor (x steps)
                                    stepper.step(upstep);
                                    stepcount = stepcount + upstep;
                                   // Serial.println("UP-StepCount = " + (String)stepcount);
                                    // }
                                
                                    //Test if manual stop.
                                    debouncerDOWN.update();
                                    if (debouncerDOWN.fell()) {
                                      stop();
                                    }
                                
                                    //Add time limit for safety?
                                    //up timeout message?
                                
                                    //Test if at end of travel.
                                    if (stepcount == BLIND_UP) {   // || digitalRead(LIMIT_UP) == LOW)
                                      stop();
                                      downstep = -1;
                                      break;
                                    }
                                
                                    //Check for incomming radio message at frequent intervals.
                                    if(stepcount > laststepcount + 500){
                                      laststepcount = stepcount;
                                      wait(1); //allows RX function.
                                   }
                                 }
                                }
                                
                                void DOWN()
                                {
                                  //If already in motion then stop and reverse direction.
                                  if (MOVING_UP == true) {
                                    stop();
                                    MOVING_DOWN = true;
                                  }
                                
                                   //Check if window open
                                   debouncerWINDOW.update();
                                    
                                  //Do not close if window is open or already closed.
                                  while (MOVING_DOWN == true && stepcount > BLIND_DOWN && debouncerWINDOW.read() == LOW)// && digitalRead(WINDOW_SENSOR) == LOW && LIMIT_DOWN == HIGH)
                                  {
                                    stepper.setSpeed(1200); //higher speed = lower torque...
                                    if (stepcount <= (BLIND_UP-500) && stepcount > 150) {
                                       downstep = -5;
                                    }
                                    if (stepcount <= 150) {
                                       downstep = -1;
                                    }
                                    // move the motor (x steps)
                                    stepper.step(downstep);
                                    stepcount = stepcount + downstep;
                                    //Serial.println("DOWN-StepCount = " + (String)stepcount);
                                    //}
                                
                                    //Test if manual stop.
                                    debouncerUP.update();
                                    if (debouncerUP.fell()) {
                                    stop();
                                    }
                                
                                    //Test if at end of travel.
                                    if (stepcount == BLIND_DOWN) { // || digitalRead(LIMIT_DOWN) == LOW) -- maybe add timer as well?
                                      stop();
                                      upstep = 5;
                                      upspeed = 900;
                                      break;
                                     }
                                     
                                     //Check for incomming radio message at frequent intervals.
                                     if(stepcount < laststepcount - 500){
                                      laststepcount = stepcount;
                                      wait(1); //allows RX function.
                                     }
                                  }
                                    debouncerWINDOW.update();
                                }
                                
                                void calibrate()
                                {
                                  //Move fully up or down and set stepcounter. - From controller, buttons or if position is unknown.....
                                }
                                /*
                                  long readVcc() {
                                  // Read 1.1V reference against AVcc
                                  // set the reference to Vcc and the measurement to the internal 1.1V reference
                                  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
                                  wait(5); // Wait for Vref to settle
                                  ADCSRA |= _BV(ADSC); // Start conversion
                                  while (bit_is_set(ADCSRA,ADSC)); // measuring
                                
                                  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
                                  uint8_t high = ADCH; // unlocks both
                                
                                  long result = (high<<8) | low;
                                
                                  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
                                  return result; // Vcc in millivolts
                                  }*/
                                

                                It works like this......

                                Pressing up or down button will move the blind up or down depending on window sensor status (I don't want blinds to close with the window open)......

                                Whilst blind is in motion pressing button corresponding to the opposite direction will stop the blind and save position to eeprom.

                                Pressing both buttons at the same time for more than 5 seconds will call a self calibration routine.

                                At any point the controller should be able to send a message to the blinds to move or stop. This now happens even whilst the blind is in motion, which is what I thought to be the best option.

                                Every time the stop is called the position is saved to eeprom so that in the event of power interruption it will know where it last was.

                                Maybe I need to re-think the whole approach to this, but it is annoyingly close to what I would like now ;)

                                mfalkviddM Offline
                                mfalkviddM Offline
                                mfalkvidd
                                Mod
                                wrote on last edited by
                                #24

                                @skywatch also, requesting that the gateway echos sent messages back to your node will have very bad effects. Could you elaborate on what you are trying to achive by requesting echo?

                                skywatchS 1 Reply Last reply
                                1
                                • mfalkviddM mfalkvidd

                                  @skywatch the reason you're getting the wait warning messages (and probably the reason why your code behaves in strage ways sometimes) is that you're calling send and wait from within receive. Doing so can have very strange side effects.

                                  skywatchS Offline
                                  skywatchS Offline
                                  skywatch
                                  wrote on last edited by skywatch
                                  #25

                                  @mfalkvidd Ah, I didn't know that it also applied to a wait within other void loop - I'll change the code so that it just sets a variable and then modify the main loop accordingly. Thank you for your time - I know it was not easy to go through that lot! ;) - Once it is working and tested I will tidy it up and optimise it all somewhat.

                                  1 Reply Last reply
                                  0
                                  • mfalkviddM mfalkvidd

                                    @skywatch also, requesting that the gateway echos sent messages back to your node will have very bad effects. Could you elaborate on what you are trying to achive by requesting echo?

                                    skywatchS Offline
                                    skywatchS Offline
                                    skywatch
                                    wrote on last edited by
                                    #26

                                    @mfalkvidd said in void receive(const MyMessage &message):

                                    @skywatch also, requesting that the gateway echos sent messages back to your node will have very bad effects. Could you elaborate on what you are trying to achive by requesting echo?

                                    I simply wanted to know that the message got through. Otherwise the controller might send 'down' command without having received the window open status. - I will look into that too..... :)

                                    mfalkviddM 1 Reply Last reply
                                    0
                                    • skywatchS skywatch

                                      @mfalkvidd said in void receive(const MyMessage &message):

                                      @skywatch also, requesting that the gateway echos sent messages back to your node will have very bad effects. Could you elaborate on what you are trying to achive by requesting echo?

                                      I simply wanted to know that the message got through. Otherwise the controller might send 'down' command without having received the window open status. - I will look into that too..... :)

                                      mfalkviddM Offline
                                      mfalkviddM Offline
                                      mfalkvidd
                                      Mod
                                      wrote on last edited by
                                      #27

                                      @skywatch if you want to know that, you need to add code in receive() to handle the echoed message. And you need to make sure those echoed messages don't interfere with "normal" messages.

                                      skywatchS 1 Reply Last reply
                                      2
                                      • skywatchS Offline
                                        skywatchS Offline
                                        skywatch
                                        wrote on last edited by skywatch
                                        #28

                                        @mfalkvidd Thank you soooo much for the tips with this, I still am learning new stuff and getting a project done = a double win for me :)

                                        SO here is what I changed.....

                                        In void loop I added

                                        //Stop if received message = STOP
                                          if(RX_STOP == true){
                                            stop();
                                            }
                                        

                                        And void receive() now looks like this ( I never needed to call up() or down() from here anyway. I realise that now - doh!).

                                        void receive(const MyMessage &message) {
                                        
                                          // STOP - if message == V_STOP, stop blinds immediately.
                                          if (message.type == V_STOP) {
                                           RX_STOP = true;
                                          }
                                        
                                          // UP - if message == V_UP call void UP()
                                          if (message.type == V_UP) {
                                            MOVING_UP = true;
                                          }
                                        
                                          // DOWN - if message == V_DOWN call void DOWN()
                                          if (message.type == V_DOWN) {
                                            MOVING_DOWN = true;
                                          }
                                        
                                          //Add if (message.type==V_PERCENTAGE); and add calculation....maybe?
                                          // for reference 1% == 395 steps....
                                        }
                                        

                                        I'll test it later as I need some food now! ;)

                                        mfalkviddM 1 Reply Last reply
                                        0
                                        • skywatchS skywatch

                                          @mfalkvidd Thank you soooo much for the tips with this, I still am learning new stuff and getting a project done = a double win for me :)

                                          SO here is what I changed.....

                                          In void loop I added

                                          //Stop if received message = STOP
                                            if(RX_STOP == true){
                                              stop();
                                              }
                                          

                                          And void receive() now looks like this ( I never needed to call up() or down() from here anyway. I realise that now - doh!).

                                          void receive(const MyMessage &message) {
                                          
                                            // STOP - if message == V_STOP, stop blinds immediately.
                                            if (message.type == V_STOP) {
                                             RX_STOP = true;
                                            }
                                          
                                            // UP - if message == V_UP call void UP()
                                            if (message.type == V_UP) {
                                              MOVING_UP = true;
                                            }
                                          
                                            // DOWN - if message == V_DOWN call void DOWN()
                                            if (message.type == V_DOWN) {
                                              MOVING_DOWN = true;
                                            }
                                          
                                            //Add if (message.type==V_PERCENTAGE); and add calculation....maybe?
                                            // for reference 1% == 395 steps....
                                          }
                                          

                                          I'll test it later as I need some food now! ;)

                                          mfalkviddM Offline
                                          mfalkviddM Offline
                                          mfalkvidd
                                          Mod
                                          wrote on last edited by
                                          #29

                                          @skywatch great work. This is a much better design.

                                          skywatchS 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