Forum Rule: Always post complete source code & details to reproduce any issue!
Page 3 of 3 FirstFirst 1 2 3
Results 51 to 63 of 63

Thread: motorized fader controller teensy 3.6 issue

  1. #51
    Here is a video of automation test to read and write faders:
    https://m.facebook.com/groups/246767...12554192176349

  2. #52
    Quote Originally Posted by Gerrit View Post
    Sorry, I don't know anything about Protools or Studio One as I use Logic and Reaper.

    Why do you send the same data to two controllers? Isn't that supposed to a NRPN controller where the value is split over two MIDI bytes? But like I said, I don't know how Protools is controlled. Logic uses the Mackie MCU protocol and this uses pitch bend to send the fader values.
    hi gerrit
    all faders moving well but i see that: when they jump to position, not all of them jump to the right place, but once they get the move commend all of them jump to the right place and start moving.
    do u have any idea what parameters should i tune?
    tnx
    rota

  3. #53
    Senior Member
    Join Date
    Jan 2017
    Location
    Maastricht
    Posts
    168
    Quote Originally Posted by rotabox View Post
    hi gerrit
    all faders moving well but i see that: when they jump to position, not all of them jump to the right place, but once they get the move commend all of them jump to the right place and start moving.
    do u have any idea what parameters should i tune?
    tnx
    rota
    I don't understand what you're saying. How can the faders jump to a position without getting a move command?
    BTW I don't have a facebook account so I can't watch the video.

    With regards to tuning the fader control, I'm afraid you'll really have to read the PID without a Phd article referenced in the thread to get an understanding what the parameters do and what PID control is about. It's also difficult to give any advice without knowing exactly what the problem is.

  4. #54
    Quote Originally Posted by Gerrit View Post
    I don't understand what you're saying. How can the faders jump to a position without getting a move command?
    BTW I don't have a facebook account so I can't watch the video.

    With regards to tuning the fader control, I'm afraid you'll really have to read the PID without a Phd article referenced in the thread to get an understanding what the parameters do and what PID control is about. It's also difficult to give any advice without knowing exactly what the problem is.
    U right first I'll go read the article.
    I'll try to explain the problem:
    I'm sending 8 faders automations move commend from the software. When I press play all the faders go the position and moving OK. But when I press stop in software and rewind to the start point of the automations all fader go to some place(a bit wronaoutomation .
    Now if I'll press play again all the faders will go immediately to the right position and will start move OK again.
    One more example:
    If I jump in software with crouser to any point in the sequence aoutomation. The faders go something near the position point. And then if I'll press play all faders go the the right starting position and start move OK.
    It looks it like some thing with the jump to start point prameters reaction of the code.

  5. #55
    All so sometimes in aoutomation reading the when faders got very hard commend of hard jump
    Sometimes one of the faders got crazy for a sec and then keeps go back to position and keep the right track.

  6. #56
    Here is a video of the problem
    https://youtu.be/5psz8AAO16Y

  7. #57
    Senior Member
    Join Date
    Jan 2017
    Location
    Maastricht
    Posts
    168
    Quote Originally Posted by rotabox View Post
    All so sometimes in aoutomation reading the when faders got very hard commend of hard jump
    Sometimes one of the faders got crazy for a sec and then keeps go back to position and keep the right track.
    If it's always the same fader that's behaving badly then I would check the wiring.

    Quote Originally Posted by rotabox View Post
    Here is a video of the problem
    https://youtu.be/5psz8AAO16Y
    I can't determine what the actual problem is from this video, there's too much going on. Limit it to a single fader or have all faders do exactly the same thing.
    You have to take a step back and systematically check the fader control and tune the PID parameters if needed.

  8. #58
    Quote Originally Posted by Gerrit View Post
    If it's always the same fader that's behaving badly then I would check the wiring.



    I can't determine what the actual problem is from this video, there's too much going on. Limit it to a single fader or have all faders do exactly the same thing.
    You have to take a step back and systematically check the fader control and tune the PID parameters if needed.
    U can see in the video that faders 1-4 found the same thing in the program that means that that send the same values but the fader controller act difrent when I'm jump to point. I test high P gain and its makes the jumps a bit better coz its higher
    voltage but not solve it

  9. #59
    Quote Originally Posted by Gerrit View Post
    If it's always the same fader that's behaving badly then I would check the wiring.



    I can't determine what the actual problem is from this video, there's too much going on. Limit it to a single fader or have all faders do exactly the same thing.
    You have to take a step back and systematically check the fader control and tune the PID parameters if needed.

    i test all values in serial print and its looks ok the send value from master and the recive value in slave.
    so its nothing i can think of.
    maybe should i add some check error commend to check if fader is on the right value and if not to correct it?

  10. #60
    here is another video of a test
    here u can see im set the start point to 0 witch in my case is 1023.
    like u can see the fader get the movement commend ok but when i jump to start u can see in serial print that the value that the master send (faderTarget[1]) is 1008.
    in first try its not send the commend coz my mac work hard to send midi and read serial but in second try u can see the problem.
    the fader trying rich ther but is stops somewhere is the middle(every time in a bit different place).
    allso if u look carefully u can see that when i press play the fader go quickly all the way down (to 1008) and complete the movement by go up.
    https://youtu.be/EDS1gZ_HIaM
    Last edited by rotabox; 03-13-2019 at 11:03 PM.

  11. #61
    Senior Member
    Join Date
    Jan 2017
    Location
    Maastricht
    Posts
    168
    Which fader control mode do you use? TARGET or FOLLOW? Have you tried the other mode to see what the difference is?

    I'm sorry but I can't help you with the tuning other than giving some general advice. It took me some time to get it right for my setup and it still needs some finetuning. You need to get an understanding of how the parameters interact with each other by experimenting. I would start with concentrating on the control of the faders without any DAW control by writing some test functions like I did with the one that cycles through some values which is shown in one of the videos. The point is to check for overshoot (combination of p and d term) when the fader has to move a large distance on the one hand and check that the fader is able to move a little (p and i term) on the other.

  12. #62
    Quote Originally Posted by Gerrit View Post
    Which fader control mode do you use? TARGET or FOLLOW? Have you tried the other mode to see what the difference is?

    I'm sorry but I can't help you with the tuning other than giving some general advice. It took me some time to get it right for my setup and it still needs some finetuning. You need to get an understanding of how the parameters interact with each other by experimenting. I would start with concentrating on the control of the faders without any DAW control by writing some test functions like I did with the one that cycles through some values which is shown in one of the videos. The point is to check for overshoot (combination of p and d term) when the fader has to move a large distance on the one hand and check that the fader is able to move a little (p and i term) on the other.
    i guess the problem is not in pid coz I try to send parameters in FOLLOW mode and its still not going to the exactly correct point when jump to start point But I'll dig it
    thank you.

  13. #63
    Quote Originally Posted by Gerrit View Post
    Which fader control mode do you use? TARGET or FOLLOW? Have you tried the other mode to see what the difference is?

    I'm sorry but I can't help you with the tuning other than giving some general advice. It took me some time to get it right for my setup and it still needs some finetuning. You need to get an understanding of how the parameters interact with each other by experimenting. I would start with concentrating on the control of the faders without any DAW control by writing some test functions like I did with the one that cycles through some values which is shown in one of the videos. The point is to check for overshoot (combination of p and d term) when the fader has to move a large distance on the one hand and check that the fader is able to move a little (p and i term) on the other.
    UPDATE:
    i read the pid artical and i think i understand most of it and good thing to know a bit more about.
    so i did a lot of test with the pid and my problem.
    i can say that that pid work great but not with pure hard square wave jump values point and faders.
    in the slave code u wrote i found that the commend of FaderPidOn[i] is the problem for my application.
    or may i say that is the speed that FaderPidOn turns to false after fader move is too quick for the fader to arrive target.
    so i tryed change cmd timer and faderRead timer but nothing brings me good result
    i figure out that when i delete out the FaderPidOn[i] from the if commend that operates the motors then the faders moving very well to target. but the motors keeps work constantly and oscillate when near to target or not exactly on target and its make the system unstable obviously.
    soo... i write an small Debug void thats run in 50000 micro interval and check if faderTarget equal faderValue and if not the faderPidOn[i] = true; thats working very nice and that the only solution i found till now. i guess ill give it a bit more fine tuning when i have some more time but now its doing the job.
    here is a demo of 16 faders in software and a demonstration of jumping 8 faders left and back right.
    here i can see that all faders rich the target:

    https://youtu.be/kmb8TCuoi8s

    and here is the slave code with my Extra Debug void:
    Code:
    /* 
      Zeus Commander Controller Series
      I2C controlled motorfader octet
    
      Full PID motor control supporting two operating modes:
      TARGET  for fast preset recall
      FOLLOW  for slow to fast following of values 
    
      This code expands on the examples provided with the i2c_t3 library for the I2Ccommunication
      
      This code is in the public domain.
    */
    #include <i2c_t3.h>
    #include <ResponsiveAnalogRead.h>
    
    // PID arrays
    float dState[8];
    float iState[8];
    float iMin[8];
    float iMax[8];
    float pGain[8];
    float iGain[8];
    float dGain[8];
    float plantDrive[8];
    float maxD=0.00;       // maximum derivative value for debugging purposes
    
    void UpdatePID(int faderIndex, float faderError, float faderPosition)
    {
      float pTerm, dTerm, iTerm, plantDriveInput;
      // calculate the proportional term
      pTerm = pGain[faderIndex] * faderError;   
      // calculate the integral state with appropriate limiting
      iState[faderIndex] += faderError;
      if (iState[faderIndex] > iMax[faderIndex]){
        iState[faderIndex] = iMax[faderIndex];
        }
      else if (iState[faderIndex] < iMin[faderIndex]){
        iState[faderIndex] = iMin[faderIndex];
      }
      iTerm = iGain[faderIndex] * iState[faderIndex];  // calculate the integral term
      dTerm = dGain[faderIndex] * (faderPosition - dState[faderIndex]);
      if (abs(faderPosition - dState[faderIndex]) > maxD){
        maxD=abs(faderPosition - dState[faderIndex]);
      }
      dState[faderIndex] = faderPosition;
    
      plantDriveInput = pTerm + iTerm - dTerm;
      if (plantDriveInput > 4096) {
        plantDriveInput=4096;
      }
        if (plantDriveInput < -4096) {
        plantDriveInput=-4096;
      }
      plantDrive[faderIndex]=plantDriveInput;
    }
    
    elapsedMicros sinceFaderDebug;                         // timer for fader check
    unsigned int  faderDebugInterval= 50000; 
    elapsedMicros sinceFaderRead;                         // timer for fader check
    unsigned int  faderReadInterval=1000;                 // interval in microseconds for checking fader position(update)
    elapsedMicros sinceTouchRead;                         // timer for touch read
    unsigned int  touchReadInterval=5000;                 // interval in microseconds for reading fader touch
    elapsedMillis sinceLastCommand;                       // timer for time-out of PIF after last command
    unsigned int  commandTimeOutInterval=500;             // interval for PID time-out in milliseconds
    int     faderWiperPin[8]={32,31,39,20,21,15,65,64};   // analog in pin for fader wipers
    int     faderTouchPin[8]={0,1,16,17,18,19,22,23};     // touchRead pins for fader touch
    int     faderMotorUpPin[8]=  {10,29,5,7,3,14,35,37};     // motor up PWM pin
    int     faderMotorDownPin[8]={9,30,6,8,4,2,36,38};   // motor down PWM pin
    int     faderValue[8];                                // fader value ranging 0 to 1023
    int     faderTarget[8];                               // fader target value ranging 0 to 1023
    int     faderTouch[8];                                // fader touch reading
    boolean faderPidOn[8];                                // status of PID
    int     faderTouchThreshold=4800;                     // threshold value for touchRead
    boolean faderTouched[8];                              // boolean indicating if fader is touched
    
    ResponsiveAnalogRead analog[8]{ResponsiveAnalogRead(32, true),ResponsiveAnalogRead(31, true),
                                   ResponsiveAnalogRead(39, true),ResponsiveAnalogRead(20, true),
                                   ResponsiveAnalogRead(21, true),ResponsiveAnalogRead(15, true),
                                   ResponsiveAnalogRead(65, true),ResponsiveAnalogRead(64, true)};
    
    // I2C communication
    // Command definitions
    #define TARGET    0x10              // All faders to target value as fast as possible. PID state is cleared with each command.
    #define FOLLOW    0x20              // Faders follow value, last byte in message is used to determine which motors should move.
                                        // PIDs will time-out after last command.
    
    // Function prototypes
    void receiveEvent(size_t count);
    void requestEvent(void);
    #define PANEL_ADDR 0x66              // I2C address, should be selectable by jumper using leftover pins.
    #define MESSAGE_LEN 17
    byte faderValueData[MESSAGE_LEN];    // 16 bytes for values, 1 byte for touch
    byte faderTargetData[MESSAGE_LEN];   // 16 for target values, 1 byte for indicating which faders should be moved.
    volatile uint8_t received;
    volatile uint8_t cmd;
    byte operatingMode = TARGET;
    
    
    void setup()
    {  
      
      //initialize faders and analog reference 
      analogReference(EXTERNAL);
      analogWriteResolution(12);
      for (int i=0; i<8; i++){
        pinMode(faderMotorUpPin[i], OUTPUT);
        pinMode(faderMotorDownPin[i], OUTPUT);
        analogWriteFrequency(faderMotorUpPin[i],14648.437);  // 14648.437 ideal frequency for 180MHz 12bit PWM
        analogWriteFrequency(faderMotorDownPin[i],14648.437);  //14648.437 ideal frequency for 180MHz 12bit PWM
        faderTouched[i]=false;
        faderValueData[i]=0;
        faderTarget[i]=500;
        faderPidOn[i]=false;
      }    
           
      readFaders();
      // set PID tuning parameters
      for (int i=0;i<8;i++){
        pGain[i]=0.5;
        iGain[i]=20;
        dGain[i]=2.00;
        iMin[i]=-1500;
        iMax[i]=1500;
      }
      
      // Setup for Slave mode pins 33/34, external pullups, 1MHz
      Wire.begin(I2C_SLAVE, PANEL_ADDR, I2C_PINS_33_34, I2C_PULLUP_EXT, 1000000);
      // register events
      Wire.onReceive(receiveEvent);
      Wire.onRequest(requestEvent);
      cmd = 0;    // incoming command operating mode
    }
    
    void loop()                     
    {
        if (sinceFaderDebug >=faderDebugInterval) {
        sinceFaderDebug = sinceFaderDebug-faderDebugInterval;
        
        Debugfader();
        }
      // check elapsedMicros and millis timers
      // faders
      if (sinceFaderRead >=faderReadInterval) {
        sinceFaderRead = sinceFaderRead-faderReadInterval;
        readFaders();
        
        // always update PID for timing consistency
        for (int i=0;i<8;i++){
            UpdatePID(i,faderTarget[i]-faderValue[i],faderValue[i]);      
          }
          
        // loop through faders and move where necessary
        for (int i=0;i<8;i++){
         if (!faderTouched[i] && faderPidOn[i]){
            //if (!faderTouched[i]){
            if(plantDrive[i]>0 && faderValue[i] <=1022){
             
              analogWrite(faderMotorDownPin[i],0);
              analogWrite(faderMotorUpPin[i],plantDrive[i]);
    
            } else if (plantDrive[i] <=0 && faderValue[i] >=1){
              analogWrite(faderMotorUpPin[i],0);
              analogWrite(faderMotorDownPin[i],-plantDrive[i]);
    
            }
          } 
          
          else if(!faderPidOn[i]){
            
              analogWrite(faderMotorDownPin[i],0);
              analogWrite(faderMotorUpPin[i],0);
            }
        }
      }
      
      //  separate touchRead timer 
      if (sinceTouchRead >= touchReadInterval){
        sinceTouchRead = sinceTouchRead - touchReadInterval;
        readTouch();
      }
      
      // command time-out  
      if (sinceLastCommand >= commandTimeOutInterval){
        for (int i=0;i<8;i++){
          faderPidOn[i]=false;
        }
        sinceLastCommand = 0;
      }
    
    }
    
    // read fader analog values and update faderValue array
    void readFaders() {
      for (int i=0; i<8; i++) {
        analog[i].update();
        faderValue[i] = analog[i].getValue();
       //Serial.println(faderValue[1]);
    
      
      } 
    }
    
    // read fader touch
    void readTouch() {
      for (int i=0; i<8; i++) {
        faderTouch[i]= touchRead(faderTouchPin[i]);
        if (faderTouch[i]>faderTouchThreshold){
          faderTouched[i]=true;
        } else if (faderTouch[i]<=faderTouchThreshold){
          faderTouched[i]=false;
        }
      } 
    }
    
    // handle Rx Event (incoming I2C data)
    void receiveEvent(size_t count) {
      size_t idx;
      int incomingTargetValue[8];
      boolean incomingFaderMove[8];
      if(count)
      {
        // grab command
        cmd = Wire.readByte();
        switch(cmd)
        {
        case TARGET:
          if (operatingMode==FOLLOW){
            // set PID tuning parameters
    //        for (int i=0;i<8;i++){
    //          pGain[i]=20.00;
    //          iGain[i]=0.5;
    //          dGain[i]=40.00;
    //        }
            operatingMode=TARGET;
          }
          break;
        case FOLLOW:
          if (operatingMode==TARGET){
            // set PID tuning parameters
    //        for (int i=0;i<8;i++){
    //          pGain[i]=20.00;
    //          iGain[i]=0.5;
    //          dGain[i]=40.00;
    //        }
            operatingMode=FOLLOW;
          }
          break;
        }
        idx = 0;
        while(Wire.available()) faderTargetData[idx++] = Wire.readByte();
              
        // Process data
        for (int i=0;i<8;i++){
          // combine bytes back to integers and put in temporary array
          incomingTargetValue[i]= faderTargetData[(i*2)];
          incomingTargetValue[i]= incomingTargetValue[i] << 8 | faderTargetData[(i*2)+1];
          // fill faderPidOn boolean array with last byte
          incomingFaderMove[i] = 1 & faderTargetData[16] >> i;
          // clear PID states if PID is switched on or if mode is TARGET
          if ((incomingFaderMove[i] && faderPidOn[i]!=incomingFaderMove[i]) || operatingMode==TARGET){
            dState[i]=faderValue[i]; 
            iState[i]=0; 
         
          }
          faderPidOn[i]=  incomingFaderMove[i];
          // update fader target
          faderTarget[i]=incomingTargetValue[i];
          //Serial.println(faderTarget[1]);
    
        }
        // reset timer
        sinceLastCommand=0;
      }
            
    
    }
    
    // handle Tx Event (outgoing I2C data)
    void requestEvent(void)
    {
      faderValueData[16]=0;
      for (int i=0;i<8;i++){
        // split value integers over two bytes in array
        faderValueData[(i*2)]=(faderValue[i] >> 8) & 0xFF;
        faderValueData[(i*2)+1]=faderValue[i] & 0xFF;
        // fill last byte in array with touch boolean array
        faderValueData[16] |= faderTouched[i] << i;
      }
      Wire.write(faderValueData, MESSAGE_LEN); // fill Tx buffer (send full mem)
    }
    void Debugfader(){
     for (int i=0;i<8;i++){
      if(faderTarget[i] != faderValue[i]){
        faderPidOn[i] = true;
      }
      }
    }
    Last edited by rotabox; 03-15-2019 at 06:02 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •