目次 [ Contents ]
I took a experiment using DC motor driver, because I thought it works as follow focus.
As a conclusion, it was a failure. But this way and the Sketch works very well for other purpose, I think.
TA7267BP
TA7267BP. I got this motor driver a year ago, because it was cheap.
Then I have been forgotten it for a while. But I found it few days ago and retry to use. And I found it works very smooth with “non-click rotary encoder” Sketch.
So I made their rigs roughly and checked whether it works or not.
The TR7267BP’s pin arrangement is as follows.
This IC seems to be out of date. It is hard to find on web shop in Japan.
But on this article, my Sketch is so simple that easy to find replacement IC perhaps.
Necessary parts
- Arduino
- Motor driver IC
- Rotary encoder(remodeled as Non-click type)
- DC motor
- A capacitor (for motor driver)
I used gearbox product which I can get easily in Japan. But, I don’t recommend this, because this product is unable for precise motor task.
Wiring
I heard this TA7267BP IC is not suitable for such small motor. But temporary, it works.
And on the photo, I use 5V battery as motor supply, which is inappropriate for this 3V motor. You should use proper voltage for your system.
Sketch
Download Arduino sketch file from down below. Or copy and paste from closed window.
Sample Sketch file – DC motor driver contorl
*This sample sketch needs “MsTimer2” library. You have to install it if you haven’t got it yet.
// DC motor driver control v1.1 // for Arudino Sketch 21.6.2017 // by jumbler (jumbleat.com) #include <MsTimer2.h> #define TIM MsTimer2 //defined values // pins #define ENCA 3 #define ENCB 4 #define MTRA 5 #define MTRB 6 #define LED 13 //values #define MOVE_VAL 10 #define REV_RAG 150 //encoder constants #define ENC_JUDGE 25 #define ECUR B00000011 // enc current position #define EPRE B00001100 // enc previous position #define EHOM B00110000 // enc home position #define ETRG B01000000 // enc has been triggered #define ECHG B10000000 // encoder count has been charged const byte enc_pins[2] = {ENCA, ENCB}; volatile byte enc_status; volatile short enc_count = 0; //motors byte motor_pins[2] {MTRA, MTRB}; short ENC_COUNT(int val) { static int enc_old; if (enc_old != enc_count) { val += enc_count - enc_old; enc_old = enc_count; enc_status = enc_status & ~ECHG; } return val; } byte SBIT(byte layer) { for (byte i = 0 ; i < 8; i++) if ((layer >> i)&B00000001) return i; } byte SBVAL(byte val, byte layer) { byte tmp = (val & layer) >> SBIT(layer); return tmp; } byte ENC_PIN_READ() { // Read encoder pins status byte enc_cur = (digitalRead(ENCB) << 1) + digitalRead(ENCA); // Modify position order if (enc_cur < 2) enc_cur = 1 + (enc_cur * -1); if (!SBVAL(enc_status, ETRG)) { if (SBVAL(enc_status, EHOM) != enc_cur) enc_status = enc_status | ETRG; } // apply update to enc_status enc_status = (enc_status & B11110000) + ((enc_status & ECUR) << 2) + enc_cur; return enc_cur; } void ENC_GAUGE() { static unsigned short gauge[2]; byte curr = ENC_PIN_READ(); // if encoder change has been triggerd if (SBVAL(enc_status, ETRG)) { byte prev, dist; dist = SBVAL(enc_status, EHOM); for (byte i = 0 ; i < (ENC_JUDGE * 1.5) ; i++) { curr = ENC_PIN_READ(); prev = SBVAL(enc_status, EPRE); // each gauge for "moved" or "not moved" bool bias = (curr != dist) ? 1 : 0; gauge [bias]++; int goal = gauge[1] - gauge[0]; if (abs(gauge[1] - gauge[0]) > ENC_JUDGE) { // encoder moved! if (goal > 0) { // increase or decrease bool dir = ((curr - dist) > 0) ? 1 : 0; if (curr == 0 && dist == 3) dir = 1; else if (curr == 3 && dist == 0) dir = 0; // add count by the direction if (dir) enc_count++; else enc_count--; // update home position enc_status = (enc_status & ~EHOM) + (curr << SBIT(EHOM)); enc_status = enc_status | ECHG; } for (byte i = 0 ; i < 2 ; i++) gauge[i] = 0; enc_status = enc_status & ~ETRG; break; } } } } void setup() { pinMode(LED, OUTPUT); Serial.begin(38400); for (byte i = 0 ; i < 2 ; i++) { pinMode(enc_pins[i], INPUT_PULLUP); pinMode(motor_pins[i], OUTPUT); digitalWrite(LED, 1 - i); delay(1000); } TIM::set(1, ENC_GAUGE); TIM::start(); enc_status = ENC_PIN_READ() << SBIT(EHOM); } void loop() { static int val; static unsigned long time_move; if (SBVAL(enc_status, ECHG)) // if encoder has changed { static int val_ref = val; static bool dir_ref = 0; digitalWrite(LED, HIGH); // get encoder's increase or decrease val = ENC_COUNT(val); // move Motor bool motor_dir = (val_ref > val) ? 1 : 0; digitalWrite(motor_pins[!motor_dir], LOW); digitalWrite(motor_pins[motor_dir], HIGH); // refresh time value if (millis() >= time_move) time_move = millis(); // if rotation has reversed if (motor_dir != dir_ref) { time_move = millis() + REV_RAG; // add times for reversed idling dir_ref = motor_dir; // update present direction } // set moving duration time_move += MOVE_VAL * abs(val - val_ref); // set present val to reference old val_ref = val; } else { if (millis() > time_move) // set move action off { digitalWrite(LED, LOW); for (byte i = 0 ; i < 2 ; i++) digitalWrite(motor_pins[i], LOW); } } }
You may feel this sketch rather long. But most of the part is for reading encoder. The main function is just “Read encoder” and “Add voltage for a while (10 ms) to encoder’s direction”.
About defined value
I mention several defined values.
#MOVE_VAL
This value is moving motor duration. This number is in milliseconds. Set it as you like.
#REV_RAG
There are some idling in gear when the rotation has been reversed on my gearbox. So this defined value add extra duration when reversing. Set 0, if you don’t want it.
The reason I failed
The motion is very good, but it lack of torque.
The lens which I wanted to use with is too tight to rotate on this system. This “SIGMA 30mm F1.4” lens is old, and hard to move focus ring.
But some on recent lens, it worked. So usefulness of this sketch will depend on your situation and what to move for.
Reference
panchiga’s blog – DCモーターを制御する