コイル(インダクター)

電流・磁界の法則

右ネジの法則

電流が流れると、その方向に対して右回りの磁界が発生する(Maxwell’s right-handed screw rule)。

右手の法則

コイルに電流を流すと、電流の向きが右手を握った各指の方向のとき親指の挿す方向に磁界が発生する。

フレミングの左手/右手の法則

絵は面倒なので割愛。人差し指が磁界、中指が電流、親指が力の方向。左手は磁界内の電流に働く力、右手は磁界内で運動する場合に発生する電流の方向。

ローレンツ力

電荷e[C]の荷電粒子が磁束密度B[T]内を運動ベクトルvで移動するとき、荷電粒子に対してフレミングの左手の法則に従って力が働く。

このとき、vが磁束に対してなす角をθとすると、荷電粒子に働く力は以下の様になる。

(1)    \begin{equation*} f = q v (\sin \theta) B \end{equation*}

ローレンツ力の方向まで含める場合、ベクトルの外積よって以下の様に表せる。

(2)    \begin{equation*} \boldsymbol{f} = q \boldsymbol{v} \times \boldsymbol{B} \end{equation*}

レンツの法則

コイルを通る磁束が変化するとき、その磁束の変化を妨げる方向に誘導電流が生じる。

たとえば以下の図では、コイルに対して磁石のN極側を近づけている。このときコイルに対して左から右へ向かう磁束が増加するので、それ打ち消す右から左の磁束を増やすように誘導電流が流れる。

この状態で磁石が離れていくときは右向きの磁束が減少するので、コイル内で同じ右向きの磁束を発生させるよう、上図と逆向きの電流が流れる。

一方、S極が近づくときは左向きの磁束が増えるので、これと逆の右向きの磁束が発生するよう、上図と逆向きの電流が流れる。

S極が離れる場合には、左向きの磁束が減少するので、これを補うように左向きの磁束を発生させる方向(上図と同じ方向)に電流が流れる。

ファラデーの法則

閉回路を貫く磁束Φが変化するとき、レンツの法則によりその変化を妨げる方向の電流が流れるが、この起電力を誘導起電力という。誘導起電力の大きさは以下のように表される。

(3)    \begin{equation*} | V | = \left| \frac{d \Phi}{dt} \right| \end{equation*}

起電力の正負の向きについて、「磁束の変化を妨げるように」というレンツの法則から、以下の様に表現される。

(4)    \begin{equation*} V = - \frac{d \Phi}{dt} \end{equation*}

またコイルの巻き数がNのときは、以下の様になる。

(5)    \begin{equation*} V = - N \frac{d \Phi}{dt} \end{equation*}

コイルの自己誘導

自己誘導とは

コイルにかかる電圧が変化した場合場合、電流の変化に応じて磁界が変化するが、レンツの法則によってそれを阻止しようとする方向の電流を流そうという起電力も生じる。このような現象をコイルの自己誘導と言い、自己誘導によって生じる元の電圧と逆の起電力を逆起電力という。

電源が立ち上がった場合

たとえば以下のような回路を考える。ここで電源電圧が0→Eに立ち上がった場合、コイルによる逆起電力、抵抗による電圧降下が生じる。電源の起電力は正極側を⊕としている。抵抗Rの電圧は電源に対して電圧降下となる電流の向きの矢印、コイルの方は電流の変化によるので両方向きの矢印としている。

電流をII(t)として、電圧のバランスを定式化すると、以下のようになる。

(6)    \begin{equation*} E - L \frac{dI}{dt} - RI = 0 \end{equation*}

この微分方程式を以下のように解いていく。

(7)    \begin{equation*} \frac{dI}{E - RI} = \frac{dt}{L} \end{equation*}

(8)    \begin{equation*} -\frac{1}{R} \ln (E - RI) = \frac{t}{L} + const \end{equation*}

(9)    \begin{equation*} I = \frac{E - k e^{- \frac{R}{L} t}}{R} \end{equation*}

ここでIt=0 = 0の条件によりkを決定する。

