RL78/G10ファミリR5F10Y47ASPとTB67H450ドライバを使ってDCモーターをPWMチョッパ制御してみた。

DC モーターを可変速度制御してみた。

使うもの

実験回路をブレッドボードに作る

前回までのソフトウェアを再利用するので、今回は実験回路を先に作る。

AE-TB67H450
> AE-TB67H450 回路図

TB67H450FNG は、PWM チョッパ方式の DC ブラシモータドライバです。

TB67H450

TB67H450

TB67H450

TB67H450 データシート

実験回路図

FA-130RA は電圧範囲 1.5V ~ 3V だけど TB67H450 のモーター電源電圧下限が 4.5V なので電源は単 3 ニッケル水素充電池 4 本直列にする。

モーターの定格電圧より供給電圧が高いけど、モータードライバーの電流制限を 1A 位にしておけば(モーターストールしていなければ)大丈夫だろうと。

schematic

おもに モータのブラシで発生するノイズ で制御回路の動作不調を引き起こすので、 それを抑えるためにモーターの端子間とケース間はセラミックコンデンサーで高周波を短絡させておく。

VREF には電源電圧の半分を与えるので、TB67H450 データシートにある式で制限電流を計算すると

Iout=0.1×2.50.221.1A I_{out} = 0.1 \times \frac{2.5}{0.22} \approx 1.1 \mathrm{A}

この程度ならモーター焼損しないだろうと。

実験回路

これは IN1,IN2 ともに H を入力してショートブレーキをかけている状態。

実験回路

この状態で

になることを確認しておく。

e2 studio で新規プロジェクトを作る。

新規 -> Renesas C/C++ Project -> Renesas RL78 から
Renesas CC-RL C/C++ Executable Project を選択して
ターゲット・デバイス: R5F10Y47 を選択して
Use 周辺コード作成にチェックを入れてプロジェクトを作る。

これはそのまま確定する。

e2studio01

クロックは基盤に 20MHz セラロックが載っているが、今回はオンチップオシレータ 20MHz を選択する。

e2studio02

周辺機能のシリアル・インターフェース IICA の転送モードはシングルマスタ

e2studio03

設定はそのままでいい

e2studio04

PWM のためにタイマーチャネル 0 を多重 PWM 出力(マスタ)、タイマーチャネル 1 を多重 PWM 出力(スレーブ)、タイマーチャネル 2 を多重 PWM 出力(スレーブ)にする。

e2studio05

チャネル 0 の周期は 1ms つまり PWM 周波数 1,000Hz

e2studio06

チャネル 1 とチャネル 2 のデューティは共に 0%

e2studio07

ロータリーエンコーダ読み取りとディレイのために 12 ビットインターバルタイマーを使用する。

e2studio08

ロータリーエンコーダを接続するポート P00, P01 を入力に設定して内蔵プルアップにチェックを入れる。

e2studio09

保存して「コードを生成する」をクリックする。

端子配置図を確認する。

e2studio10

に接続する。
(P00/P01 はマイコン内臓プルアップを SCL/SDA は液晶モジュールの変換基盤に載っているプルアップを利用した)

image06

プロジェクト設定

プロジェクト設定は 前前前回と同じ。

GitHub リポジトリ

https://github.com/ak1211/R5F10Y47_dcmotor

コード

詳細はGitHub リポジトリ で確認してください。

/src/cg_src/r_cg_main.c

r_cg_main.c コードの一部を貼っておきます。

PLAINTEXT
static void set_speed(int8_t speed) {
	if (speed < -100 || 100 < speed) {
		return;
	}
	// PWM出力の周期
	uint32_t pwm_period = (TDR00H << 8 | TDR00L) + 1;
	//
	uint16_t forward = 0;
	uint16_t backward = 0;
	if (speed < 0) {
		forward = 0;
		backward = pwm_period * (uint32_t) (-speed) / 100;
	} else if (speed > 0) {
		forward = pwm_period * (uint32_t) speed / 100;
		backward = 0;
	}
	TDR01H = (forward >> 8) & 0xFF;
	TDR01L = forward & 0xFF;
	TDR02H = (backward >> 8) & 0xFF;
	TDR02L = backward & 0xFF;
}
クリックして展開し、詳細を表示
PLAINTEXT
void main(void)
{
    R_MAIN_UserInit();
    /* Start user code. Do not edit comment generated here */
	// 100ms待つ
	delay(100);
	// LCDの初期化
	AQM1602A_init();
	// 1行目
	AQM1602A_puts("RL78 DC motor");
	//
	gROTATION_COUNTER = 0;
	while (1U) {
		// 2行目
		char message[17];
		strcpy(&message[0], "ON duty = ");
		to_string(&message[8], gROTATION_COUNTER);
		strncat(message, " % ", 5);
		//
		AQM1602A_send_command(0x80 | 0x40); // アドレス設定
		AQM1602A_puts(message);
		//
		set_speed(gROTATION_COUNTER);
		//
		delay(100);
	}
	/* End user code. Do not edit comment generated here */
}
クリックして展開し、詳細を表示
PLAINTEXT
static void R_MAIN_UserInit(void)
{
    /* Start user code. Do not edit comment generated here */
	R_IT_Start();
	R_TAU0_Channel0_Start();
	EI();
	/* End user code. Do not edit comment generated here */
}
クリックして展開し、詳細を表示

Renesas Flash Programmer で書き込む

rfp01

実行

IN1/IN2(TB67H450)の入力

チャネル CH1(黄色): IN1 / CH2(緑色): IN2

マイナスのデューティは逆転と読み替えてください。

電流波形

PWM の OFF 期間中モーター電流を電源に回生しているので、トルクがよわよわ。

