Quantcast
Channel: メモたんく
Viewing all 39 articles
Browse latest View live

ロボコン4号の製作 その10

$
0
0

停滞気味である

一月近く倒立振子ロボットの記事を更新してない。
カルマンフィルタ+PID制御の倒立振子ロボットの静止に四苦八苦。停滞気味である。

まずは、暇を見つけて試行錯誤した結果の報告。

MPU6050-DMPの試行錯誤

MPU6050-DMPモードのソースにモータなどの姿勢制御プログラムを追加してコンパイルするとLPC1114では容量オーバしてしまうのだ。MPU6050をDMPモードで動かす魔法の長い呪文がブログラム領域にあるのが原因だ。余裕のあるMPUならいいがLPC1114では無理なようで開発は断念した。

といってもKalmanフィルタは倒立振子ロボットを立たせるぐらいの正確さがあるので問題はない。

筐体の静止に試行錯誤

筐体を自在に操る為には、まず静止させるということが必要だ。それが意図どおりに静止しないのだ。

1.DCモータのブレを抑制
モータが動くか動かない微妙にところで倒立振子ロボットは立っている。ダブルギヤボックスのギヤ比32.8:1とモータの組み合わせでは、モータが回転するかしないか約1.2Vぐらいのところで安定しているのだ。少しの電圧の変化でも動き出してしまうので制御が難しいのだ。

試しにダブルギヤボックスをギヤ比を114.7:1で組み立て直して倒立させてみたが、姿勢を安定させるにはより多くモータが回転しなければならないので、反応が鈍くなり、加わる電圧も高いためモータドライバの発熱が大きくなり使えないのだ。

2.モータの回転計からのフィードバック
フォトインタラプタで得られた回転数からフィードバックを掛けたみたのだけど、静止しないのだ。ロジックが悪いのかと、思いつくまま修正してテストしたのだが、改善しないのだ。

参考にしているBalanduinoは、静止しているようなのだか、ロボコン4号は安定しないのだ。

何か問題があるから安定しないのだ、しかし何か悪いのか分からない。手詰まりだ!

道具の開発

DCモータ版の倒立振子ロボットを解析・制御する為に、C#にてコントローラを作成した。
このコントローラの通信相手はBluetoothのHC-05だ。簡易なプロトコルを作って姿勢制御の送信や姿勢情報の受信を行う。
倒立振子ロボット側は、ノンブロッキングで受信できるよう、そしてC#のコントローラは、HC-05が切れ切れに送ってくるパケットでも受信できるような細工が必要だった。

ロボコンコントローラその1

ロボコンコントローラその1

ロボコンコントローラその2

ロボコンコントローラその2

工夫して作ったコントローラを利用しても、静止しないのだ。これは手詰まりだ!!

静止した

何をやっても静止しなかったのだが、PIDのゲイン値を滑らか動作重視から反応重視に変えてみたところ、少しカクカクとした不自然な動きながら静止するようになった。静止しなかったのはPIDゲイン値が悪かったということになるのだろうか、奥が深い。

次は走行・ブレーキ

ロボコン1号2号の経験からすると単純に前方・後方に車輪を回すだけでは倒立振子ロボットは安定して走行しない。
筐体を傾ければスムーズに走行するのは実験済みなのだが、スムーズにブレーキを掛ける方法を考える必要がある。

【2015/4/25追記】

昨日アップロードした動画の撮影角度が悪く、安定しているように見えなかったので、撮影し直してyoutubeにアップロードした。ご覧のように数センチの移動で静止している。


ロボコン4号の製作 その11

$
0
0

制御

前回、倒立振子ロボットが安定したと報告した。次は最後の難関の制御である。

旋回させるにはプラス・マイナス・ゼロになるように左右のモータに加える電圧を加減すれば良いのであるが、電圧の加減で前後に動かそうとすると倒立を維持するPID処理が破綻する可能性があるのだ。

参考にさせてもらったBalanduinoはどうしているかというと、前進するときにはターゲット角度を前に、後進するときには後ろに移動することによって実現している。さらにモータの回転速度などのフィードバックを細かく入れている。

そしてラシオ少年さんやkookyさんが参考にされたArduinoの倒立振子ロボットINSTABOTは、リモコンから送信される値でモータの加える電圧の加減しているのだ。

どのやり方も正解

Balanduinoのロジックをロボコン4号に組み込んで制御してみると前後に操縦できないばかりか姿勢を安定することもできない。PID処理が破綻するのだ。Balanduinoのモータはパワーがあり少々の誤差でも制御は破綻しないのだが、ロボコン4号のモータはピーキーなのだ。動きもBalanduinoはカブトムシのようでロボコン4号は蝶のみたいにふわふわしている。しかも回転計の精度が悪いのだ。これらが問題なのだ。

もうひとつのラシオ少年さんやkookyさんが参考にされたArduinoの方法のようにモータの電圧を加減して操縦しようとすると、これまたPID処理が破綻するのだ。

Balanduinoのモータや筐体などのバランスなら、Balanduinoのロジックは正しいのだろう。ラシオ少年さんやkookyさんが参考にされたINSTABOTの方法は、このモータと筐体のバランスなら、これが正解なんだろう。

つまり我がロボコン4号用の、正しい制御の方法が必要だということだ。

ロボコン4号用の制御方法

Balanduinoのように車輪の動きのフィードバックを掛けたいところなのだがフィードバックを掛けるとPID制御が破綻してしまうのだ。そこで車輪のフィードバッグを入れず角度偏差だけを入れ、PCのC#のプログラムは以下のように改変してテストしてみた。

ロボコン4コントローラ

ロボコン4コントローラ


いつもなら動作してる動画を公開するのだが、PCのプログラムでは制御するのが難しいので録画できなかった。

実験から取得した倒立状態が維持できる最大角度0.5度を上限として与えてみたところ、ソロソロという感じで筐体が前に動き出し偏差角を0度に戻すとゆったりと静止するのだ。イケそうな感じだ。
実験した手応えからするとアナログジョイスティックを持ったコントローラなら自在に操作できるような感じだ。

kookyさんは制御出来たようだ

この記事を書いているときにkookyさんから制御出来たという報告をいただいた。モータに加える電圧を除々に大きくすればPID制御は破綻しないらしいのだ。

何にしてもコントローラを作らないと始まらない。HC-05でBlueToothコントローラを作るか・・・

ロボコン4号の製作 その12(ひと区切り)

$
0
0

ロボコン4号の操縦できた

BluetoothなのでAndriodでプログラムを組めばスマホで操縦できるのだが、今はそこまでの情熱がないのだ。
そこでPCのコントローラソフトを以下のように改造してみたところ、何とか制御できた。

改良ロボコン4コントローラ

改良ロボコン4コントローラ

PCの画面を見ながらロボコンの操作は難しいのだ。動画を撮る余裕がないので今回も動画なしだ。

ロボコン4号を操縦してみて分かったことは、kookyさんも報告されてたが、当方の方法(ターゲット角度を操作して前進・後進させる)でも走り出すのだ。良く考えてみれば当然なことで、重力加速度が常に鉛直な方向に働いてる。本来の重心位置からずれたところにターゲット角度を設定すると重力の分力が進行方向に働き続けるのだ。常に力が加わっているのではじめはゆっくりと動きそして次第に早くなっていくのだ。これはたとえ重心が低い筐体でも解決しないと思われる。

この走り出しも、人間の補正(PCのコントローラの角度を除々に戻していく)で安定した速度を得ることができることを確認した。

参考にさせていただいたBalanduinoはもっとスマートで、車輪の回転速度が早くなればターゲット角度を重心のある角度に戻して一定の速度を保つようなロジックを組んでいる。
ロボコン4号も、想定して回転計を自作したのだが、モータ+ギヤボックスがピーキーな上、回転計の精度も悪いので、適切な角度補正ができないのである。
ロボコン4号に関してはこれが限界なような気がする。これで一区切りにしよう。

もう少し研究が必要だ

ロボコン4号でも回転計(ロータリエンコーダ)の作り変えとモータ+ギヤボックスの変更をすれば、実用なレベルになると思う。
次のロボコン5号では、回転計(ロータリエンコーダ)とモータ+ギヤボックスの研究して組み立てたいと思う。

ロータリエンコーダに関してはWheelEncoderGeneratorというソフトを発見した。透明なシールにWheelEncoderGeneratorが創りだしたロータリエンコーダのパターンを印刷して透明な円盤に貼り付けるということで精度の高いものを得られそうだ。扱い易いモータ+ギヤボックスもあると思うので調査をしたい。

WheelEncoderGenerator

WheelEncoderGenerator

記事のタイトルを変更した。

$
0
0

記事のタイトルを変更

DCモータを使った倒立振子ロボットの記事のタイトルは、これまで『DCモータ版倒立振子ロボットの製作』としてきたが、このタイトルではDCモータを作った倒立振子ロボットを再製作したとき混乱しそうなので、タイトルを『ロボコン4号の製作』に変更した。

通販トラブル

$
0
0

MPU6050の誤配

ばんとさんは電子部品を通販で入手することが多いのだが、最近は誤配に次ぐ誤配で少々呆れ気味なのだ。

