TB6643KQで30kHzのPWM

どうも高周波数のPWMで動かすにはパワーMOSFET系のトランジスタじゃないとダメらしい。
パワーMOSFET系のトランジスタはNchのを2種類(しかも1つはチップトランジスタ)しか持ってないので、フルブリッジは作れない。

「確か先日、モータドライバを2種類(TA8428K, TB6643KQ)買っておいたのがあったなぁ…」とデータシートを確認したら、TB6643KQがMOSFET系だったので、急遽差し替えて試してみたら無事に動いた。

回路図は次のようになっています。

回路図
回路図

スケッチは次のようになっています。

#define PIN_SW1   2 // Speed Up
#define PIN_SW2   3 // Speed Down
#define PIN_IN1   9 // Output Pin for IN1
#define PIN_IN2   10 // Output Pin for IN2
#define MAX_VALUE 256
#define LIMIT_VALUE (MAX_VALUE-1)
#define DELTA_SPEED (MAX_VALUE/8)

int prev_sw1 = HIGH;
int prev_sw2 = HIGH;

int value_speed = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("TB6643KQ PWM 30kHz");

  pinMode(PIN_SW1, INPUT);  // Speed Up
  pinMode(PIN_SW2, INPUT);  // Speed Down
  pinMode(PIN_IN1, OUTPUT);  // Output Pin for IN1
  pinMode(PIN_IN2, OUTPUT);  // Output Pin for IN2

  // PWM 30kHz
  TCCR1A = 0b00000001;
  TCCR1B = 0b00000001;
  
  analogWrite(PIN_IN1, value_speed);
  analogWrite(PIN_IN2, value_speed);
}

void loop() {
  // put your main code here, to run repeatedly:
  int curr_sw1, curr_sw2;
  curr_sw1 = digitalRead(PIN_SW1);
  curr_sw2 = digitalRead(PIN_SW2);
  if (curr_sw1 != prev_sw1) {
    if (curr_sw1 == LOW) {
      // これが押された判定
      Serial.println("sw1");
      if (value_speed == -LIMIT_VALUE) {
        value_speed = -MAX_VALUE;
      }
      value_speed += DELTA_SPEED;
      if (value_speed > LIMIT_VALUE) {
        value_speed = LIMIT_VALUE;
      }
      updateSpeed();
    }
    prev_sw1 = curr_sw1;
    delay(10);
  }
  if (curr_sw2 != prev_sw2) {
    if (curr_sw2 == LOW) {
      // これが押された判定
      Serial.println("sw2");
      if (value_speed == LIMIT_VALUE) {
        value_speed = MAX_VALUE;
      }
      value_speed -= DELTA_SPEED;
      if (value_speed < -LIMIT_VALUE) {
        value_speed = -LIMIT_VALUE;
      }
      updateSpeed();
    }
    prev_sw2 = curr_sw2;
    delay(10);
  }
}

void updateSpeed() {
  if (value_speed > 0) {
    Serial.print("(");
    Serial.print(value_speed);
    Serial.println(", 0)");
    analogWrite(PIN_IN2, 0);
    analogWrite(PIN_IN1, value_speed);
  } else if (value_speed < 0) {
    Serial.print("(0, ");
    Serial.print(value_speed);
    Serial.println(")");
    analogWrite(PIN_IN1, 0);
    analogWrite(PIN_IN2, -value_speed);
  } else {
    Serial.println("(0, 0)");
    analogWrite(PIN_IN1, 0);
    analogWrite(PIN_IN2, 0);
  }
}
カテゴリー: Arduino, ソフトウェア, 部品 | タグ: , | コメントする

TA7291Pで30kHzのPWMを試す

(3.8kHzも試したけどモータの鳴りが止まらなかった。)

しかしanalogWriteの値が240以上じゃないと回らない。しかも255に近いのでほぼ全開。

127とか途中の値だと全然動かないのでオシロで波形を確認すると波形が崩れていて電圧が上がらない。

