日記帳だ! with Tux on Libserver

二度目の大改造!! 日記帳…か?を継承し、より柔軟でパワフルなBlogに変身しました。

RSSに対応しています。リンク・コメント・トラックバックは自由にしていただいてほぼ問題ありません。
RSS購読方法、僕のリンク・コメント・トラックバックについての考えを読むことをおすすめします。

JavaScriptを有効にし、Cookieを受け入れ、以下のブラウザを使うことで完全なコンテンツが楽しめます。
Mozilla Firefox 3.0(Get Firefox)・Opera 9.6・Safari 3.2・Lunascape 4/5(Gecko)・Lunascape 5(WebKit)
Internet Explorer 7/8とそれを使うIEコンポーネントブラウザ(Lunascape・Sleipnirなど)

<< 過去

世界各地で売るか日本だけで売るか

昨日は大学院時代の知り合いに会った。

大半は技術者として働いていて、その中でも製品開発に従事している人が多い。

ところが違えば仕事の仕方にも差があって、その中でも顕著だったのが規格対応だよね。

どこで売るかというのが顕著に表れるところなので。


実は、僕の勤務先では新製品は基本的には世界各地で販売される。

これがとても大変で、というのも各国の法規制などに適合しなければならないから。

また、想定される用途によってな特殊な規格に対応する必要があったり、

法規制というのは、勤務先の製品開発で非常に重いウェイトを占めている。

技術的な難しさというよりは手続きの問題という側面もあるが、一方で一部の規制は技術的にも難しく、大変苦慮している。


ところで、電子機器の法規制は日本はとても緩いと言っていいと考えている。

分野によるが、関わっている製品群では日本の法規制対応は皆無とされており、

一部の製品は日本国内限定となっているが、これは何の法規制対応も行っていないという意味。

全てにおいてそうだとは言わないけど、日本の法規制で技術的に難しいという話はあまり聞かない。

日本国内の規格も国際規格と同じ内容になるようにするなど、日本独自の技術的要求は少なくなる傾向にある。

というわけで、日本というのは外国メーカーの製品も入ってきやすく、選びやすいと言える。

僕はいいことだと思ってるけどね。世の中、不条理な規制をやっている地域も多いから。


ということは、日本国内だけで商売をやっているところは、規格適合の手間はほとんどかかっていない。

その代わり、お役所相手の特別な要求に応える製品を作る必要があったり、

ローカル企業ならではのきめ細かい対応を行うなど、また違ったところに特徴がある。

あと、外国向けもあるけど、この製品はこの地域の規制には対応しないなどの割り切りを行っているところもあるようだ。

確かに売れなければ対応しても無意味ですからね。

うちの勤務先ではあまりそういうやり方してないけど、実際に売れるからでしょうね。


グローバル企業という言葉があるけど、本当に世界中で商売するということは難しい。

独自の商慣例、独自の法規制、そういうのに対応していかないといけない。

国によっては政府系の仕事を取るには、地元の雇用状況とか、そういう要求もあり、単に製品だけの問題ではない面もある。

その全てに対応するのは難しいが、可能な範囲で世界各地のニーズに応えていきたいという考えはある。実際、ニーズはありますから。

製品開発という点では、法規制対応のめどが立たないと製品として出せない(一部地域、一部用途は後日対応というやり方はある)

というのは確かで、それに開発のリソースを一定割かなければいけなくて、スピード感のある開発が難しくなっている面はある。


だから、そこで小回りが利くローカル企業というのはとても重要だなと思っていて、

特に日本だと市場規模も大きいですから、国内メインでも大きな会社はいくらでもありますからね。

商売の種類にもよるけど、必ずしも世界に打って出なければならないということもなく、むしろ出ないほうがいいこともある。

あと、全世界に出る必要も必ずしもなくて、この地域内でという対応でよい例もある。


勤務先のメインの商売は、どうしても日本から外国に出て行かないといけない商売でしたから。

じゃあトコトンやろうということでやった結果、それなりに成功を収めているんじゃないでしょうか。

全てが全てよい方向に行っているとも言えないのは確かでしょうけどね。

逆に日本メインで長く商売してきたがために、日本では売れるが、それ以外の地域ではさっぱり売れない製品というのもある。

そういうのをなんとか整理していきたいという思いもあるが、どうしても日本のお客さんは多いので、うまく整理できないのが実情だ。


どれも正解なんだけど、見えている正解が会社によって全く違うというのはおもしろい話。

国内の規制がゆるい分、他国の規制にどこまで対応するかというのは特徴が出やすい。

そんな答えもあるんだというのは聞いてて思ったけどね。


Author : hidemaro
Date : 2018/08/05(Sun) 21:25
電気・数学・物理 | Comment | trackback (0)

どうやって光に載せてるの?

ふと気になったんだけど、光伝送方式のケーブルテレビってどうやって実現されてるんだろ?

インターネットとテレビの情報を1本の光ファイバーに重畳して送る一方で、

光終端装置(ONU)をテレビ用とインターネット用と分けて設置することもあり、それぞれ独立して動作をできると言う。