呆れたのはMPU6050。これロボコン4号に使っているのだが格安で扱い易いので、先日予備品として改めてアマゾンで発注したのだ。アマゾンで破格で販売されているMPU6050はたぶん中国製のパチモンで、何故か沢山のショップ(しかも電子部品なんか扱っていなようなショップ)から同価格で販売されているのだ。
注文後数日で郵便受けにMPU6050が入った封筒が届いた。本来ならこれで売買は完了するはずなんだが、数週間後に、MPU6050が入った封筒が届いた。どちらの封筒も同じ注文番号が書かれた送り状が入ってた。

明らかな誤配だ。人によったら貰っちゃうかもしれないが、ばんとさんはこういうのは嫌いなので、アマゾンを通じてショップに確認を入れたのだ。
MPU6050は安価で予備品が2個になっても良いと思ったの返品ではなく買取の交渉をした。買い取るということでショップの指示通り改めて発注をした。普通ならこれで売買は完了なのだが、数日後郵便受けにMPU6050入の封筒が届いた。目がテンだ。”何故部品が届く!! どうなってんだ〜って!!”ところだ。

誤配のフォローで誤配、杜撰すぎる。ショップは2重に誤配したのも気がついてないのではないかと思う。
呆れたし邪魔臭くなったので、ショップが誤配と気付き何らかのアクションを起すまで放置することにした。

写真は中国のショップから国を超えて誤配されたモータシールドとともに誤配されたMPU6050だ。ひとつは半田付けしたが今回の一連のトラブルで手元に残ったMPU6050だ。

これでMPU6050の数はロボコン4号に取り付けたのもカウントすると4つになる。こうなると在庫過多で消化しないといけなくなる。誤配されたモータシールド(意外と高性能)とMPU6050は、PINがバッティングしてないので使えそうだ。誤配部品でロボコン5号とか作れそうだ。

誤配だらけ

誤配だらけ

部品が不足しかも…

これもトラブルだがアマゾンで安いLCDを発見したので4つ発注したのだ。発注後に気がついたのだが、これが中国のショップだったのだ。気が付かないうちに個人輸入することになったのだ!!

普通なら4つLCDが届いて売買終了なんだが、3つしか入ってなかった。確認してみるとLCDを4つ梱包した形跡はあるのだけど、ひとつ抜かれた感じだ。
アマゾン経由して不足のクレーム入れたら個人で交渉してくれとのこと、頭が痛くなるような日本語で書かれたメールを送ってくるショップ相手に延々と交渉して、やっと足りないひとつを送って貰ったのだ。
aliexpressでの発注なら、これがチャイナクオリティ!!、覚悟の上だが、アマゾンで注文したのに、どういうことなんだというところだ。
アマゾンさんょ!!中国のショップをなぜ混ぜる。個人輸入はリスキーなんだ。お手軽アマゾンとは違うのだ。怒ってるぞ!!

写真はトラブルのLCD。ショップはGAOHOUというところ。皆さん気をつけて!!

抜き取られてた

抜き取られてた

STM32CubeMX その1-紹介

$
0
0

STM32CubeMX

STM32CubeMXは便利なのでみなさんに紹介する。

STM32CubeMXは、STマイクロ提供のC言語ソースのひな型を吐き出すジェネレータだ。

STM32CubeMX起動画面

STM32CubeMX起動画面

特徴は

  • MCUメーカ純正品である
  • 無償である
  • グラフィクで直感的に操作できる
  • keil uViosnなど市販の開発環境プロジェクトのソースが吐き出される
  • STマイクロ社のほとんどのSTM32シリーズのMCUをサポートしている
  • javaプログラムなので動作環境を選ばない

Standard Peripherals Libraryとの決別

これまでSTマイクロは自社のCortex-M(ARM)用にStandard Peripherals Libraryを用意していたが、新規にHAL(hard ware abstraction layer)を中心としたSTM32Cubeという新しい開発環境のファームウェアセットを提供した。
Standard Peripherals LibraryとHAL(hard ware abstraction layer)には互換性がない。そしてSTM32CubeMXは、HAL(hard ware abstraction layer)を含むCソースを吐き出すのだ。

逆に云うと、HAL(hard ware abstraction layer)が自在に扱えないとSTM32CubeMXを使いこなせない。

特徴はとしては、多種なSTM32 MCUをサポートするSTM32CubeMXでの自動生成を意識してかCMSIS規格を元にペリフェラルの抽象化と移植性の向上されている。

こんな感じ

//GPIOにクロックを提供

//Standard Peripherals Libraryなら
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

// HAL(hard ware abstraction layer)なら
__GPIOD_CLK_ENABLE();

Standard Peripherals LibraryとかHAL(hard ware abstraction layer)とか言ってもMCUのレジスタを如何に適切に設定するかという手順が書かれたライブラリィだ。ばんとさんは、Standard Peripherals Libraryなら川内さんの『STM32マイコン徹底入門』で学習したのである程度は使えるのだが、HAL(hard ware abstraction layer)は、書籍はない上Webでの情報も少ないのでSTマイクロが提供したサンプルとHALで書かれたmbedのソースを眺めながら再学習しているところだ。

STM32CubeMXは便利なものだ

ここではビジュアライズされて直感的に操作できるところを紹介したい。

これはMCUの選択画面、STマイクロのほとんどのMCUが網羅されているようだ。

MCU選択画面

MCU選択画面

これはGPIOの設定、MCUのイラストのピンをクリックして設定するというのは直感的で画期的。
左にはMCUが用意している周辺機器が列挙されている。

PinOut画面

PinOut画面

細い設定は別の画面でする。
割り込みやDMA、USARTやSPIなどの設定もできる。

Pinコンフィグ

Pinコンフィグ

これはクロックの設定。ARMは周辺機器が豊富でクロックも複雑怪奇なので、これまではデータシートを注意深く読んで設定してたが、このように直感的に設定できるのは画期的。

クロック設定

クロック設定

これまでのStandard Peripherals Libraryを使ったプログラム作成方法と比べて、直感的で理解しやすく画期的だと思う。

続きを書くョ

STM32CubeMXもHALも試行錯誤(学習中ということ)なのだが、少しずつ慣れてきたので、続きはボチボチ書いていきます。

STM32CubeMX その2-Lチカやってみよう

$
0
0

環境を構築

ソフトウェア

ソフトのインストールなどの細かい説明は省略するが、ばんとさんは、STM32CubeMXは一応Windowsのみ対応というので、STマイクロサイトよりダウンロードしたSTM32CubeMXをWindows8.1にインストールした。
ばんとさんはmbed LCP1114用にMDK-ARM V4(uVision 4) LITE(32Kの制限のあるフリー版)をインストールしているので、STM32CubeMXから吐き出すソースはMDK-ARM V4とすることにした。

ハードウェア

参考にするSTM32マイコン徹底入門

参考にするSTM32マイコン徹底入門

今回ばんとさんがSTM32CubeMXを学習するプラットフォームはSTM32 Value line DiscoveryとSTbeeである。共にCortex-MのARMでSTマイクロではF1シリーズと呼ばれるMCUが載っているボードだ。現在入手が容易でばんとさんも持っているSTM32F401RE-Nucleoなどのボードでもいいのであるが、STbeeはSTM32を勉強した川内さんの『STM32マイコン徹底入門』のターゲットボードで、書籍で使うStandard Peripherals Libraryとは違うがハードウェアは同じなので参考にできるという算段で選んだ。

STM32 Value line Discoveryは各種!?端子付きのベースボードに載っててテストしやすいのでメインで使用する。

STM32VLD

STM32VLD

STbeeはUSBやSDIOなどをサポートした高性能なMCUなので、STM32 Value line Discoveryでテストできないときは、こちらを利用することにする。

STbee

STbee

STM32CubeMXでの作業

改めてSTM32CubeMXの話である。
STM32CubeMXでは以下の手順でひな形のソースを吐き出す。

  1. MCUの選択
  2. クロックの設定
  3. 各種周辺機器の設定
  4. プロジェクトのセーブ
  5. ひな形のソースの吐き出し

設定データをファイルとして保存できるので、納得できるまで設定修正できる。

ここではSTM32 Value line DiscoveryをターゲットにLチカプログラムが出来るまで順を追って説明する。

MCUの選択

STM32CubeMXを起動すると以下のような画面が出るのでNew Projectを選ぶ。

STM32CubeMX起動画面

STM32CubeMX起動画面

MCU選択画面が出てくるのでSTM32 Value line DiscoveryのMCUであるSTM32F100RBTxを選択する。

STM32F100RBTxを選択

STM32F100RBTxを選択

MCUを選択すると、Pin設定などができる画面に移行する。

クロックの設定

STM32(ARM)は周辺機器が豊富なのでクロックは複雑で、データシートや川内さんの解説本でも多くのページを割いて記述されている。設定も相当ややこしいのであるが、クロックを正しく設定しないと正しく動作しないのだ。

第一の関門である。

クロック信号を入力するPinの設定

