Controlling faulhaber motor using potentiometer

Hello
I am trying to adapt a wireless lens control system (called a Follow focus) that is based on an arduino Leonardo using a stepper motor
https://www.motiondogs.com/wireless-follow-focus-kits-and-packages/1-lenzhound-base-kit.html
to a film industry standard DC motor.
The motor I wish to use is a Heden m 26ve
http://heden-engineering.com/products/motors/m26ve_1/
Inside the casing is a faulhaber 2342s024cr motor
https://fmcc.faulhaber.com/details/o…8_13813/fr/DE/
At the bottom of the thread below are pictures of the Heden opened up:
http://www.reduser.net/forum/showthread.php?153329-Create-DIY-controller-for-Heden-motor

From what I understand, the Heden uses a quadrature motor system, connected to a controlling system via a 7 pin lemo connector. I have built a controller box, that contains the motiondogs receiver board connected to a Cytron 13A, 5-25V Single DC Motor Controller

that is wired to the 7 pin lemo.
For the moment, I am testing the possibilties using a potentiometer from motion dogs
https://www.motiondogs.com/products/7-thumbwheel-kit.html
The whole motiondogs system is controlled by software written in arduino leonardo sketches that can be downloaded here

The final goal is to integrate the new box with the wireless handset, but first I need to get the Heden motor working using the thumbwheel.

Motiondogs sent me a test sketch for a non quadrature motor that is primarily designed to test the Softpwm library. Obviously the sketch does not work with the Heden motor.

If I understand correctly, (you might have noticed by now that I am a total newby to all this) the sketch should be using the A&B encoder channels to control the motor. As the potentiometer cannot do this, maybe a PID library can do the error correction, but this is conjecture as I do not know if it is the right direction to go or how to integrate it into the code below.

For more information on industry standard follow focus systems connections:
http://www.prestoncinema.com/Manuals/FIZ-HU3manual2014.pdf page 25
https://www.schneideroptics.com/pdfs/chrosziel/Digi%20FOX%20Manual%20V3.2.pdf page 16

Below is the sketch that correlates to the attached pdf schematic.
Any help is much appreciated.
thank you