まず、インターネットとテレビの伝送が独立してできるのは、それぞれ使う光の波長が違うから。

インターネットとテレビの伝送に使われる光ファイバーには3種類の波長の光が流れている。

インターネットの下りが1490nm, 上りが1310nm、そしてテレビが1550nmとのこと。(テレビは下りしかない)

波長が異なる光信号同士は独立して使えるので、それぞれの干渉は考えなくて良い。


その上でテレビの信号はどうやって光ファイバーを流れているのかというと、実はアナログ変調らしい。

テレビの信号は70MHz~770MHz(地上波・CATV) , 1000MHz~2071MHz(BS・CS)の帯域を含んでいるが、

これを波長1550nm(193THz)の光を搬送波として、AM変調またはFM変調をして伝送しているようだ。

一般的にはAM変調だが、フレッツ・テレビでは雑音に強いFM変調を使っているようだ。その分、送受信の装置は複雑になるけど。

AM変調では帯域幅Bの信号を伝送するのに、2Bの帯域幅を使う。テレビ信号の帯域幅は2GHzなので、帯域幅4GHz必要となる。

ところが搬送波の周波数が193THzとかなので、使う帯域幅は無視できるほど小さい。

というわけで、今後の4K放送にも光伝送方式のケーブルテレビは比較的容易に対応できる予定だ。

4K放送用のBS・CS左旋の信号は同軸ケーブルでは2224MHz~3224MHzで伝送されるが、光信号の帯域幅にとってみれば大したことではない。


FMラジオ以外の信号はいずれもデジタル変調された信号だし、光通信もデジタルの印象が強いが、そこでアナログ変調が出てくるのは意外だった。

ただ、光伝送のための装置をシンプルに作ろうとすると、これがいいらしい。

同軸ケーブルで伝送を行う場合、108-170MHz, 222-470MHzにBS・CSの情報を載せる必要があり、

そのためには、BS・CSの信号を一旦、1チャンネルずつ復調して、改めてこれらの周波数帯にデジタル変調して送り直すということをやっている。

ところが、光伝送ではその手間を省いて前後でアナログ変調するだけだから、シンプルに複数チャンネルの情報を転送できる。

あくまでも電気⇔光 の部分がアナログ変調というだけで、映像⇔電気の部分はデジタルですので。


ところで、家庭用の光インターネットでは、1本の芯線を複数戸で分け合って使っている。

1戸で光ファイバーを占有するほどの通信はしないだろうということだ。

局舎から出た1本の光ファイバーを末端でスプリッターで数本に分けて、複数戸に引き込むわけだ。

これ、どういう仕組みなんだろう? と思ったら、時分割で送受信しているのね。

スプリッターというのは、単純に局舎からの信号を単純に分配して、複数戸からの信号を単純に混ぜ合わせるだけのものらしい。

そのため、ある人に送っている光信号は同じ光ファイバーを共有する他の人にも届いてしまうが、暗号化されているのでご安心を。

この方式では、同じ光ファイバーを共有する他の人と1本の回線を分け合うので、他の人の通信状況により通信速度が変わるようだが、

むしろフレッツ光だとプロバイダーとの接続点の方が問題で、光ファイバーを共有していることによる問題は顕在化しにくいようだ。


電気通信と光通信だと多少やり方に差はあるようだが、

光通信が家庭に普及していく中で、安価な装置で効果的な通信ができるように工夫されてきていることがわかる。

幹線ネットワークだともっといろいろあるらしいんだけど、高価な装置を家庭に導入するのは難しいですから。

テレビ信号の伝送方式は意外とシンプルなんだなと思ったけど、おかげで家庭で普通に使えるわけですから。


Author : hidemaro
Date : 2018/07/30(Mon) 22:31
電気・数学・物理 | Comment | trackback (0)

エミュレータでの単体テストは好調

最近、マイコンのプログラムについて、エミュレータでの単体テストが軌道に乗ってきている。

うちでもユニットテストできるの?

実機の到着はまだ先だけど、ハードウェアに関係ない部分の実装はかなり進んでいて、

実機がなくても、作っては動作確認してということができるのはよい。


設計して、実装して、単体テストで動作確認して、ということをやっていると想定と違うことが出てくる。

特に異常時の挙動で、ここでこっちの状態に遷移するはずとか、このフラグが落ちてるはずとか期待値を書いたら、

実際には想定外の状態遷移をしてたり、禁止操作をしてたり、前の処理の残骸が残ってたり。

それに応じて設計を見直してということをやっていた。

もしかすると、想定と違う部分があっても、実機ではそれなりに動いてしまうような気もするのだが、

単体テストでは厳密に期待値を書くので、少しでも想定と違うところがあると引っかけることができると。


あと、ハードウェア設計中ということもあって、仕様変更も少しある。

その仕様変更に対して、まずテストを変更して、NGになるのを確認して、

それから、設計・実装を変更して、それでOKになるのを確認するという手順を踏めるのは単体テスト環境が揃ってるからこそ。

