So-net無料ブログ作成
検索選択

MC9S08JS8 でLEDマトリックスを駆動する ~ ソフトウェア編 (1) ~ [HCS08]このエントリーを含むはてなブックマーク#

2813417

ハードウェアは、ひとまず放っておいて、ソフトウェアの話を書きます。

LATCH*信号をトグルするプロトコル

ハードウェアを工夫する事によって、SPIモジュールが使えるようになったのですが、実際に 16×16 LED マトリックス基板を使うには、もう一工夫必要です。 理由は、この基板のプロトコルが純粋なSPIではないからです。

通常のSPIプロトコルは、通信の前に Slave Select (SS) 信号をアサートして、データの転送が終わったら SS 信号をネゲートして通信の終了を知らせます。 ところが、この 16×16 LED マトリックス基板では、通信の終了時に LATCH* 信号を一回だけトグルするプロトコルが使われています。 また、データ通信の単位は、接続する 16×16 LED マトリックス基板の枚数に依存していて、今回のように3枚の基板を使用した場合には144ビット (18バイト)の通信が必要です。

LedMatrixUsbTiming1.png

この図では、24ビット(3バイト)のデータを送信する場合のタイミングを示しています。 SPIを使用して1バイトのデータを3回送信してからLATCH*パルスを発生させています。

SPIは、送受信バッファを持っている

MC9S8JS8のSPIモジュールは、1バイトずつの送受信バッファを持っています。 また、送信バッファが空になったことを示す SPTEF (SPI Transmit Buffer Empty Flag) というフラグと受信バッファにデータが到着した事を示す SPRF (SPI Read Buffer Full Flag) というフラグがあり、ソフトウェアは、これらのフラグを調べて送信データを送信バッファに書き込み、受信データを受信バッファから読み込みます。

LedMatrixUsbSequence1.png

今回、LATCH*パルスを発生させるために採用したのは、SPRFフラグだけに着目する方式です。 SPRFフラグは、SPIの通信が終了したときにセットされます。 そのため、確実に通信が終了してからLATCH*パルスを発生させることができます。


LedMatrixUsbSequence2.png

この時、SPTEFフラグも併用して、送信バッファを有効に使うことができないかと考えたのですが、うまくいかない事がわかってきました。 理由は、SPRFフラグを確実に検出しないと、SPRFフラグ検出の間に二つ以上のSPI通信が入ってしまう可能性があるからです。 この例では、メインループの動作が間に合わなかった場合を図示しています。 一番目のSPRFフラグの処理に手間取ったため、二番目のSPRFフラグ(赤い枠を付けたもの)がクリアされてしまいます。 そのため、メインループは、二番目のSPRFフラグの発生を検知することができません。 このような状況が発生してしまうと、SPI通信の終了が正しく検出できなくなり、LATCH*パルスを発生させる直前でプログラムの実行が止まってしまいます。

SPRFフラグとSPTEFフラグを併用する方法は、もちろんあります。 それは、割り込みを使用する方法です。 フラグの発生と同時に処理を開始すれば、フラグの取りこぼしはほぼなくなると思います。 ところが、このアプリケーションでは、USBインターフェースで優先的に割り込み処理を行うために、他のモジュールが発生する割り込みはなるべく使いたくありません。 このような事情から、SPRFフラグだけをメインループで監視する方法を取り入れました。

ノンプリエンプティブなステートマシン

SPIにデータを送り込む処理は、ステートマシンで記述できます。 また、ステートマシンの動作は、割り込みを使わずにメインループに取り込みます。 そこで、ステートマシンの処理単位を細切れにして、自発的にプログラム実行件を返納する「ノンプリエンプティブ」なステートマシンとして実装しました。

LedMatrixUsbState1.png

この状態遷移図が、データ送信を行うためのステートマシンです。 まず、SPIの送信バッファが空いていることを確認します。。 そして、SPRFフラグを監視しながら、16ビットのデータを9回送信し、LATCH*をトグルします。 これで、1フレーム分の処理が終わりです。 最後に次のフレームに備えて、RTCフラグを待ちます。 この処理を延々と繰り返すのが、ステートマシンの仕事です。

ステートマシンの状態コードは、このように割り当てました。

状態状態コードお仕事
Generate ROW data0LEDマトリックスに送る行指定データ"row"を作成します。
Confirm TX buffer empty1送信バッファが開いている事をあらかじめ確認します。
Send column 525桁目のデータを送信します。
Wait for column 5 transfer ends3通信の終了を待ちます。
Send column 444桁目のデータを送信します。
Wait for column 4 transfer ends5通信の終了を待ちます。
Send row for column 4 and 564、5桁目の行指定データを送信します。
Wait for row transfer for column 4, 5 ends7通信の終了を待ちます。
Send column 383桁目のデータを送信します。
Wait for column 3 transfer ends9通信の終了を待ちます。
Send column 2102桁目のデータを送信します。
Wait for column 2 transfer ends11通信の終了を待ちます。
Send row for column 2 and 3122、3桁目の行指定データを送信します。
Wait for row transfer for column 2, 3 ends13通信の終了を待ちます。
Send column 1141桁目のデータを送信します。
Wait for column 1 transfer ends15通信の終了を待ちます。
Send column 0162桁目のデータを送信します。
Wait for column 1 transfer ends17通信の終了を待ちます。
Send row for column 0 and 1180、1桁目の行指定データを送信します。
Wait for row transfer for column 0, 1 ends19通信の終了を待ちます。
Assert LATCH20LATCH*出力をアサートします。
Negate LATCH21LATCH*出力をネゲートします。
Assert STROBE22STROBE出力をアサートします。
Go to next line23行カウンタを進めます。
Prepare for 1msec timer24RTCフラグをクリアします。
Wait for 1msec timer25RTCフラグを監視し、フレームの開始タイミングを待ちます。
Return to state 0>25最初の状態#0に戻ります。

たとえば、それぞれの状態での処理は、こんな風になります。

    case 3:
      // Wait for a transfer ends
      if (SPIS_SPRF) {
        vwDummy = SPID16;
        st++;
      }
      break;

SPRFフラグが検出されたら、フラグをクリアし、次の状態に遷移します。 検出されなければ、今の状態に留まります。

    case 4:
      // Send column 4
      SPID16 = buf[line][4];
      st++;
      break;

次の16ビット・データの送信を指示し、次の状態に遷移します。

次回予告

次回は、最初のテスト・プログラムのご紹介と実行の様子をごらんに入れます。


MC9S08JS8 でLEDマトリックスを駆動する ~ ハードウェア編 (2) ~ [HCS08]このエントリーを含むはてなブックマーク#

2813417

秋月電子通商で購入した 16×16 LED マトリックス基板を MC9S08JS8 につなぎました。 第二回目は、完全シリアル化のおはなしです。

データ線3本は、使いにくい

今回使用した、 16×16 LED マトリックス基板は、複数の基板をデイジーチェインに接続して使用することが出来るとされています。 制御すべき主な信号は、3本のデータ線と1本のクロック線です。 ところが、このままでは都合の悪い事があります。 それは、マイコンのハードウェアとして内蔵されているSPIモジュールが使えないということです。

Serial Peripheral Interface (SPI) という規格は、4線式シリアルとも呼ばれるように、4本の信号線で双方向の通信を行います。 その中の二本がデータ出力とクロック出力です。 つまり、SPIモジュールからはデータ線が一本しか出てこないのです。 そのため、もし、 16×16 LED マトリックス基板をそのまま使おうとしたら、SPIを使うのではなく、ソフトウェアで汎用入出力ポートからシリアルデータを送出するプログラムを書かなくてはなりません。 ここで作成しようとしているアプリケーションは、 MC9S08JS8 を使うので、当然、USBによる通信を考えています。 できたら、ソフトウェア処理は減らしたいので、何とかしてSPIを使いたいところです。

SerializedInterface.png

そこで、このアプリケーションでは、データ線の構成を組み替えることにより、データ線を一本に統一しました。 つまり、真にシリアル化されたインターフェースになったというわけです。 SPCK端子の出力がクロックとして使われ、MOSI端子の出力がデータ線として使われます。

もちろん、デメリットが無いわけではありません。 キットで想定されている接続では、 16×3=48 クロックで全てのデータを送出することができました。 ところが、完全シリアル化した場合には、 16×3×3=144 クロックの時間が必要になります。 ただ、完全シリアル化した場合には、SPIというハードウェアの力を借りることができますので、実際の処理時間が3倍になる訳ではありません。

クロックの取り回しも変更した

キットで想定されている接続と異なっているのは、データ線だけではありません。 クロック線もなぜか逆順に接続されています。


ForwardClockTiming.png

これは、キットで想定している接続を行った場合の簡略図とタイミング図です。 クロック信号は、各 16×16 LED マトリックス基板でバッファリングされながら、隣の基板に伝達されます。 タイミング図では、このバッファリングによる伝播遅延が大きかった場合を示しています。

クロック信号"CK2"が遅延した場合、"CK1"クロックによって"Q1"信号が変更されてから"CK2"クロックが到着します。 すると、本来、"Q2"は"Q1"の前の値である"D1"となるべきだったのに、"D0"となってしまいます。 データ入力"D0"が突き抜けて出力に出てしまったというわけです。 この現象を「レーシング」と呼んでいます。

レーシングの原因は、専門的にはホールド時間の不足です。 ホールド時間を増加するためには、データ線に遅延を加えるとうまくいきます。 しかし、遅延を加えるには素子の追加が必要です。 しかも、適切な遅延を加える必要がありますが、どのくらいが適切なのでしょうか。 適切な遅延時間は、基板の環境にもよるので、一概には決められません。


BackwardClockTiming.png

そこで、このアプリケーションでは、別の解決策をとりました。 それが、クロックをデータとは反対方向に走らせるという方法です。

このようなクロック線の取り回しを行うと、シフトレジスタのホールド時間が極端に短くならない限り、原理的にはレーシングが起きなくなります。 しかも、クロック・バッファでの遅延が大きいほど、ホールド時間に余裕が出来ます。

デメリットは、全体の配線長が長くなってしまうことと、ホールド時間が改善した分セットアップ時間の余裕が減少してしまうことです。 セットアップ時間の心配については、 16×16 LED マトリックス基板の最大クロック周波数がSPIとしては遅い500kHzとされていることから、問題にはなりません。

このキットの場合、直接接続された基板同士でホールド時間制約を満たせばよいので、キットの想定どおりの接続にしても、それほど心配は無いのだろうとは思います。 ただ、変なところでつまずきたくは無いので、ちょっとばかり気を使ってみました。