STM32 Value line Discoveryは、8MHzの水晶発振子とRTC用水晶発振子をクロックソースとしているので、以下の手順で設定を行う。
まずはPinout設定で、クロック信号を入力するピンの設定で、8MHzの水晶発振子とRTC用水晶発振子を信号を利用するように設定する。

外部クロックのPin設定

外部クロックのPin設定

クロック信号の適切な設定

STM32 Value line DiscoveryのMCUであるSTM32F100RBTxの動作周波数は24Mhzが最高らしいので、8Mhzのクロックを2分周してPLL(位相同期回路)のソースとし、これを6逓倍して24Mhzを作る。

これをクロックコンフィグ画面にて設定していく。クロックの分岐の具合や最高速度超えの設定をすると赤文字の警告が出てくるので、データシート片手にソースを書くより効率的だ。

クロック設定

クロック設定

GPIOの設定

ボード上のLEDの次はLチカをする為にGPIOの設定だ。AVRなどでGPIOの設定をするならポート方向レジスタの設定で終わりなのだが、STM32(ARM)の場合はポートの設定の他にも、クロック配給設定が必要になってくる。
GPIOやタイマなどの周辺機器は、デェフォルトは停止状態でクロックを配給して始めて動くのである。

STM32 Value line Discoveryは、PC8,PC9にLEDが接続されているので、今回はこれを出力用のGPIOに仕立ててLチカさせてみる。

これをSTM32CubeMXで設定するなら以下のようになる。PC8,PC9のピンをクリックしてGPIO_Outputにする。

GPIOの設定

GPIOの設定

GPIO_Outputのプッシュプル接続・オープンドレイン接続などの詳細設定は、この画面でGPIOのポタンをクリックする。

GPIOを選択

GPIOを選択

クリックすると詳細画面が出るので設定をする。

GPIOの詳細設定

GPIOの詳細設定

Lチカなら以上の設定で終わりだ。

プロジェクトの保存及びソースコードの生成

次にプロジェクトを生成する為に設定をする。ALT+PまたはメニューのProjectよりSettingsを選択し適切に設定する。

プロジェクト設定

プロジェクト設定

これでプロジェクトがセーブできるようになったので、メニューからFileからSaveを選んで保存する。

Ctrl+Shift+GかメニューからProjectよりGenerate Codeを選べばソースコードが生成される。

ソースコード生成完了

ソースコード生成完了

これでSTM32CubeMXの作業は一旦終わり。

生成されたMDK-ARMのプロシェクト

生成されたプロジェクトをMDK-ARM V4で読み込むと以下のように読み込まれた。コンパイルなどは問題なく行えるのだが、ST-Linkの”JTAG接続からSW接続へ”の修正をしないと書き込み・デバッグが出来なかった。

生成されたプロジェクト

生成されたプロジェクト

ソースはHALの流儀通り、周辺機器の初期化はstm32f1xx_hal_msp.cファイルに割り込みなどはstm32f1xx_it.cファイルに分かれて生成される。

ユーザコードを書き込む場所

生成されたソースは周辺機器の初期化までなので、生成されたものをコンパイルしてターゲットに書き込んでもLEDは点滅しない。LEDの点滅はユーザがプログラミングする必要がある。

以下は生成されたソースの抜粋だ。
/* USER xx BEGIN xx */ と /* USER xx END xx */ という一対のコメントがあるが、このコメント間にユーザコードを書く必要がある。これ以外の場所で書くとSTM32CubeMXで再度コードを生成したときに消されてしまうので注意が必要だ。

/* USER CODE END 0 */

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
	HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);  // ここはばんとが追加
	HAL_Delay(100);                         //
	HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);  //
	HAL_Delay(100);                         //
  }
  /* USER CODE END 3 */

}

/* USER CODE BEGIN 3 */と/* USER CODE END 3 */の間に、LEDが点滅するようにコードを追加した。これをコンパイルして書き込めばボード上のLEDは点滅する。

Lチカ

Lチカ

今回はSTM32CubeMXの簡単な使い方を書いたが、これにて終了。
次回以降は、もう少しつっこんだSTM32CubeMXの使い方やHAL流のソースの書き方を検証しながら書く。

参考資料

データシート関係

今となっては日本語マニュアル等をどこで入手したかわからないので、当方手持ちのPDFファイルをアップロード公開した。最新版があるならそちらを参考してください。

STM32F100xx 日本語リファレンスマニュアル"STM32F100xx 日本語リファレンスマニュアル"をダウンロード
STM32F103xx日本語リファレンスマニュアル"STM32F103xx日本語リファレンスマニュアル"をダウンロード
STM32F100x データシート"STM32F100x データシート"をダウンロード
STM32CubeMXのユーザスマニュアル"STM32CubeMXのユーザスマニュアル"をダウンロード
STM32F1xxx HALドライバ・ユーザマニュアル"STM32F1xxx HALドライバ・ユーザマニュアル"をダウンロード

プログラム関係

中古PCを購入

$
0
0

何周遅れのリプレイスだろうか!?

ばんとさんの、今のメインPCはDELL INSPIRON 531だ。これ2007年発売の何と8年落ちのPCである。このPCはVistaマシンだったのだが、ダウングレードしたXPとUbuntu12.04LTSをインストールして使ってた。XPは今年初めに死んだ。ばんとさんはLinux使いなのでUbuntuさえ動いてれば問題ないので誤魔化しながら使用してたが、この夏の暑さでハードディスクがおかしくなり頼みのUbuntu 12.04LTSの動作が不安定になったのだ。ハードディスクを入手してインストールし直せば元に戻るのはのだけど、8年落ちのロートルで新たにハードディスクを交換するとなると4つ目だ。さすがに修理する気がなくなって新たにPCを入手することにした。

いつもなら新規に購入となるのだがsenshuさんが中古PCを購入され上手にメンテして使用している記事を読んでたので、ばんとさんも中古PCを入手することにした。

昨年新規購入したASUSのノートPCはCore i3だしRaspberry Piですら4コアが発売され、次期メインPCはCore i5以上(4コア数以上)のPCという条件で物色した。

引っかかってきたのが代引き+送料込の価格が25000円でWindows 7 Pro(64Bit)でIntel Core i5 2400@3.1GHzで4GBメモリと500GBのハードディスクが載っているHP 8200 Elite SFFだった。
Intel Core i5 2400@3.1GHzなら第二世代のCore i5で、調べてみると2011年発売で4年落ちのリリース切れPCと判断しポチって購入した。

これまでPCに関しては、ばんとさんは先頭を追ってた訳でもないが半周遅れぐらいでリプレイスしてた。今回はOSに関してもハードに関しても3~4周遅れのものだ。

届いた中古PC

注文した翌々日には届いた。本体と電源コードそしてCD-Rが一枚だけ、ショップのWebではOSのメディアがあるとあったのだけど起動ディスクのことだったようだ。OSのイメージがハードディスクにあった。

中古PCを購入

中古PCを購入

PCの中は綺麗に掃除されてた。

掃除されてて中は綺麗だった

掃除されてて中は綺麗だった

保証は30日

この中古PCを購入したジャンクワールドの保証は30日らしいので、がんがん使ってテストだ!!

OSはどうしようか

Ubuntuインストールは決まりだけど、Windowsは7にするか10にするか迷うところだ。


これは苦行だ

$
0
0

PCを入手したらまずやること

今回購入した中古PCは、Windows7 Pro(64Bit)がハードディスクにインストールされた状態で届きました。
この状態ならまず第一にやらないといけないのが外部メディアから再インストールできるようにすること。

以下の手順で行った。

  1. 内臓ハードディスクにあるOSイメージをUSB接続された外部ハードディスクにコピー
  2. 外部ハードディスクにコピーしたOSイメージから再インストールテスト

再イントールできることが確認できた。

Windows10のディスクイメージを作成する

保証期間の1年が過ぎた途端、起動しなくなったlenovoのクソ・ノートPCがWindows7だった。ASUSノートPCのWindows8.1になれしまったので、久々感があり何処に何があったかとか失念してた。こうなるとWindows10でも変わりがないので、どちらも選べるようにWindows10のディスクイメージを作成することにした。

まずはWindows7 Proのアップデート

今回の鬼門はWindows7のアップデート。Webの情報によるとWindows7からのアップデートの条件はOSが最新状態であることらしいのだ。Windows7を使い続けるにしても最新状態にする必要があるので実施したみた。

みなさんもご経験があると思うが、PCを買ってOSを最新状態しようとアップデートをするとこんなに時間がかかるのでしょうか!!
中古PCに入っているWindows7 Pro(64Bit)はSP1版なのだが、ネットに接続してアップデートしようとすると更新ファイルが190もあると表示された。結果として更新ファイルは250以上、そして4時間以上の時間が掛かった。
メインストリームの更新が終わったWindows7、バグだしは完璧で大量の更新ファイルがあるということなんだろうけど、4時間以上も必要なのはどうなんでしょうかね。

再インストールしようとしたら、また4時間かかるのというのはうんざりなので、ハードディスクのバックアップイメージをUSB接続された外部ハードディスク作成した。

最新状態になってやっとWindows10アップデート案内が出た。

Windows10のアップグレード