修正部分がほかの動作に影響しないかの確認も改めて全部のテストをかけなおせばできるし。

以前から論理回路設計のときはこういうやり方でやってたんだけどね。(cf. シミュレーションをするのが仕事)


単体テストは、リファクタリングということで、外部から見た動作を変えずに内部設計を変更するのに使われることがある。

内部設計が変わってもテストが通れば外部から見た動作が変わっていないことが確認出来ると。

その分、テストの内容が充実していないとダメですけどね。

テスト内容が充実してれば、テストで追えるから、内部設計を変更しても安心感がある。


今回は全く新規にコードを書いているので、マイコンにペリフェラルに依存する部分と、依存しない論理的な部分を分けて、

エミュレータでのテストをやりやすい設計にしている。

でも、よくあるマイコンのプログラムは抽象度が低くて、エミュレータでのテストにはなかなか向かないんだよね。

最初からテストを意識した設計じゃないと、単体テストを活用するのは難しい。

というわけで、エミュレータでの単体テストを他のシステムで活用するのは難しいなと思った。

逆にうまく切り分けられれば、実機では気づきにくい問題もいろいろ発見できたのでメリットが大きい方法だとは思ったけど。


Author : hidemaro
Date : 2018/07/25(Wed) 23:01
電気・数学・物理 | Comment | trackback (0)

夏休み直前に分周器を消す

今日は午後に研修があって、終わったら夏休みだ、

と思って職場に戻ると、ハードウェア設計者がマイコンの起動時の処理について相談にやってきた。

その場で検討したところ、マイコン外部で持っていた分周器の機能をマイコン内部に取り込むと解決できることがわかった。

それに伴うピン割り付け変更の候補だけ決めて、それに伴う回路の変更は僕が夏休みの間にやるとのこと。


そもそも、事の発端はアナログ回路の駆動に必要なクロックをマイコンから供給することにしたこと。

当初、ハードウェア設計者はマイコンのクロックをそのまま出して、それを外部で分周することを考えていたのだが、

このマイコンはクロックを直接出力する機能がないので、タイマからPWM信号としてクロックを出力する必要があった。

メインクロックが8MHzで、周期8クロック、Duty比50%のPWM信号を出力すれば、それは1MHzのクロックを供給できる。


一方で、どうせタイマからPWM信号でクロックを出すなら、直接、希望の周波数で出力すれば、外部の分周器は不要なのでは? と提案した。

必要なクロックは2種類、タイマペリフェラルの個数は足りることはわかっていた。

ただ、このときはこの提案は採用されず、当初想定していた分周器を置く方式が採用された。

当時、ピン割り付けに懸念があったようで、そのあたりも外付けの分周器が維持された背景にあったようだ。


ところが、通電時の挙動を検討したところ、通電~クロック供給開始の間の分周器の出力と供給先のアナログ回路の組み合わせがよくないらしい。

それで、マイコン側で追加の制御信号を出して解決できないかと相談に来たのだった。

分周器の使い方が悪いんじゃないの? とも思いつつ、「そもそも、分周器やめたら、この問題解決できるんじゃないですか」と言ったら、一気に事が動いたと。

マイコンの出力ピンは通電後、プログラムで設定するまではハイインピーダンスなので、

外でプルアップなりプルダウンして、供給先のアナログ回路にとって都合の良い出力を選べる。これが決め手だった。

これはハードウェア設計者にとっては想定外の回答だったようだが。

手早く追加のクロック出力ピン候補を決めて帰ったのだった。来週に回路の詳細が検討されるようだ。


こんなことをよりによって、夏休み直前、数十分前に言い出すなよと思ったけど。

ハードウェア設計者側からすれば、ギリギリで間に合ったということなんでしょうね。

別に僕の夏休みを軸に引いたスケジュールではないんだけど、本当は今週にはハードウェア設計は一通り終わってるはずだったような。

本来、僕が担当するマイコンの設計はスムーズに進んでいて、自分はやることやって夏休みと思ってたんだけどね。

でも、事情も知らずにへんてこりんな設計にされて、後でなんだこの設計と言うよりはいいか。

この問題を解決するために、本来は別の目的で使っている信号を無断で転用される恐れもあったわけだし。


Author : hidemaro
Date : 2018/07/06(Fri) 23:11
電気・数学・物理 | Comment | trackback (0)

反転の反転なんてするから

以前、マイコンのCRC計算回路とDMAを組み合わせてCRC計算をする話を書いた。

CRC演算は時間がかかるからDMA

とりあえず成功したのだが、その後に困ったことが起きた。


というのも、CRC計算回路内部では右送り(MSBファースト)、ビックエンディアンで計算しているのよね。

以前、このBlogでCRC演算の右送り・左送りの話は紹介している。

CRCの計算で一般的なのは、右のビットをMSB、左のビットをLSBと考えて計算する方法。

除数(0x104C11DB7)のMSB・LSBを反転させた値を使いながら、データを右ビットシフトしながら計算するので、右送りと呼ばれる。

(思っていたCRC32とは少し違う)

普通は一番左のビットがMSB、右のビットをLSBと言う。