どうもTA7291Pはバイポーラトランジスタで構成されていて、30kHzだと反応が遅くてダメらしい。

カテゴリー: Arduino, 部品 | タグ: , , , | コメントする

ArduinoのPWM周波数を変更する

ArduinoのanalogWriteでPWM出力できるのは、デジタルピンの~が付いた3, 5, 6, 9, 10, 11の6つ。3と11, 5と6, 9と10が同じタイマーを使うようになっている。
詳しくは、次のサイトをチェック。とても詳しくてわかりやすい。
analogWrite()

今回は9, 10を使う事にした。
次のようにTCCR1A, TCCR1Bを設定する事で、約30kHzに設定できた。

void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);

  TCCR1A = 0b00000001;
  TCCR1B = 0b00000001;

  analogWrite(9, 127);
  analogWrite(10, 127);
}

カテゴリー: Arduino, 部品 | タグ: , , , | コメントする

TA7291PのArduinoのPWMでの制御

モータをArduinoのPWMで制御しようとするとモータ(FA-130RA)が鳴る。
「モータが鳴る」というのはPWM制御の前調べしていてわかっていたけど、思っていたより音が大きくて、これは「使えない」と思った。

カテゴリー: Arduino, 部品 | タグ: , , , | コメントする

モータ用フルブリッジ・ドライバ TA7291P

昨年の暮れに発掘したTA7291Pを再度調べ直して、シンプルな動画にしました。

もう新規設計用には非推奨になっていますが、制御用とモータ用の電源が分かれていて、特に小さな電圧用のモータ(ここでは1.5V用のFA-130RAを使用)を動かすのに便利なフルブリッジ・ドライバのTA7291Pの紹介です。

制御用とモータ用の電源があって、制御用の入力IN1, IN2を”0″, “1”にするとモータ用の出力の状態が変わって、回転方向も制御できるフルブリッジ・ドライバです。 本来はマイコンなどで入力IN1, IN2を制御しますが、ここではIN1, IN2を直接スイッチで入力してモータの動きを確認しています。

※ 1.5V用のFA-130RAの電源に3Vをつないでいますが、TA7291P内部の2ヶ所のスイッチングでそれぞれ約1V、計2V下がるのでモータには1V程度しか供給されません。

データシートのファンクション部分
回路図

参考記事
https://www.marutsu.co.jp/contents/shop/marutsu/mame/81.html

カテゴリー: 部品 | タグ: , | コメントする

KiCadの起動がスムーズに

macOS 11 Big SurでArduino IDEがちゃんと起動しない件でJavaを更新したら、KiCadの起動がスムーズになった。それまでは起動にかなり時間がかかって、最初のうちはフリーズしたんじゃないかと強制終了してたくらいに時間がかかっていた。

カテゴリー: KiCad, ソフトウェア | タグ: , | コメントする

macOS 11 Big SurでArduino IDEがうまく起動しない

macOS 11 Big SurでArduino IDEが起動しない(3回に1回くらいは起動する)現象があって、さすがにググったらあった。

Javaを更新すればいいみたい。

ここを参考にJavaをインストール

https://adoptopenjdk.net/archive.html?variant=openjdk11&jvmVariant=hotspot

ここから選択されているOpenJDK11, Hotspotのインストーラーをダウンロードしてインストール。

コレでArduino IDEがちゃんと起動するようになった。
と、思ったけどダメ。「再度開く」で起動はする。

カテゴリー: Arduino, ソフトウェア | タグ: | コメントする

リードスイッチ

Amazonでリードスイッチという磁石に反応するスイッチを見つけたので、試しに買ってみた。

リードスイッチ
リードスイッチ

大きさ的にホールICの方が小さいし、反応範囲(最大で約5mm。3mmくらいだと確実。)的にもホールICと大差ないのであまり利用価値はないかと思う。後、真ん中より両端の方がより反応するので長さ方向に磁石が動く場合、2回反応する可能性がある。

