Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 25 of 63

Thread: motorized fader controller teensy 3.6 issue

Threaded View

  1. #1

    motorized fader controller teensy 3.6 issue

    hi
    im working on a motorized midi controler with 8 motor faders.
    i start develop my project with 1 teensy trying to use it for all functions.
    first after few weeks since i connect the first teensy the teensy just die one day (i did not make any changes or touch any thing just power it up as usual.
    so i thout that bay be my connection or wires soldering so i order another teensy and i solder everything from start to be sure its not my mistake. after few weeks of development i decided thats i should add 1 more teensy as a slave coz 1 teensy starts act weird when i used all the functions i need in the code. so i buy another teensy and connected it as a master in i2c with pullup resistors.
    it work for few days of code development untill today. i must say that again i didnt touch any thing or make any changes. the only change i made was in the master code trying to send movement data to gerrit slave code to move the faders and i did it they move to the place i send them. so i know the system work and also the codes work until the teensy dies.

    first i must say im new in the code field and im not programer.
    my goal is to send usb midi from pc to the master process the data and send it to faders.
    i have already did this process in serial rx tx connection test and its work fine also sending data from the fader to the pc was ok
    but only when i tryd to read and write from both sides its got stack. so i move to gerrit slave code that i know is build for this goal.
    but after 2 or 3 times i change the slave code and send the data to master the master stop responed and just die.
    i tryd all the recovery methods from press reset button and plug the cable also tryd to look in verbos info and even i lookd under- about this mac / usb/
    and nothing.... the chip is dead.

    ther is any chance the master can kill the slave chip with overflow data? coz if so that the only think i can think of.

    im waitng now for the pcb i develop and orderd. and im waiting for new teensy to come to build this project again in the best way but im realy afraid that this is gonna heppend again from no where.
    so if u gays can halp me to understend what im doing wrong ill be very grateful.
    also ill be glad to get any help with the code.

    this is the PCB schematic i made of the project its the same as gerrit project.(i have one mistake over ther coz the pcb ready for Serial RX TX 33,34 and im gonna use I2C. so ill solder 2 new lines in the back of the pcb with pull ups resistors from 33,34 in the slave to new free pin that il choos in the master)

    https://drive.google.com/file/d/1Rzp...ew?usp=sharing


    gerrit controller project:
    https://forum.pjrc.com/threads/42477...torfader-panel.


    i used the same parts in my project:

    220 ac to 12 dc 4A psu
    2X dc to dc step down (for 5v and 10v)
    2X teensy 3.6
    4X l9110s H briges
    8X ALPS motorized faders 100mm
    AD70 cricut for AREF

    gerrit code for the slave i used (i tryd put this code to run in the loop for test that the code that moves my faders in the last time)
    Code:
    void sendFaderCommand(byte mode){
      size_t idx;
      faderTargetData[16]=0;
      for (int i=0;i<8;i++){
        // split Target integers over two bytes in array
        faderTargetData[(i*2)]=(faderTarget[i] >> 8) & 0xFF;
        faderTargetData[(i*2)+1]=faderTarget[i] & 0xFF;
        // fill last byte in array with faderMove boolean array
        faderTargetData[16] |= faderMove[i] << i;
      }
      // Transmit to Slave
      Wire.beginTransmission(PANEL_ADDR);   // Slave address
      // Send mode
      Wire.write(mode);
      // Send target data
      for(idx = 0; idx <= MESSAGE_LEN; idx++) // Write data to I2C Tx buffer
          Wire.write(faderTargetData[idx]);
      Wire.endTransmission();           // Transmit to Slave
    }
    the way i tryd to run it
    Code:
    // -------------------------------------------------------------------------------------------
    // Basic Master
    // -------------------------------------------------------------------------------------------
    //
    // This creates a simple I2C Master device which when triggered will send/receive a text 
    // string to/from a Slave device.  It is intended to pair with a Slave device running the 
    // basic_slave sketch.
    //
    // Pull pin12 input low to send.
    // Pull pin11 input low to receive.
    //
    // This example code is in the public domain.
    //
    // -------------------------------------------------------------------------------------------
    
    #include <i2c_t3.h>
    
    // Memory
    #define MESSAGE_LEN 17
    uint8_t PANEL_ADDR = 0x66; 
    char databuf[MESSAGE_LEN];
    
    int count;
    int     faderTargetData[8]={500,500,500,500,500,500,500,500}; 
    boolean faderMove[8];
    int     faderTarget[8];
    
    
    void setup()
    {
        pinMode(LED_BUILTIN,OUTPUT);    // LED
        digitalWrite(LED_BUILTIN,LOW);  // LED off
        pinMode(12,INPUT_PULLUP);       // Control for Send
        pinMode(11,INPUT_PULLUP);       // Control for Receive
    
        // Setup for Master mode, pins 18/19, external pullups, 400kHz, 200ms default timeout
        Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
        Wire.setDefaultTimeout(200000); // 200ms
    
        // Data init
        memset(databuf, 0, sizeof(databuf));
        count = 0;
    
        Serial.begin(115200);
    }
    
    void loop()
    {
    sendFaderCommand(MESSAGE_LEN);
    //    if(digitalRead(11) == LOW)
    //    {
    //        digitalWrite(LED_BUILTIN,HIGH);   // LED on
    //
    //        // Print message
    //        Serial.print("Reading from Slave: ");
    //        
    //        // Read from Slave
    //        Wire.requestFrom(PANEL_ADDR, (size_t)MESSAGE_LEN); // Read from Slave (string len unknown, request full buffer)
    //
    //        // Check if error occured
    //        if(Wire.getError())
    //            Serial.print("FAIL\n");
    //        else
    //        {
    //            // If no error then read Rx data into buffer and print
    //            Wire.read(databuf, Wire.available());
    //            Serial.printf("'%s' OK\n",databuf);
    //        }
    //
    //        digitalWrite(LED_BUILTIN,LOW);    // LED off
    //        delay(100);                       // Delay to space out tests
    //    }
    }
    void sendFaderCommand(byte mode){
      size_t idx;
      faderTargetData[16]=0;
      for (int i=0;i<8;i++){
        // split Target integers over two bytes in array
        faderTargetData[(i*2)]=(faderTarget[i] >> 8) & 0xFF;
        faderTargetData[(i*2)+1]=faderTarget[i] & 0xFF;
        // fill last byte in array with faderMove boolean array
        faderTargetData[16] |= faderMove[i] << i;
      }
      // Transmit to Slave
      Wire.beginTransmission(PANEL_ADDR);   // Slave address
      // Send mode
      Wire.write(mode);
      // Send target data
      for(idx = 0; idx <= MESSAGE_LEN; idx++) // Write data to I2C Tx buffer
          Wire.write(faderTargetData[idx]);
      Wire.endTransmission();           // Transmit to Slave
    }
    gerrit code for the slave i used

    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 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]={1,0,16,17,18,19,22,23};     // touchRead pins for fader touch
    int     faderMotorUpPin[8]={29,9,7,5,3,14,36,38};     // motor up PWM pin
    int     faderMotorDownPin[8]={30,10,8,6,4,2,35,37};   // 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=3000;                     // 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]=10;
        iGain[i]=1;
        dGain[i]=50.00;
        iMin[i]=-1500;
        iMax[i]=1500;
      }
      
      // Setup for Slave mode pins 33/34, external pullups, 400kHz
      Wire.begin(I2C_SLAVE, PANEL_ADDR, I2C_PINS_33_34, I2C_PULLUP_EXT, 400000);
      // register events
      Wire.onReceive(receiveEvent);
      Wire.onRequest(requestEvent);
      cmd = 0;    // incoming command operating mode
    }
    
    void loop()                     
    {
      // 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(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();
      } 
    }
    
    // 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];
        }
        // 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)
    }
    my final goal is send PROTOOLS faders data to motor faders thru usbmidi and receive data from motor faders to PROTOOLS with faders touch sens press / release command in the highest speed response i can get and best stability.
    soon ill upload the assembled pcb and ill up load the codes im gonna use to get ur opinion before i run it again,

    thank u all
    Rota
    Last edited by rotabox; 01-28-2019 at 12:55 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
  •