右送りはデータを右シフトしながら、すなわちLSB側から順番に計算することなので、このマイコンの説明書ではLSBファーストと書かれていた。

ところが、このマイコンのCRC計算回路は左送りが標準となっている。けど、右送りのCRCがないわけでもないし。


解せないのがバイトオーダーがビックエンディアンということ。

このマイコンのプロセッサーはリトルエンディアンなのに、なぜかCRC計算回路はビックエンディアンになっている。

バイトオーダーとは、複数バイトのデータ、例えば32bitのデータを格納するときのバイト順を表している。

ビックエンディアンは1バイト目にMSBが含まれるバイトが、リトルエンディアンは1バイト目にLSBが含まれるバイトが格納される。

16進数で0x12345678というデータを 12 34 56 78と並べるのがビックエンディアン、78 56 34 12と並べるのがリトルエンディアンである。

このあたりはプロセッサーによるんだけど、リトルエンディアンのプロセッサーが主流のよう。

というわけで、メモリ上に12 34 56 78 9A BC DE F0 と格納されたデータを、4バイトずつ読み込むと 0x78563412, 0xF0DECB9A と解釈される。

ところが標準設定のままCRC計算回路に 0x78563412 を転送すると、78 56 34 12 という順番で、各々左送りでCRC計算することになる。

複数バイト一括でCRC計算回路に転送すると、データの順番が逆になっちゃってるんだよね。


ただ、左送り、ビックエンディアンが実際に使いたいCRCの計算方式とは限らないので、

CRC計算回路の前後で、バイト順反転、ビット順反転をできるようになっている。

右送り・リトルエンディアンの場合は、入力・出力ともに、バイト順反転、ビット単位でビット順反転 を有効にすればよい。

ビット順を反転して入力して左送りで計算すれば、右送りでCRC計算した結果のビット順反転になるので、また反転すればよいということらしい。

左送り・リトルエンディアンの場合は、入力側のみバイト順反転にすればよいはず。


というわけで、正しく設定をすればどうってことはないわけだが、1つ問題があった。

それがCRC計算の初期値だ。

CRC計算の初期値としては 0x00000000 と 0xFFFFFFFF がよく使われる。

世間的には0xFFFFFFFFの方がよく使われているようだが、うちの製品群では専ら0x00000000ですね。

いずれにせよ初期値を任意に設定できる仕組みを付けておけばよい。

その機能を使って、一連のCRC演算を分割して行おうとした。

初期値0x00000000からCRC演算を0バイト目からNバイト目まで計算して、そのCRC(ビット反転なし)が0xEDB88320だったとする。

次に初期値0xEDB88320からN+1バイト目からMバイト目までCRCを計算する、そうして求まるCRCは0~Mバイト目のデータのCRC値になる。


ところがこうやって計算すると、結果が合わないんだよね。

それでおかしいなぁってデバッガで調べてみたら、初期値に値を設定して、なにも計算せずに読み出すとビット順が反転していることに気づいた。

すなわち初期値0xEDB88320をセットしたら、途端に結果が0x04C11DB7になっているということだ。

それで過去の同様の実装例を調べたら、途中の計算では出力側のバイト順反転、ビット単位でビット順反転を無効化して、

最後の計算のときだけ、バイト順反転、ビット単位でビット順反転を有効にするという方法を取っていた。

こんな使い分けをしてるなんて今まで気づいてなかったけど、そうだったんだね。1発計算と同じだと思っていた。


ちなみに初期値を0x00000000 と 0xFFFFFFFF をセットするのであれば、ビット順が反転でも何の問題もない。

だってビット順を反転しても0x00000000 と 0xFFFFFFFFだからね。だから右送り・左送りともにこの値を初期値に設定すればよい。

典型的なケースでは問題にならないことから、マイコンのマニュアルにもはっきりとは書かれていなかった。

回路構成を読み解くと、なぜこうなるかはわかるようになってたけど、ちょっと微妙ですね。


そもそも、なんでリトルエンディアンのプロセッサーにビックエンディアン・左送りが標準のCRC演算回路を載せてるんだって話だけど。

マイコンのマニュアルには、CRC16では左送りが標準っぽいことが書かれているけど、僕が知る限りではCRC16も右送りが主流だと思うんだけどね。

左送り+ビックエンディアンというのは、最初のバイトのMSBから順番にという点では一貫性があるけど、

いや、それなら右送り+リトルエンディアンで、最後のバイトのLSBからっていう方を選べよと思うんだが、ようわからん。

まぁ前後で反転すればよいというアプローチはその通りだと思うんだけど。


Author : hidemaro
Date : 2018/06/28(Thu) 22:32
電気・数学・物理 | Comment | trackback (0)

エミュレータからデバッグ情報を吐き出す

マイコンのデバッグ用に使っているツールがある。

プログラムの中に自動的にデバッグ用のコードを埋め込んで、そのコードによりデバッグ情報をシリアル通信で出力する。

このシリアル通信を受信して、プログラムの内部動作を解析するというもの。