カテゴリー: センサー, 部品 | タグ: | コメントする

コンデンサによってLEDが消えるのを遅延させる

以前の記事で車両の位置表示を作成したが、レイアウトを変更するたびにプログラムを書き換えないといけないので、センサーと表示器を1:1でモジュール化しようと考えた。

しかし、車両がホールIC上を通過する時に意外に短いので単純にホールICのVoutでLEDをON/OFFさせるとLEDの点灯時間が短すぎる。実際にプログラム内で0.2秒消灯を遅らせていた。それで、コンデンサでLEDが消えるのを遅延させるテストをする事にした。

回路図は次のようにした。

回路図
回路図

回路図を実際に回路を組んで試したら、16V 47μFでも充分長い感じ。

カテゴリー: 作ったモノ, 回路, 部品 | タグ: , , , , , , | コメントする

Nゲージ ホールICによる位置表示

ホールICは単純なので数を増やすのが簡単という事で、ホールIC6つにケーブルをつけてレイアウト上に配置して、車両の位置を表示してみた。

レイアウト上に6つのホールICを配置
レイアウト上に6つのホールICを配置

実際に動かした様子。

回路図はこちら。

回路図

スケッチはこちら。

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define LEN_124 28
#define HALF_124  (LEN_124/2)
#define LEN_117 24
#define HALF_117  (LEN_117/2)
#define SIZE_SENSOR 6
#define MARK_SENSOR 3

#define CENTER_X  (SCREEN_WIDTH/2)
#define CENTER_Y  (SCREEN_HEIGHT/2)

#define NUM_SENSORS 6

typedef struct {
  int x, y;
} Point;
Point pts[NUM_SENSORS] = {
  {CENTER_X-HALF_124, CENTER_Y+LEN_117},
  {CENTER_X+HALF_124, CENTER_Y+LEN_117},
  {CENTER_X+HALF_124+LEN_117, CENTER_Y},
  {CENTER_X+HALF_124, CENTER_Y-LEN_117},
  {CENTER_X-HALF_124, CENTER_Y-LEN_117},
  {CENTER_X-HALF_124-LEN_117, CENTER_Y}};

typedef struct {
  int pin;
  int prev;
  int state;
  unsigned long msec;
} Sensor;
Sensor sensors[NUM_SENSORS] = {
  {2, LOW, LOW, 0}, {3, LOW, LOW, 0}, {4, LOW, LOW, 0}, {5, LOW, LOW, 0}, {6, LOW, LOW, 0}, {7, LOW, LOW, 0}
};

int needUpdate = 0;

