Go Down

Topic: Controlling faulhaber motor using potentiometer (Read 9746 times) previous topic - next topic

MorganS

OK, so the encoder was working 'backwards' and showing negative numbers when we only expected to get positive numbers.

Glad it's working. Now you can try tuning the gain and making it work like you want.
"The problem is in the code you didn't post."

chlowden

#61
May 11, 2017, 08:51 pm Last Edit: May 11, 2017, 08:57 pm by chlowden
I have reduced the GAIN to 0.2 which leaves a very slight jitter that does not affect the lens. hThe system is occasionally erratic at start up, so there is some work to do. But for the moment, the project has fulfilled its purpose.


----------

Below is the sketch with a quick explanation so that maybe another newbie like me will understand.


EQUIPMENT USED FOR THE SKETCH BELOW
Leonardo
Cytron 13A, 5-25V Single DC Motor Controller
http://www.robotshop.com/en/cytron-13a-5-30v-single-dc-motor-controller.html
16-12 volt V_MOUNT battery source.
Lenzhound Thumbwheel 10K potentiometer
https://www.motiondogs.com/products/7-thumbwheel-kit.html

Below is video of the systems working with the sketch below
https://eshare.yr.com/fl/XCYEsJPE27/170510_
plus a picture of the hardware (that I will clean up soon)


Code: [Select]
/* POTENTIOMETER CONTROLLER FOR DC MOTOR WITH QUADRATURE ENCODER TYPE HEDEN M26VE FOR CINEMA LENS FOLLOW FOCUS SYSTEMS.
 *  
 * The sketch is a proof concept for controlling a digital professional follow focus motor (HEDEN M26VE) with a 10K potentiometer supplied by MOTIONDOGS.
 * The goal is that when the potentiometer is turned, the motor follows either backwards or forwards.
 *
 * The sketch was written by MORGANS (MANY MANY THANKS FOR YOUR PATIENCE AND ENERGY). I would to thank TOMGEORGE & DELIAS for their thoughts.
 *
 * The script was designed on a Leonardo, drivng a Cytron 13A, 5-25V Single DC Motor Controller with a 16-12 volt V_MOUNT battery source.
 * This sketch should work on similar digital follow focus motors from Preston & Arriflex, but this is to be tested
 * The link below follows the sketches development.
 * https://forum.arduino.cc/index.php?topic=460220.0
 */


#include <PWM.h>
#include <Encoder.h>

#define GAIN 0.2
//how agressively it tries to get to the desired position. This is a multiplier to add or reduce voltage to drive the motor to the right point.

#define PWMPIN 10 // Output pin to control PWM for motor controller on digital
#define DIRPIN 9 // Output direction for motor controller on digital
#define CHANNELA 3 // motor position sensor pin Digital Pin - NOTE: IF THE PIN ORDER OF THE CHANNELA & B IS INVERTED, THE MOTOR WILL JITTER ERRATICALLY WITH NEGATIVE VALUES
#define CHANNELB 2 // motor position sensor pin Digital Pin
#define POTPIN A0    // select the input pin for the potentiometer on analog pin
Encoder MyEnc(CHANNELA, CHANNELB);

int32_t frequency = 30000; //frequency (in Hz) for PWM.h Library. Used to attenuate high pitched motor noise.

// Define the number of samples to keep track for the SMOOTHING. The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input.  Using a constant rather than a normal variable lets
// use this value to determine the size of the readings array.
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
//

void driveMotor(int speed) {
  //drive motor at desired speed
  //-255 is max reverse, +255 is max forwards
  if (speed >= 1) {
    digitalWrite(DIRPIN, 0);
    pwmWrite(PWMPIN, speed); // replaces analogWrite with pwmWrite to make it work with PMW.h library
  } else {
    digitalWrite(DIRPIN, 1);
    pwmWrite(PWMPIN, -speed); // replaces analogWrite with pwmWrite to make it work with PMW.h library
  }
}

long int desiredPosition() {   // long added to cover large encoder values
  //Put the mathematics to convert pot position to encoder position here
  //This can be called from anywhere in the code with consistent results 17879

  return map(total, 0, 1023 * numReadings, 0, 48000);
  // 1023 is the 10K potentiometer voltage equivalence.
  // 48000 is the number of motor encoder return values to cover the rortation of the lens ring from infinity to the closest lens point (my test lens is a 50mm Zeiss Superspeed T1.4 MK1). This value may change depending on the lens barrel size.  
}

void setup() {
  pinMode(PWMPIN, OUTPUT);
  pinMode(DIRPIN, OUTPUT);
  pinMode(CHANNELA, INPUT_PULLUP);
  pinMode(CHANNELB, INPUT_PULLUP);

  //initialize all timers except for 0, to save time keeping functions for PWM.h Library
  InitTimersSafe();

  //sets the frequency for the specified pin for PWM.h Library
  bool success = SetPinFrequencySafe(PWMPIN, frequency);

  // Motor Setup Sequence
  driveMotor(0);  //stop
  delay(5000);     //delay before starting setup.

  //drive motor all the way one way, then take this as the zero position
  driveMotor(50); //drive backwards slowly
  delay(8000);    //maybe it takes 8 seconds to get there?
  driveMotor(0);  //stop
  delay(100);     //let it settle.
  MyEnc.write(0); //call this zero
  //now drive the motor somewhere close to where the pot currently is
  //this is to stop it slamming there at full speed.
  while (MyEnc.read() < desiredPosition()) {
    driveMotor(0);
  }
  driveMotor(0);

  Serial.begin (9600);

  // initialize serial communication with computer:
  //Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}

void loop() {

  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(POTPIN);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;


  long int actualPosition = MyEnc.read(); // long added to cover large encoder values
  driveMotor(GAIN * (actualPosition - desiredPosition()));

//Prints quadrature encoder return value in comparison to the potentiometer voltage equivalence
  // send it to the computer as ASCII digits
  Serial.println(average);
  delay(0);        // delay in between reads for stability

  Serial.print (actualPosition); // Print Encoder Library return
  Serial.print ("/");
}




chlowden

#62
May 11, 2017, 11:36 pm Last Edit: May 11, 2017, 11:44 pm by chlowden
Attached is the sketch with the libraries plus the test sketches I used. Also I have attached the wiring schematic.
Enjoy

Go Up