アプリケーションをインストールしてないほどんど素のOS状態なので、Windows10のアップグレードは一時間ほどで無事完了。Windows10 Proがイントールされた。Windows10まで5時間以上かかっていることになる。Windows10 ProのハードディスクのバックアップイメージをUSB接続された外部ハードディスクに作成した。

苦行を耐えたおかけで、Windows7 Pro(64Bit)、Windows10 Proいつでもインストールできるようになった。

2008年製のハードディスク

$
0
0

なんと!!

今回も中古PCの話題です。

改めてHP 8200Elite SFFの内部をチェックしてみた。コンデンサ等の膨らみとか目に見える不具合はなく問題はなさそうだ。

ただ一点ハードディスクに問題!?があった。

ハードディスクの動作は問題はないのだが、製造年月日を確認して驚いた。
メーカはメイド イン コリアのサムソン製。

サムソンのハードディスク

サムソンのハードディスク

そして製造年月日は2008年6月

なんと2008年6月製

なんと2008年6月製

HP 8200Elite SFFの裏蓋には2011-12-14のスタンプがある。スタンプから2011年12月14日に製造されたのだろう。

2008年6月製のハードディスクが2011年12月14日製造のPCに入いることはないので、購入したショップが換装したのだろうか?
推測になるが、換装の経緯はハードディスクの調子の悪いHP 8200Elite SFFを入手したショップが手持ちで比較的状態のよい中古ハードディスクに換装して販売したのだろう。

ハードディスクは消耗品

ハードディスクは消耗品だから壊れて当たり前なのだが、2008年6月製のハードディスクなんて何時壊れるかわからない。ショップ保障の30日持つかどうかも怪しい代物だ。

ばんとさんは、壊れる前に交換し”まだ壊れていないハードディスク“は常時接続しない外部ストレージの中身にしている。テレビ番組などの動画ファイルが腐るほどあるので”まだ壊れていないハードディスク“なら使い道はあるのだ。 :roll:

HP 8200Elite SFFには、退役予定のDELL inspiron 531で使ってた1T容量のシーゲートのバラクーダに入れ替えた。
このバラクーダはハードディスクの矛盾で不安定になったのだが、異音など発生していないのでハードウェアは問題はないと判断している。 😉

Atmelが買収…

$
0
0

Atmelが買収された

AVRシリーズのMPUは、ばんとさんのメインMPUのひとつであるのだが、製造しているAtmelが買収されてしまった。買収後はMPUも整理されてATtinyシリーズとかなくなるかもしれないなぁ…

まぁ秋月が在庫を持っている限り大丈夫なんだけど。

ロボコン5号 その1

$
0
0

放置状態!!

夏前に配送ミスで届いたMPU6050とarduinoモータモジールでステッピングモータ版ロボコン5号の筐体をでっち上げてたのだが、夏の暑さでやる気がおきずソフトを組まず放置してた。

放置状態は、不憫なのでソースを弄って魂を入れてみた。といってもソースは一から書いてはいない。
MPU6050はDMPモードで動くライブラリ、モータドライブはメーカ提供のライブラリとか、肝心なところは、メーカ標準のライブラリやArduinoのPIDライブラリとか極力便利なライブラリを利用した。

10秒ほど立っただけ

テストがてら書いた簡単なソースだから仕方ないが、数十秒ほどは倒立するのだが、ちょっとしたきっかけでバランスを崩してゴロンと転がるのだ。

ジャイロの姿勢情報とPIDを使った姿勢制御部分は問題はないのだが、ステッピングモータを十分に回しきれてないので姿勢が崩れたとき元の姿勢に戻せないのだ。
今のところ、メーカ提供のライブラリを使ってるので、チューニングされてないのだ。

これが取り合えず立ってるところ。
ステップひとつひとつを制御してるのでビシッと静止している。

ステッピングモータ版ロボコン5号

ステッピングモータ版ロボコン5号

ノウハウが必要

DCモータもノウハウが必要だったがステッピングモータを使うにもノウハウが必要なのだ。

DCモータの回転制御は電圧の加減で行うが、ステッピングモータの回転は電圧の加減で行う訳ではないので、低速回転時のほうがより電流が流れやすく倒立振子ロボットのように低速回転が常態なものは電池の消耗が激しいのだ。

しかもDCモータに比べたらトルクは少ないので、回転数によって電圧を加減したり回転パターンを変えたりと工夫が必要なのだ。

DCモータは使いやすいがギヤが必要だったり回転数を把握するために特別な構造必要だったりと幾分複雑で、DCモータはギヤの遊びもあってかなり姿勢がぶれるのだが、遊びがないステッピングモータを使えばビシッと姿勢も安定し制御しやすいのだが、ソフトがその分邪魔臭いのだ。一長一短がある。

またまた通販トラブルこれもチャイナリスク

$
0
0

またまた

kookyさんの倒立振子ロボット製作記を参考に、10日ほど前にAliexpressに電子部品を発注した、それが先ほど届いた。

中身を確認してみたところ、1ロッド(5個)で注文したはずが3個しか入ってない。

数が足りない

数が足りない

アマゾンで発注した電子部品が中国のショップでそれが数が足りなかったり、最近アマゾン(これまた中国ショップ)で買ったがnRF24L01+が4個のうちひとつが不良品だったりとトラブル続きだったのだが、今回もその例に洩れなかった訳です。

ショップにクレーム

とりあえず足りない部品2個を送ってくれとショップにクレームを入れた。
商品単価が安いので泣き寝入りも覚悟してるが、それでも言わなければいけないことはしっかりと主張するつもりだ。中国のショップ相手にクレームを入れるのは相当疲れる。
それが今から始まるかと思うと気が重い。

これが嫌なので、最近は注文を控えてたのだけどね…