デバッグ用のコードを埋め込む必要があるのは難点だが、他のツールではできない解析ができるのが長所だ。

なかなか使い所が難しいという話もあるが、僕はデバッグの効果を高められるツールだと思っている。


このツールをエミュレーターでのユニットテストと組み合わせて使うことができないかということを考えていた。

うちでもユニットテストできるの?

エミュレータを使ってのユニットテストでハードウェアに依存しない機能のテストをしようと考えている。

このときの内部動作を実機でのデバッグで使っているのと同じツールで解析しようと考えたわけだ。


というのも、このツールはデバッグ用のコードを埋め込む都合、全機能の内部動作を一気に解析するのは難しい。

過去には何度かに分けて解析を行ったこともあるが、同じような操作を何度か繰り返す必要があるなど不都合も多かった。

そこで、ハードウェアに依存しない部分の詳細はエミュレータで詳しく内部動作を調べて、

実機ではハードウェア依存の部分の内部動作と、結合しての動作の解析と役割分担するとよいと考えた。

同じツールを使うことで、エミュレータでの解析結果と実機での解析結果との結合ができるというメリットもある。


とはいえ、1つ問題があって、それはエミュレータではシリアル通信でデバッグ情報を出力することができないということ。

そこで代替策がないか調べたところ、このツールはデバッグ情報をファイル出力する方法も持っていると書いてある。

ファイルシステムを持っているシステムでデバッグ情報を自分のファイルシステムに保存するようなのを想定しているらしいが、

エミュレータならメモリダンプをファイルに保存することはできそうだし、なんとでもなるでしょう。

というわけで方法を調べてみた。


具体的な方法だが、データブレイクポイントを使うとできるようだ。

書き込み用バッファをプログラム内で用意しておいて、そのバッファの最終バイトへの書き込みにブレークポイントを仕掛ける。

一般的にブレイクポイントはコード上に仕掛けるものだが、データの読み書きに対して仕掛けることもできる。

特にマイコンのエミュレータでは、ペリフェラルを模擬するのにデータブレイクポイントが使われることがあると。

ブレークポイントでコードを停止するのではなく、ここでエミュレータのマクロを呼び出すように設定する。

このマクロに書き込みバッファのダンプをファイルに出力するというように書いておく。

するとプログラム中ではバッファに書き込むだけで、そのバッファの内容がファイルに出力される仕組みが作れる。

出力されたデータをツールに食わせれば、見事に内部動作の解析ができるというわけ。


このファイルにはタイムスタンプを埋め込むことができる。タイムスタンプを埋め込むことで実行時間の解析などができる。

シリアル通信でデバッグ情報を出力する方式では、受信側でタイムスタンプを付けることができるが、

ファイルに出力する方式ではタイムスタンプは出力する側で付ける必要がある。

必須ではないものの、できることならエミュレータでもそれらしいタイムスタンプを付けたいものである。


それでエミュレータのマニュアルを見ていたら、エミュレータ内のサイクル数をカウントするレジスタがあることがわかった。

ファイル出力時にこの値を持ってきて、実機のクロック周波数でわり算した値をタイムスタンプとして埋め込む。

すると、解析結果にそれらしい実行時間が表示されるようになった。

エミュレータはマイコンのサイクル数も模擬しているはずなので、それなりの見積もりにはなっているはず。

厳密に実機での実行時間と一致するということはないだろうが、感覚的にはそんなもんだよねという数字になっていた。


このツールを使って解析することで、ユニットテストの妥当性の確認が容易になる。

こういう内部動作を期待して、こういう入力を用意したけど、本当にその通りになっているか。

ブレークポイントを差し込んで内部変数の値を調べて妥当性を確認することもできるが、

ツールをうまく使えば、収集したデバッグ情報を一括解析して、妥当性が確認できる。

すでに実機で使っているのと同じツールなので納得感も高い。

そこまでしてエミュレータで使うかという話もあるが、完成したものを見てみるとなかなかよいと思う。


Author : hidemaro
Date : 2018/06/20(Wed) 21:48
電気・数学・物理 | Comment | trackback (0)

ヒステリシスがないがために

とある製品に搭載されているファンの回転数を監視するシステムの調査をしていた。

というのも、これと同じ機能を持ったものを新しく作る必要があったので、既存のはどうなってるのか調べたかったと。

ファンユニットに組み込まれたロータリーエンコーダーのパルスをカウントして回転数を監視しているのだが、

このロータリーエンコーダー出力をファンクションジェネレータで模擬するのにいろいろ治具が必要で、

それで後回しになってたんだけど、治具を作ったり、集めたりして、実験環境を整えられた。


それで実験していたら、ファン回転数異常状態と正常状態を行ったり来たりする周波数があることがわかった。

って、その前に設計資料を確認していた時点でこうなることは知ってたんだけどね。

というのも、このシステムでは一定時間内のパルスの回数を数えることで回転数を測定して、異常か正常か判定している。

1秒間に60回以上のパルスが入れば正常と判定するようになっていたとする。

ここで、65.5Hzのパルスを入れれば1秒間に65回か66回かパルスが入るので、必ず正常と判定される。