SPIではレーシングは起きないのか

SPIでも、複数のデバイスをデイジーチェーンに接続して使用する方法が使われる場合があります。 そのような場合にも、レーシングの心配は無いのでしょうか。 結論から言うと、SPIという規格を守っているデバイスを接続する限り、問題は起こりません。 理由は、SPIという規格が「クロックの二つのエッジを使って送受信を行うシステムだから」です。


ShiftRegisterTiming.png

例えば、クロックの立ち上がりエッジで動作するシフトレジスタの場合、シフトレジスタがシリアルデータを受信するタイミングは、クロックの立ち上がりです。 また、シフトレジスタの出力が変化するタイミングもクロックの立ち上がりです。 そのため、このようなシフトレジスタを複数デイジーチェーン接続すると、シフトレジスタが動作するタイミングのバラツキによって、変化した直後のデータを受信してしまい、「レーシング」を引き起こす配があります。


SpiDeviceTiming.png

SPIでは、ちょっと事情が違います。 例えば、クロックの立ち上がりで出力が変化するデバイスの場合には、クロックの立ち下がりエッジでデータを受信します。 そのため、ホールド時間に半クロック周期分の余裕が生じ、安全に通信を行うことが出来ます。 もちろん、セットアップ時間も半クロック周期になってしまうので、高速動作させる場合には不利になります。

では、シフトレジスタでもSPIのようにデータ受信と出力変化のタイミングをずらす方法はないでしょうか。 実は、あります。 図のようにシフトレジスタ(青いブロック)の入力にハーフラッチ(緑のブロック)を追加して、シフトレジスタが受け取るデータを半クロック分遅延させてやるのです。 「ハーフラッチ」は、「Dラッチ」とも呼ばれ、具体的には、74HC75または74HC375などの製品があります。 「ハーフラッチ」が手に入らない場合には、「D型フリップフロップ」に逆相のクロックを与えて使っても、同じ効果が得られます。 これで、より安全なシリアル通信を行うことが出来ます。

次回予告

ハードウェアに関して、言い残したことは…


MC9S08JS8 でLEDマトリックスを駆動する ~ ハードウェア編 (1) ~ [HCS08]このエントリーを含むはてなブックマーク#

2813417

秋月電子通商で購入した 16×16 LED マトリックス基板を MC9S08JS8 につなぎました。 つい最近まで、別の 32-bit プロセッサがつながっていたんですけどね。

回路図

ハードウェアは、コントローラ基板一枚と 16×16 LED マトリックス基板とそのベースボード三組で構成されています。 もちろん、USBから電源を供給するわけにはいかないので、外部からACアダプタで供給します。


LedMatrixUsbMcu-sch.png

コントローラ基板には、 MC9S08JS8 が搭載されています。 基本的な構成は、MC9S08JS8 デモボードの回路図で 紹介したデモボードとそっくりです。 16×16 LED マトリックス基板を制御するための信号線が4本出力されています。


LedMatrixUsbBase-sch.png

ベースボード基板は、コントローラから来る信号を三つのベースボードに送るための配線が引かれています。 16×16 LED マトリックス基板のメーカは、こんな複雑なベースボードなど要らないと思ったことでしょうが、今回は、ある事情からベースボードで配線を引き回す構成としました。

BLMS端子にLEDをつなぎたい

コントローラ基板には、LEDが一つだけ装備されています。 接続先は、BLMS端子で、なにやら妙な抵抗ネットワークが構成されています。


LedMatrixUsbBlms1.png

BLMS端子は、 MC9S08JS8 に内蔵されているブートローダを起動するための端子です。 パワーオン・リセット時、BLMS端子はモード設定入力として使われます。 そして、LOW入力であればブートローダ・プログラムが起動し、HIGH入力であれば、BLMS端子は出力専用端子として再設定され、ユーザ・プログラムが実行されます。


ここで必要になるのは、

  1. LEDが接続されたままでも、ジャンパによってモード切り替えができる。
  2. 出力の値にしたがってLEDに十分な電流を流すことができる。
  3. ジャンパが接続された状態でBLMS端子が出力になっても安全である。

という条件を満たす回路です。 その解決案のひとつがこの抵抗ネットワークです。


LedMatrixUsbBlms2.png

まず、BLMS端子がモード設定入力として使用されるときを考えます。 ジャンパが接続されていなければ、BLMS端子をLOWレベルに落とす要因は一切ありません。 このため、BLMS端子はマイコン内部のプルアップ素子で確実にHIGHレベルになります。

一方、ジャンパが接続されると、LEDと二本の抵抗には電流が流れます。 LEDの電圧降下を1.6V、電源電圧を5.0Vと仮定すると、流れる電流は4.9mAです。 よって、BLMS端子の電圧は、1.1Vとなり、VIL (0.35×VDD=1.75V) を十分に下回ります。 ちなみに、マイコンに内蔵されている最小20kΩのプルアップ素子は無視しています。


LedMatrixUsbBlms3.png

次は、BLMS端子がLOWを出力をした場合を考えます。 データシートによると、 MC9S08JS8 がLOWを出力した時のインピーダンスは11Ωとなっています。 ジャンパが接続されていないときに流れる電流は、電源電圧を5.5V、LEDの電圧降下を1.6Vと仮定すると4.1mA、電源電圧を4.5V、LEDの電圧降下を2.1Vと仮定すると2.5mA、となります。 これだけの電流が流れていれば、LEDは点灯するでしょう。

また、ジャンパが接続されている時には、ジャンパに流れる電流が増加するため、LEDに流れる電流が増加し、マイコンに流れ込む電流は減少します。


LedMatrixUsbBlms4.png

最後に、BLMS端子がHIGHを出力をした場合を考えます。 このときに問題になるのは、ジャンパが接続されているときにマイコンから流れ出す電流です。 データシートによると、 MC9S08JS8 がHIGHを出力した時のインピーダンスは40Ωとなっています。 電源電圧を5.5V、LEDの電圧降下を2.1Vと仮定するとマイコンから流れ出す電流は6.6mAとなります。 これなら、マイコンが壊れる心配はないでしょう。

次回予告

次回は、 16×16 LED マトリックス基板にシリアルデータを送り込む方法について書きます。


MC9S08SE4CRL - また、サンプルチップだ。 [HCS08]このエントリーを含むはてなブックマーク#

2830971

ニュースリリースが出ると、サンプル請求したくなる今日このごろ、またまたサンプルチップの登場です。

特徴が無いのが特徴デス

本日、ご紹介するのは、MC9S08SE8CRLという、これといって特徴の無いちっぷです。 ご覧のように、いまや化石でしか見られないような28ピンのDIPパッケージに収められたチップには、たった4KiバイトフラッシュROMと256バイトのRAMが内蔵されています。 ペリフェラルは、SCIは内蔵されていますがSPIは入っていないもようです。 実に清々しい・ さて、これで何をつくろうかな?

飲酒投稿につき、オ見苦しい点がありましたことをお詫びいたします。 失礼いたしました。


MC9S08JS8 デモボードの回路図 [HCS08]このエントリーを含むはてなブックマーク#

2729707

遅ればせながら、回路図を描きました。

usbdemo-sch.png
  • おなじみ、6ピンのBDMコネクタが装備されています。 "RESET*" 端子のCRフィルタは省略しています。
  • "BLMS*"端子は、ジャンパピンでプルダウンできるようになっています。 この端子は、パワーオン・リセットの時に限りプルアップ付き入力になりモード設定に使われます。 また、通常は出力専用ポートとして使われます。 そのため、本来は抵抗を使ってプルダウンすべきなのですが、今のところ省略しています。
  • 発振子として、 12MHz のセラロックをつけました。 帰還抵抗には 1MΩ の抵抗を使っています。
  • "PTA0"端子にLEDを付けました。 ポート出力は、LOW出力の方が電流を流せるらしいので、極性を逆にすべきでした。
  • USBコネクタは、MINI-Bタイプを使用しています。 抵抗は、 1% 精度の 33Ω 抵抗を使用しています。 バス・パワーは、使用していません。

さて、どう料理しようかな?

参考文献


MC9S08JS8 をUSBにつないだ [HCS08]このエントリーを含むはてなブックマーク#

2729707

MC9S08JS8には、4KiB の "Bootloader ROM" が搭載されていて、モードによってブートローダが起動する仕掛けになっています。 ブートローダを動かすぐらいなら、何とかなるだろう。

部品の追加

まずは、ハードウェアを整えます。

  • 前回の記事でも書いたように、12MHzのセラロックを取り付けています。
  • 変換基板に搭載したUSBコネクタを33Ωの抵抗を解して接続しました。
  • 7番ピンの/BLMS端子に2Pヘッダを取り付けて、ジャンパでプルダウンできるようにしました。

電源は、バスパワーではなく、従来どおりのNi-MH電池です。

Windows XP SP3 で試す

MC9S08JS8 を USB デバイスとして認識させるには、デバイスドライバが必要です。 DEMO9S08JS16 評価ボードの製品ページDownload タブの中に Bootloader_GUI.zip という名前の ZIP ファイルが並んでいます。 デバイスドライバと GUI アプリケーションは、 この ZIP ファイルに含まれています。

WS000356.png

インストーラを起動すると、途中でこんなダイアログが表示されて、インストールが中断されました。 このGUIアプリケーションは、"WinUSB"という仕組みを使っています。 "WinUSB"は、"Vista"では標準装備らしいのですが、"Windows XP"では、ダイナミック・リンク・ライブラリが必要です。 必要なダイナミック・リンク・ライブラリは、もちろんインストール・パッケージに含まれてはいるのですが、それが Windows XP SP2 には対応するけれど Windows XP SP3 には対応していないためインストールが中断されたものと思われます。


WS000354.png

「デバイスドライバが無くても、USBデバイスとして認識ぐらいするだろう。」と思い、つないでみた結果が、この画面です。 "JS8" というデバイスがつながっていて、 VID=15A2, PID=0038 であることがわかります。

デバイスとしては認識されたのだけど、ここから先に進むことができません。

Windows XP SP2 で試す

仕方がないので、 Windows XP SP2 のデスクトップPCで GUI をインストールしました。 オペレーティング・システムが「こんなソフトウェア、入れても大丈夫か?」と何度もきいてきましたが、構わずインストールを続行しました。

WS000246.png

インストールの結果、出てきたアプリケーションが、これです。 背景の画像と各コンポーネントの位置が合っていないので、非常にダサイのですが、まあ使えそうです。 本当にこんなGUIは必要なのか?