正直、うんざり!! :-(

5個あった!!

返品も考えて袋を開けずにいたが、袋の横から中身を覗くと部品が重なっているように見える。
思い切って袋を開けてみたら5個出てきた。
残りの2個は見えていた3個の下に綺麗に重なって隠れたのだ!!

5個ありました。

5個ありました。

クレーム入れたショップにはメールを入れたりと、てんやわんやだ!!
タイトルを訂正して”粗忽者のばんと”とかしないといけないなぁ。

色々なこと…

$
0
0

mbed OS…

隣町で開催されたmbed祭吹田に行ってきました。
この祭りに参加して分かったことがmbed OSというのは、ARM系のMPUをIoTで接続するためのフレームワーク(OS)だということ…

昔PHPカンファレンスに出かけたときPHPの話題が一切なくWindows AZUREの話題とかが中心でうんざりしたことがあった。今回のmbed祭はmbedの話題が中心でぶれることもなくよかった。

気になったことがmbed OSである。IoTって流行りなのはわかるが、少なくともばんとさんはmbedでIoTはやらないと思う。
誤解を恐れず書くが、ばんとさんはmbedを使っているのはCortex-MのMPUが簡単に扱えるからなのだ、ネットワークやるのなら新規に勉強が必要なmbedよりLinux環境は慣れて経験もあるのでRubyとかPthonとかC言語とかで実装するのが遥かに楽なのだ。

そして稚拙な自家製電子デバイスをインターネットつないでIoTデバイスにしたいいう欲求は今のところない。
仕事なら我儘はいえないが趣味でIoTやるのならRaspberry PIあたりを使ってセンサ類の情報を加工してネットに繋げるだろうなと考える。
mbedでIoTを実装し満足が得られる人も多いと思うが、ばんとさんは少なくともそのタイプではないようだ。

ばんとさんは籤運が悪い

謎なおもちゃ

謎なおもちゃ

mbed祭では運営の方々が色々とプレゼントご用意されて頭が下がります。

気前よく頂いたものにコメントを書くのは恰好の悪い話とわかりつつ書くが、ばんとさんはBath-Duckとタグがついたラバーのおもちゃが当たったのだ。しかし正直なところ戸惑ってしまった。 :roll:
ラバーのおもちゃがARMのノベルティだとかmbed関係者のサインでも入ってれば大喜びだったのだけど…調べてみるとYarto-Ducksとかいうイギリスのおもちゃメーカ製でARMとかmbedと関係ないような。おっさんにラバーのおもちゃは何のこちゃです。 😥

まぁ一言でいえば、ばんとさんは籤運が悪いということ。しかしそう考えると少し寂しくなるので“年末ジャンボ宝くじの為の運を無駄に使わなかった”と思うことにしておこう。 :-(

次はArduinoで

mbed祭りと関係ない話題だが、Aliexpressに注文した商品がやっと届いた。

Arduino Nano 3コンパチ

Arduino Nano 3.0コンパチ

最後に届いたのが一個1.85ドルで入手した激安のArduino Nano 3.0パチもん。すこし前まで正規版がスイッチサイエンスで4320円で売られていた。

倒立振子ロボットのジャイロ・加速度センサのMPU6050をDMPモードで動かそうとするとLPC1114の32Kのフラッシュでは収まらない。同じ32Kのフラッシュの8ビットのArduinoなら収まるのだ。つまり使えるMPUなのだ。
ばんとさんはmbedでものを作ることが目的ではないので、次の倒立振子ロボットはArduinoで作ることにしようかと思う。

久々の更新

$
0
0

久々の更新

我が家に仔猫がやってきて、てんやわんやで電子工作はしてませんでした。電子工作をしないとブログを更新するネタが尽き中断となってた次第。久々にアマゾンに出店している中華ショップに発注してので久々に更新することにした。

大人買いの発注

たまたまアマゾンで安いGPSモジュールを発売している中華ショップを発見。中華ショップの値段と品揃えを見ているうちに欲しくなったのて発注することにした。
気になったものをチェックすると19点、6000円近くになった。GPSなどの大物があるのにこの値段。業務スーパーで大判振る舞いで購入している気分になった。

一週間で届く

中国からの発送なので一・二週間かかるとのことだったが、一週間で届いた。大人買いしたので航空便で送ってくれたようだ。

小さな箱で届いた。

小さな箱で届いた。

届いた商品は、片手に乗るような小さな箱に入ってた。19点も購入したのに、このサイズ!?でと疑問になったのだが、開けてみるとみちっり商品が詰まっていた。 😐

商品はみっちり詰まってた。

商品はみっちり詰まってた。

商品チェックしたところ19点揃ってた。とりあえず合格。

商品は不足なし

商品は不足なし

Arduino Leonardoを購入したのだが、これが630円の価格。純製品ではないと確信を持っているのだが基板を見ると本物と思えてくる。 😯

これは本物!?

これは本物!?

久々の半田付け

とりあえずSTM32開発ボード(STM32F103C8T6)にピンヘッダを半田付け、ST-Link V2との接続用ケーブルを自作した。久々の半田付け、久々のケーブル作りだ。

通電&ケーブルテストも兼ねてSTM32CubeMX+Keil uVision4にて、Lチカプログラムを書いてテストした。テストはOKだった。

久々の半田付け

久々の半田付け

このSTM32開発ボード(STM32F103C8T6)は、ひとつ310円(3個購入)で購入したのだが、STM32F103で64KのフラッシュやUSBつき、そしてボードには8MHzの水晶は載っているしRTC用の水晶も載っている。秋月でLPC1114が400円とかと比べるとこちらの方が断然お得なのです。工夫すればmbedで開発できるらしいので、これをメインでST HALライブラリの学習をするつもり…


STM32CubeMX その3-タイマ1、比較出力(アウトプットコンペア)

$
0
0

STM32F103C8T6マイコンボード

アマゾンで310円でSTM32F103C8T6マイコンボードを購入した。
ブレッドボードに刺して実験できるので使い勝手がよい。

そこでSTM32学習で使おうとSTM32CubeMXでソースを生成することにした。

久々の半田付け

久々の半田付け

プロジェクト設定

STM32CubeMXのMPUをSTM32F103C8T6を選択しプロジェクト設定は以下のようにした。
生成するコードはMDK-ARM V4用である。
MPUの選択の詳細はSTM32CubeMX その2-Lチカやってみようを参照のこと。

プロジェクト設定

プロジェクト設定

クロックの設定

STM32(arm)のマイコンの最初の鬼門はクロック設定である。今回入手したSTM32F103C8T6マイコンボードには参考になるソースがなかったので試行錯誤で設定をした。
要点は、STM32F103C8T6は72Mhzが最高速度で、このボードには小さいながら8MHzとRTC用の水晶が載っているので適切に設定する必要ということ、幸いにもSTM32CubeMXは限界を超える設定をすると赤い警告がでるので直観的で設定しやすい。

STM32CubeMXで試行錯誤で設定した結果がこれである。
詳細はキャプチャした画面図を参考して貰いたい。

クロックの設定

クロックの設定

その3はタイマのプログラム

その2でGPIOを使ったLチカのプログラムを記述したが、その3はタイマだろうということで、タイマについて書く。

STM32のタイマの機能は、

  1. カウンタ値によってタイマ出力ピンのレベルを変化させる。
  2. カウンタ値によって割り込みを発生させる。
  3. タイマ入力ピンに与えられたパルスの回数やパルス幅の測定。

がある。

1.には、タイマ値によってタイマ出力ピンをオンオフする比較出力(アウトプットコンペア出力)とPWMがあるが、今回は比較出力(アウトプットコンペア出力)である。

比較出力(アウトプットコンペア出力)

そもそも比較出力(アウトプットコンペア出力)とはという話であるが、STM32は複数のタイマを持っているが、タイマひとつに4つのタイマ出力ピンを持っている。
異論があるかもしれないが、タイマ出力ピンのオンオフの割合を設定するのがPWMとするなら、タイマ出力ピンのオンオフの周期を設定するのが比較出力(アウトプットコンペア出力)だと言えるかもしれない。
タイマ出力の変化タイミングは、タイマに与えられたクロックとプリスケールと自動再ロードレジスタの値できまるのである。

比較出力とPWMのタイミング

比較出力とPWMのタイミング

タイマ1の4つのタイマ出力ピンを1秒間隔で点滅

今回はタイマ1の4つのタイマ出力ピンを1秒間隔で点滅させる。これが目標である。

Pinout設定

まずはSTM32CubeMXのPinoutでTIM1を図のように設定する。

タイマ1のPinout設定

タイマ1のPinout設定

この設定でタイマ1のクロックを72MHzの内部クロック(APB2)とし、PA8~PA11までの4ピンをタイマ出力ピンとした。

TIM1コンフィグ

次は1秒間隔で点滅するように設定をしていく。コンフィグでタイマ1のボタンを選択し、

タイマ1の選択ボタン

タイマ1の選択ボタン

タイマ1の詳細を設定する。

タイマ1のコンフィグ

タイマ1のコンフィグ

これは意図した周期でタイマ出力ピンをオンオフさせる設定である。

まずはオンオフさせる周期の設定である。STM32のタイマのプリスケールと自動再ロードレジスタはともに16ビットつまり 65535まで設定できる。プリスケールを72000000にすればプリスケールだけで1秒間隔を作れるが65535までの値が設定できるので、今回は36000分割(36000-1)を設定する。これで72Mhz÷36000=2000つまり2KHzの周期で変化するので自動再ロードレジスタを2000カウント(2000-1)と設定すれぱ1秒周期を作り出せる。

次にピンの振る舞いであるが、これは各ピンの設定でする。
今回は4つアクティブにしたタイマ出力ピンのmodeをToggle on modにすれば点滅をする。点滅の開始点はPulseの値できまるので1,501,1001,1501にした。以上で設定は終わりである。

プログラム生成

初期コードを生成である。これにてSTM32CubeMXの作業は終わりである。

プロジェクトの生成

プロジェクトの生成

コードを追加

STM32CubeMXでは初期化までのコードを生成してくれるが、動作させるコードはユーザが書く必要がある。今回はタイマ1比較出力を始めるコードだ。/* USER CODE BEGIN 2 */と/* USER CODE END 2 */の間に以下のコードを追加した。

  /* USER CODE BEGIN 2 */
  if (HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_1) != HAL_OK) 
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2) != HAL_OK) 
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_3) != HAL_OK) 
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_4) != HAL_OK) 
  {
    Error_Handler();
  }

  /* USER CODE END 2 */

これで4つのLEDが1秒ごとに点滅するようになる。

一秒間隔で点滅

一秒間隔で点滅

簡単だが難しい

STM32CubeMXの完成度が高く直観的かつ簡単にプロトタイプのソースを生成できるのだが、ソースを完成させるにはSTM32そのものの知識が必要なうえHALライブライに詳しい必要がある。
HALライブライの情報がすくないので、ターゲットMPUのデータシートやHALライブラリィのドキュメントやHALライブラリィのサンプルソースを丹念に読み込んで理解する必要がある。簡単だが難しい。

参考資料

データシート関係

今となっては日本語マニュアル等をどこで入手したかわからないので、当方手持ちのPDFファイルをアップロード公開した。最新版があるならそちらを参考してください。

STM32F100xx 日本語リファレンスマニュアル"STM32F100xx 日本語リファレンスマニュアル"をダウンロード
STM32F103xx日本語リファレンスマニュアル"STM32F103xx日本語リファレンスマニュアル"をダウンロード
STM32F100x データシート"STM32F100x データシート"をダウンロード
STM32CubeMXのユーザスマニュアル"STM32CubeMXのユーザスマニュアル"をダウンロード
STM32F1xxx HALドライバ・ユーザマニュアル"STM32F1xxx HALドライバ・ユーザマニュアル"をダウンロード

プログラム関係

STM32CubeMX その4-タイマ1、PWM出力

$
0
0

PWM出力

出力ピンのHighとLowの比率で実現するPWM出力である。

今回はSTM32CubeMX その3-タイマ1比較出力(アウトプットコンペア)で作ったSTM32CubeMXのファイルを再設定して利用し、タイマ1の4つの出力ピンをじんわりと点灯消灯させてみる。

STM32CubeMXの変更箇所

別名保存

STM32CubeMX その3-タイマ1比較出力(アウトプットコンペア)で作ったSTM32CubeMXのファイルを一旦読み込んで別名保存しなおす。

別名で保存

別名で保存


クロック設定はそのまま使えるということだ。

Pinoutの再設定