(10)    \begin{equation*} \frac{E - k}{R} = 0 \quad \Rightarrow \quad k = E \end{equation*}

よって、自己誘導を含めた電流変化は以下のように求められる。

(11)    \begin{equation*} I = \frac{E}{R} \left(1 - e^{- \frac{R}{L} t} \right) \end{equation*}

以下のグラフは、L = 100mH、R = 1kΩ、E = 5Vの場合にスイッチON以降の電流変化を計算したもの。自己誘導の影響がなくなり定常電圧になるのに500μsほどかかっている。

電圧が立ち下がった場合

初期電流It=0 = E/Rとして、t = 0でE = 0になったとして先の微分方程式を解いてみる。まず式(6)でE = 0と置く

(12)    \begin{equation*} - L \frac{dI}{dt} - RI = 0 \end{equation*}

これを解いて

(13)    \begin{equation*} I = k e^{- \frac{R}{L} t} \end{equation*}

初期条件を考慮して以下を得る。

(14)    \begin{equation*} I = \frac{E}{R} e^{- \frac{R}{L} t} \end{equation*}

この式形は式(11)と上下逆の形になっていて、以下のようなグラフになる。

サージ

サージの考え方?

コイルを含む回路を半導体素子で開閉した場合、スイッチOFFの際に高電圧のサージが発生するということを知った。ただし定性的な(あるいは感覚的な)原理は多くみられるが、そのメカニズムがどうも腹に落ちない。

「スイッチOFFにしても電流が流れようとするので誘導起電力が発生し・・・」という説明を見かけるが、もし理想的なスイッチで瞬間的にOFFとなるなら、誘導電流が流れる時間がゼロだから、回路としてはそのまま黙ってしまうのではないか(dI/dtが無限大になるのとどう関係するのか定かではないが)。

スイッチが完全にOFFになるまでに若干のスパークが発生することや、スイッチング阻止の抵抗が無限大ではないことを含めて説明している場合もあり、これは現実論として納得できる。

特にこちらのサイトはとても参考になったので、これを自分なりにトレースして、理解を試みた。

まず以下の図で、電源Eに接続していた状態からスイッチを抵抗S側に切り替えたとする。ただし以下の点に留意する。

  • 切り替え前は定常状態で、回路の電流はI = E/R
  • ここでのスイッチは理想的なスイッチとし、抵抗Sが現実のスイッチ切り替え時の抵抗に相当

ここで切り替えの瞬間をt = 0として微分方程式は以下のようになる。

(15)    \begin{equation*} - L \frac{dI}{dt} - RI - SI = 0 \end{equation*}

初期条件t = 0でI = E/Rとして解いて、以下を得る。

(16)    \begin{equation*} I = \frac{E}{R} e^{- \frac{R + S}{L}t} \end{equation*}

この電流に対してコイルは起電側となり、2つの抵抗で電圧降下となって、それらは以下のようになる。

