Sending custom value to move DC motor a specific # of degrees



  • Hello everyone,

    On to a new project, I have a DC motor with an encoder that I would like to control from OpenHAB, would appreciate some help in directing me to the right place, as I have not been able to find any solutions on my own yet 😕

    Basically I need to send a custom degree value from OpenHAB to the Node, and the motor should move that many degrees, store the value and display "current" position in degrees would be ideal. (the value I sent last)

    I was able to move the motor using the code below, if placed within void receive(const MyMessage &message) however it would not stop the motor at the right degree... so clearly I was doing something wrong 😕

    Right now the bellow code will move the motor to "target" which is set at 360 on the sketch

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    // Enable repeater functionality for this node
    //#define MY_REPEATER_FEATURE
    
    #include <SPI.h>
    #include <MySensors.h>
    #define CHILD_ID 6
    
    
    MyMessage message(CHILD_ID, S_CUSTOM);
    
    #define total 7560                     //x4 pulses per rotation.
    #define target 360
    #define motorSpeed 125                 //Change speed of the motor. 125 to 135 is optimal speed for perfect stops
    long degree;
    long pulses;                              //Output pulses.
    int encoderA = 3;
    int encoderB = 2;
    const int pwm = 5;                      //Power of motor.
    const int dir = 6;
    const int dir2 = 7;                      //Direction of the motor.
    int pulsesChanged = 5;
    #define degree pulses/21                   // total / 360 = total ticks per degree of shaft rotation
    
    void setup() 
    {
      Serial.begin(115200);
      pinMode(pwm, OUTPUT);
      pinMode(dir, OUTPUT);
      pinMode(dir2, OUTPUT);
      analogWrite(pwm, 0);                     //Make sure the motor in reset mode.
      digitalWrite(dir, HIGH);
      digitalWrite(dir2, HIGH);
      pinMode(encoderA, INPUT);
      pinMode(encoderB, INPUT);
      delay(50);
      attachInterrupt(0, A_CHANGE, CHANGE);
      attachInterrupt(1, B_CHANGE, CHANGE);
    }
    
    void presentation()  
    { 
      sendSketchInfo("Program", "1.0");
      present(CHILD_ID, S_CUSTOM);
    }
    
    void loop() 
    {
        if(degree==target){
        analogWrite(pwm,0);
        digitalWrite(dir,HIGH);
        digitalWrite(dir2,HIGH);
        delay(500);
        //saveState(message.sensor, message.getBool());
        //request(CHILD_ID, V_VAR1);
        return;
        
      }
      else{
        if (degree>target){
          analogWrite(pwm,motorSpeed);
          digitalWrite(dir,LOW);
          digitalWrite(dir2,HIGH);
          //saveState(message.sensor, message.getBool());
          //request(CHILD_ID, V_VAR1);
    
          
        }
        else if(degree<target){
          analogWrite(pwm,motorSpeed);
          digitalWrite(dir,HIGH);
          digitalWrite(dir2,LOW);
          //saveState(message.sensor, message.getBool());
          //request(CHILD_ID, V_VAR1);
        }
      }
      if (pulsesChanged != 0) {
        pulsesChanged = 0;
        Serial.println(degree);
      }
    }
    
    void receive(const MyMessage &message) {
          saveState(message.sensor, message.getBool());
          request(CHILD_ID, V_VAR1);
    
    }
    
    void A_CHANGE(){
      if( digitalRead(encoderB) == 0 ) {
        if ( digitalRead(encoderA) == 0 ) {
          // A fell, B is low
          pulses--; // moving reverse
        } else {
          // A rose, B is low
          pulses++; // moving forward
        }
      }else {
        if ( digitalRead(encoderA) == 0 ) {
          // B fell, A is high
          pulses++; // moving reverse
        } else {
          // B rose, A is high
          pulses--; // moving forward
        }
      }
      pulsesChanged = 1;
    }
    
    void B_CHANGE(){
      if ( digitalRead(encoderA) == 0 ) {
        if ( digitalRead(encoderB) == 0 ) {
          // B fell, A is low
          pulses++; // moving forward
        } else {
          // B rose, A is low
          pulses--; // moving reverse
        }
     } else {
        if ( digitalRead(encoderB) == 0 ) {
          // B fell, A is high
          pulses--; // moving reverse
        } else {
          // B rose, A is high
          pulses++; // moving forward
        }
      }
      pulsesChanged = 1;
    }```


  • Any idea on how I can do this guys? 🙂

    I basically need whatever value I receive from V_VAR1 to = target

    I am receiving the values I send from OpenHAB, but at the moment it does nothing because I don't know how to define this 😕

    Please correct me if I am wrong but it should look something like this in the void loop() no?
    if V_VAR1 value is updated
    then V_VAR1 value = target
    then run loop..

    Just don't know how to do it in programming language 🙂 any help would be appreciated 🙂



  • Right now, you are requesting V_VAR1, but don't have anything in the receive() function to handle the return message. I haven't worked with V_VAR type messages before, but if it is the same as other message types something like this should work. In the receive() function add:

    if (message.type == V_VAR1) {
         target = message.getInt();
    }
    

    There might be some more examples in the forums if you search S_CUSTOM or V_VAR

    One other thought. I think you need to move your reqest() function into loop(). The request() function tells the controller to send the variable. When the controller responds, the receive() function is called to handle the incoming message.



  • Yah tried to find examples on the forums with no luck unfortunately 😕

    I am able to receive & send the last value from/to OpenHAB, however I am unable to convert the payload to = target... that is the only missing piece I think..

    this is from my debug log

    183728 TSF:MSG:READ,0-0-1,s=6,c=1,t=24,pt=0,l=2,sg=0:55
    183735 TSF:MSG:SEND,1-1-0-0,s=6,c=2,t=24,pt=0,l=0,sg=0,ft=0,st=OK:
    


  • @nizoo91 said in Sending custom value to move DC motor a specific # of degrees:

    Yah tried to find examples on the forums with no luck unfortunately 😕

    I am able to receive & send the last value from/to OpenHAB
    However I am unable to convert the payload to = target... that is the only missing piece I think..

    this is from my debug log

    183728 TSF:MSG:READ,0-0-1,s=6,c=1,t=24,pt=0,l=2,sg=0:55
    183735 TSF:MSG:SEND,1-1-0-0,s=6,c=2,t=24,pt=0,l=0,sg=0,ft=0,st=OK:
    


  • Yes. This looks good. Dropped it in the parser here: https://www.mysensors.org/build/parser
    Looks like V_VAR1 is being sent with value 55.
    I think the code I posted above should get it from the incoming message and assign to target. If not, then I am not sure what is the problem. Perhaps someone that has worked more with V_VAR can respond?



  • @nagelc said in Sending custom value to move DC motor a specific # of degrees:

    Yes. This looks good. Dropped it in the parser here: https://www.mysensors.org/build/parser
    Looks like V_VAR1 is being sent with value 55.
    I think the code I posted above should get it from the incoming message and assign to target. If not, then I am not sure what is the problem. Perhaps someone that has worked more with V_VAR can respond?

    Actually I finally got it to work! and yes indeed, it was using your code!!! 🙂
    I don't know what I was doing before, but I tried your code previously but didn't work, and the only way to read the value was using : target = message.getString(); for some reason..

    But I changed quite a few things in the code, and now when I tried your code again, it actually worked!

    Dude thank you, you are a hero! I will post the final version once I polish up the code in case anyone else needs to do a similar thing!


 

277
Online

8.4k
Users

9.3k
Topics

97.9k
Posts