タイマ1の4つの出力ピンをPWMで利用できるように、TIM1の各ピンをPWM Generation CHxにする。

Pinoutの再設定

Pinoutの再設定

TIM1の詳細設定

ここで改めてPWMのタイミングである。

比較出力とPWMのタイミング

比較出力とPWMのタイミング

この表を見ながら以下のように設定した。

TIM1の設定

TIM1の設定

PWMの周期はLEDがチラチラしなければよいので、72MHzのクロックを7200分割(7200-1)にし自動再ロードレジスタを100(100-1)にした。自動再ロードレジスタを100(100-1)にしたのでLEDを100階調で変化させることができる。

各ピンのPWMのモードだがドキュメントを読んだがmode1とmode2の違いがよく分からなかった。とりあえずPWM mode1とした。
各ピンのpulse値でPWMの割合が決まるのだが、今回はプログラムで変更するので、ここもとりあえず0に設定した。
以上である。

プログラム生成

初期コードを生成である。これにてSTM32CubeMXの作業は終わりである。

プロジェクトの生成

プロジェクトの生成

コードを追加

今回はPWMをスタートさせるコードと、変化させるコードを追加した。

まずはスタートさせるコード。/* USER CODE BEGIN 2 */と/* USER CODE END 2 */の間に以下のコードを追加した。

  /* USER CODE BEGIN 2 */
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE END 2 */

そして変化させるコードの追加は2ケ所。
まず /* USER CODE BEGIN 1 */と /* USER CODE END 1 */の間に

  /* USER CODE BEGIN 1 */
  int pwm;

  /* USER CODE END 1 */

そして /* USER CODE BEGIN 3 */と /* USER CODE END 3 */の間に

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    
    for(pwm = 0; pwm < 100; pwm++)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,pwm);
      HAL_Delay(10);
    }
    for(pwm = 99; pwm >= 0; pwm--)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,pwm);
      HAL_Delay(10);
    }   
    
    for(pwm = 0; pwm < 100; pwm++)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,pwm);
      HAL_Delay(10);
    }
    for(pwm = 99; pwm >= 0; pwm--)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_2,pwm);
      HAL_Delay(10);
    } 
    
    for(pwm = 0; pwm < 100; pwm++)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,pwm);
      HAL_Delay(10);
    }
    for(pwm = 99; pwm >= 0; pwm--)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,pwm);
      HAL_Delay(10);
    } 
    for(pwm = 0; pwm < 100; pwm++)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,pwm);
      HAL_Delay(10);
    }
    for(pwm = 99; pwm >= 0; pwm--)
    {
      __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,pwm);
      HAL_Delay(10);
    } 
  }
  /* USER CODE END 3 */

これで4つのLEDが順送りにじんわりと点灯消灯するようになる。

__HAL_TIM_SetCompare関数はコンベアレジスタ(STM32CubeMXならpulse値)を再設定する関数である。
STM32は動作中に再設定しても問題なく動作する。

参考資料

データシート関係

今となっては日本語マニュアル等をどこで入手したかわからないので、当方手持ちのPDFファイルをアップロード公開した。最新版があるならそちらを参考してください。

STM32F100xx 日本語リファレンスマニュアル"STM32F100xx 日本語リファレンスマニュアル"をダウンロード
STM32F103xx日本語リファレンスマニュアル"STM32F103xx日本語リファレンスマニュアル"をダウンロード
STM32F100x データシート"STM32F100x データシート"をダウンロード
STM32CubeMXのユーザスマニュアル"STM32CubeMXのユーザスマニュアル"をダウンロード
STM32F1xxx HALドライバ・ユーザマニュアル"STM32F1xxx HALドライバ・ユーザマニュアル"をダウンロード

プログラム関係

STM32CubeMX その5-タイマ1、更新割り込み

$
0
0

割り込み

今回はSTM32は複雑なMPUであり高性能なタイマであるタイマ1を利用しているので、一番簡単な更新割り込みつまり、自動再ロードレジスタが溢れたときに発生する割り込みが主題である。
割り込みで一秒周期で、オンボードのLEDを点滅させるプログラムを作ることにする。

Pinoutの再設定

今回も前回作ったSTM32CubeMXのファイルをtim1_led_interruptとして別名保存する。

そしてPinoutの再設定である。
一つ目はオンボードLEDの設定である。このLEDはPC13に接続されており、ピンの状態がHighの時は消灯しLowの時は点灯する。

オンボートLEDのPin設定

オンボートLEDのPin設定


MPUのイラストのPC13の端子を右クリックするとメニューが現れるのでGPIOの出力ピンとして設定し、別名をONBOARD_LEDとしておく、便利なことにこのONBOARD_LEDという名称が生成されるプログラムで利用できるようになる。

つぎはタイマ1の設定である。クロックのみタイマ1に供給し、各チャンネルのタイマピンはDisableにする。
この設定で各チャンネルのタイマピンはタイマから切り離されたことになる。

クロックだけを供給

クロックだけを供給

これでPinoutの設定終わり。

TIM1の詳細設定

更新割り込みが入るようにTIM Update interruptにチェックを入れる。

TIM1 update interruptにチェック

TIM1 update interruptにチェック

次に1秒周期、つまり500ms毎に割り込が入るようにプリスケールと自動再ロードレジスタの設定である。

タイマ1の設定

タイマ1の設定

プリスケールは36000分周(36000-1)なので72MHz÷36000=2KHzの周期、そして自動再ロードレジスタを1000(1000-1)にしたので、これで2Hzつまり500msの割り込みが発生するようになる。

以上である。

プログラム生成

初期コードを生成である。これにてSTM32CubeMXの作業は終わりである。

プログラムの生成

プログラムの生成

コードを追加

まずはいつものように、割り込み開始のコードを/* USER CODE BEGIN 2 */と/* USER CODE END 2 */の間に追加した。

  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim1);

  /* USER CODE END 2 */

HALライブラリィの割り込みのプログラム流儀は、HALライブラリィ指定のコールバック関数に処理を書く、今回はHAL_TIM_PeriodElapsedCallbackという関数を、/* USER CODE BEGIN 0 */と/* USER CODE END 0 */の間に追加した。

/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim->Instance == TIM1)
  {
    HAL_GPIO_TogglePin(ONBOARD_LED_GPIO_Port, ONBOARD_LED_Pin);
  }
}
/* USER CODE END 0 */

STM32CubeMXでオンボードLEDの別名をONBOARD_LEDとするとONBOARD_LED_GPIO_PortとかONBOARD_LED_Pinとかが定義されより抽象的にコードを書くことができる。

HAL_TIM_PeriodElapsedCallbackはタイマのハンドルが渡ってくるのでタイマ1の割り込みか否かチェックする必要がある。

これで書き込めば一秒間隔でオンボードLEDが点滅する。

参考資料

データシート関係

今となっては日本語マニュアル等をどこで入手したかわからないので、当方手持ちのPDFファイルをアップロード公開した。最新版があるならそちらを参考してください。

STM32F100xx 日本語リファレンスマニュアル"STM32F100xx 日本語リファレンスマニュアル"をダウンロード
STM32F103xx日本語リファレンスマニュアル"STM32F103xx日本語リファレンスマニュアル"をダウンロード
STM32F100x データシート"STM32F100x データシート"をダウンロード
STM32CubeMXのユーザスマニュアル"STM32CubeMXのユーザスマニュアル"をダウンロード
STM32F1xxx HALドライバ・ユーザマニュアル"STM32F1xxx HALドライバ・ユーザマニュアル"をダウンロード

プログラム関係

STM32CubeMX その6- USB-CDCの実装

$
0
0

STM32F103C8T6マイコンボードのUSB-CDC

次のネタはタイマのインプットキュプチャを利用してロータリエンコーダをゴリゴリ回して回転数を計測するというプログラムとか、タイマの比較出力(アウトプットコンペア)の周波数を微妙に設定しなおして音階を出すプログラムなどを用意してるのですが、ロータリエンコーダとか圧電スピーカーなどのモジュールを組み立てていないので今回はペンディングというとで、USB-CDCをやってみる。

マイコンボードにはUSB端子が付いていて、PCなどに接続すると電源が供給されるが、PC側は不明なデバイスが接続されたと警告が出てしまう。ハードウェアのレベルでは接続されているが、ソフトウェアがのっていないのでエラーが出てしまうのだ。

STM32F4-DicoveryなどはUSB OTG機能があるのでUSBメモリなどを接続して利用することができるが、STM32F103C8T6はUSB OTG機能ないのでUSBメモリなどを接続しても利用ができないが、適切なプログラムを載せればPCから見てUSBクライアントデバイスとしてふるまうことができる。
USBクライアントソフトによってPCから見てSTM32F103C8T6マイコンボードをUSBマウスやキーボードUSBメモリなど見せることができるが、今回はあとあと使い道がありそうなPCとの通信ができるUSB-CDCとして実装してみる。

STM32CubeMXでの設定

今回もSTM32CubeMXでの設定から始まる、MPUの選択やクロック設定をいちから始めるのは邪魔臭いので前回作ったSTM32CubeMXのファイルをCDC_testとして別名保存する。