55.5Hzのパルスを入れると1秒間に55回か56回かパルスが入るので、これは60回未満だから必ず異常と判定される。

一方、59.5Hzのパルスを入れたときを考えてみると、1秒間に59回か60回となり、59回のときは異常、60回のときは正常になってしまう。

こういうことが原理的に起きてしまうことは設計から明らかだった。


この問題の解決策はいくつかあるけど、一番簡単なのがヒステリシスを用意すればいいんですね。

1秒間60回未満で異常と判定、62回以上で正常に復帰とすれば、

1秒間で59回か60回の場合は、59回を測定した時点で異常と判定、その後62回以上にならないから復帰しない。

判定値にヒステリシスを持たせているものはけっこう多いが、境界値付近で厄介な挙動を起こさないようにと考えられたものだ。

簡単な仕組みだが、うまい解決になっているように見える。

というか、このシステム、本来ならばヒステリシスを持っていてもよさそうなところに全くヒステリシスがない。


もっとも新しく作るシステムでは、ファン回転数の測定方式が変わる予定で、

同じ周波数を入れ続けている限りにおいては回転数が揺らぐことはごく少なくなる。

原理的には境界値付近のごく狭い周波数では発生しうるが、なかなかそこを狙うのは難しいだろう。

なので、ヒステリシスを持たせなくても、簡単に異常状態・正常状態を行き来する状態になることはなさそう。

他も状況を鑑みると、境界値付近に留まり続けるのはなかなか難しい。

というかファン回転数もファンクションジェネレーターで模擬すれば簡単に起こせるけど、実機で起こすのは難しいし。


だからヒステリシスはいらないのかというと、そういうもんではないとも思うのだが。

ただ、もともとヒステリシスがあることを想定した仕様になっていないので、注意が必要とも。

ヒステリシスの幅をごく狭くすれば許されそうな気もするけど。


Author : hidemaro
Date : 2018/06/13(Wed) 22:06
電気・数学・物理 | Comment | trackback (0)

なぜか2段構えのWDT

使っているマイコンのウォッチドックタイマ(WDT)がちょっとクセのある動作をする。

というのも設定した時間の倍の時間経たないとリセットが発生しないからだ。


そもそも、WDTというのは、こういうもの。

WDTはプログラムの暴走を検出するために使われる、いわば最後の砦である。

WDTはタイムアップするとマイコンをリセットするなどするタイマだ。

WDTを使うシステムでは、定期的にWDTをクリアするプログラムを作っておく。正常に動いているときはWDTがタイムアップすることはない。

ところが何らかの理由でプログラムが暴走するとWDTがクリアされなくなり、指定時間経過するとWDTタイムアップで検出できる……ということを期待している。

(マイコンはタイマだらけ)

WDTがタイムアップするとプログラムが暴走したと判断するわけだが、

実はWDTタイムアップ=リセットというわけでもない。


というのも、WDTタイムアップで割り込みを発生させて、エラーログの取得とかを行うシステムもあるから。

このマイコンのWDTは、1回目のタイムアップで割り込み発生、2回目のタイムアップでリセットとなっている。

1回目の割り込みでエラーログの取得などの処理を行い、これが終わらなくても2回目のタイムアップで強制的にリセットしてしまうという用途を想定しているのだろう。

こういう用途で使う分にはよくできた仕組みなのだが、このシステムってWDTでリセットさえできればいいんだよね。

すなわち1回目のタイムアップで発生する割り込みは何もせず、2回目のタイムアップのリセットだけを使うのだ。

なんかおかしくね? と思うんだけど、最終的にリセットされるという結論に差はないから、あまり気にしていないようだ。


WDTもいろいろあって、マイコンの種類によって全く異なる。

同種のARMコアを使っているマイコンでも、メーカーによって全く違うぐらい。

そもそもWDTタイムアップ=リセットというマイコンもあるし、

あるマイコンでは、タイムアップ手前の所定の値で割り込み発生、タイムアップでリセットとなっている。

調べた限りで多かったのが、割り込みかリセットか選択制になっているもの。

1つのマイコンで複数のWDTを持っていることも多いので、1つのWDTで割り込み、1つのWDTでリセットという使い分けをすることも想定しているのかも。

1つのWDTに割り込み・リセットの両方の役割を持たせるより、こっちの方がわかりやすい気がするな。


というわけで、やっぱりこのマイコンのWDTはちょっと変だなと思ったんだけど、

ペリフェラルマニュアルをよく見てみると、WDT割り込みでとある操作を行うと、即WDTリセットにできるようになっていた。

割り込み処理にこの操作を書いておけば1回目のタイムアップでWDTリセットになるってことだね。

もししくじっても、2回目のタイムアップでリセットになるので安心感があるとも言える。

いろいろ総合して考えてみると、これが正しい使い方のような気がしてきたが、その割にはサンプルプログラムとかには書かれていないのが解せないところ。


今回はマイコン内部のWDTの話をしているが、WDTというのもいろいろあって、