ON 時に上昇したモーター電流が OFF 時に逆向きの電流になって電源に回生されている。

SlowDecay 方式

トルクが弱いので /src/cg_src/r_cg_main.c を SlowDecay になるように変更する。
OFF 時にモーター端子間に電流を流すことで、モーター電流をできるだけ維持するように制御する方式。
具体的には IN1/IN2 のロジックを反転する。

PLAINTEXT
static void set_speed_fast_decay(int8_t speed) {
	if (speed < -100 || 100 < speed) {
		return;
	}
	// PWM出力の周期
	uint32_t pwm_period = (TDR00H << 8 | TDR00L) + 1;
	if (speed > 0) {
		//
		// 正転
		// IN1: PWM(Active High)
		// IN2: Low
		//
		// タイマー出力論理(TO01/TO02共にアクティブハイ)
		TOL0 &= (uint8_t)~0x06;
		// TO01デューティ
		uint32_t timer = pwm_period * (uint32_t)speed / 100;
		TDR01H = (timer >> 8) & 0xFF;
		TDR01L = timer & 0xFF;
		// TO02デューティ
		TDR02H = TDR02L = 0;	// 出力Low固定
	} else if (speed < 0) {
		speed = -speed;
		//
		// 逆転
		// IN1: Low
		// IN2: PWM(Active High)
		//
		// タイマー出力論理(TO01/TO02共にアクティブハイ)
		TOL0 &= (uint8_t)~0x06;
		// TO01デューティ
		TDR01H = TDR01L = 0;	// 出力Low固定
		// TO02デューティ
		uint32_t timer = pwm_period * (uint32_t)speed / 100;
		TDR02H = (timer >> 8) & 0xFF;
		TDR02L = timer & 0xFF;
	} else {
		// タイマー出力論理(TO01/TO02共にアクティブハイ)
		TOL0 &= (uint8_t)~0x06;
		// TO01デューティ
		TDR01H = TDR01L = 0;
		// TO02デューティ
		TDR02H = TDR02L = 0;
	}
}

static void set_speed_slow_decay(int8_t speed) {
	if (speed < -100 || 100 < speed) {
		return;
	}
	// PWM出力の周期
	uint32_t pwm_period = (TDR00H << 8 | TDR00L) + 1;
	if (speed > 0) {
		//
		// 正転
		// IN1: High
		// IN2: PWM(Active Low)
		//
		// タイマー出力論理(TO01/TO02共にアクティブロー)
		TOL0 |= (uint8_t)0x06;
		// TO01デューティ
		TDR01H = TDR01L = 0; // 出力High固定
		// TO02デューティ
		uint32_t timer = pwm_period * (uint32_t)speed / 100;
		TDR02H = (timer >> 8) & 0xFF;
		TDR02L = timer & 0xFF;
	} else if (speed < 0) {
		speed = -speed;
		//
		// 逆転
		// IN1: PWM(Active Low)
		// IN2: High
		//
		// タイマー出力論理(TO01/TO02共にアクティブロー)
		TOL0 |= (uint8_t)0x06;
		// TO01デューティ
		uint32_t timer = pwm_period * (uint32_t)speed / 100;
		TDR01H = (timer >> 8) & 0xFF;
		TDR01L = timer & 0xFF;
		// TO02デューティ
		TDR02H = TDR02L = 0; // 出力High固定
	} else {
		// タイマー出力論理(TO01/TO02共にアクティブハイ)
		TOL0 &= (uint8_t)~0x06;
		// TO01デューティ
		TDR01H = TDR01L = 0;
		// TO02デューティ
		TDR02H = TDR02L = 0;
	}
}
クリックして展開し、詳細を表示
PLAINTEXT
void main(void)
{
    R_MAIN_UserInit();
    /* Start user code. Do not edit comment generated here */
	// 100ms待つ
	delay(100);
	// LCDの初期化
	AQM1602A_init();
	//
	gROTATION_COUNTER = 0;
	while (1U) {
		// 2行目
		char message[17];
		strcpy(&message[0], "ON duty = ");
		to_string(&message[8], gROTATION_COUNTER);
		strncat(message, " % ", 5);
		//
		AQM1602A_send_command(0x80 | 0x40); // アドレス設定
		AQM1602A_puts(message);
		// ポート2でfast decay / slow decay を切り替える
		if(P0_bit.no2) {
			set_speed_slow_decay(gROTATION_COUNTER);
			// 1行目
			AQM1602A_send_command(0x80); // アドレス設定
			AQM1602A_puts("RL78 DC motor(S)");
		} else {
			set_speed_fast_decay(gROTATION_COUNTER);
			// 1行目
			AQM1602A_send_command(0x80); // アドレス設定
			AQM1602A_puts("RL78 DC motor(F)");
		}
		//
		delay(100);
	}
	/* End user code. Do not edit comment generated here */
}
クリックして展開し、詳細を表示

実行

明らかにトルクが増えた。

IN1/IN2 の出力波形(Slow Decay)

チャネル CH1(黄色): IN1 / CH2(緑色): IN2

マイナスのデューティは逆転と読み替えてください。

電流波形(Slow Decay)

OFF 期間中に抵抗 RS を通じて電源に流れる電流は無い。

ON 期間中に増加したモーター電流を OFF 期間中にモータ端子間に回生する制御によって、常にモーター電流が流れ続ける状態を作り、そのことでトルクが増えるということ。

著作権表示

著者: Akihiro Yamamoto

リンク: https://ak1211.com/posts/7740/

ライセンス: CC BY-NC-SA 4.0

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Please attribute the source, use non-commercially, and maintain the same license.

コメント

検索を開始

キーワードを入力して記事を検索

↑↓
ESC
⌘K ショートカット