#include <SoftPWM.h>
#define PWMPIN A0 // Output pin to control PWM for motor controller
#define DIRPIN A1 // Output direction for motor controller
#define CHANNELA A2 // position sensor pin
#define CHANNELB A3 // position sensor pin
#define POTPIN A4 // select the input pin for the potentiometer
//#define DIRSW A3 // direction switch
//int dirSwState = 0; // last state of the direction switch
//int dirLast = 0; // last state to compare direction switch against
int potValue = 0; // variable to store the value coming from the sensor
int sensorValue = 0; // value of position sensor
long prevPos1 = 0;
long prevPos2 = 0;
long curPos = 0;
long prevSPos1 = 0;
long prevSPos2 = 0;
long curSPos = 0;
#define MIN_POT_VAL 0
#define MAX_POT_VAL 1023
#define MIN_SENSOR_VAL 32
#define MAX_SENSOR_VAL 1018
#define SLOW_RANGE 51 // number of encoder values away before decel begins
int mspeed = 0;
int newspeed = 0;
void setup() {
SoftPWMBegin();
SoftPWMSet(PWMPIN, 0);
SoftPWMSetFadeTime(ALL, 100, 400);
//pinMode(PWMPIN, OUTPUT);

pinMode(DIRPIN, OUTPUT);
// pinMode(DIRSW, INPUT);
Serial.begin(9600);
}
void loop() {
// read the value from the sensor:
long newPos = analogRead(POTPIN);
long newSPos = analogRead(CHANNELA);
// debounce pot
if (newPos != prevPos1 && newPos != prevPos2) {
prevPos1 = prevPos2;
prevPos2 = newPos;
curPos = map(newPos, MIN_POT_VAL, MAX_POT_VAL, MIN_SENSOR_VAL, MAX_SENSOR_VAL);
}
// debounce encoder
if (newSPos != prevSPos1 && newSPos != prevSPos2) {
prevSPos1 = prevSPos2;
prevSPos2 = newSPos;
curSPos = map(newSPos, MIN_SENSOR_VAL, MAX_SENSOR_VAL, MIN_POT_VAL, MAX_POT_VAL);
}
if(curPos <= curSPos){ // Backwards
digitalWrite(DIRPIN, LOW);

unsigned int in_range = curPos + SLOW_RANGE;
if(curSPos > in_range){ // Max speed
SoftPWMSet(PWMPIN, 255);
} else {
if((curPos+50) == curSPos) // 75%
{
SoftPWMSet(PWMPIN,190);
}
if((curPos+40) == curSPos) // 50%
{
SoftPWMSet(PWMPIN, 125);
}
if((curPos+30) == curSPos) // 25%
{
SoftPWMSet(PWMPIN, 60);
}
if((curPos+20) == curSPos) // 12%
{
SoftPWMSet(PWMPIN, 31);
}
if((curPos+10) == curSPos) // 12%
{
SoftPWMSet(PWMPIN, 15);
}
if((curPos+3) == curSPos) // 6%
{
SoftPWMSet(PWMPIN, 0);
}
}
}

if(curPos >= curSPos){ // Forward
digitalWrite(DIRPIN, HIGH);
unsigned int in_range = curPos - SLOW_RANGE;
if(curSPos < in_range){ // Max speed
SoftPWMSet(PWMPIN, 255);
} else {
if((curPos-50) == curSPos) // 75%
{
SoftPWMSet(PWMPIN,190);
}
if((curPos-40) == curSPos) // 50%
{
SoftPWMSet(PWMPIN, 125);
}
if((curPos-30) == curSPos) // 25%
{
SoftPWMSet(PWMPIN, 60);
}
if((curPos-20) == curSPos) // 12%
{
SoftPWMSet(PWMPIN, 31);
}
if((curPos-10) == curSPos) // 12%
{
SoftPWMSet(PWMPIN, 15);
}
if((curPos-3) == curSPos) // 6%
{
SoftPWMSet(PWMPIN, 0);

}

}
}

if(curPos == curSPos){ // Stop
SoftPWMSet(PWMPIN, 0);
}
// if(dirLast != dirSwState){
// Serial.println(dirSwState);
// dirLast = dirSwState;
//}
//analogWrite(pwmPin, val);
//SoftPWMSet(PWMPIN, val);
}

170228_LENSHOUND_SCHEMATIC.pdf (172 KB)

Below is more info on the project:

The SoftPWM library will be an additional library to include with the rest of the Lenzhound system as you expected. Another library you might want to take advantage of that's bundled with the Arduino platform is the Encoder library, this library may simplify using the data for position feedback from your motor.

The DIR pin can be directly re-mapped to the DIR pin on the Cytron DC driver.

Here's a short rundown of the Lenzhound systems hardware:

Both the controller and receiver use an ATMEGA32U4 16-bit microcontroller and an nRF24L01+ 2.4Ghz wireless transceiver.

As for the controller, the remaining available pins on the microcontroller are used for the LEDs, buttons, rotary encoder, focus knob/potentiometer, and a few pins for ISP programming.

On the receiver, the stepper driver is an Allego A3967, the datasheets may be helpful in understanding what all the macro functions you've discovered in the code do - ENABLE, SLEEP, DIR, STEP, MS1, MS2
http://www.allegromicro.com/en/Produ...ers/A3967.aspx

Below is the softpwm code used in this youtube test

Also, here's the code I used to connect a potentiometer and run my DC motor; http://pastebin.com/GxVTxX86

"With the motor I have, once at full speed, a lot of electrical noise is introduced on the motors position feedback line. I added a couple 0.1uF capacitors between my GND and pin that provides position. Many motors use encoders, my old school motor has a potentiometer on it. More modern industry motors are using encoders with A/B channels (which helps improve accuracy) so code would need to be adjusted for that difference.

Cobbled together some code for absolute bare minimum functionality. With a little accel/decel code improvements this could be quite viable."

Attached is a picture of my controller box

First, please go back to your original post and edit it to put [code][/code] tags around the code. The forum software eats some of your code if you don't.