WS000247.png

MC9S08JS8をハブを介してPCに接続し、電源を入れると、地味に「JS8がつながった」という表示がでてきます。 どうやら、アプリケーションから無事に認識されているようです。


WS000248.png

デバイスマネージャで確認すると、"WinUSB"関連のデバイスドライバが関連付けられている事がわかります。

アプリケーションを書き込んでみる

ブートローダの動作が確認できたので、ブートローダ経由でプログラムを書き込んでみます。 使用したのは、 ProcessorExpert を駆使して作った、 LED ピカピカ・プログラムです。 でも、前回のプログラムとは違います。 今回のプログラムでは、LEDの点灯パターンが変化していきます。

プログラムは、普通に CodeWarrior で作成することができます。 ブートローダで書き込むことだけを目的としているので、 "Debug" を選択する必要はありません。 逆に言うとこの環境ではデバッグはできません。 プロジェクト・アーカイブは、このリンクを "JS04.zip" という名前で保存すると再現できます。

プロジェクトを "Make" すると、 S19 ファイルが出来上がります。 デフォルトの状態では、プロジェクトディレクトリの "bin" ディレクトリの中に "Project.s19" というファイルができるはずです。 このファイルを GUI の左の枠の中に指定します。

WS000249.png

以上で準備完了です。 画面中央の "Commands" のところに並んだボタンを "Mass Erase" "Program" "Reset" の順番にクリックしていくと、あっという間にプログラムが書き込まれて、LEDの点滅が始まります。


以上、USBでつながるけれど、USBは全く使わないプログラムの作成でした。 そろそろ、回路図を書かなきゃ。

参考文献

USBコネクタの信号線を確認しました。

USBハード&ソフト開発のすべて―USBコントローラの使い方からWindows/Linuxドライバの作成まで (TECHI―Bus Interface)

USBハード&ソフト開発のすべて―USBコントローラの使い方からWindows/Linuxドライバの作成まで (TECHI―Bus Interface)

  • 作者: インターフェース編集部
  • 出版社/メーカー: CQ出版
  • 発売日: 2006/07
  • メディア: 単行本

MC9S08JS8 にセラロックを付ける [HCS08]このエントリーを含むはてなブックマーク#

2718677

MC9S08JS8でUSBを使うために外部セラロックをつけてみました。 あれ? セラロックでいいんだっけ?

この写真は、セラロック取り付け前のものです。

MC9S08JS8では、PLLを使う

USBでは、正確なクロックを必要とします。 MC908JB16では、12MHzの発振器を使用していましたが、MC9S08JS8では、24MHzのバスクロックと48MHzの内部クロックの二つが必須とされています。 外部から48MHzのクロックを入れるのでしょうか。 いいえ、マイコン内蔵のPLLを使用して48MHzのクロックを生成します。

また、このマイコンには「ブートローダ」というプログラムが内蔵されていて、簡単にファームウェアを更新することができます。 当然のことながら、ブートローダ・プログラムでは、あらかじめ外部発振器の周波数がわかっていないと仕事になりません。 発振器に求められる周波数がどこかに書いてあるはずです。 この情報は、リファレンス・マニュアルの44ページにありました。

USB bootloader requires an external oscillator which must be at 2 MHz, 4 MHz, 6 MHz, 8 MHz, 12 MHz, or 16 MHz. Bootloader code can identify the external oscillator automatically.
USBブートローダには、外部発振器が必要です。 その周波数は、2MHz、4MHz、6MHz、8MHz、12MHz、16MHzのいずれかでなくてはなりません。 ブートローダ・プログラムは、外部発振器を自動的に検出することができます。

どういう仕組みかわかりませんが、外部発振器の種類と周波数を自動的に検出するようになっているそうです。 本当かなあ。 このマイコンを使うときには、これらの周波数を持つ外部発振器を選んでおけばUSBブートローダも使えるUSBアプリケーションにすることができます。

ひとつだけ、気になったところが。 リファレンス・マニュアルには、外部発振器 (external oscillator) と書いてありました。 外部発振子は、使えないのかな?

セラロックをつないだ

Js8Pll1.png

手持ちのセラロックから 12MHz のものを接続してみました。 以前、 MC908JB16 で使った残りです。 PLL を使ったクロックチェーンは、このようになりました。

PLL を使うときの条件は、 "RDIV_CLK" が 1MHz から 2MHz の範囲に収まることです。 この条件を満たすように RDIV, VDIV, BDIV を決定します。

「え~い、面倒だ。」 と思ったら、 ProcessorExpert に任せてしまいましょう。 すべてを "ProcessorExpert" に任せなくても、 "DeviceInitialization" で初期設定ルーチンを利用するだけでも効果があります。

PLLを使うまでの長い道のり

リファレンスマニュアルの "MCG" の章を読むと、リセット後の状態 "FLL Engaged Internal (FEI)" から USB にを使うときに必要な状態 "PLL Engaged External (PEE)" に遷移するまでには、いくつものステップを踏まなくてはなりません。 その手順が、 "9.5.2.1 Example # 1: Moving from FEI to PEE Mode: External Crystal = 4 MHz, Bus Frequency = 8 MHz" に具体的に延々と書いてあります。

「こりゃあ、面倒だ。」 と思ったら、やはり ProcessorExpert に任せてしまいましょう。 手順どおりの初期化ルーチンを作成してくれます。

という訳で、 12MHz セラロックを使った場合にも、0行コーディングで LED ピカピカができました。 プロジェクト・アーカイブは、今回も省略します。 次回は、ブートローダが起動するかどうか試してみましょう。

参考予定文献

Usb Complete: Everything You Need To Develop Custom Usb Peripherals (Complete Guides Series)

Usb Complete: Everything You Need To Develop Custom Usb Peripherals (Complete Guides Series)

  • 作者: Jan Axelson
  • 出版社/メーカー: Lakeview Research
  • 発売日: 2005/06/15
  • メディア: ペーパーバック
Usb Complete: The Developer's Guide (Complete Guides Series)

Usb Complete: The Developer's Guide (Complete Guides Series)

  • 作者: Jan Axelson
  • 出版社/メーカー: Lakeview Research
  • 発売日: 2009/06
  • メディア: ペーパーバック

MC9S08JS8 で「とりあえず」 [HCS08]このエントリーを含むはてなブックマーク#

2718677

新しいマイコン"MC9S08JS8"のサンプルを入手しました。 USB2.0に対応しているそうです。 とりあえず…

ご紹介

2718678

MC9S08JS8は、USB2.0に対応しているマイコンです。 パッケージは半田付けに慣れない方にも使いやすい20ピンSOICです。

サンプルプログラムは、ProcessorExpertで作る0行コーディング「LEDピカピカ」 電源は外部電源。 つまるところ、このマイコンである理由はどこにもありません。 まあ、とりあえず…

プロジェクト・アーカイブは、省略。

参考文献

今から、これを参考にしてアプリケーションを作ります。

Usb Complete: Everything You Need To Develop Custom Usb Peripherals (Complete Guides Series)

Usb Complete: Everything You Need To Develop Custom Usb Peripherals (Complete Guides Series)

第4版が出るまでに間に合うか?

Usb Complete: The Developer's Guide (Complete Guides Series)

Usb Complete: The Developer's Guide (Complete Guides Series)

  • 作者: Jan Axelson
  • 出版社/メーカー: Lakeview Research
  • 発売日: 2009/06
  • メディア: ペーパーバック

MC9S08SH4 のギャング出力でバックコンバータ (6) [HCS08]このエントリーを含むはてなブックマーク#

BuckConverter4.png

今回は、ちょっと予定変更。 定電圧バックコンバータでステップ応答を確認します。

ハードウェアの変更点

実験の前にカット・アンド・トライで変更したハードウェアのおさらいから。

LCフィルタのコンデンサは、100µFにしようか470µFにしようか考えていましたが、470µFだとあまりにも大きいので間をとって220µFにしました。

実験では、Ni-MH電池を電源にしていたのですが、どうも電源インピーダンスが十分に低くなっていないようで、出力にノイズがのります。 そこで、電源の方に470µFの電解コンデンサを付けてやりました。

出力波形の観測には、2SA1015を使ったエミッタ・フォロワを付けました。 100Ωのエミッタ抵抗を使用しています。

ステップ応答向けプログラム改定

ステップ応答を調べる目的は、限界感度を確定させるためです。 そのため、P制御器のゲイン"kp"を変化させながらステップ応答を観測するという手順になります。 この手順で実験を行うとき、前回作成したプログラムでは、以下の問題が考えられます。

  • 目標電圧"target"が固定されている

    本来のステップ応答は、入力が0からある値まで遷移時間ゼロで立ち上がった場合の出力を意味します。 このバックコンバータの場合、入力は、目標電圧変数"target"です。 デバッガから"target"を変更させてステップ応答を見ても良いのですが、たいへん手間がかかりそうです。 そこで、今回のプログラムでは、256フレームごとに"target"を変化させてステップ応答を実現しました。

  • ゲイン"KP"が定数に固定されている

    前回のプログラムでは、ゲインによって受け入れる誤差"err"の上下限を決定する方式をとっていました。 そのため、ゲインは上下限値と共にプログラム中にハードコーディングしてあったのですが、さすがに使いにくくなってきました。 今回は、ゲイン変数"kp"を導入して、デューティー変数"duty"に上下限を設定する方式としました。

  • ゲインが整数値である

    前回のプログラムでは、かなり計算量が多くなることを予想して、整数の乗算だけで済むようにゲインを整数として計算を行いました。 限界感度を求めるには、さすがにこれでは荒すぎます。 そこで、今回のプログラムでは、ゲイン"kp"を小数部4ビットの固定小数点数として計算を行って、ゲインを細かく変化させられるようにしました。

ステップ入力生成

ステップ入力は、変数"target"を変更するだけで実現可能です。

    // Update TARGET if required.
    if (frame_count == 0) {
      target = 114 - target;
    }

変数"frame_count"は、新たに導入した8ビットのカウンタで、デューティーを変更するタイミング(フレーム)でインクリメントされます。 1フレームは、PWM波形8周期分なので、 25.6µ秒 × 8 = 204.8µ秒 です。 このカウンタが0になるたびに"target"を更新するので、出力には、周期 204.8µ秒 × 256 × 2 = 104.9m秒 の矩形波が現れることが期待されます。