アナログ回路で構成されるWDTもあるし、他のロジックにWDTを持たせることもある。

とあるシステムでは、マイコンのWDTを使わず、このマイコンと通信を行うプログラムが一定時間以上の通信停止を発見したら、

マイコンをリセットさせるという仕組みになっていた。これもWDTの一種だよね。

目的が実現できればマイコン内のWDTを使う必要は必ずしもないということだね。

一番手軽なのがマイコン内のWDTを使うという方法なだけで。


Author : hidemaro
Date : 2018/05/25(Fri) 22:50
電気・数学・物理 | Comment | trackback (0)

CRC演算は時間がかかるからDMA

ところで、このプログラム、ちょっと奇妙だよね。

for(unsigned long *p=PTR_START; p<PTR_END; p++){
  CRCIN = *p;
}
crc_result = CRCOUT;

CRCINにひたすら値を代入して、CRCOUTを読んでいると。

当然のことながら、このCRCINというのは普通の変数ではなくて、マイコンの機能レジスタで、

CRCINレジスタに1回書き込むとCRC演算が1回行われ、その結果はCRCOUTから取得できるということ。


CRC演算って普通にプログラムで書くとめんどくさいが、回路で作れば比較的簡単だ。

使用しているマイコンでは、CRC16とCRC32の代表的なものが計算できるようになっている。

マイコンのペリフェラルってこういうのもあるんですよ。

普通にプログラムで書くよりも高速に計算できるのは言うまでもないが、

それでも大量のデータに対してCRC演算すると時間がかかってしまう。

しかも、最初に書いたようなプログラムでやると計算中は他の処理ができないという問題もある。


そこでDMAである。

DMAはDirect Memory Access、CPUを使わずにデータ転送を行う仕組みだ。

上の処理は、データを右から左に流しているだけだから、DMAにやらせればその間はCPUは手放しにできる。

送信元のポインタだけ進めて、送信先のポインタは固定ということもできるので、機能レジスタに書き込み続けること、

逆に送信元を固定にして、機能レジスタを読み込み続けるということもできる。

そしたら、DMAを使うと手放しにできるだけでなく、転送速度も速かった。倍速近かった。

今回の用途では、計算完了までにかかる時間はそこまで重要ではないし、CPUが手放しにならないとしても工夫すればなんとかなるのだが、

DMAを使って悪いことは何もないので、DMAを使ってCRC計算をすることにしようと思う。


さて、大量のデータを転送するならばDMAは大きなメリットがある。

他にペリフェラルからの割り込みをDMAで受けて、それに応じてデータ転送をすることもできると。

例えば、シリアル通信の送信バッファに4バイト×100回転送するとDMAに設定して、送信バッファが空のときに発生する割り込みをDMAにつなげておく。

その上で、最初の1回はプログラムからトリガをかけてやれば、

バッファに4バイト転送→4バイト送信→バッファが空になったので4バイト転送→4バイト送信……とプログラムを介さずにできる。

4バイト×100回の転送を終えたら、DMA転送完了となるので、そこで割り込みを発生させるなり、転送完了をポーリングしておけばよい。

AD変換との組み合わせで、AD変換結果からRAMに1ワード×16回転送とDMAに設定して、AD変換完了割り込みをDMAにつなげる。

それで、ADコンバータは定周期で動くようにしておけば、プログラムを介さずに定周期で16回取得したアナログ値がRAMに格納される。


ただ、DMAは単純に左から右にデータを流すことしかできない。CPUを使わないというのはそういうこと

シリアル通信の受信バッファからRAMに受信バッファが満タンになるごとにDMAに転送させるということもできるが、

DMAに設定した回数よりも、受信したデータが少ないと、DMA転送は永遠に終わらないし、

受信中にデータ転送以外の処理をしなければならないとなれば、DMAだけに任せておけない。

1回の転送量が少なくても、回数が多いのを手放しでできればメリットはあるが、どうせ1回1回は少量だしという考えもある。

やり方次第ですかね。


DMAというもの自体は知ってたけど、大量のデータ転送をすることもそんなに多くないしなぁと思ってたら、

CRC計算という意外な用途でDMAが大きな効果を発揮したので、よい発見だった。

そもそもCRC計算のプログラムを書かずに済むだけでもラッキーと思ったけど、

ハードウェアでCRC計算できるとこんなこともできちゃうんだよね。


Author : hidemaro
Date : 2018/05/21(Mon) 22:24
電気・数学・物理 | Comment | trackback (0)

シフトレジスタにシリアル通信も可

回路設計をしている人からマイコンのピン割り付け案を受け取って確認していた。

この機能はここでいいねとかいうのを確認していた。

その表でシフトレジスタの入出力にシリアル通信機能と書かれていた。

GPIOのつもりだったんだけどなぁ、と思いつつも、確かにシリアル通信でもシフトレジスタとの入出力できるんだよね。

もっとも、シリアル通信とすればピン割り付けがおかしいので、ここはここに割り付けてと指示したが。


入出力の拡張としてシフトレジスタが使われることがある。

TC74VHC165F: 8-Bit Parallel-In/Serial-Out Shift Register  (TOSHIBA)