(17)    \begin{equation*} \left\{ \begin{array}{l} V_R = RI = E e^{- \frac{R + S}{L}t} \\ V_S = SI = \dfrac{S}{R} E e^{- \frac{R + S}{L}t} \\ V_L = - L \dfrac{dI}{dt} = - \dfrac{R + S}{R} E e^{- \frac{R + S}{L}t} \end{array} \end{equation*}

この式によるなら、t=0でコイルによる起電力は(R + S)/Rとなり、このうちS/Rが抵抗Sの電圧降下となる。たとえばR=1kΩのときにSが10kΩでも元の電源電圧の10倍の電圧がSの両端にかかることになる。

この様子を先と同じ条件L = 100mH、R = 1kΩ、E = 5Vに加えてS = 10kΩとして描いたのが以下のグラフ。スイッチOFFのときにEの10倍の50Vが生じ、そこから急激に電圧が下がっている。また時定数(R + S)/Rも大きくなるので、減少の時間も1オーダー短くなっている。

このSが大きくなると、その倍率に応じて大きな電圧が生じ、低減時間は短くなる。すなわち、一瞬の間だけ高電圧が発生する。これがコイルによるサージと呼ばれるものではないか。

ただし元々接続されていたRの両端の電圧の最大値は変わらないので、サージの影響を受けるのはスイッチ素子ということになる。ここにトランジスターなどを使っていると、たとえばCE間に逆向きの高電圧がかかって破壊されてしまう。

保護回路

コイルサージから回路を保護するためにいろいろあるようだが、最も簡単なのは以下の様にダイオードを加えることらしい。

通常のスイッチONの状態ではダイオードが逆向きなのでコイルに電流が流れ、サージ電流はダイオードを通じて戻るので、RSには影響を与えない。

 

Raspberry Pi – ブザー

概要

Raspberry Pi用キットのアクティブ・ブザー、パッシブ・ブザーの実験。

アクティブ・ブザー

単純接続

アクティブ・ブザーは振動源を内蔵していて、電流が流すだけで音が出る。まず、単純に3.3Vの電源に繋いでみた。

抵抗なしで直接GNDに繋ぐと、「ピュー」という音が鳴る。抵抗値が10Ωで音はかなり小さくなり、100Ωにするとかすかに聞こえるくらいの音になった。

回路図

ブザーを電源に直接GPIOに繋いでもRasberry Piで制御できるが、キットの回路図はPNP型のトランジスターを介して接続していた。GPIOから流れる電流をより少なくするためと思われる。

この回路の場合、GPIOをHIGHにすると音はならず、LOWにするとC-E間にも電流が流れて音が出る。音量は直接3.3Vに繋いだ時と同じ。

コード

以下のコードでは単純にGPIOのHIGH/LOWを切り替えて、一定間隔でブザーを鳴らす。周期を短くすると「ピュピュピュピュ・・・」と連続して鳴動する。

パッシブ・ブザー

ソフトウェアによる音

パッシブブザーは入力の1パルスに対して1回だけクリック音が出る。アクティブ・ブザーと同じ回路図でブザーをパッシブブザーに取り換えて同じコードで実行すると”click, click, …”と単調な音が続く。

ここで入力をある周波数にすると、その周波数に対応した音程のビープ音になる。

以下のコードは440Hzの音を鳴らすもので、設定した周波数の周期で矩形パルスを発生させてAの音を出す。ソフトウェア制御なので、ときどき音が途切れたりする。

PWMによる音

上と同様のことを、ハードウェアのPWMで実装したのが下記のコード。

ハードウェアPWMのGPIO13にピンを変えて、周波数やデューティー・サイクルを指定してAの音を2秒間出している。

音階

PWMを使ってスケールを鳴らしてみた。

辞書定数で各音階に対応する周波数をセットして、ある周波数の1音を鳴らすクラスを定義。Cのスケールで音階を鳴らしている。

音楽

改めて音符・給付を並べて音楽を演奏するクラスを定義。ついでにテンポも指定できるようにした。

このクラスを使って、D-durの音階を鳴らしている。

 

トランジスター

バイポーラトランジスター

バイポーラ(bipolar)は「二極の」という意味で、バイポーラトランジスターはP型・N型の2つの半導体、電子(electron)と正孔(hole)の2つが対をなして機能する。

PNP型トランジスター

PNP型トランジスターの原理は以下の通りで、正孔を持つP型半導体でごく薄いN型の半導体を挟んでいる。

エミッター~コレクター間に正電圧をかけても、それぞれの正孔がベースの電子と結合して空乏層(deplation layer)が生じ、電流は流れない。

ここでエミッター~ベース間に正電圧をかけると、それぞれの間の成功と電子は結合するが、ベースが非常に薄いためエミッターの正孔が通り抜けてコレクターに達し、電流が流れる。

回路図の表現は以下の通りで、コレクター・ベースに対してにエミッターに正電圧をかける。

たとえばエミッター側に負荷素子を繋ぎ、エミッター電圧をかける。ベース側の電流のON/OFFによってE-C間の電流が流れ、IBに比べて大きなIEのスイッチングや増幅が可能になる。

 

S8550トランジスター

S8550はFairchild社のSS8550の中国製らしい。PNP型のトランジスターで、以下の特徴を持つ。

  • 低圧、大電流タイプのPNPトランジスター
  • To-92パッケージ
  • 連続最大コレクター電流:500mA
  • CE間電圧:VCEO = –25V
  • CB間電圧:VCBO = –40V
  • EB間電圧:VBEO = –5V
  • 電流増幅率:hFE = 85~300

ピン配置は以下の通り。

 

Raspberry Pi – I2C~LCD1602

概要

ここではI2C接続によるLCD1602の制御について整理する。

Raspberry Pi用のキットにはI2CがセットされたLCD1602が同梱されていたが、Pythonのモジュールが見つからなかった。ゼロから組み立てようかとCのコードを読んでみたが、いま一つわからない。そこでネット上をいろいろと探して、自分なりに理解してみた。

LCD1602

LCD1602のピン配置

LCD1602のピン配置は以下の様になっているらしい。上から順番に1~16。

各ピンの意味は以下の通り。

GND Ground
+5V Vcc(電源)
CNT L→H→LでDB0~DB7ピンと信号伝送
RS Register Select -> H: Data, L: Command
R/W H: Read, L: Write
E L→H→LでDB0~DB7ピンと信号伝送
DB0~DB7 8ビットデータ
A LEDのアノード
K LEDのカソード

表示領域~DDRAM

2行表示の場合のDDRAMアドレスの割り当ては以下の様になっている。

LCD1602のコマンド

LCD1602のコマンドは以下の通り。H→1、L→0で表している。

  • RS=0のときはコマンド、RS=1のときはデータを表す
  • R/W=1で読み出し、R/W=0で書き込みで、コマンドは常にR/W=0
  • コマンドの場合は8ビットのDB7~0で最初に1が現れたビットによってコマンドが変わる
  • 書き込み/読み出しは、EをL→H→Lと変化させて実行

8ビット/4ビットモードの設定

LCD1602起動時、確実に8ビット/4ビットモードをセットする手順は以下の通り。

起動直後の初期設定では、適切な待機時間を挟んで4ビットで0x3を3回書き込んだ後に0x2を書き込むことで4ビットモードに設定される。

I2CによるLCD1602の制御

接続

キットのLCD1602にはあらかじめI2C接続のためのボードが接続されていた。チップはHLF8574Tと書かれていたが、これは中国製らしくフィリップス製のPCF8574と同じ機能らしい。PCF8574はI2C I/Oエクスパンダ―というチップで、I2Cに準拠しSDAを介したシリアルの通信と、P0~P7の8ビットパラレルの通信を変換する。

PCF8574のP0~P7が8ビットのレジスターの各ビットに相当し、それらはLCD1602の各ピンと以下のように接続されている(他のピンは省略している)。

参考サイト:

PCF8574 LCD1602 LCD1602の機能
P7 DB7 4ビットデータのbit3
P6 DB6 4ビットデータのbit2
P5 DB5 4ビットデータのbit1
P4 DB4 4ビットデータのbit0
P3 K バックライトのカソード
P2 E L→H→LでDB0~DB7ピンと信号伝送
P1 R/W H: Read, L: Write
P0 RS Register Select -> H: Data, L: Command

DB0~DB3は接続されていないことから、このモジュールは常に4ビットモードで使用する必要がある。

P2に接続されたKピンはバックライトのカソードにあたり、トランジスターのC~Bを介してGNDに接続されている。

LCDとRaspiの接続

Rasberey PiのGPIO2と3(3番ピンと5番ピン)がSDAとSCLに対応しており、電源・GNDとともにこれらをLCDの端子(正確にはLCDに接続されたエキスパンダーの端子)に接続する。

SDAとSCLに対するプルアップ抵抗がないが、LCD/I2C内部でプルアップされているらしい。

初期手順

Raspberry Piの手順に従ってI2Cを有効化した後、デバイスアドレスを確認(I2Cを参照)。ここでは、LCD1602のデバイスアドレスは0x27。

コード

動作テスト

LCDモジュールを4ビットモードにセット後、画面をクリアしてカーソルをブリンクさせる。

冒頭で定数を定義している。TWはEを1にしてからLに戻すまでの待機時間で、データシートでは最小230nsという値もあったが、Pythonのtime.sleepの分解能もあり、1ms(以上)としている。

次に、4ビットのデータを書き込む関数を定義している。

  1. 引数のデータの下位4ビットを取り出し、4ビットシフトして上位4ビットへ
  2. 下位4ビットにコマンドセット
    • バックライトON、転送Enable、Writeモード、コマンドレジスターに書き込み指示
  3. 書き込みウェイト
  4. EnableをLowにして書き込み

もう1つの関数は、1バイトのコマンドをLCDに書き込む。4ビットモードなので上位・下位の4ビットに分けて書き込んでいる。

コマンド送信の場合の手順は、上位4ビットの場合は0xF0でマスク、下位4ビットの場合は0xFでマスクして4ビット分シフトした後、以下の通り。

  1. 下位4ビットはコマンド書き込みイネーブルで、KE(RW)(RS)=0b1100=0xC
  2. TWの間ウェイト
  3. その後Eのみ0とするため0b11111011=0xFBでマスクして書き込み

実行部分の先頭で、8ビットモードを確定してから4ビットモードを設定。

いろいろなサンプルコードで0x33→0x32とバイト単位で書き込む例が多いが、4ビットごとの待機時間を意識するならこの方がデータシートの説明とも合っている。

最後にコマンド送信。

まず001で始まるFunction setで0b00101000=0x28とする。

  • DL=0で4ビットモード
  • N=1で2行表示
  • F=0で5×8フォントを使用

次に00001で始まるDisplay ONで0b00001111=0x0Fとする。

  • D=1でディスプレイ表示
  • C=1でカーソル表示
  • B=1でブリンクさせる

最後に0b00000001=0x01でディスプレイをクリア。

文字表示

先のコードに変更・追加を加えて、LCDに文字を表示してみる。

まず、write_command関数をwrite_byte関数に変更し、引数is_commandTrue/Falseに応じてRSの0/1を切替え、コマンド・データの両方を取り扱えるようにした。

データ送信の場合イネーブル時にRS=0となるため、下位4ビットはKE(RW)(RS)=0b1101=0xDとなる

また、新たに文字を表示する関数write_charを定義した。アドレスが与えられた場合はDDRAMのそのアドレスに、アドレスを指定しない場合は現在のアドレスに文字を書き込む。1文字書き込むとアドレスはインクリメントされるため、続けて文字を書き込む場合にはアドレス指定はしなくてよい。

実行の前半では、カーソルOFF、ブリンクOFFとしている。

文字表示の部分は以下の通りで、1行目に”ABC”、2行目に半角カナで”アイウ”と表示している。

LCD1602クラス

LCD1602を扱うクラスを作成。これまで作った関数をクラスのメソッドにしただけ。インスタンス生成時にLCDのアドレスを与える。

 

I2C

概要

I2C(I squared C)はフィリップス社で開発されたシリアルバス。正式な呼称はInter-Integrated Circuitの略で表記はI2Cと上付きが本来とのこと。

マスターに対して1つ以上のスレーブを繋ぐことができて、接続はクロック線(SCL)とデータ線(SDA)の2本だけで済む。マスターからスレーブを指定して、Read/Write信号によりデータを書き込んだり読み込んだりすることができる。

原理(マスターからスレーブへの書き込み)

ビットデータの転送

データはクロック信号に同期してビット情報を転送。SCLの立ち上がり開始から立ち下がり開始までの間にデータを転送する。データを変更(H ⇔ L)する場合には、SCLがLの間にSDAを変更する。

スタートコンディション/ストップコンディション

データ転送のためSCLがHの間にSDAは変化させないが、この間にSDAが変化した場合は不正・無効ではなく、スタートコンディション/ストップコンディションの意味を持つ。

SDAがH→Lに変化した場合はスタートコンディションで、SCLがH→LになったあとLの間に最初のビットの準備をする。

SDAがL→Hに変化した場合はストップコンディションで、その前にSCLがLの間にSDAをLにしてストップコンディションの準備をする。

バイトデータの転送

データはバイト単位で転送される。

マスターからスレーブへの書き込みの場合、フォーマットは以下の様になる(スレーブアドレスが7ビットの場合)。

  1. マスターからスタートコンディション、スレーブアドレス7ビット、RW = 0を送信
  2. 指定されたアドレスのスレーブからACK送信→マスターで受信
  3. マスターから1バイトのデータを送信
  4. スレーブがデータ受信後、ACK送信→マスターで受信
  5. 以降、必要バイト数を送信
  6. 送信終了後、マスターからストップコンディション送信

マスターがスレーブのデータを読み込む場合には、フォーマットは以下の様になる。

  1. マスターからスタートコンディション、スレーブアドレス7ビット、RW = 1を送信
  2. 指定されたアドレスのスレーブからACK送信→マスターで受信
  3. スレーブから1バイトのデータを送信
  4. マスターが受信後、ACK送信→スレーブで受信
  5. 以降、必要バイト数を受信
  6. 受信終了後、マスターからストップコンディション送信

スレーブアドレス送信とRW

マスターからスレーブに対してスタートコンディションを送信し、各スレーブが受信体勢に入る。その後マスターからスレーブアドレスを送信する。

スレーブアドレスが7ビットの場合、MSBから順に7ビット送り、最後にRWを1ビットで送る。RW=1のときマスター側が読み取り、RW=0のときマスターからスレーブへ書き込み。

ACK

I2Cのデータは8ビット単位で転送され、その後にACK/NACKが返される。マスターからスレーブへの書き込みの場合ACKはスレーブからバスに発信され、マスターがスレーブから読み出す場合はマスターから発信される。

スレーブアドレス指定の際、選択されたスレーブはACK信号を1ビットのLで返す。選択されなかったスレーブはストップコンディションを待機。何らかの理由でスレーブ側がデータを受け取れなかったときはNAK信号を1ビットのHで返す。

マスターからスレーブへデータを書き込む場合、8ビット目の送信後にSCLをLにし、スレーブからACKを受け取ってから次のデータの送信を開始する。

マスターがスレーブからデータを読み込む場合、アドレスは上記と同じだが、データについてはマスターがデータ受信後にACKを送る。

ただしスレーブ側で次のクロックサイクルに合わせてデータを送るのに間に合わない場合、スレーブ側でSCLを強制的にLにして、マスターでのデータ読み込みを抑制する(クロックストレッチ)。スレーブの準備完了後にクロックストレッチは解除され、データの読み込みが再開される。

I2Cの有効化

Raspberry PiでI2Cを有効化する手順。

  1. コマンドラインでsudo raspi-configを実行
  2. 画面が変わるので、5 Interfacing Optionsを選択
  3. P5 I2Cを選択

I2Cツール

LinuxベースのRaspberry Piで利用可能なツール。

i2cdetect

sudo i2cdetect ...で実行。Raspberry Piで管理者権限を持っているなら、sudoなしでもok。

i2cdetect -V

バージョン確認。

i2cdetect -l

利用可能なバスの一覧を表示。

i2c-1'1'がバス番号になる。

i2cdetect -F [bus]

指定したバスで利用可能な機能の一覧を表示。

i2cdetect -y [bus]

指定したバスのデバイスアドレスを表示する。

各行の2桁目がアドレスの上位桁、各列がアドレスの下位桁を表していて、ここではデバイスアドレスが1つ(0x27)確認できる。

ライブラリー

Raspberry PiとPythonでI2Cを扱うためのライブラリーsmbus2について(ドキュメントはこちら)。

sudo pip install smbus2でインストール。SMBusはSystem Management Busの略でI2Cのプロトコルと概ね同じ。

smbus2モジュールのSMBusクラスでバスへアクセスするインスタンスを取得。コンストラクターの引数にはバス番号を指定。バス番号はsudo i2cdetectで確認されたバス番号。

以降、read_bytewrite_byteなど、このインスタンスのメソッドを使う。