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

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

最終更新 2023/11/17 23:24 JST

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データシートにある式で制限電流を計算すると $$ I_{out} = 0.1 \times \frac{2.5}{0.22} \approx 1.1 \mathrm{A} $$ この程度ならモーター焼損しないだろうと。

実験回路

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

この状態で

  • IN1をH, IN2をLの信号を入力するとモーターが正転
  • IN1をL, IN2をHの信号を入力するとモーターが逆転
  • IN1をH, 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

  • VSS(7番ピン)をGND
  • VDD(8番ピン)を5V
  • TOOL0(2番ピン)を書き込み器
  • RESET#(3番ピン)を書き込み器
  • SCLA0(15番ピン)を液晶モジュールのSCL
  • SDAA0(16番ピン)を液晶モジュールのSDA
  • TO02(14番ピン)をTB67H450モータードライバーのIN2
  • TO01(13番ピン)をTB67H450モータードライバーのIN1
  • P00(9番ピン)をロータリーエンコーダのB相出力
  • P01(10番ピン)をロータリーエンコーダのA相出力

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

image06

プロジェクト設定

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

GitHubリポジトリ

https://github.com/ak1211/R5F10Y47_dcmotor

コード

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

/src/cg_src/r_cg_main.c

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 */
}
1
2
3
4
5
6
7
8
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

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

  • オンデューティ10% オンデューティ10%
  • オンデューティ25% オンデューティ25%
  • オンデューティ50% オンデューティ50%
  • オンデューティ75% オンデューティ75%
  • オンデューティ100% オンデューティ100%
  • オンデューティ-10% オンデューティ-10%
  • オンデューティ-25% オンデューティ-25%
  • オンデューティ-50% オンデューティ-50%
  • オンデューティ-75% オンデューティ-75%
  • オンデューティ-100% オンデューティ-100%

電流波形

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

image08

PWM出力によるブラシ付DCモーターの駆動:PWM駆動時の電流回生方法

  • CH1(黄色): IN1の信号(IN2はLow固定)
  • CH2(緑色): 回路図の抵抗RSの電圧 ≒ モーターと電源間の電流 オンデューティ10%時に回路図のRS抵抗に流れる電流波形

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

SlowDecay方式

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

image09

PWM出力によるブラシ付DCモーターの駆動:PWM駆動時の電流回生方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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;
	}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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

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

  • オンデューティ10% オンデューティ10%
  • オンデューティ25% オンデューティ25%
  • オンデューティ50% オンデューティ50%
  • オンデューティ75% オンデューティ75%
  • オンデューティ100% オンデューティ100%
  • オンデューティ-10% オンデューティ-10%
  • オンデューティ-25% オンデューティ-25%
  • オンデューティ-50% オンデューティ-50%
  • オンデューティ-75% オンデューティ-75%
  • オンデューティ-100% オンデューティ-100%

電流波形(Slow Decay)

  • CH1(黄色): IN2の信号(IN1はHigh固定)
  • CH2(緑色): 回路図の抵抗RSの電圧 ≒ モーターと電源間の電流 オンデューティ10%時に回路図のRS抵抗に流れる電流波形

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

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

comments powered by Disqus

This website uses cookies to improve your experience.
このサイトは「Googleアナリティクス」を使用しています。
Googleアナリティクスはデータの収集のためにCookieを使用しています。


Built with Hugo
テーマ StackJimmy によって設計されています。