void drawRail() {
  // Rail line
  display.drawFastHLine(CENTER_X-HALF_124, CENTER_Y-LEN_117, LEN_124, SSD1306_WHITE);
  display.drawFastHLine(CENTER_X-HALF_124, CENTER_Y+LEN_117, LEN_124, SSD1306_WHITE);
  display.drawCircleHelper(CENTER_X-HALF_124, CENTER_Y, LEN_117, 1, SSD1306_WHITE);
  display.drawCircleHelper(CENTER_X-HALF_124, CENTER_Y, LEN_117, 8, SSD1306_WHITE);
  display.drawCircleHelper(CENTER_X+HALF_124, CENTER_Y, LEN_117, 2, SSD1306_WHITE);
  display.drawCircleHelper(CENTER_X+HALF_124, CENTER_Y, LEN_117, 4, SSD1306_WHITE);
  // sensor points
  display.fillCircle(CENTER_X-HALF_124, CENTER_Y-LEN_117, SIZE_SENSOR, SSD1306_BLACK);
  display.drawCircle(CENTER_X-HALF_124, CENTER_Y-LEN_117, SIZE_SENSOR, SSD1306_WHITE);
  display.fillCircle(CENTER_X+HALF_124, CENTER_Y-LEN_117, SIZE_SENSOR, SSD1306_BLACK);
  display.drawCircle(CENTER_X+HALF_124, CENTER_Y-LEN_117, SIZE_SENSOR, SSD1306_WHITE);
  display.fillCircle(CENTER_X+HALF_124+LEN_117, CENTER_Y, SIZE_SENSOR, SSD1306_BLACK);
  display.drawCircle(CENTER_X+HALF_124+LEN_117, CENTER_Y, SIZE_SENSOR, SSD1306_WHITE);
  display.fillCircle(CENTER_X+HALF_124, CENTER_Y+LEN_117, SIZE_SENSOR, SSD1306_BLACK);
  display.drawCircle(CENTER_X+HALF_124, CENTER_Y+LEN_117, SIZE_SENSOR, SSD1306_WHITE);
  display.fillCircle(CENTER_X-HALF_124, CENTER_Y+LEN_117, SIZE_SENSOR, SSD1306_BLACK);
  display.drawCircle(CENTER_X-HALF_124, CENTER_Y+LEN_117, SIZE_SENSOR, SSD1306_WHITE);
  display.fillCircle(CENTER_X-HALF_124-LEN_117, CENTER_Y, SIZE_SENSOR, SSD1306_BLACK);
  display.drawCircle(CENTER_X-HALF_124-LEN_117, CENTER_Y, SIZE_SENSOR, SSD1306_WHITE);
  // sensor marker
  /*
  display.fillCircle(CENTER_X-HALF_124, CENTER_Y-LEN_117, MARK_SENSOR, SSD1306_WHITE);  // 0->4
  display.fillCircle(CENTER_X+HALF_124, CENTER_Y-LEN_117, MARK_SENSOR, SSD1306_WHITE);  // 1->3
  display.fillCircle(CENTER_X+HALF_124+LEN_117, CENTER_Y, MARK_SENSOR, SSD1306_WHITE);  // 2->2
  display.fillCircle(CENTER_X+HALF_124, CENTER_Y+LEN_117, MARK_SENSOR, SSD1306_WHITE);  // 3->1
  display.fillCircle(CENTER_X-HALF_124, CENTER_Y+LEN_117, MARK_SENSOR, SSD1306_WHITE);  // 4->0
  display.fillCircle(CENTER_X-HALF_124-LEN_117, CENTER_Y, MARK_SENSOR, SSD1306_WHITE);  // 5->5
  */
  for (int i=0; i<NUM_SENSORS; i++) {
    if (sensors[i].state == HIGH) {
      display.fillCircle(pts[i].x, pts[i].y, MARK_SENSOR, SSD1306_WHITE);
    }
  }
}

void initSensors() {
  for (int i=0; i<NUM_SENSORS; i++) {
    pinMode(sensors[i].pin, INPUT);
  }
}

void updateSensors() {
  needUpdate = 0;
  unsigned long msec = millis();
  for (int i=0; i<NUM_SENSORS; i++) {
    sensors[i].prev = sensors[i].state;
    int curr = digitalRead(sensors[i].pin);
    if (curr == HIGH) {
      sensors[i].msec = msec;
    }
    unsigned long delta = msec - sensors[i].msec;
    if (delta < 200) {
      sensors[i].state = HIGH;
    } else {
      sensors[i].state = LOW;
    }
    if (sensors[i].prev != sensors[i].state) {
      needUpdate++;
    }
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("multi-hall-sensor-system");

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.display();
  delay(2000); // Pause for 2 seconds

  initSensors();
  // Clear the buffer
  //display.clearDisplay();
  //display.display();
  display.clearDisplay();
  drawRail();
  display.display();
}

void loop() {
  // put your main code here, to run repeatedly:
  updateSensors();

  if (needUpdate > 0) {
    display.clearDisplay();
    drawRail();
    display.display();
  }

  //delay(1);
}
カテゴリー: Arduino, Nゲージ, センサー, 作ったモノ | タグ: , , , , | コメントする