別名保存

別名保存

Pinoutの再設定

Pinoutの再設定である。
USBにチェックを入れ、Class For FS IPはCDCを選択する。

Pinoutの設定

Pinoutの設定

これでPinoutの設定終わり。CDCに必要なMiddle Wareがインクルードされる。

詳細設定

Configurationのタブをクリックしたのがこれだ。

コンフィグ

コンフィグ

USB_DevviceのMiddle wareがインクルードされたのが分かる。
今回は割り込みやDMAなどを利用しないのでデフォルトのままで使用する。

以上である。

プログラム生成

初期コードを生成である。これにてSTM32CubeMXの作業は終わりである。

プログラム生成

プログラム生成

コードを追加

USB_DevviceのMiddle wareのソースも生成されている。赤ペンで囲んだところだ。

生成されたファイル

生成されたファイル

STM32F103C8T6マイコンボードがCDCデバイスとして認識されテキストを送信するのが今回のゴールだ。

STM32CubeMXで生成されたプログラムは初期化まで完了している。今回も同じだ。

/* USER CODE BEGIN Includes */と/* USER CODE END Includes */に、以下を追加

/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"

/* USER CODE END Includes */

さらに/* USER CODE BEGIN 1 */と /* USER CODE END 1 */の間に

  /* USER CODE BEGIN 1 */
    uint8_t Buf[] = "test\n";

  /* USER CODE END 1 */

そして/* USER CODE BEGIN 3 */と /* USER CODE END 3 */の間に追加

  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    CDC_Transmit_FS(Buf, sizeof(Buf));
    HAL_Delay(1000);
  }
  /* USER CODE END 3 */

これで、終わりである。
今回はusbd_cdc_if.cは弄らないが、CDC_Transmit_FSはusbd_cdc_if.cで実装されていてCDC経由で文字列を送信する関数である。

これをコンパイルして書き込めばOKなはず。

STM32 Virtual Comport Driver

Windows環境では、ここからSTM32 Virtual Comport Driverをダウンロードしてインストールする必要がある。

トラブル発生!!

これで問題なく動くはずだが、PCはSTM32F103C8T6マイコンボードをCDCデバイスとして認識しないのだ。

試行錯誤した結果、使用していないRTCを外してSTM32CubeMXでプログラムを再生成したらCDCデバイスとして認識した。
RTCとCDCは両立できるばすだが!???
もしかしたらSTM32F103C8T6マイコンボードの回路のミスとか、実装時の半田トラブルなどがあるのかもしれない。

認識した

認識した

データシート関係

今となっては日本語マニュアル等をどこで入手したかわからないので、当方手持ちのPDFファイルをアップロード公開した。最新版があるならそちらを参考してください。

STM32F100xx 日本語リファレンスマニュアル"STM32F100xx 日本語リファレンスマニュアル"をダウンロード
STM32F103xx日本語リファレンスマニュアル"STM32F103xx日本語リファレンスマニュアル"をダウンロード
STM32F100x データシート"STM32F100x データシート"をダウンロード
STM32CubeMXのユーザスマニュアル"STM32CubeMXのユーザスマニュアル"をダウンロード
STM32F1xxx HALドライバ・ユーザマニュアル"STM32F1xxx HALドライバ・ユーザマニュアル"をダウンロード

プログラム関係

NodeMCU V1.0(ESP8266)の勉強 その1-WebServer

$
0
0

youtubeでESP8266(NodeMCU V1.0)のチュートリアル

最近は引っ越して、何かと忙しく電子工作は中断状態だ。

一昨日、新しく買ったTVでyoutubeを観てると、NodeMCU V1.0のWebServerの構築のチュートリアルビデオがリストに上がってきたので観てみた。これによると結構簡単にWebServerが構築できるようなのだ。
そういえば、昨年アマゾンの中華ショップで色々と電子部品を購入したのだが放置状態、このビデオで使われているNodeMCU V1.0もあったはず、ふたつ買ったNodeMCU V1.0(ESP8266)もひとつだけ封を開けオンボードLEDをチカチカさせただけだった。
とう言うわけでチュートリアルビデオとネットを頼りで学習してみることにした。

ESP8266 for Arduinoの備忘録

最近は物覚えが悪くなっているので、少し時間が経つと学習したことをすっかり忘れてまう可能性があるのでメモを残す。

ESP8266 for Arduinoの基本

ArduinoでESP8266をWebServerに仕立てるには、以下のようにプログラムを書けばよいらしい、結構シンプルな記述ができるようだ。
WiFiオブジェクトでWiFiルータに接続し、severオブジェクトでWebサーバの振る舞いを書くということみたいだ。

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

const char* ssid = "xxxxxx";
const char* password = "xxxxxx";

void setup()
{
    Serial.begin(115200);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(500);
    }
    Serial.println("");
    Serial.print("Local IP: ");
    Serial.println(WiFi.localIP());

    server.on("/", []() {
        server.send(200, "text/plain", "Hello World!");
    });
    server.begin();
    Serial.println("HTTP server started");
}

void loop()
{
    server.handleClient();
}

サーバオブジェクトのURLルーティング

サーバオブジェクトのURLルーティングはserver.on関数とserver.onNotFound関数が引き受け、応答レスポンスを記述するようだ。

書き方は以下のとおりserver.on関数にURLルートと応答関数のポインタを渡す。

  ・
  ・
void onRoot()
{
    server.send(200, "text/plain", "Hello World!");
}
  ・
  ・  
void setup()
{
  ・
  ・
    server.on("/", onRoot);
  ・
  ・
}

または、以下のようにラムダ式で書いてもOKなようだ。

void setup()
{
  ・
  ・
    server.on("/", []() {
        server.send(200, "text/plain", "Hello World!");
    });
  ・
  ・
}

ちなみにWebでは存在しないファイルにアクセスしたときのURLルーティングはserver.onNotFound関数が引き受け、以下のように書くようだ。

  ・
  ・
void handleNotFound()
{
    server.send(404, "text/plain", "File Not Found");
}
  ・
  ・
void setup()
{
  ・
  ・
    server.onNotFound(handleNotFound);
  ・
  ・
}

LEDサーバで実験

サーバといえば情報などを資源を提供するのが役目、NodeMCU V1.0(ESP8266)はセンサなどのハードウェアを自在に扱えるので、ハードウェアの資源を提供するサーバに仕立てることにする。

ここではNodeMCU V1.0(ESP8266)のオンボードLEDというデバイスを提供するサーバに仕立ててみた。
以下の機能を実装した。

  • LEDの点灯・消灯の制御
  • “LEDの点灯・消灯の回数”という情報の提供

コードは以下の通り。

#include <ArduinoJson.h>
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>

ESP8266WebServer server(80);

const char* ssid = "XXXXXXXXX";
const char* password = "XXXXXXXX";

// HTML
const String html_header =
    "<!doctype html>"
    "<html><head><meta charset=\"UTF-8\"/>"
    "<meta name=\"viewport\" content=\"width=device-width\"/>"
    "<title>ESP8266 テスト</title>"
    "</head><body>";

const String html_footer = "</body></html>";

int led_on_req_count = 0;
int led_off_req_count = 0;

void handleNotFound()
{
    digitalWrite(LED_BUILTIN, LOW); // ボード上のLED点灯
    String message = "File Not Found\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET) ? "GET" : "POST";
    message += "\nArguments: ";
    message += server.args();
    message += "\n";
    for (uint8_t i = 0; i < server.args(); i++)
    {
        message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }
    server.send(404, "text/plain", message);
    digitalWrite(LED_BUILTIN, HIGH); // ボード上のLED消灯
}

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output

    Serial.begin(115200);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(500);
    }
    Serial.println("");
    Serial.print("Local IP: ");
    Serial.println(WiFi.localIP());

    server.on("/", []() {
        String html =
            html_header +
            "<h1>NodeMCU!</h1><br>ようこそESP8266 for Arduinoのプログラムへ" +
            html_footer;
        server.send(200, "text/html", html);

    });

    server.on("/led/on", []() {
        String html =
            html_header + "<h1>NodeMCU!</h1><br>LED点灯" + html_footer;
        digitalWrite(LED_BUILTIN, LOW);
        led_on_req_count++;
        server.send(200, "text/html", html);
    });

    server.on("/led/off", []() {
        String html =
            html_header + "<h1>NodeMCU!</h1><br>LED消灯" + html_footer;
        digitalWrite(LED_BUILTIN, HIGH);
        led_off_req_count++;
        server.send(200, "text/html", html);
    });

    server.on("/ledToggle", []() {
        String html;

        if (digitalRead(LED_BUILTIN) == HIGH)
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED点灯" + html_footer;
            digitalWrite(LED_BUILTIN, LOW);
            led_on_req_count++;
        }
        else
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED消灯" + html_footer;
            digitalWrite(LED_BUILTIN, HIGH);
            led_off_req_count++;
        }
        server.send(200, "text/html", html);

    });

    server.on("/led", []() {
        String html;
        String led_condition = server.arg("light");

        if (led_condition == "on")
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED点灯" + html_footer;
            digitalWrite(LED_BUILTIN, LOW);
            led_on_req_count++;
        }
        else if (led_condition == "off")
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED消灯" + html_footer;
            digitalWrite(LED_BUILTIN, HIGH);
            led_off_req_count++;
        }
        else
        {
            html = html_header +
                   "<h1>NodeMCU!</h1><br>データの渡し方が間違ってます!!" +
                   html_footer;
            digitalWrite(LED_BUILTIN, HIGH);
        }
        server.send(200, "text/html", html);
    });

    server.on("/jBlink", []() {
        String data = server.arg("plain");
        StaticJsonBuffer<200> jBuffer;
        JsonObject& jObject = jBuffer.parseObject(data);
        String n = jObject["times"];
        String t = jObject["delay"];
        for (int i = 0; i < n.toInt(); i++)
        {
            digitalWrite(LED_BUILTIN, LOW);
            delay(t.toInt());
            led_on_req_count++;

            digitalWrite(LED_BUILTIN, HIGH);
            delay(t.toInt());
            led_off_req_count++;

            server.send(204, "");
        }
    });

    server.on("/led.json", []() {
        String json_output;
        StaticJsonBuffer<200> jBuffer;
        JsonObject& root = jBuffer.createObject();
        // データ登録
        root["name"] = "ESP8266WebServer";
        root["on_req_count"] = led_on_req_count;
        root["off_req_count"] = led_off_req_count;
        root.printTo(json_output);
        server.send(200, "application/json", json_output);
    });

    server.onNotFound(handleNotFound);

    server.begin();
    Serial.println("HTTP server started");
}

