Arduino勉強会

2014/11/16からのアクセス回数 2021

勉強会の参加者で、I2Cのデバイスを使ってパソコンにデータを送る小さなアダプターあると便利という ご意見があり、LPC810を使って試してみようと思います。

ここで、紹介しているプログラムは、Githubにlbed/LBED_LPC810から取得できます。

LPC810を使ったI2Cデバイスのシリアル読み込みプログラム

サンプリングレートが1秒間に1回程度なので、パソコンへはGPIOを使ったソフトシリアルで通信します。 *1

LPC810の5番ピンをソフトシリアルの送信用に使用します。 LM73を使って温度センサーの値をシリアルに送信ガジェットをブレッドボードに組みました。

bread.png

変なエラー

どうもI2Cデバイスからの応答が2回目以降表示されない、奇妙なバグが発生しました。

こんな時には、プロトコルアナライザとして購入しておいたLabToolの出番です。

LabToolでデバッグ

ターゲットデバイスとLabToolの結線を以下に示します。 *2

ここでは、D1, D2にSDA, SCLを接続しました。

LabToolLPC810
D1: 茶8: SDA
D2: 赤2: SCL
  • LabToolを起動し、Newを選択する。
  • Add Signalをクリックし、D1, D2をチェックし、Analyzers:でI2C Analyzerを選択する。

Add_signal.png

  • I2C AnalyzerでSDAにD1, SCLにD2を選択し、Synchronize: Triggerを選択する

I2C_Analyzer.png

Analyzerの結果

デバッガでI2C関連の関数でブレークポイントをセットし、

  • 初期化
  • 1回目の読み込み
  • 2回目の読み込み

をアナライザーに掛けてみると以下のようになりました。

初期化は、プログラム通りの動きを確認

  • 0x4CのアドレスにData 0x04, 0x60を書き込み
  • 0x4CのアドレスにData 0x00を書き込む

th_initialize.jpg

1回目の読み込みでは、

  • 0x4Cのアドレスに0x00を送ると
  • 0x4Cのアドレスから0x0b, 0x64が返される

th_first_read.jpg

一方2回目の読み込みでは、

  • 0x4Cのアドレスに0x10を送って、ここで止まっている。

th_2nd_read.jpg

障害の原因

これまで何回も使っていたLM73::readメソッドにバグがあることが判明しました。 送信用のコマンド0x00をセットするのを忘れていた。

int LM73::read()
{
    char cmd[2];
     // cmdの1バイト目を0をセットし忘れている。2014/11/16発見
     cmd[0] = 0;
     i2c.read( LM73_ADDR, cmd, 2); // Send command string
     int int_val = cmd[0] <<1 | cmd[1]>>7;
     int ceil_val = ((cmd[1] & 0x7f)*200) >>8;
     return (int_val*10 + ceil_val/10);
}

完成したI2Cからシリアルへの送信プログラム

LPC810では、float型を使用すると急にプログラムサイズが大きくなるため、 温度センサーLM73の戻り値を小数点1桁までの温度を整数とする値に変更しました。

以下にI2Cから読み込んだ値をシリアルに送信するプログラムを示します。 このプログラムは、I2CデバイスLM73から値を読み取り、シリアルに4800ボーで送信する 簡単なものです。

#include "lbed.h"
#include "SoftSerialTxOnly.h"
#include "LPC8xx.h"

// 4800bps
#define SERIAL_TIME_PER_BIT1    105
#define SERIAL_TIME_PER_BIT2    104

SoftSerialTxOnly::SoftSerialTxOnly(PinName pin) : _out(pin) {

}

int SoftSerialTxOnly::_putc(int value) {
     uint8_t data = value;
     _out = 0;
     wait_us(SERIAL_TIME_PER_BIT1);

     uint8_t i;
     for (int cnt = 0, i=0x01; cnt < 8; i<<=1, cnt++) {
          if (data & i)
               _out = 1;
          else
               _out = 0;
          wait_us(SERIAL_TIME_PER_BIT2);
     }
     _out = 1;
     wait_us(SERIAL_TIME_PER_BIT1);

     return value;
}

メインのプログラムは、以下の通りです。

/*
  SoftSerialTxOnly
  I2CデバイスLM73から値を読み取り、シリアルに4800ボーで送信する
 */

#ifdef __USE_CMSIS
#include "LPC8xx.h"
#endif

#include <cr_section_macros.h>

#include "lbed.h"
#include "SoftSerialTxOnly.h"
#include "LM73.h"

int main(void) {
    // lbedライブラリの初期化
    lbed_setup();
     /* I2C用スイッチマトリックスの設定 */
     I2C_SwitchMatrix_Init();

     // 8番ピンSDA, 2番ピンSCL
     LM73lm73(P8, P2);
     // 5番ピンをURARTのRxに接続
     SoftSerialTxOnly pc(P5);
     pc.println("Hello World\n");
     while(1) {
         pc.print("temp=");
        //pc.print(lm73.read(), 2);
        // floatを使うとサイズオーバーになるので、0.1度までを整数で出力
        int v = lm73.read();
        pc.print(v, DEC);
        pc.println();
        wait_ms(1000);// 1秒待つ
    }
    return 0 ;
}

コメント

選択肢 投票
おもしろかった 3  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。勉強会で分からなかったこと等、お気軽に問い合わせて下さい。

スパム防止に画像の文字列も入力してください。

  • SoftWerialTxOnlyのソースを忘れていました。 -- 竹本 浩? 2014-12-13 (土) 11:01:17

(Input image string)


*1 そのため、文字化けすることがあります。
*2 デジタルインプットピンは、自由に選択できます。

添付ファイル: fileI2C_Analyzer.png 421件 [詳細] fileAdd_signal.png 396件 [詳細] fileth_initialize.jpg 330件 [詳細] fileth_first_read.jpg 340件 [詳細] fileth_2nd_read.jpg 324件 [詳細] fileinitialize.png 166件 [詳細] filefirst_read.png 153件 [詳細] filebread.png 355件 [詳細] file2nd_read.png 159件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-03-26 (木) 23:46:12 (996d)
SmartDoc