I recently came across some very neat Faulhaber actuators. They seemed more like brushless DC motors unrolled into a linear actuator. The driver board was pretty much a black box - you have to have the Faulhaber original.

The link you put to Faulhaber has "..." in the middle. Perhaps it got shortened by something? Can you post the full link?

Hello
Thanks for the reply
here is the link for the motor

https://fmcc.faulhaber.com/resources/img/EN_2342_CR_DFF.PDF

I suppose my question is simple. Is it possible to drive this kind of motor using a potentiometer? Is there any useful use for the Channel A & B information that is returned to the motor? Is the motor using an quadrature encoder?
None of the example sketches I have tested even come close to working, so I presume that I have something very wrong.
Many thanks to anyone who might be able to push me in the right direction

A summary of what I know:

When I use the example Analogreadserial sketch on pin A4, which is connected to the pot, when i turn the pot I get values between 0 around 50. The stream of numbers is not very stable at all as it varies between 50 and 40 at the far end of the pot turn.

When I use the example DigitalreadSerial sketch on pin A2 or A3 and turn manually the motor, I get values between 1 and 0. When it is not turned, the last value that what shown when it was turning is kept. (This might be because this sketch seems to be about checking a button)

When I use the example Read Quadrature Encoder sketch on pin A2 or A3 and turn manually the motor, I get negative or positive numbers depending on which direction I turn it.

Using the sketch below, the motor goes forward, stop & backward

 /* Read Quadrature Encoder
  * Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
  *
  * Sketch by max wolf / www.meso.net
  * v. 0.1 - very basic functions - mw 20061220
  *
  */  
 int val; 
 int encoder0PinA = A2;
 int encoder0PinB = A3;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;
 
const int pwm = A0 ;  //in itializing pin 2 as pwm
const int in_1 = 18 ; //Leonardo interupt pins are 18 & 19
const int in_2 = 19 ;



 void setup() { 

     pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);

   
 pinMode(pwm,OUTPUT) ;    //we have to set PWM pin as output
pinMode(in_1,OUTPUT) ;  //Logic pins are also set as output
pinMode(in_2,OUTPUT) ;


   Serial.begin (9600);
 } 

 void loop() { 

     n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
     Serial.print (encoder0Pos);
     Serial.print ("/");
   } 
   encoder0PinALast = n;

  //For Clock wise motion , in_1 = High , in_2 = Low

digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,LOW) ;
analogWrite(pwm,255) ;

/*setting pwm of the motor to 255
we can change the speed of rotaion
by chaning pwm input but we are only
using arduino so we are using higest
value to driver the motor  */

//Clockwise for 3 secs
delay(3000) ;     

//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(1000) ;

//For Anti Clock-wise motion - IN_1 = LOW , IN_2 = HIGH
digitalWrite(in_1,LOW) ;
digitalWrite(in_2,HIGH) ;
delay(3000) ;

//For brake
digitalWrite(in_1,HIGH) ;
digitalWrite(in_2,HIGH) ;
delay(1000) ;

 }

But how can I integrate the pot AnalogRead into this code ?

As for my tests on the code at the start of the thread, in the line:

void loop() {
  // read the value from the sensor:
  long newPos = analogRead(POTPIN);  
  long newSPos = analogRead(CHANNELA);

when I declare the new position as CHANNELA , the motor jitters around. This seems logical as this is digital data on an analog channel.

The original sketch declares

#define SENSORPIN A3 // position sensor pin

void loop() {
// read the value from the sensor:
long newPos = analogRead(POTPIN);  
long newSPos = analogRead(SENSORPIN);

and I can't find a SENSORPIN on the Heden motor

At the bottom of the thread below are pictures of the Heden opened up:
http://www.reduser.net/forum/showthread.php?153329-Create-DIY-controller-for-Heden-motor

I can't see the pictures without logging in. Since they seem to be your pictures, you can attach them here. Look for the guide in one of these forums on how to get the pictures to show inline.

chlowden:
I suppose my question is simple. Is it possible to drive this kind of motor using a potentiometer? Is there any useful use for the Channel A & B information that is returned to the motor? Is the motor using an quadrature encoder?
None of the example sketches I have tested even come close to working, so I presume that I have something very wrong.
Many thanks to anyone who might be able to push me in the right direction

Potentiometers don't "drive". You may wish to use a pot as an input to your Arduino and thereby control the motor. You can choose lots of ways to do this. It may be position-based or the pot changes speed. At this point, I can't imagine the same thing that you're imagining.

"Quadrature" usually refers to the position encoder. Not the motor. Encoders have A and B outputs. Often they will behave as simple switches: closed for part of the rotation and open or floating for another part. Measuring analog values form this will have no meaning because floating has no analog. Use a digital input in INPUT_PULLUP mode.

You should use the Encoder.h library to read the position of the encoder. Then write a function to drive the motor towards the commanded position.

Thanks for the reply
Attached are pictures of the motor.

I don’t know what is the best way to drive the motor. The final result is simply to have the motor follow the position of the pot.

The motor Lemo socket pin configuration :

Pin 1: Motor- to DC Driver A
Pin 2: Motor+ to DC Driver B
Pin 3: Encoder channel A
Pin 4: +5V
Pin 5: earth/gnd
Pin 6: Encoder channel B
Pin 7: earth/gnd

that is a connected to the motor driver board.

Personally, I don’t really know what the use of the Channel A & B could be when all I want for the moment is for the motor to follow the pot.

Controlling the motor using just the PWM and DIR pins on the motor controller board may well be sufficient but I just can’t find an example sketch that I understand. I think that my main problem is that each sketch uses different vocabulary which does not correspond to my wiring schematic (attached) so I don’t really understand how to adpat them.

170228_LENSHOUND_SCHEMATIC.pdf (172 KB)

chlowden:
Personally, I don't really know what the use of the Channel A & B could be when all I want for the moment is for the motor to follow the pot.

You must make it clear to us what you mean by "follow". Does the pot control speed or position?! I expect you mean position but we must be absolutely clear on this before we can move forwards. Most camera lenses need more than a full turn and most pots only turn 270 degrees so there will be some multiplication factor required.

Either way, when you drive the motor with a known amount of input power, how fast or far does it move? Well, it depends on the friction of the lens it's attached to. You can't predict ahead of time, not to any level of accuracy. So you need to find out where the motor's output is before you can drive it towards where you want it to be. The encoder lets you know where it is.

Hello MorganS
Here is some background to the project.

Contrary photo lenses, professional film camera lenses are designed to have a short and even focus pull range (which is why they so much more expensive). The reason is that when filming, you have to pull focus all the time and it is difficult to turn your hand more than 180 degrees without letting go of the lens. Also, focus pulling is a delicate matter as in general is should be seen, so the lens is designed to offer subtlety in a single hand turn. In reality, the focus will be more around the 120 degrees, but it really depends on the lens.

To help do this, cameramen often use a, follow focus that is a knob attached to a cog on the side of the lens. But very often, this knob & cog is replaced but a wireless motor system that has a transmitter handset with a knob on it. Therefore, you turn the wireless transmitter knob, setting both extremes of the lens which in turn controls the motor that is attached to the lens.

I have a system that is based on an arduino and controls a stepper motor.

Here is a video showing the system that I am trying to hack :Lenzhound Cine-Standard Demo - YouTube

The reason that I am doing this project is that the system in the video above have a stepper motor that:

  1. does not have enough torque to control my cinema lenses. (the system was designed for DSLR camera that have very loose focus rings)
  2. you cannot use industry standard motors that have much more torque, are far quieter and lighter.

So, in short, part one of this project is to follow “exactly” what the pot is doing, backwards and forwards and at the speed that I turn.

The actual system uses a pot and not encoders, due to the stepper motor. With industry standard digital, quadrature encoder motors, I am looking for a way to take out the stepper motor control code and replace it with an equivalent quadrature motor control code.

I hope this makes it all some what clearer
Many thanks

Get the encoder library from here: Encoder Library, for Measuring Quadarature Encoded Position or Rotation Signals

Then try this code…

#include <Encoder.h>
const int gain = 20; //how quickly it wants to get to the target position
const int AnalogInputPin = A0;
const int MotorAPin = 5; //assuming an A/B H-bridge
const int MotorBPin = 6; //chose PWM pins
Encoder MyEnc(2,3); //chose at least one pin with interrupt ability (2 or 3 on UNO)

void driveMotor(int speed){
  //drive motor at desired speed
  //-255 is max reverse, +255 is max forwards
  if(speed==0) {
    digitalWrite(MotorAPin, 1);
    digitalWrite(MotorBPin, 1);
  } else if(speed>0) {
    digitalWrite(MotorAPin, 0);
    analogWrite(MotorBPin, speed);
  } else {
    analogWrite(MotorAPin, -speed);
    digitalWrite(MotorBPin, 0);
  }
}

void setup() {
  pinMode(MotorAPin, OUTPUT);
  pinMode(MotorBPin, OUTPUT);
  //drive motor all the way one way, then take this as the zero position
  driveMotor(-50); //drive backwards slowly
  delay(5000);    //maybe it takes 5 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.
  int desiredPosition = analogRead(AnalogInputPin);
  while(MyEnc.read() < desiredPosition) {
    driveMotor(50);
  }
  driveMotor(0);
}

void loop() {
  int desiredPosition = analogRead(AnalogInputPin);
  int actualPosition = MyEnc.read();
  driveMotor(gain * (actualPosition - desiredPosition));
}

chlowden:
So, in short, part one of this project is to follow “exactly” what the pot is doing, backwards and forwards and at the speed that I turn.

That is not a sufficient specification. The code I show above does what you ask but what you ask makes very little sense. A normal analog input on an Arduino gives vales from 0 to 1023. So 0-1023 represents 270 dgrees turn on a conventional pot. Your encoder on your motor might do 1023 counts per turn but more likely it does some other number of counts. Maybe even millions. So there must be a mathematical function that converts the pot position into a desired lens position. You will have to determine this yourself for the hardware you have.

MorganS
It looks like you have understood the logic that I m trying to find.
I have tried to use your sketch but as I am using the Cytron card that does not have 2 motor ports, I am struggling to integrate into my hardware.

Below is the pin attribution on the card as is.

#define PWMPIN A0 // Output pin to control PWM for motor controller
#define DIRPIN A1 // Output direction for motor controller
#define CHANNELA A2 // motor position sensor pin
#define CHANNELB A3 // motor position sensor pin
#define POTPIN A4 // select the input pin for the potentiometer

Attached below is a jpg of the card pin distribution on the card.

I presume that the interrupt are good.

I tried the code below:

const int AnalogInputPin = A4;
const int MotorAPin = A0; //assuming an A/B H-bridge
const int MotorBPin = A1; //chose PWM pins
Encoder MyEnc(A2,A3); //chose at least one pin with interrupt ability (2 or 3 on UNO)

Unsurprisingly it does not work.

Thank you so much for all your help.

OK, now we’re getting somewhere.

Let’s use your names for the pins. Now that you have clearly identified PWMPIN and DIRPIN then I know how to set up the motor driver code.

For the encoder, neither of those pins are capable of interrupts. It just means you have to call encoder.read() as fast as possible, which my code did anyway.

#include <Encoder.h>
#define GAIN 20    //how agressively it tries to get to the desired position
#define PWMPIN A0 // Output pin to control PWM for motor controller
#define DIRPIN A1 // Output direction for motor controller
#define CHANNELA A2 // motor position sensor pin
#define CHANNELB A3 // motor position sensor pin
#define POTPIN A4    // select the input pin for the potentiometer
Encoder MyEnc(CHANNELA, CHANNELB);

void driveMotor(int speed){
  //drive motor at desired speed
  //-255 is max reverse, +255 is max forwards
  if(speed>=0) {
    digitalWrite(DIRPIN, 0);
    analogWrite(PWMPIN, speed);
  } else {
    digitalWrite(DIRPIN, 1);
    analogWrite(PWMPIN, -speed);
  }
}

int desiredPosition() {
  //Put the mathematics to convert pot position to encoder position here
  //This can be called from anywhere in the code with consistent results
  return map(analogRead(POTPIN), 0, 1023, 0, 1023);
}

void setup() {
  pinMode(PWMPIN, OUTPUT);
  pinMode(DIRPIN, OUTPUT);
  pinMode(CHANNELA, INPUT_PULLUP);
  pinMode(CHANNELB, INPUT_PULLUP);
  //drive motor all the way one way, then take this as the zero position
  driveMotor(-50); //drive backwards slowly
  delay(5000);    //maybe it takes 5 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(50);
  }
  driveMotor(0);
}

void loop() {
  int actualPosition = MyEnc.read();
  driveMotor(GAIN * (actualPosition - desiredPosition()));
}

I uploaded the sketch as is and the motor went into an erratic, random jittering mode.

You write:

int desiredPosition() {
//Put the mathematics to convert pot position to encoder position here

I uploaded the Read_Quadrature_encoder sketch that gives me positive and negative values in the serial monitor when I turn the motor by hand. On bootup , the serial monitor is zero. When Turn the motor cog clockwise by approximately 270 degrees, I get a value of about -9066. When I restart the leonardo turn anti clockwise I get a value of about 9050.

Firstly, do you you know if these numeric values are usable?

If so, I have 18116 points that equal the 1023 potentiometer values

My very rudimentary maths gives me a ratio of 1:17.7

Is this the sort of function I should be looking for?

Thank you for all your help

So you need to change this line:

  return map(analogRead(POTPIN), 0, 1023, 0, 9066);

Thank you again. I did not realise it was so obvious.
Your sketch is perfectly clear to me ... but when I up load it, the motor jitters randomly about and when I turn the pot it struggles to move backwards and forward. The motor does not perform your setup commands at all.
I uploaded the ReadAnalogVoltage sketch to check if there is not a short circuit on the pot and it give me values between 0 and 0.2. The AnalogReadSerial sketch gives me 0 to 20. The stream of values is reasonably stable. I was expecting values between 0 and 5 volts . Do you think this could be the source of the jittering?
Also, I have read about debouncing ? Is debouncing pertinent for your sketch?

Hi,

I uploaded the ReadAnalogVoltage sketch to check if there is not a short circuit on the pot and it give me values between 0 and 0.2. The AnalogReadSerial sketch gives me 0 to 20. The stream of values is reasonably stable. I was expecting values between 0 and 5 volts

What is the voltage across the pot on your analog input?
What voltage do you get between the gnd end of the pot and the wiper as you turn it from one end to the other?

The analogRead should give you 0 to 1023 for 0 to 5V input.

Can you post a picture of your potentiometer?
Can you post a picture of your project?

Thanks. Tom.. :slight_smile:

Hello Tom

What is the voltage across the pot on your analog input?

As shown in the pictured attached,
The volt meter attached to GND & LIVE is 5.02 volts
The volt meter attached to GND and the VCC+ (GREEN) when turned off is 0volts
The volt meter attached to GND and the VCC+ (GREEN) when turned completely on dances around 0.18 volts.
I have attached a schematic of my wiring
There is a capacitor soldered between Live and the Vcc+ (green cable), type 105 blue Multilayer Ceramic Capacitor / MLCC Capacitor

I attach a link that has videos of the system with motor jittering about with and without the pot.
https://eshare.yr.com/fl/QHkvozHTOB

Even if the voltage values on the pot jitter between .18 & 21, I don’t think it would give a result as erratic as in the video.

Thank you for your interest

170228_LENSHOUND_SCHEMATIC.pdf (172 KB)

Hi,
You have you potentiometer wired incorrectly.
The centre terminal should go to the analog input.
The outer terminals to Gnd and +5V .
pot.jpg
The centre terminal is the one that moves/wipes from gnd to +5V potential.

VCC+ (GREEN)

Sorry wrong, look at your circuit diagram, Vcc is RED. GREEN wiper/analog input, BLACK is gnd.

Tom… :slight_smile: