BSch3V

2023年5月 1日 (月)

Arduino UNOで3相モーターを回す

ラジオペンチblog:DVDのスピンドルモーターを低速回転させる-続編
に倣って、ジャンク箱から発掘した小さな3相モーターを
回してみました。

ラジオペンチさんの記事を見て、
 「光学ドライブかHDDか何からだったかは忘れた
  けど、小さな3相モーターがあったはず」
っと、ジャンク箱を漁りました。
発見できたので、真似っこしてみました。

仕事では、RX220マイコンと L6234 という
3相モータードライブICを使って「回した」こと
があります。
RX220には3相駆動用のPWM出力が付いてい
ますが、Arduino UNOのATmega328Pは
別個のタイマーユニットを操作しなくてはなりません。

3つあるタイマー、そのうちタイマー0がdelay()などの
タイマー処理で使われています。
それを・・・Arduinoから「タイマー0」を取り上げる(ユーザーが使う)
の手法で「我がモノ」にします。

初期化(setup)から、もう、Arduinoの環境からは外れて
しまいます・・・
でも、ATmega328Pはちゃんと「言うことを聞いてくれます」
ので。

試した回路、はこんな様子。
M11_20230501175601
下の銀色のがモーター。
右のユニバーサル基板が駆動回路。
モーターとは3本の電線がつながります。
2ph1
タイマー0のOC0AとOC0B出力。
そしてタイマー2のOC2B出力で、3つのPWM出力を
制御します。
  ※N-ch、P-ch MOS FETの記号は
   簡略化して記述。
  ・パワーMOSFETの回路記号:MOSFETの矢印
  ※ゲートのプルダウン抵抗はゲートの浮き防止。
   浮くと貫通電流が流れるかも。
  ※3相モータの回路記号↓ (BSch3V用)
     bsch3v_lib_230502.zip
   6本線を3本線にしたのはSHAPES.LIBの中に。

オシロ波形、緑・青・赤の3つがこの3相制御出力。
M12_20230501175601

・スケッチ
  ・ダウンロード - 3ph_mot1a.txt

  ※.inoではなく.txtにしています。
  ※ちょいと虫を発見したんで
    mot1→mot1aに入れ換え

タイマー0とタイマー2は似たような8bitタイマー。
  ※タイマー1は16bit
それを「同期」させて3相の制御パルスを得ます。
二つを「8bit位相基準PWM」に初期化して、同期したPWM制御
ができるようにします。

スケッチをピックアップすると・・・

//  タイマー0,2  PWM出力 OC0A,OC0B,OC2B
TIMSK0 = 0b00000000; // 割込禁止
TIMSK2 = 0b00000000;
// ||+--- TOIE
// |+---- OCIEA
// +----- OCIEB
GTCCR = 0b10000011; // ★1
// | |+--- PSRSYNC タイマ0,1前置分周器リセット
// | +---- PSRACY タイマ2前置分周器リセット
// +---------- TSM 同期処理
TCNT0 = 0; // タイマーカウント値クリア
TCNT2 = 0;
OCR0A = 128; // U相 中央値
OCR0B = 128; // V相 (-1せず)
OCR2B = 128; // W相 (H=128:L=127)
TCCR0A = 0b10100001;
// |||| ++--- 8bit位相基準PWM
// ||++------- OCR0B 非反転PWM
// ++--------- OCR0A 非反転PWM
TCCR0B = 0b00000010;
// || |+++--- CS 1/8 2MHz →3.92kHz
// || +------ WGM02
// ++--------- FOC0
TCCR2A = 0b00100001;
// |||| ++--- 8bit位相基準PWM
// ||++------- OCR2B 非反転PWM
// ++--------- OCR2A Portで
TCCR2B = 0b00000010;
// || |+++--- CS 1/8 2MHz
// || +------ WGM22
// ++--------- FOC2
GTCCR = 0b00000000; // ★2
// +---------- TSM=0で計数開始
  :
★1でタイマー0とタイマー2の前置分周回路を停止。
★2で計数再開。

★1でクロックの供給が止まり、その間に二つのタイマーを
「8bit位相基準PWM」に初期化しています。
   ※タイマー1は16bitなので
    ちょっと、この二つとは
    違います。これをタイマー
    割り込みに使います。
PWMの周波数は、
  16MHz/8 = 2MHz
  1/255  1/2 → 3.92kHz
になります。

★2の計数再開でタイマー0とタイマー2の「頭」が
そろいます。

もう一つ、高速化のための手法。
三角関数データをROM内のテーブルに配置します。
「gawk」を使って配列を作り、それをPROGMEMで
ROMに配置します。
角度0~359度から「±127」の「8bitの数値=sin値」が
得られるようにしておきます。
  ※PWMの設定値が8bitなので
これで浮動小数点演算→三角関数の演算を使わなくて
良いようになります。

下表のように角度0~359度からテーブル読み出しで
8bitの「sin値」が出てきます。

/*****  SIN 0~359      *****/
// 振幅±127, 中央値は0
const int8_t sin_tbl[] PROGMEM ={
0, 2, 4, 6, 8, 11, 13, 15, 17, 19, // 0
22, 24, 26, 28, 30, 32, 35, 37, 39, 41, // 10
    :
  125, 125, 125, 126, 126, 126, 126, 126, 126, 126, // 80
127, 126, 126, 126, 126, 126, 126, 126, 125, 125, // 90
125, 124, 124, 123, 123, 122, 122, 121, 120, 120, // 100
    :
-22, -19, -17, -15, -13, -11, -8, -6, -4, -2, // 350
};

ツールは「gawk」。
  文字を処理するなら、コレ!。

駆動周期でPWM値を更新します。

    pwm_3ph[0] = degpwm(rot_deg,       ad_vr[0]); // U相
pwm_3ph[1] = degpwm(rot_deg + 120, ad_vr[0]); // V相
pwm_3ph[2] = degpwm(rot_deg + 240, ad_vr[0]); // W相
cli(); // 割り込み禁止で
OCR0A = pwm_3ph[0]; // U相 PWM duty設定
OCR0B = pwm_3ph[1]; // V相 (-1せず)
OCR2B = pwm_3ph[2]; // W相
sei(); // 割り込み有効に戻す
rot_deg++; // 0~359度
if(rot_deg >= 360) rot_deg = 0;

120度位相差の3つの信号からPWM設定値を得て、
それをタイマー0、2の「OCR」レジスタに書き込んで
sin波に合致したデューティ比のパルスを得ます。
ad_vr[0]は、「PWM振幅調整用」の8bitデータです。

正弦波データテーブルを読んでいる処理がこれ。

/****  角度からPWMデータに変換   *****/
// 角度 0~359 → 8bit PWMデータ(0~255)
// VR1値(8bit)でPWMの振幅を設定
// 中央値は128
byte degpwm(short deg, short vr1)
{
short a, g;
byte d;
while(deg < 0){ // マイナスならdeg+360
deg = deg + 360; // プラスに
}
// deg = deg % 360; // 0~359の範囲に(割り算やめて)
while(deg >= 360){ // 360を越えている場合はdeg-360
deg = deg - 360;
}
// SIN値に変換
a = (short)(int8_t)pgm_read_byte(&sin_tbl[deg]); // 0~359度→sin
g = (a * vr1) / 256; // VR1 : PWM振幅調整 ±127最大
d = (byte)(g + 128); // 8bitの中央値
return d;
}

g = (a * vr1) / 256; のところ
ぎりぎりで符号付16bit乗算が可能。
  aは±127でvr1は0~255。
aとgをlongにして乗算するとずいぶん遅くなります
んで、shortの範囲にしておきたかった。


今回の実験(お休み中の腕試し)はここまで。

※面白がって追試
3相PWM出力の処理時間が11~12usだったので、
「これなら100us割り込み内で処理できるぞ」
っと、タイマー割り込み内でPWM出力を制御する
ように書き直してみました。
お試し下さい。
  ・ダウンロード - 3ph_mot2.txt
    ※.inoではなく.txtにしています。

VR2を絞って最高速度にすると
360度の経過が1秒間に27~28回。
  1度の変化が0.1ms。
  0~359度で 36ms。
  1秒 ÷ 36ms = 27.78


| | コメント (5)

2023年4月 3日 (月)

ラズピコのピン:自由になりそうだけど定義で固定されている

Arduino IDEでのラズピコのI/Oピン、RP2040そのものの
ハードでは自由に割り振りできるようになっているんですが、
pins_arduino.h」でほぼ固定されています。

ラズピコユーザー、まずはこのファイルを確認しと
きましょう。 ざっと、こんな具合。

// LEDs  基板上のLED
#define PIN_LED   (25u)
#define LED_BUILTIN PIN_LED

// Analog pins アナログ入力
#define PIN_A0 (26u)
#define PIN_A1 (27u)
#define PIN_A2 (28u)
#define PIN_A3 (29u)

// Serial シリアル:定義はSerila1だけ
#define PIN_SERIAL_TX (0ul)
#define PIN_SERIAL_RX (1ul)

// SPI  SPIも固定
#define PIN_SPI_MISO (16u)
#define PIN_SPI_MOSI (19u)
#define PIN_SPI_SCK  (18u)
#define PIN_SPI_SS  (17u)

// Wire  I2Cも固定
#define PIN_WIRE_SDA (4u)
#define PIN_WIRE_SCL (5u)

汎用I/Oは、基本これ以外の場所を選んでという使い方に
なります。

残りの「Serial2SPI1I2C1」を使うには
どうすりゃいいの?
は、まだ調べ切れていません。

Serila2は「UART Serial2(4, 5, NC, NC);」で行けたけど。

※追記
ラズピコ基板の
  水魚堂さんの回路図エディタBSch3-V部品ライブラリ
ピン名称、ちょっと追記しました。
Rp1
左側がこれまでの。
真ん中が、Xサイズをちょい増やして、TX/RX、SPI、
I2C信号を追加。
空いているポートがわかりやすいかと。
右のは 秋月のAE-RP2040マイコンボード

ここからダウンロードしてください。
・BSch3V用パーツライブラり bsch3v_lib_230403.zip
この中の「SPECIAL.LB3」に入れてます。
ご自由にどうぞ。


※注記
これ、Arduino Mbed OS RP2040 Boads の環境での話。
Earle F. Philhower, III」版だとどうなるのか、
Arduino IDE、触ってみます。



| | コメント (2)

2022年12月28日 (水)

BSch3Vのパーツライブラリ:MOTOR_3COIL

ラジペンさんのブログ記事で使ってもらってます。
  ・ラジオペンチ:外側に回転子を持つ誘導モーターを動かす

202

BSch3Vのパーツライブラリまとめ

| | コメント (0)

2022年11月 9日 (水)

BSch3V CE3ファイルからコメント文字をピックアップ

常用している回路図CADが、
   水魚堂さんの回路図エディタ BSch3V
仕事、趣味、トランジスタ技術の原稿も、みんなこれ。
  ※指定のある場合を除いて

過日、トラ技編集部から
  「原稿の回路図から文字だけを抜き出したい」
という要望があり、gawkで試してみました。

# BSch3V CE3ファイルからコメント文字をピックアップ
# CE3ファイルはUTF-8N
# gawkとUTF-8Nの相性がもうひとつなので,いったんCE3ファイルをSJISに変換して保存
# +COMMENT,L:0,X:560,Y:100,D:1,DIR:0,W:-1,S:Pch%20MOSFET,FN:Tahoma,TAG:0,FS:12,FF:,-COMMENT
# +COMMENT,L:0,X:780,Y:430,D:1,DIR:0,W:-1,S:マイナス%0D%0A出力,FN:Tahoma,TAG:0,FS:13,FF:,-COMMENT
# 1 2 3 4 5 6 7 |---- 8 ------
# 「Pch MOSFET」「マイナス」「出力」をピックアップ
BEGIN{
FS = "," # 区切りをコンマに
}