void loop()
{
    server.handleClient();
}

LEDの点灯・消灯の制御

LEDの点灯・消灯の制御は、いくつかの方法が考えられたので冗長的であるが実装した。

URLルーティングでLED制御

一番簡単なのが、URLルーティングでLED制御だ。

“http://xxx.xxx.xxx.xxx/led/on”にブラウザなどでアクセスしたときLEDは点灯させるには、以下のように書く。

  ・
  ・
    server.on("/led/on", []() {
        String html =
            html_header + "<h1>NodeMCU!</h1><br>LED点灯" + html_footer;
        digitalWrite(LED_BUILTIN, LOW);
        led_on_req_count++;
        server.send(200, "text/html", html);
    });
  ・
  ・

“http://xxx.xxx.xxx.xxx/led/off”にブラウザなどでアクセスしたときLEDは消灯させるには、以下のように書く。

  ・
  ・
    server.on("/led/off", []() {
        String html =
            html_header + "<h1>NodeMCU!</h1><br>LED消灯" + html_footer;
        digitalWrite(LED_BUILTIN, HIGH);
        led_off_req_count++;
        server.send(200, "text/html", html);
    });
  ・
  ・

“http://xxx.xxx.xxx.xxx/ledToggle”にブラウザなどでアクセスしたときLEDは点灯/消灯させるには、以下のように書く。

  ・
  ・
    server.on("/ledToggle", []() {
        String html;

        if (digitalRead(LED_BUILTIN) == HIGH)
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED点灯" + html_footer;
            digitalWrite(LED_BUILTIN, LOW);
            led_on_req_count++;
        }
        else
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED消灯" + html_footer;
            digitalWrite(LED_BUILTIN, HIGH);
            led_off_req_count++;
        }
        server.send(200, "text/html", html);
    });
  ・
  ・

GETメソッドによるLED制御

“http://xxx.xxx.xxx.xxx/led?light=on”にブラウザなどでアクセスしたときLEDを点灯。または”http://xxx.xxx.xxx.xxx/led?light=off”のときLEDを消灯させるには以下のように書く。

  ・
  ・
    server.on("/led", []() {
        String html;
        String led_condition = server.arg("light");

        if (led_condition == "on")
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED点灯" + html_footer;
            digitalWrite(LED_BUILTIN, LOW);
            led_on_req_count++;
        }
        else if (led_condition == "off")
        {
            html = html_header + "<h1>NodeMCU!</h1><br>LED消灯" + html_footer;
            digitalWrite(LED_BUILTIN, HIGH);
            led_off_req_count++;
        }
        else
        {
            html = html_header +
                   "<h1>NodeMCU!</h1><br>データの渡し方が間違ってます!!" +
                   html_footer;
            digitalWrite(LED_BUILTIN, HIGH);
        }
        server.send(200, "text/html", html);
    });
  ・
  ・

WebAPIでLED制御

LEDの制御をするWebAPIを実装してみる。データの受け渡しはXMLとかjsonとかが一般的らしいのだが、ここはjavascriptで簡単に扱えるjsonを扱う。

実装したのは{“times”:5,”delay”:250}というjsonデータを送れば、(250ms x 2)間隔で5回点滅するというWebAPIである。

  ・
  ・
    server.on("/jBlink", []() {
        String data = server.arg("plain");
        StaticJsonBuffer<200> jBuffer;
        JsonObject& jObject = jBuffer.parseObject(data);
        String n = jObject["times"];
        String t = jObject["delay"];
        for (int i = 0; i < n.toInt(); i++)
        {
            digitalWrite(LED_BUILTIN, LOW);
            delay(t.toInt());
            led_on_req_count++;

            digitalWrite(LED_BUILTIN, HIGH);
            delay(t.toInt());
            led_off_req_count++;

            server.send(204, "");
        }
    });
  ・
  ・

そしてRubyで書いたjsonを”http://xxx.xxx.xxx.xxx/jBlink”に送るクライアントプログラム

#!/usr/bin/env ruby

require 'uri'
require 'net/http'
require 'json'

uri = URI('http://xxx.xxx.xxx.xxx/jBlink')
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req.body = {:times => 10, :delay => 250}.to_json
http = Net::HTTP.new(uri.hostname, uri.port)
http.set_debug_output $stderr  #

http.start do |h|
  response = h.request(req)
end

そしてUbuntu上で実行したときの応答。
デバッグモードにしてるのでjsonデータが無事送信されたことがわかる。

bant@ORCA:~/workspace/Arduino/webserver_ruby_client/client$ ./blink_req.rb 
opening connection to 192.168.1.108:80...
opened
<- "POST /jBlink HTTP/1.1\r\nContent-Type: application/json\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nHost: 192.168.1.108\r\nContent-Length: 24\r\n\r\n"
<- "{\"times\":10,\"delay\":250}"
-> "HTTP/1.1 204 No Content\r\n"
-> "Content-Type: \r\n"
-> "Content-Length: 0\r\n"
-> "Connection: close\r\n"
-> "Access-Control-Allow-Origin: *\r\n"
-> "\r\n"
Conn close

“LEDの点灯・消灯の回数”という情報の提供3>

ブラウザ・WebAPIで情報提供

以下の実装で”http://xxx.xxx.xxx.xxx/led.json”というWeb上仮想ファイルにアクセスされたらjsonデータを送信する。

  ・
  ・
    server.on("/led.json", []() {
        String json_output;
        StaticJsonBuffer<200> jBuffer;
        JsonObject& root = jBuffer.createObject();
        // データ登録
        root["name"] = "ESP8266WebServer";
        root["on_req_count"] = led_on_req_count;
        root["off_req_count"] = led_off_req_count;
        root.printTo(json_output);
        server.send(200, "application/json", json_output);
    });
  ・
  ・

rubyで書いたクライアントプログラム

#!/usr/bin/env ruby

require 'net/http'
require 'uri'
require 'json'

uri = URI.parse('http://xxx.xxx.xxx.xxx/led.json')

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = false
http.set_debug_output $stderr

res = http.start do |h|
  h.get(uri.request_uri)
end

if res.code == '200'
  result = JSON.parse(res.body)
  puts result
else
  puts "ERROR!! #{res.code} #{res.message}"
end

そしてUbuntu上で実行したときの応答。
デバッグモードにしているが、こちらは表示が少々うざい(^_^;;

bant@ORCA:~/workspace/Arduino/webserver_ruby_client/client$ ./json_req.rb 
opening connection to 192.168.1.108:80...
opened
<- "GET /led.json HTTP/1.1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nAccept: */*\r\nUser-Agent: Ruby\r\nHost: 192.168.1.108\r\n\r\n"
-> "HTTP/1.1 200 OK\r\n"
-> "Content-Type: application/json\r\n"
-> "Content-Length: 64\r\n"
-> "Connection: close\r\n"
-> "Access-Control-Allow-Origin: *\r\n"
-> "\r\n"
reading 64 bytes...
-> ""
-> "{\"name\":\"ESP8266WebServer\",\"on_req_count\":30,\"off_req_count\":30}"
read 64 bytes
Conn close
{"name"=>"ESP8266WebServer", "on_req_count"=>30, "off_req_count"=>30}

30回ずつLEDの点灯・消灯をしたことがわかる。
Webブラウザ上のベタな表示なら利用するのは大変だが、jsonやXMLのような構造的なデータならばアプリで活用しやすい。

とりあえずWebServerはこれで終わり

クライアントとかUDPなどでの実験は残っているが、WebServerに関しては、これぐらいツボを抑えておけば、なんとかなりそうだ。

Viewing all 39 articles
Browse latest View live