Release 2017.6.20 / Update 2017.11.3

Use motor driver

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.

Sengoku Net

But on this article, my Sketch is so simple that easy to find replacement IC perhaps.

Necessary parts

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モーターを制御する

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA


This site uses Akismet to reduce spam. Learn how your comment data is processed.