#loop
{
if(($0 ~/^+COMMENT/) && ($0 ~/-COMMENT$/)){ # コメント行
if($8 ~/^S:/){ # S:先頭
gsub(/^S:/, "", $8) # S:消す
gsub("%20", " ", $8) # %20はスペース
gsub("%0D", "\r", $8) # 復帰
gsub("%0A", "\n", $8) # 改行
gsub("%2C", ",", $8) # ',' コンマ
print $8 # 出力
}
}
}

CE3ファイルの中から「+COMMENT」~「-COMMENT」の1行を
ピックアップして、コメント文字の本体部を拾い出します。

コメント中の改行はそのまま変換しましたが、編集用には
削除して1行にしてしまうほうが良いかもしれません。

UTF-8N → SJISの変換はテキストエディタの機能を使いました。
  探せばなにか良いツールがあるんでしょうけれど。
GAWKそのものでもなにか対処方法があるのかもしれません。

| | コメント (0)

2022年9月 4日 (日)

よく使うパラレル接続液晶(LCDモジュール)のコネクタ信号

文字表示の液晶、いろんな種類を置いているし、安価だし、という
ことで ついつい秋月電子通商 の通販で買っちゃいます。

その液晶、パラレル接続で使う昔からの製品は
2列x7ピン:14ピンのものが使われています。
それがブレッドボードでつなぐのに便利だからと
1列のピンのものが出てきました。

それをまとめてみました。

002_20220904095901

注意点は昔からある「SC1602」、「SC2004」の1・2番ピン
Vss、Vddの電源接続が入れ替わっています。
  ※痛い目に会ってます。1回だけ。
   何度も!という人はいますかな?
1pinがVdd」になっている16文字x2行のSC1602と
その互換ピン配置の表示器が「異端」なんでしょなぁ。
他のは1列コネクタのも含めて「1pinがVss」になっています。

1列タイプのはバックライトLEDの位置。
これもややこしい。


★BSch3V用パーツライブラリ
液晶のコネクタは、「OPT.LB3」の中。
最新のをアップしておきました。
http://act-ele.c.ooco.jp/jisaku/jisaku1.htm#BSCH3V_LIB
   bsch3v_lib_220904.zip (新)
 現用している部品ライブラリを圧縮しています。
 ご自由にお使いください。
※水魚堂さんのライブラリに追加しているパーツもあります。


※関連
■液晶表示モジュールを4ビットモードで使ったときの空きピン処理
※トランジスタ技術2005年9月号に掲載されました。
  ※「E」信号にプルダウン抵抗を入れておきたい理由も。 

| | コメント (0)

2022年4月18日 (月)

Arduino IDEでRaspberry Pi Pico:BSch3V部品ライブラリ

「Raspberry Pi Pico」のBSch3V部品ライブラリ をアップしておきます。
Rr1

ピン番号だけだと面白くないので、USBコネクタなど、
外形を模擬しています。

※21ピンの信号名を修正しました。 (2022-04-27)
P11_20220427104101
「ピコ」の場所は「SPECIAL.LB3」の一番最後。
  ・ダウンロード - special.zip   圧縮しています。

| | コメント (2)

2022年2月26日 (土)

現用中のBSch3V部品ライブラリのバックアップ

バックアップがわりにアップロードしときました。
  ※http://act-ele.c.ooco.jp/jisaku/jisaku1.htm#BSCH3V_LIB

前回が2020年3月でしたんで、2年ぶり。
Aa21_20220226160101

Aa22_20220226160501

水魚堂・岡田さんに大感謝!

| | コメント (3)