TC74VHC595F: 8-Bit Shift Register/Latch (3-State) (TOSHIBA)

標準ロジックICの74シリーズのこのあたりがよく使われるらしい。

74165は入力用に使われる。8bitのパラレル入力をシリアル化する。

74595は出力用に使われる。8bitのシフトレジスタとラッチを持っている。

シフトレジスタにデータを格納して、全部格納できたら一括してラッチするということができる。


マイコンのピンにも限りがあるが、74165を使えばマイコンの入出力3ピンで8bitの入力を受けられる。

すなわち、これで5ピンの節約になる。

さらに複数の74165を連結して使うこともできるから、そうすると節約効果はなおさら大きい。

74595も8bitの出力をマイコンの出力を最小3ピン使えば操作出来る。(Hi-Z状態を制御したい場合は+1ピン)

これも複数の74595を連結して使うことができる。


ただし、入出力にあたってはシフトレジスタの操作が必要になる。

そこで、当初想定していたのはプログラムで信号を1つずつ操作する方法だった。

ロード信号を下げて上げて、シフトレジスタ出力を格納して、クロック信号を上げて下げて……というのを全部プログラムで書くと。

この方式のメリットは特別な機能を使わずに済むこと。GPIOさえ使えればよい。

GPIOはGeneral Purpose Input/Output、単純なデジタル入出力のことですね。マイコンのほぼ全てのピンがGPIOで使える。

ただ、欠点は信号の操作を全てプログラムで書くので、データ転送のスピードが遅くなってしまうこと。


一方でシフトレジスタとのデータ転送にクロック同期シリアル通信が使えるという話がある。

74165も74595もクロックの立ち上がり時にデータを1bit転送されるわけですからね。

クロック同期シリアル通信はSPIバスなどで使われるので、マイコンにはほぼ搭載されている機能。

この機能を使えば、プログラムで信号を1つ1つ操作するより高速に、なおかつ転送中は他のプログラムの実行ができる。

そういうわけでパフォーマンス面ではマイコンのシリアル通信機能を使う方が有利なわけである。


そのことを意識してシフトレジスタの入出力ピンをシリアル通信機能のピンに割り付けようとしていたのだろう。

その割にはピン割り付けがおかしかったから、本当はよくわかってなかったのかもしれないけど。

とりあえず、シリアル通信機能にも使えるようにピンは割り付けてもらうことにした。

GPIOはほぼ全てのピンで使える機能なので、ほとんどどこに割り付けても自由だ。

なので、シリアル通信機能が使えるように割り付けておけば、GPIOでの操作もできる。


というわけで、シフトレジスタとのデータ転送方法について シリアル通信 と GPIO の2種類の選択肢を得たわけだが……

どうしてもシリアル通信を使わないといけないほどパフォーマンスが厳しいわけではない。むしろ暇をもてあますことになりそう。

GPIOだと信号の操作を1つずつプログラムに書かないといけないが、プログラムで書いた通りの波形が出てくるという安心感はある。

どっちがいいんだろ? というわけでチームリーダーに相談してみた。

そしたら「どっちでもいいけど、通信機能の操作をあれこれ考えるぐらいなら、GPIOの方が楽なのでは」とのことだった。


そこで教えてもらったのだが、1世代前のシステムではEEPROMへのアクセスをGPIOを使って行っていたらしい。

クロック同期のシリアルバスの通信をプログラムで信号を1つずつ操作してやってたらしい。

それでもなんとかなっていたのだが、問題は通信速度が遅いこと。

8msあたり2Byteずつという遅いスピードで行っていたようで、すなわち1kByte転送するのに4秒かかるということだ。

というわけで当時はEEPROMに格納するデータサイズをできるだけ小さくする工夫をしていたようだ。

それでも128Byteのデータを転送するのに0.5秒ですからね。リード→ライトとやると2回転送するから1.0秒かかってしまう。

最新世代のシステムでは、マイコンのシリアル通信機能を使うことで、8msあたり32Byteずつ転送するようになった。

EEPROMの書き込み時間を考慮すると、書き込みでは限界に近いスピードになっているとのこと。

すると1kByteのデータを250msで転送できるようになった。1世代前のシステムで128Byte転送するよりも短時間で済む。

これにより設定情報の大容量化が実現できたということらしい。


500kbpsで128bitのデータを転送するのにかかる時間は0.256ms。

オーバーヘッドなど考慮しても通信機能を使えば1ms間隔で74165または74595 16個分のデータ転送をすることもできそう。

マイコンはたった3ピンだけで、ロジックICを16個外付けすれば、128ピンの入出力が1ms間隔でできるというのはなかなかすさまじい。

とはいえ、今回はシフトレジスタはせいぜい1個(16bit)、データ転送間隔は数百ms間隔である。

通信機能を使って本気で転送しなければならないスピードということは決してない。

じゃあGPIOでいいねって。


Author : hidemaro
Date : 2018/05/10(Thu) 22:55
電気・数学・物理 | Comment | trackback (0)

Tools