”target"変数は、初期値として"77"が入っているので、37と77の間を往復します。 0と77の間を往復させなかったのは、デューティが飽和して発振が観測できなかったからです。

エラー・アンプ・プログラム

誤差増幅には、算術演算が欠かせませんが、できるだけ難しい演算を行わせないように工夫しました。 以下は、電圧出力が目標よりも低い場合の処理です。

    if (vadc[1] << target) {
      // More DUTY expected.
      err = target - vadc[1];
      diff = err * kp >> 4;
      if (diff > MAX_DUTY-TYP_DUTY) {
        duty_nxt = MAX_DUTY;    // maximum duty
      } else {
        duty_nxt = TYP_DUTY + diff;
      }

変数"kp"は、小数部4ビットの固定小数点数です。 "err * kp"で誤差に比例定数をかけて、"err * kp >> 4"で整数に変換します。 "err"も"kp"も符号なし8ビットの"byte"型変数として定義していますが、"err * kp"の演算結果は、なぜか16ビットの数値になってしまっています。 そのため、4ビット右シフトして12ビットの整数値を得ることができます。

もし、確実に"err * kp"を16ビットで演算したい場合には、"(word)err * kp"として、16ビットの演算であることを明示すると良いでしょう。 どちらの記述でもコンパイル後は同じコードが得られます。

符号なし16ビットの"word"型変数"diff"に目標値からの差分が得られたので、これに"TYP_DUTY"を加えてデューティー値とします。 ただし、デューティー値には上限"MAX_DUTY"が定めてあるので、"diff"の値が大きすぎる場合には、デューティー値を"MAX_DUTY"で制限するようにしています。

実験の結果

ゲイン"kp"を変えながら、出力の波形を観測しました。 まず、"kp=24"(1.5倍)の結果です。

WS000351.png

矩形波出力を期待していたのに、ずいぶん歪んだ波形が出てきました。 これは、PCのライン入力がDC信号をカットしてしまっているからです。 60ms付近にあるのがステップ応答の波形です。 安定して立ち上がっていることがわかります。


WS000352.png

一方、これは、"kp=128"(8倍)の結果です。 ステップ応答入力により出力が発振していることがわかります。 この波形を見ると、発振波形の振幅が一定しているように見えますが、これは、デューティー値に上下限を与えたためです。 理論的には、振幅は際限なく無限大まで拡大するはずです。


WS000353.png

これは、"kp=78"(4.9倍)の結果です。 振幅が少しずつ小さくなっています。 これが、安定の限界で"kp=79"にすると振幅が小さくならなくなり、安定した発振状態になります。 このため、"kp=79"が求めるゲインであることがわかります。

"kp=79"の時の発振波形から周期を計算して、3.20m秒を得ました。 これが、限界感度法で得られるもう一つのパラメータです。 次は、いよいよPI制御器に取り掛かります。

プロジェクト・アーカイブ

プロジェクトを公開します。 興味がありましたら、ご覧になったうえでダメ出しをしていただければ幸いです。 このリンクを"SH11.zip"という名前で保存するとZIPファイルが再現できます。

参考文献

Scilab/Scicosで学ぶシミュレーションの基礎―自然・社会現象から、経済・金融、システム制御まで

Scilab/Scicosで学ぶシミュレーションの基礎―自然・社会現象から、経済・金融、システム制御まで

  • 作者: 橋本 洋志
  • 出版社/メーカー: オーム社
  • 発売日: 2008/01
  • メディア: 単行本
Scilabで学ぶシステム制御の基礎

Scilabで学ぶシステム制御の基礎

  • 作者: 橋本 洋志
  • 出版社/メーカー: オーム社
  • 発売日: 2007/04
  • メディア: 単行本

MC9S08SH4 のギャング出力でバックコンバータ (5) [HCS08]このエントリーを含むはてなブックマーク#

BuckConverter4.png

MC9S08SH4 のギャング出力でバックコンバータ (4)でプログラムを書いて実験した結果、ゲインが3から4の範囲で発振を起こすことがわかってきました。 今回は、発振する様子をシミュレーションで確認してみます。 順序は、きっと逆なんだろうな。

前回の記事の訂正

前回の記事を書いた後、いくつか今までの記事と矛盾している点を見つけましたので、訂正しておきます。

  1. LCフィルタのコンデンサは470&micro;Fだった。

    設計段階では、100µFのコンデンサを使っていたのですが、リップルを取るために大き目のコンデンサと交換して、そのままにしていました。

  2. マイコンの内蔵発振器が調整されていなかった。

    HCS08マイコンの内蔵発振器は、ソフトウェアでICSTRMレジスタに積極的に値を書き込まない限り、正確な周波数には調整されません。 今回のプログラムでは、このICSTRMレジスタに値を書き込む部分が抜けていたため、内蔵発振器は推定36kHzに調整されていたはずです。

  3. マイコンのBUSCLKが、divide-by-2のままだった。

    今回のアプリケーションでは、厳しいタイミング制約から高速なBUSCLKが要求されます。 にもかかわらず、BUSCLK分周器の設定を最高速の設定にはしていませんでした。 ICSTRMの問題とあわせて、BUSCLKは、9.216MHzになっていたはずです。

    これは、A/D変換やPWM周期の時間にも影響しています。 道理でPWMの周波数が20kHzになっていたはずです。

  4. PCのライン入力をそのまま接続していた。

    出力を観測するために"WaveSpectra"というソフトウェアを使用しているのですが、この時、決して高インピーダンスとは言えないPCのライン入力を直接接続していました。 本当は、エミッタフォロワなどのバッファを間に入れるべきでした。

と、色々と問題が見つかりましたが、シミュレーションの方の条件を合わせて検証していこうと思います。

scilabでシミュレーション

シミュレーションに使用するのは、scilabです。 バックコンバータの部品のモデルをscilabで記述して、シミュレーションを行います。 scilabの使い方調査したを「scilabで遊ぼう」シリーズの記事一覧を作りました。 こういうまとめは、Wikiにでも書きたいね。

諸定義

伝達関数を書くためにszを使った多項式を記述します。 最初は、これらの項を定義します。

//==============================================
//  Primary elements
//==============================================
s = poly(0,'s');
z = poly(0,'z');

続いて、これから解析するシステムの基本的な定数を定義します。

//==============================================
//  Parameter Declarations
//==============================================
fmin = 1;
fmax = 1d4;
ts   = 0.444d-3;

fminfmaxは、ボード線図を描くときの上下限周波数を指定します。 1Hzから10kHzまでの範囲を表示させることにします。

tsは、サンプリング周期です。 本当は、204.8µ秒となるはずだったのですが、マイコンのクロック設定の間違いにより444.4µ秒と長くなってしまいました。

LCフィルタ

//==============================================
//  LC filter
//  LC filter consists of a Toroidal Core Coil
//  and a Chemical Capacitor.
//  The output impedance of the driver is added
//  to the L elements.
//==============================================
L1 = s * 5.8d-3 + 0.2 + 6.46;       // L1 with DCR
C1 = 1 / (s * 470d-6) + 0.07;       // C1 with ESR
R1 = 15;
Z1 = C1 * R1 / (C1 + R1);
lc_cont = syslin('c', Z1 / (L1 + Z1));
scf(1);clf;bode(lc_cont,fmin,fmax);
lc = ss2tf(dscr(tf2ss(lc_cont),ts));

最初にLCフィルタの定義を行います。 このモデルでは、LとCに直列抵抗成分を入れてあります。 L1の抵抗成分には、Lの直流抵抗0.2Ωに加えてギャングポート出力のインピーダンスも加えてあります。 ギャングポート出力のインピーダンスは、MC9S08SH4 でギャング出力の実験で求めた値6.46Ωを入れています。

C1は、東信工業UTWRZシリーズです。 等価直列抵抗の70mΩは、常識的な値として適当に決めたものです。 まあ、こんなもんでしょう。

R1は、出力につないだ15Ωの抵抗負荷です。 1.5Vを出力した時に100mAの電流が流れます。

WS000346.png

LCフィルタの周波数応答をみると、100Hzから-20dB/decでゲインが低下しますが、4kHzから先は-10dB/decになっているのがわかります。 これは、C1の直列抵抗が無視できなくなったためです。

連続時間表現の"lc_cont"に加えて、離散時間表現の"lc"も定義しています。 周波数特性で示したのは連続時間表現の特性ですが、マイコンで実際に使用するのは、離散時間表現です。

アンチ・エリアス・フィルタ

//==============================================
//  Antialias filter
//  Antialias filter consists of an CR filter.
//==============================================
C2 = 1 / (s * 1d-6) + 0.1;          // C2 with ESR
R2 = 470;                           // R2
aa_cont = syslin('c', C2 / (R2 + C2));
scf(2);clf;bode(aa_cont,fmin,fmax);
aa = ss2tf(dscr(tf2ss(aa_cont),ts));

アンチ・エリアス・フィルタは、一次のCRフィルタです。 C2にも等価直列抵抗として100Ωを加えてあります。

WS000347.png

340Hzをカットオフ周波数とする素直な特性です。 この範囲では、等価直列抵抗の影響もないようです。

アンチ・エリアス・フィルタも連続時間表現の"aa_cont"と離散時間表現の"aa"を定義しています。

P制御器

//==============================================
//  P controller
//  P controller is implemented with a software.
//==============================================
kp = 3.12;
p_factor = syslin(ts,kp*(1/(z^2)));
controller = p_factor;

今回作成したのは、比例(P)制御器です。 伝達関数はただの定数になるはずなのです。 ところが、このプログラムでは、A/D変換してから実際にPWM出力に影響が出るまで2サンプリング時間を要する設計にしたため、"z-2"の項をかけてあります。

係数"kp=3.12"は、限界感度法によって求めた「安定して発振を続けるゲイン」です。 実際には、3から4の範囲に目的のゲインがあることがわかりましたから、矛盾しない結果であると言えるでしょう。

開ループ・ゲイン

//==============================================
//  Open loop
//  Calculate the open loop gain.
//==============================================
open_loop = controller*lc*aa
scf(3);clf;bode(open_loop,fmin, fmax);
[G,freqGM] = g_margin(open_loop)
[P,freqPM] = p_margin(open_loop)

開ループ・ゲインは、システムの安定性を見るための重要な要素です。 要するに、P制御器、LCフィルタ、アンチ・エリアス・フィルタの三つを通った時のゲインです。

WS000348.png

同時に利得余裕と位相余裕を計算させました。

 freqGM  =
 
    129.19211  
 G  =
 
  - 0.0031370  
 
 freqPM  =
 
    129.22903  
 P  =
 
  - 0.0412623  

発振をするための条件出しをしているので、利得余裕も位相余裕も"0"になっています。 周波数は、129Hzです。 実際に観測された発振周波数は、200Hzでしたが、桁は合っています。

閉ループ・ゲイン

//==============================================
//  Closed loop
//  Calculate the closed loop gain.
//==============================================
closed_loop = controller*lc/.aa
scf(4);clf;bode(closed_loop,fmin, fmax);

閉ループ・ゲインは、システムの入力から出力までの特性を現します。 このシステムの場合の入力は、基準電圧です。

WS000349.png

129Hzのところに鋭いピークが出ています。 この周波数で発振が起こっているということを意味します。

ステップ応答

//==============================================
//  Step responce
//  Simulate the step responce.
//==============================================
t = [0:ts:ts*100];
x = ones(1,101);
y = flts(x,closed_loop);
scf(5);clf;plot(t,x,t,y);ax5=gca();ax5.grid=[4,4];

100サンプリング周期分のステップ応答シミュレーションを行いました。 先のP制御器のゲインは、このステップ応答の結果を見ながら微調整したものです。

WS000350.png

このように安定して発振します。

次回は、もっと実用的なP制御器プログラムに書き換えて、変動する負荷をつないでみます。

参考文献

Scilab/Scicosで学ぶシミュレーションの基礎―自然・社会現象から、経済・金融、システム制御まで

Scilab/Scicosで学ぶシミュレーションの基礎―自然・社会現象から、経済・金融、システム制御まで

  • 作者: 橋本 洋志
  • 出版社/メーカー: オーム社
  • 発売日: 2008/01
  • メディア: 単行本
Scilabで学ぶシステム制御の基礎

Scilabで学ぶシステム制御の基礎

  • 作者: 橋本 洋志
  • 出版社/メーカー: オーム社
  • 発売日: 2007/04
  • メディア: 単行本

MC9S08SH4 のギャング出力でバックコンバータ (4) [HCS08]このエントリーを含むはてなブックマーク#

BuckConverter4.png

定電流制御の前に定電圧制御プログラムを作成します。 最初は、P制御からです。

各部分でのゲイン

PWM出力部分では、無次元の変数"duty"を入力として電圧の出力を出しています。 "duty"が1カウント増えるごとに電圧は、VDD/256[V] 増加しています。 そのため、PWMのゲインは VDD/256[V/count]と計算されます。

LCフィルタとアンチエリアス・フィルタでのゲインは、DCの時に 0dB になっており、さらにほぼ既知の周波数特性を持っています。

A/Dコンバータでは、電圧を入力として無次元の変換値を出力しています。 ここでは、処理速度を優先するため、8-bitの変換値を受け取ることにします。 A/Dコンバータの基準電圧は、VDDとVSSになっていますので、 A/Dコンバータのゲインは、 256/VDD[count/V] と計算されます。

エラーアンプとコントローラ以外の部分でのゲインは、DCの時にちょうど "1" になります。

P制御器

以上の計算から、ソフトウェアからみた時のPWMからA/Dコンバータまでのループゲインが "1" になることがわかりました。 この構成で「P制御器」を作るときには、A/Dコンバータから得た値 "vadc" から目標値 "target" を引いて得られるエラーアンプの出力 "err" を定数倍した値を変数 "duty" に設定すればおしまいということになります。 何だ、簡単だね。 目標値は、とりあえず1.5Vとします。

ところで、エラーアンプの計算結果が "0" になった時には、 "duty" の値はいくつにしたら良いのでしょうか? "0" の時には理論的に目標の電圧出力になる "duty" 値を設定することにします。 無負荷の状態の時に5.0V電源から1.5V出力を得るためには、デューティー比は30%になります。 このときの "duty" の値84を中心にしてみます。

err = vdac - target
duty = 84 + err * kp

ゲイン "kp" は、大きくすればするほど、出力の誤差が小さくなりますが、大きくしすぎると発振をおこします。 「P制御器」のゲインと発振の関係については、scilabで遊ぼう (10)で調べました。

処理のタイミング

BuckConverter6.png

今回、ただのCISCマイコンでソフトウェアPWMまでやらせようとしているので、CPUの処理能力の限界まで引き出さなくはなりません。 そこで、割り込みサービスルーチンの時間配分を考えました。

デューティーの更新は、PWM波形と非同期に行おうとしていたのですが、A/D変換時にGND電位が浮くかも知れないという心配が出てきたので、PWMの動作と同期させることにしました。 具体的には、PWM出力がLOWになって、主にショットキーダイオードが電流を流す期間にA/D変換を行います。

この時、問題になるのが、A/D変換に要する時間です。 データシートによると、A/D変換に要する時間は、最短で"20 ADCK + 5 BUSCLK"となっています。 ADCKの周波数は、8MHzが上限です。 20MHzのBUSCLKを4分周した5MHzをADCKに使おうとすると、最短A/D変換時間は"85 BUSCLK"つまり4.25µ秒と計算できます。 少なくともこの期間だけはPWM出力をLOWにしなくてはなりません。 つまり、デューティー比の上限が決まってしまうということになります。

実際の設計では、A/D変換時のサンプリング時間を長めにして変換時間を8.25µ秒とし、PWMデューティー比の上限を50%としてあります。

また、A/D変換時には、PWMの二波形分を使用し、変換開始と変換結果の受け取りを分けて、PWM波形8周期でデューティー比の更新を行うものとしてあります。 このため、サンプリング周波数は、1 / (25.6µsec × 8) = 4880Hz と当初の予定よりも低くなりました。

PHASEお仕事
0AD27(内蔵バンドギャップ)のA/D変換開始
1AD27のA/D変換結果受け取り
2AD2(PTA2)のA/D変換開始
3AD2のA/D変換結果受け取り
4AD3(PTA3)のA/D変換開始
5AD3のA/D変換結果受け取り
6-
7変換結果の転送とフレーム終了の通知

PHASE#7では、一次バッファに貯めた三つのA/D変換結果をまとめて最終バッファに転送します。 そして、メインループにフレームが終了した、つまりA/D変換結果が出揃ったことを通知します。 メインループでは、この通知に同期してデューティー比の計算を開始します。

いや、とにかく、ギリギリいっぱいです。

火入れ式

プログラムができたので、実行させてみます。 使用したコイルは、MC9S08SH4 のギャング出力でバックコンバータ (2)で作成した"35T0870-00H SINGLE"です。

最初のプログラムでは、P制御のゲインはハードコーディングしてあります。 また、変数"duty"の下限と上限をそれぞれ[20,132]としました。 まずは、VDDの0.3倍(77÷256)の値をターゲットにして出力電圧をハンディテスタで測定しました。 VDDは、5.05Vなので、理論的には1.519Vになるはずです。

kp無負荷時15Ω負荷
11.524V1.398V
21.524V1.435V
31.523V1.457V
41.527V1.474V
51.513V1.463V

ゲインを上げていくと負荷をつないだときの電圧の落ち込み(ロードレギュレーション)が改善されていることがわかります。 ただ、"kp"が4以上になると様子が変です。


WS000345.png

実は、この実験では、"kp"を4にした時から発振を起こしてしまいました。 周波数は、200Hzです。


WS000344.png

こちらは、”kp"が3の時です。 激しい発振は観測されないのですが、200Hzにピークがあるので、発振気味であることに変わりはないようです。 スペクトラムを見ると20kHz近辺にもピークがあります。 これは、PWMの周波数です。 LCフィルタでは取りきれなかったようです。

プロジェクト・アーカイブ

稚拙ではありますが、このプロジェクトを公開します。 興味がありましたら、ご覧になったうえでダメ出しをしていただければ幸いです。 このリンクを"SH10.zip"という名前で保存するとZIPファイルが再現できます。

参考文献

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

  • 作者: Fabio Pereira
  • 出版社/メーカー: Booksurge Llc
  • 発売日: 2007/11/13
  • メディア: ペーパーバック

MC9S08SH4 のギャング出力でバックコンバータ (3) [HCS08]このエントリーを含むはてなブックマーク#

今回からバック・コンバータの制御方法を考えていきます。 最初は、定電圧制御のシステムを考えます。

バック・コンバータのシステムを考える

BuckConverter4.png

これが、今から作ろうとしているDC/DCコンバータのブロック図です。 前回までの記事では、ソフトウェアでPWMを作り、その出力にコイル(L)を付けて定電流源としました。 定電圧源にするため、コイルにキャパシタ(C)を付けてLCフィルタ(LC Filter)を構成し出力(Output)とします。

出力電圧は、アンチ・エリアス・フィルタ(Antialias Filter)を介してA/Dコンバータ(A/D Converter)により監視します。 出力電圧と目標値(Target)の差をエラー・アンプ(Error Amplifier)ソフトウェアで計算します。 その差によりPWM出力をコントローラ(Controller)ソフトウェアで制御して一定電圧の出力を得るという仕組みです。

フィルタの定数を考える

ソフトウェアで作ったPWMの周波数は、40kHzです。 そのため、40kHz付近にPWMが発生するノイズ成分が発生します。 このノイズ成分は、LCフィルタでフィルタリングされます。 出力に付けるキャパシタの値を470100&micro;Fとすると、LCフィルタのカットオフ周波数は、以下のように計算できます。

L = 5.8mH
C = 100µF
fC = 1 / ( 2 π sqrt( L C ))
fC = 209Hz

40kHz付近のノイズ成分を取るには十分です。 ゲインは -40dB/dec で低下していきます。

サンプリング周波数自体はA/Dコンバータの能力をめいっぱい使えば数100kHzにすることができます。 しかし、このシステムでは、サンプリングごとにPWMのデューティー比を計算する必要があるので、計算時間も考慮してサンプリング周波数を5kHzとしてみました。

A/Dコンバータの入力には、ナイキスト周波数と呼ばれるサンプリング周波数の半分以下の周波数まで入れることができます。 ナイキスト周波数を超える成分をフィルタリングするためにA/Dコンバータの入力に置かれるのがアンチエリアス・フィルタです。 ここでは、簡単にカットオフ・周波数約300HzのCRフィルタとしてみました。 ゲインは -20dB/dec で低下していきます。

R = 470&Omega;
C = 1µF
fC = 1 / ( 2 π C R)
fC = 339Hz

サンプリング周波数が上げられたら、カットオフ周波数をもっと高くしてみましょう。

BuckConverter5.png

それぞれのゲインは、この図のようになります。 アンチエリアス・フィルタのゲインは、サンプリング周波数で -22dB です。 カットオフ周波数をもっと低くした方が良いような気もしますが、ひとまずこれでやってみます。


MC9S08SH4 のギャング出力でバックコンバータ (2) [HCS08]このエントリーを含むはてなブックマーク#

2660661

MC9S08SH4 のギャング出力でバックコンバータ (1)で、5.7mHのインダクタが必要なことがわかりました。 今回は、コイルを巻きます。

トロイダル・コアを選ぼう

コイルを巻くためのトロイダル・コアの候補については、トロイダル・コア・カタログで調べました。 この記事で調べたコイルのインダクタンスを見ると、 5.7mH などという大きなインダクタンスが、果たして実現できるのだろうかという値が並んでいます。 インダクタンスは、巻き数の自乗に比例するので、もちろん巻き数を増やせばインダクタンスを増やすことはできます。

巻き数を増やすと、もう一つ好ましくない現象が発生します。 参考文献にも書いてありますが、トロイダル・コアを使うときには、磁気飽和という現象に気をつけなくてはなりません。 磁気飽和とは、簡単にいうと、電流を流すことによって発生した磁束をコアが受け入れられなくなってしまう現象です。 この現象が発生すると、コイルはインダクタンスとしての役目を果たせなくなり、電流が流れすぎてしまいます。

コイルに流れる電流に巻き数を掛けた値を「起磁力」と呼びますが、コアには、その上限を示す「限界起磁力」と呼ばれる値があって、この値を超えないように流す電流を決めなくてはなりません。 限界起磁力(NI, 単位は A turn)は、トロイダル・コアの場合は、コアの材質によって決まる飽和磁束密度(Bs, 単位はT; Tessra)と比透磁率(μs, 単位は H/m)およびコアの内径(d, 単位はmm)から近似的に求めることができます。

NI = 2500 &times; Bs × d / μs

そこで、いくつかのコアについて、限界起磁力、100mAの電流を流したときに許容される巻き数、その巻き数で実現できるインダクタンスの値を計算してみました。

コアBs (T)d (mm)μs (H/m)NI (A turn)N (turn)AL (nH / turn2)L (mH)
FT37#610.234.7512521.85218552.61
FT50#610.237.1512532.89328697.42
FT37#430.284.758503.91393000.46
FT50#430.287.158505.89583751.26
35T0501-10H0.457.1450001.611636590.94
35T0870-00H0.4513.7250003.093060405.44

一番インダクタンスを大きくできそうなのは、FT50#61という結論になりました。 でも、そのためには、あの小さなコアに何百回もコイルを巻かなきゃいけないのか。

次点は、"35T0870-00H" です。 このコアは、トロイダル・コア・カタログでは出場しませんでしたが、digi-keyで見つけたかなり大き目のコアです。 このコアでは、コアが飽和する寸前の状態まで使って6.98mHのインダクタンスにすることができます。 従って、あまり余裕はありません。 惜しいな、もうちょっと。

必殺技!ツイン・コア

2660662

と、参考文献を見ていたら、解決方法が書いてありました。 トロイダル・コアを何枚か重ねれば、コアの断面積が増えてインダクタンスが上がります。 そのため、巻き数を減らすことができ、流せる電流も増えます。 "35T0870-00H" を二枚重ねにして、コイルを22回巻くと 5.85mH のインダクタになります。 100mA流した時の計算上の磁束密度は、 0.32T です。 きっと、これならいけるだろう。

コイルを巻くぞ

計算ができたら、あとはコイルを巻くだけです。 比較のため、別のコイルも巻いてみました。

ゼッケンコア巻き線巻き数L (mH)B (T)
135T0501-10H0.50mm323.750.90
235T0501-10H TWIN0.50mm295.740.81
335T0870-00H1.0mm315.800.45
435T0870-00H TWIN1.0mm225.850.32
2660663

"35T0870-00H" は、巻き数が少ないので1.0mmの極太UEW線を巻いてみました。 先端には、ブレッドボードに挿すための0.6mmスズめっき線が追加されています。 #35コアの飽和磁束密度は、0.45Tなので、計算によれば、ゼッケン番号4以外のコアは飽和してしまうはずです。

オープン・ループ制御の実験

BuckConverter3.png

バック・コンバータとしての動作を見るため、 15&Omega; の抵抗負荷をつないで、デューティー比と入力電流、出力電圧(VOUT)の関係を調べました。 入力電流は、5.0V電源に 2.2Ω の抵抗をつないだときの電圧降下(VBAT)から計算しています。 このため、入力電圧(VDD)も多少変動するので、入力電圧も記録して入力電力の計算に使用しています。 実際には、これにパスコンが追加されています。

使用したプログラムは、MC9S08SH4 のギャング出力で作るPWMで作成したプログラムです。 デバッガから変数を直接操作して、出力を観測します。


WS000340.png

変数 "duty" と出力電圧の関係はこうなりました。 90mAの電流を流したいので、抵抗両端の電圧が1.35Vになる付近が気になるところです。 どのコイルの場合にも出力電圧には変化がないようです。 理論的には、出力電圧はデューティー比だけに依存するので妥当な結果です。


WS000341.png

次に入力電力(PIN)と出力電力(POUT)の関係を見てみました。 それぞれの値は、以下のように計算しています。

PIN = VDD × ( -VBAT / 2.2Ω )
POUT = VOUT2 / 15Ω

どのグラフも50mW付近でX軸と交わっています。 これは、マイコンが動作するための電力であると考えられます。 また、この実験は、デバッガである USBMULTILINK を接続した状態で行っていますので、デバッガが消費する電力も含まれるはずです。 グラフの傾きは、電力変換の効率に相当します。 ゼッケン番号1のコイル(T0501 S)には、高出力部分で少し落ち込みが見られます。 これが磁気飽和の影響なのかな?


WS000342.png

最後のグラフは、出力電圧と全体の効率のグラフです。 効率は、 POUT を PIN で除したものと定義しています。 出力電圧が低い(出力電流が低い)部分で効率が極端に悪いのは、電力変換とは無関係な電力、たとえばマイコンの消費電力などが大きく見えるからです。 90mA出力(VOUT=1.35V)で効率57%というところですね。 ドロッパを使うよりはマシということにしておきましょう。

どのコイルにしようか?

実験の結果、磁気飽和による極端な効率の落ち込みは見られませんでした。 そのため、どれが良いという結論は出せませんでした。 これら四つのコイルを取り替えながら実験を続けようと思います。

次回は、定電流制御を考えます。

参考サイト

Ferrite Toroids & Balun Cores
Steward社のトロイダル・コア等のカタログです。 コアの材質に関する詳細なデータも掲載されています。 ところが、Steward社を買収したはずのLaird社のカタログには、これほど詳しい情報は出ていませんでした。 このリンク先もいつまであることやら。

参考文献


MC9S08SH4 のギャング出力でバックコンバータ (1) [HCS08]このエントリーを含むはてなブックマーク#

いよいよ、ギャング出力でDC-DCコンバータを作ります。 まずは、基本的な構成を考えます。

定電流電源の構成

ここで作ろうとしているMC9S08SH4のギャング出力を使ったDC-DCコンバータは、およそ5.0Vの電源から公称1.2Vのニッケル水素電池を充電しようというものです。 一般には、入力よりも低い電圧の出力を出すので「ダウン・コンバータ」と呼ばれています。 その中で「バック・コンバータ」と呼ばれる回路方式をとります。

BuckConverter1.png

回路は、こんな感じになります。 一連の実験に使用している4本で5.1Vの単三型ニッケル水素電池を電源と使用しています。 ニッケル水素電池でニッケル水素電池の充電?

バック・コンバータの動作は、二つのフェーズで構成されています。 第一のフェーズでコイルにエネルギーを貯めて、第二のフェーズでコイルに貯めたエネルギーを放出します。

第一フェーズ

BuckConverter1Source.png

コイルにエネルギーを貯める第一フェーズの動作状態です。 VDD に接続された PチャネルMOSFET が ON して、マイコンの出力は"HIGH"になります。 ここで言う"HIGH"は、論理的な意味合いしかありません。 実際には、出力電流を取り出したためにPチャネルMOSFETで電圧降下が発生し、出力に現れる電圧は 5.1-0.7=4.4[V] になります。

マイコンの出力ポートから流れ出した電流は、コイルを経て被充電電池に流れ込みます。 そして、被充電電池の負極から3.3Ωの抵抗を経てグランドに達します。 この抵抗は、被充電電池に流れる電流を検出するためのものです。 被充電電池の負極の電圧をA/Dコンバータで検出すると電流値を求めることができるというわけです。 抵抗値は、暫定的なものなので、あとで変更するかもしれません。

図を見るとわかるように、コイルの両端には、 4.4-1.5=2.9[V] の電圧が印加されています。 そのため、コイルを流れる電流は、時間と共に増加していきます。 その割合は、コイルのインダクタンスを L とすると、 2.9/L [A/sec] と計算できます。

第二フェーズ

BuckConverter1Fly.png

コイルに貯めたエネルギーを取り出す第二フェーズの動作状態です。 VSS に接続された NチャンネルMOSFET が ON して、マイコンの出力は、"LOW"となります。 このときのマイコンの出力は、 VSS から出力に向けて電流が流れるため、 VSS よりも低くなります。 そのため、もしかしたら、出力の電圧が最大定格である -0.3V を下回ってしまうかもしれません。

この状態を防ぐのが出力とVSSの間に接続されたショットキー・ダイオードです。 ショットキー・ダイオードで電流を流すことによって、出力電圧の低下を防いでいます。

この図から、コイルの両端には、第一フェーズの時とは逆方向に -0.3-1.5=-1.8 [V] の電圧が印加されています。 そのため、コイルを流れる電流は、時間と共に減少していきます。 その割合は、コイルのインダクタンスを L とすると、 1.8/L [A/sec] と計算できます。

VDDとマイコンの出力の間にもショットキー・ダイオードが付いています。 これは、出力が"LOW"から"HIGH"に切り替わる際に出力端子が高インピーダンス状態になり、瞬間的に高電圧が発生するのを防ぐためのものです。

充電が終わったら、どうする?

ギャング出力は、「出力」にしか設定できません。 充電が終了したときに"HIGH"固定にすると際限なく充電が行われます。 また、"LOW"固定にするとせっかく充電した電池から電流が流れ出してしまいます。 そのため、ギャング出力は「高インピーダンス」にしたいのですが、一度GNGCレジスタでギャング出力設定を指定したら元には戻せないことになっています。

そこで、充電が終了したら、ソフトウェア的にリセットをかけて、ギャング出力ポートを「入力」すなわち「高インピーダンス」に設定します。 ソフトウェア・リセットの方法については、参考文献にいくつか記述されています。 この中で簡単にできそうなのは不正命令リセットか不正アドレス・リセットですね。

PWM周期と電流リップルの関係

BuckConverter2.png

コイルに流れる電流は、 2.9/L の割合で増加し、 -1.8/L の割合で減少します。 充電器の充電電流をなるべく一定にしたいので、増加分と減少分を等しくします。 すると、マイコンの出力が "HIGH" および "LOW" になっている時間 T1 と T2 は、 T1:T2=1.8:2.9 を満たすことになります。 もちろん、 T1+T2 が PWM の周期になることは、いうまでもありません。 現在、考えている PWM の周期は、 25.6µ秒です。

ニッケル水素電池の規格を調べるで調べたニッケル水素電池の規格から、充電電流の最大値を 90mA とします。 一方、平均電流を大きくするためには、充電電流の最小値をできるかぎり大きくしなくてはなりません。 そこで、充電電流の最小値を 85mA とし、リップル幅を 5mA と仮定すると必要なインダクタンスLが求まります。

T1 = 5mA / 2.9V × L
T2 = 5mA / 1.8V × L
T1 + T2 = 4.5mS × L
L = (T1 + T2) / 4.5mS = 5.7mH

インダクタンスが大きくなれば、電流リップルも減ります。 そのため、これよりもインダクタンスを大きい方が効率的になります。

あぁ、コイルを巻くところまでたどり着けなかった。

参考文献

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

  • 作者: Fabio Pereira
  • 出版社/メーカー: Booksurge Llc
  • 発売日: 2007/11/13
  • メディア: ペーパーバック

MC9S08SH4 のギャング出力で作るPWM [HCS08]このエントリーを含むはてなブックマーク#

2630227

MC9S08SH4 のギャング出力でPWMは使えるか?で判明したように、ギャング出力にハードウェアPWMを接続することはできませんでした。 しかたないので、ソフトウェアでPWMを実現します。

PWMの周波数をどのくらい高くすればいいか

今回のPWMの最終使用目的は、LEDではなく、DC-DCコンバータです。 一般にDC-DCコンバータの駆動周波数は可聴周波数よりも十分に大きくする必要があります。 これは、もし可聴周波数領域で駆動するとコイルなどの振動が耳障りな音として聞こえてくるからです。

また、周波数が低くなるとDC-DCコンバータのコイルのインダクタンスを大きくする必要があります。 インダクタンスを大きくすると、コイルが大きくなり、コイルの巻き数が増加して抵抗成分も増加し、いいことがありません。

そのため、できる限り周波数を高くしたPWMを設計する必要があります。 目安としては、インバータ式蛍光灯で使われている20kHzから50kHzというところでしょう。

MCUの駆動周波数

今回使用する MCU MC9S08SH4 は、最大バスクロックが 20MHz とされています。 これまで、良く使ってきた MC9S08QG8 の最大バスクロックが 10MHz だったので、二倍高速に動作することがわかります。 そのため、ソフトウェア PWM の周波数も従来の MCU に比べて二倍にすることができます。 今回は、この最大バスクロック20MHzで動作させることにします。

PWMの周波数を 20kHz から 50kHz と決めました。 そのため、 PWM 波形一周期に入るバスクロックは、 400サイクル から 1000サイクルということになります。 ここでは、「キリのいい」 512サイクルとします。 時間にして 25.6µ秒、周波数にして 約39kHzです。

成功の鍵は、割り込み処理にあり

ソフトウェアは、512サイクルごとにパルスを発生させなくてはなりません。 このイベントをハードウェア・タイマを使用して発行できたとしても、それをソフトウェアがきちんと受け止めなくてはタイミングが合わなくなります。 また、PWMパルスを発生させる裏では、電流や電圧を監視するA/Dコンバータ、PWMのデューティーを決定するための制御プログラムなどが動作します。 そのため、PWM出力をメイン・ルーチンに組み込むわけにもいきません。

このような事情から、PWMの処理は、割り込みによって行い、割り込み処理ルーチンの所要時間をできる限り削減することで対応することにしました。

初代割り込み処理ルーチン

最初に作成した割り込み処理ルーチンは、こんなものです。

word    duty;           // Duty value.

ISR(pwm_overflow_isr) {
  TPM2C0V = duty;       // Set next duty ratio.
  TPM2SC_TOF = 0;       // Clear overflow flag.
  GPort_SetVal();       // Assert GPORT
}

ISR(pwm_channel_isr)
{
  GPort_ClrVal();       // Negate GPORT
  TPM2C0SC_CH0F = 0;    // Clear channel flag.
}

タイマのオーバフロー周期をPWM周期の 25.6µ秒に設定し、オーバフロー割り込みの発生ごとにギャング出力をセットします。 このとき、同時に16ビットのアウトプット・コンペアにデューティ比を設定します。

アウトプット・コンペア割り込みが発生したら、ギャング出力をクリアします。

たった、これだけの処理なのですが、コンパイルの結果をみると意外に時間がかかっていることがわかります。

   36:  ISR(pwm_overflow_isr) {
  0000 8b       [2]             PSHH  
   39:    TPM2C0V = duty;       // Set next duty ratio.
  0001 320000   [5]             LDHX  duty
  0004 3500     [5]             STHX  _TPM2C0V
   41:    TPM2SC_TOF = 0;       // Clear overflow flag.
  0006 1f00     [5]             BCLR  7,_TPM2SC
   42:    GPort_SetVal();       // Assert GPORT
  0008 1000     [5]             BSET  0,_PTCD
   43:  }
  000a 8a       [3]             PULH  
  000b 80       [9]             RTI   
   44:  
   46:  ISR(pwm_channel_isr)
   47:  {
  0000 8b       [2]             PSHH  
   48:    GPort_ClrVal();       // Negate GPORT
  0001 1100     [5]             BCLR  0,_PTCD
   49:    TPM2C0SC_CH0F = 0;    // Clear channel flag.
  0003 1f00     [5]             BCLR  7,_TPM2C0SC
   50:  }
  0005 8a       [3]             PULH  
  0006 80       [9]             RTI   

行番号がバラバラですが、お気になさらず。 "pwm_overflow_isr"では、割り込み受付を含めておよそ54サイクル必要で、"pwm_channel_isr"では、割り込み受付を含めておよそ44サイクル必要です。 割り込みが連続して発生したとしても、ギャング出力に出力される最小パルス幅は、およそ34サイクルなので、理論上の最小デューティー比は6.6%ということになります。

変数はゼロページに置くべし

HCS08には、ゼロページという概念があります。 ゼロページ、すなわち$0000から$00FFまでの範囲のメモリ・アクセスは高速に実行されます。 そこで、変数"duty"をゼロページに配置します。

#pragma DATA_SEG __SHORT_SEG MY_ZEROPAGE
word    duty;           // Duty value.
#pragma DATA_SEG DEFAULT

これだけで、オーバフロー処理が1サイクル高速になります。

   36:  ISR(pwm_overflow_isr) {
  0000 8b       [2]             PSHH  
   39:    TPM2C0V = duty;       // Set next duty ratio.
  0001 5500     [4]             LDHX  duty
  0003 3500     [5]             STHX  _TPM2C0V
   41:    TPM2SC_TOF = 0;       // Clear overflow flag.
  0005 1f00     [5]             BCLR  7,_TPM2SC
   42:    GPort_SetVal();       // Assert GPORT
  0007 1000     [5]             BSET  0,_PTCD
   43:  }
  0009 8a       [3]             PULH  
  000a 80       [9]             RTI   

まあ、わずかに1サイクルではありますが。

Hレジスタの退避は、必要か?

"pwm_channel_isr"では、割り込み処理ルーチン内でHレジスタが使われないにも係わらずスタックに退避されています。 これはムダなので退避させないようにします。

#pragma TRAP_PROC SAVE_NO_REGS
ISR(pwm_channel_isr)
{
  GPort_ClrVal();       // Negate GPORT
  TPM2C0SC_CH0F = 0;    // Clear channel flag.
}

関数の前に"#pragma"宣言を置くと、Hレジスタの退避が省略されます。

   45:  #pragma TRAP_PROC SAVE_NO_REGS
   46:  ISR(pwm_channel_isr)
   47:  {
   48:    GPort_ClrVal();       // Negate GPORT
  0000 1100     [5]             BCLR  0,_PTCD
   49:    TPM2C0SC_CH0F = 0;    // Clear channel flag.
  0002 1f00     [5]             BCLR  7,_TPM2C0SC
   50:  }
  0004 80       [9]             RTI   

同様に"pwm_overflow_isr"でもHレジスタの退避を省略したいところですが、こちらの処理ルーチンでは、16ビットレジスタへのアクセスのためにHレジスタが使用されています。 そこで、タイマのプリスケーラを2倍に設定することでデューティー比変数"duty"を8ビットとし、上位8ビットには、常に0を書き込むことにします。 これで、Hレジスタを退避する必要がなくなりました。

#pragma DATA_SEG __SHORT_SEG MY_ZEROPAGE
byte    duty;           // Duty value.
#pragma DATA_SEG DEFAULT

#pragma TRAP_PROC SAVE_NO_REGS
ISR(pwm_overflow_isr) {
  TPM2C0VH = 0;
  TPM2C0VL = duty;      // Set next duty ratio.
  TPM2SC_TOF = 0;       // Clear overflow flag.
  GPort_SetVal();       // Assert GPORT
}

この部分、デューティ比設定レジスタは、下位8ビットのデータだけを設定するだけでいいんじゃないかと思っていました。 ところが、 MC9S08SH4 のタイマでは16ビット分設定しないとレジスタが変更されませんでした。 したがって、ムダではありますが、 "TPM2C0VH = 0;" という行を入れてあります。

   31:  #pragma DATA_SEG __SHORT_SEG MY_ZEROPAGE
   32:  byte    duty;           // Duty value.
   33:  #pragma DATA_SEG DEFAULT
   34:  
   35:  #pragma TRAP_PROC SAVE_NO_REGS
   36:  ISR(pwm_overflow_isr) {
   37:    TPM2C0VH = 0;
  0000 3f00     [5]             CLR   _TPM2C0V
   38:    TPM2C0VL = duty;      // Set next duty ratio.
  0002 4e0001   [6]             MOV   duty,_TPM2C0V:1
   41:    TPM2SC_TOF = 0;       // Clear overflow flag.
  0005 1f00     [5]             BCLR  7,_TPM2SC
   42:    GPort_SetVal();       // Assert GPORT
  0007 1000     [5]             BSET  0,_PTCD
   43:  }
  0009 80       [9]             RTI   

デューティー比レジスタを書き込む部分で多少てこずりましたが、3サイクル削減しました。 最初は34サイクルあった処理が、30サイクルまで減りました。 もうちょっと、がんばりたいけど、今のところはここまで。

設定値とデューティ比の確認

プログラムができたので、変数 "duty" に設定した値と実際のデューティー比を確認します。 デューティー比は、 2.2kΩ の抵抗と 0.1µF のマイラ・コンデンサで作った一次ローパスフィルタの出力電圧で代用しています。 電源電圧は、 5.1V でした。

dutyVOUT (V)ratio (%)
04.6591.2
11.76334.6
20.25024.9
:::
200.25024.9
210.27015.3
220.29005.7
230.31006.1
:::
1342.52049.4
1352.54049.8
1362.56050.2
1372.58050.6
:::
2374.5789.6
2384.5990.0
2394.6190.4
2404.6390.8
2414.6591.2
:::
2554.6591.2

この結果から、このPWMが正しくパルスを出すことができるのは、 "duty" の値が 20 から 241 までであり、そのときのデューティ比は、 4.9% から 91.2% の範囲になることがわかりました。

次は、コイルを作ります。

2009-03-19 追記

変数をゼロページに配置するための #pragma の記述方法が間違っておりましたので、訂正しました。

参考文献

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

  • 作者: Fabio Pereira
  • 出版社/メーカー: Booksurge Llc
  • 発売日: 2007/11/13
  • メディア: ペーパーバック

MC9S08SH4 のギャング出力でPWMは使えるか? [HCS08]このエントリーを含むはてなブックマーク#

2579176

MC9S08SH4 でギャング出力の実験では、ギャング出力でLEDを点灯させました。 LEDの明るさがPWMで変えられたら、きっとうれしいよね。

ギャング出力の制御

MC9S08SH8のデータシートでは、ギャング出力は汎用入出力ポートの一機能として記述されています。

  1. すべてのポートは、出力設定になる
  2. すべてのポートは、PTCD0の値を出力する
  3. すべてのポートは、PTCDS0に従って強さが決定される
  4. すべてのポートは、PTCSE0に従ってスルーレートが決定される

これらは、すべて汎用ポートとしての動作の説明です。 PTC0には、TPM1CH0もつながっているのでPWM出力が出るかも知れないと思い確認してみました。

ギャング出力は、PWM制御できない

実験の結果、ギャング出力は、PWMでは制御できないことがわかりました。 つまり、PWMを使いたければ、ソフトウェアで何とかしなくちゃいけません。 これでは、ギャング出力をハードウェアで実装した意味が薄れていませんか?

ギャング出力をソフトウェアで制御しなくてはならないので、短い周期のPWMを実現することはできなくなりました。 たとえば、DC-DCコンバータを作ろうとした場合、周期を長くしなくてはならないので、必然的にインダクタンスを大きくしなくてはならないので、コイルも大きくなります。 さらに、あまりPWMパルスの周波数を下げると、可聴周波数に達するのでコイルが鳴くことが予想されます。 こりゃ、困ったね。

GNGCレジスタが何度も変更できる?

今回の実験には、おなじみの ProcessorExpert を使用しました。 よくできたもので、 ProcessorExpert では、リセット直後に GNGC を設定するようになっています。 これなら、安全のため一回しか書き込めないようになっているGNGCレジスタを確実に設定できます。

ところが、ところが、そうとは知らない私は、 main() に GNGC レジスタを書き換えるコードを書いてしまったのでした。 でも、動いてるよ? 何で?

実は、初版の MC9S08SH4/8 には、「GNGCレジスタが複数回書き込める」というエラッタが存在しましたが、このエラッタは第2版では消えていました。 私が取り寄せた MC9S08SH4 は、 2M84G のマーキングがあるので、当然、このエラッタは解決済みと思っていましたが、解決されていなかったのかな? ちょっと、問い合わせてみるか。

参考文献

MC9S08SH8
MC9S08SH8のデータシートです。 なんと、すでに第3版になっているそうです。
MSE9S08SH8_0M84G
初版(第0版)MCUのエラッタ(既知の問題点)リストです。 ここには、GNCGレジスタが複数回変更できるという問題が記述されています。
MSE9S08SH8_2M84G
第2版MCUのエラッタ(既知の問題点)リストです。 ここには、GNCGレジスタの問題が記述されていないので、解決したかと思ったのですが。

関連文献

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers


MC9S08SH4 でギャング出力で電球を光らせる [HCS08]このエントリーを含むはてなブックマーク#

2612962

MC9S08SH4 でギャング出力の実験では、LEDをピカピカさせましたが、豆電球を光らせることができませんでした。 このたび、仕様の異なる電球を入手して、みごとに点滅させることができました。

電球あれこれ

近所のホームセンターで電球を探してみました。 目安は、電圧が高くて電流の少ないもの。 つまり、抵抗成分の大きな電球です。 そこで、見つけたのが、定格 6.3V 0.15A の電球です。 単純に計算すると、5V電源で駆動したときに、だいたい100mAの電流を流してくれそうです。

そのまま接続すると、若干電流値が多すぎたので、5.6&Omega;の抵抗を入れました。 これで、ちょうど100mAになります。 このとき、ポート出力の電圧は、0.7Vでした。

それにしても、LEDの時の五倍も電流を流しているのに、地味だねぇ。

関連文献

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

  • 作者: Fabio Pereira
  • 出版社/メーカー: Booksurge Llc
  • 発売日: 2007/11/13
  • メディア: ペーパーバック

MC9S08SH4 でギャング出力の実験 [HCS08]このエントリーを含むはてなブックマーク#

2579177

MC9S08SH4の20ピンDIPパッケージが、ようやく手に入りました。 ご覧のようにブレッド・ボードにもぴったりです。 まずは、LEDピカピカですね。

ギャング出力という妙な機能

MC9S08SH4は、良くある汎用マイコンです。 電源電圧が2.7Vから5.5Vの範囲なので、最近のS08マイコン・シリーズですね。 仕様書を読んでいると、パラレル I/O の所に「Ganged Output」という記述がありました。 何じゃ、こりゃ?

仕様書を読んだところ、最大8本のポートを束ねて、一本の強力な出力として使う機能なんだそうです。 最大出力電流は、直接的には書いてありませんが、「Max total IOL for all ports」(最大全ポート総 IOL )の 100mA が最も厳しそうです。

ポートの本数を変えて白色LEDを光らせる

2579176

定格20mAの白色LEDを使って、束ねるポート本数を変えながら電流とポート出力での電圧降下を測定してみました。 電源電圧には実測 5.1V のニッケル水素電池4本、電流制限抵抗は実測 87.1Ω の抵抗を使いました。

本数VOL (V)VR (V)IOL (mA)RON (Ω)
10.7351.43516.4844.60
20.4351.68519.3522.48
30.3181.78220.4615.54
40.2561.83521.0711.80
50.2151.87121.4810.01
60.1881.89421.758.64
70.1671.91021.937.62
80.1431.92822.146.46

マイコンのポートでの電圧降下が VOL です。 ポート本数を増やすと徐々に減っていくのがわかります。

電流制限抵抗での電圧降下が VR です。 この電圧から求めたのが、出力電流 IOL です。

マイコンのポート出力の等価抵抗 RON は、 VOL を IOL で割ると求まります。 束ねたポート本数にほぼ反比例して抵抗値が減っていきます。 完全に反比例になっていないのは、 VSS あたりの共通インピーダンスの影響でしょう。

調子にのって

この実験では、100mA 流せるはずのポートに 22mA しか電流を流していませんでした。 100mA も流せるのであれば、「もしかしたら豆電球が点灯するんじゃないか」と思って 30Ω の電流制限抵抗に 4.8V 0.3A のクリプトン球をつなぎました。 しかし、さすがに点灯する様子は観測できませんでした。 豆電球のインピーダンスがあまりにも低すぎたようです。 残念。

さて、他にはどんな使い道が考えられるかな?

参考文献

この本には、ギャング出力についての記述はあるのですが、仕様書に書いてある以上の事は書いてありません。 もっと、怪しいことはできないかな?

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the HCS08 Microcontrollers

  • 作者: Fabio Pereira
  • 出版社/メーカー: Booksurge Llc
  • 発売日: 2007/11/13
  • メディア: ペーパーバック

今日は、amazon.comで洋書を2冊 [HCS08]このエントリーを含むはてなブックマーク#

1922909

なんのかんのと、書きましたが、結局買ってしまいました。

amazon.co.jp で取り扱いが始まる前に amazon.comに発注を出してから2週間ほどで届きました。 もうちょっと、円高にがんばって欲しかったんだけどな。

ぱらぱらとめくったところ、見本のPDFから受ける印象ほど悪い無いようには見えません。 悪いところだけPDFにしたのかな?


1922935

コッチもついでに買いました。 さあ、買ったからには、読まねば。

商品のご紹介

HCS08 Unleashed: Designer's Guide to the Hcs08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the Hcs08 Microcontrollers

Usb Complete: Everything You Need To Develop Custom Usb Peripherals (Complete Guides Series)

Usb Complete: Everything You Need To Develop Custom Usb Peripherals (Complete Guides Series)

  • 作者: Jan Axelson
  • 出版社/メーカー: Lakeview Research
  • 発売日: 2005/06/15
  • メディア: ペーパーバック

HCS08の本が出たらしい - ただし海外 [HCS08]このエントリーを含むはてなブックマーク#

HCS08 Unleashed: Designer's Guide to the Hcs08 Microcontrollers

HCS08 Unleashed: Designer's Guide to the Hcs08 Microcontrollers

(たぶん)初のHCS08の本が出たようです。 ただし、英語版。 U.S.のamazon.comでは、取り扱っていますが、 amazon.co.jpでは、まだ取り扱っていない模様です。

amazon.comの情報によると、発行は今年の三月だそうですが、 amazon.co.jpの情報では、昨年の十一月だそうです。 なんで、食い違う?

さあ、日本版はどうする?

2008-07-06 追記

amazon.co.jpでも、取り扱いが始まりました。


この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。