{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"オリジナルの作成:2014/11/16"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 0D-LPC810でI2Cデバイスの値を取得する\n",
"勉強会の参加者で、I2Cのデバイスを使ってパソコンにデータを送る小さなアダプターあると便利という ご意見があり、LPC810を使って試してみようと思います。\n",
"\n",
"ここで、紹介しているプログラムは、Githubにlbed/LBED_LPC810から取得できます。\n",
"\n",
"- https://github.com/take-pwave/lbed"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## LPC810を使ったI2Cデバイスのシリアル読み込みプログラム \n",
"サンプリングレートが1秒間に1回程度なので、パソコンへはGPIOを使ったソフトシリアルで通信します。 \n",
"\n",
"LPC810の5番ピンをソフトシリアルの送信用に使用します。 LM73を使って温度センサーの値をシリアルに送信ガジェットをブレッドボードに組みました。\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 変なエラー\n",
"どうもI2Cデバイスからの応答が2回目以降表示されない、奇妙なバグが発生しました。\n",
"\n",
"こんな時には、プロトコルアナライザとして購入しておいたLabToolの出番です。\n",
"\n",
"### LabToolでデバッグ\n",
"ターゲットデバイスとLabToolの結線を以下に示します。 \n",
"\n",
"ここでは、D1, D2にSDA, SCLを接続しました。\n",
"\n",
" | LabTool\t | LPC810 | \n",
" |---|---|\n",
" | D1: 茶\t | 8: SDA | \n",
" | D2: 赤\t | 2: SCL | \n",
"\n",
"LabToolを起動し、Newを選択する。\n",
"Add Signalをクリックし、D1, D2をチェックし、Analyzers:でI2C Analyzerを選択する。\n",
"\n",
"\n",
"\n",
"I2C AnalyzerでSDAにD1, SCLにD2を選択し、Synchronize: Triggerを選択する\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Analyzerの結果\n",
"デバッガでI2C関連の関数でブレークポイントをセットし、\n",
"\n",
"- 初期化\n",
"- 1回目の読み込み\n",
"- 2回目の読み込み\n",
"\n",
"をアナライザーに掛けてみると以下のようになりました。\n",
"\n",
"初期化は、プログラム通りの動きを確認\n",
"\n",
"- 0x4CのアドレスにData 0x04, 0x60を書き込み\n",
"- 0x4CのアドレスにData 0x00を書き込む\n",
"\n",
"\n",
"\n",
"1回目の読み込みでは、\n",
"\n",
"- 0x4Cのアドレスに0x00を送ると\n",
"- 0x4Cのアドレスから0x0b, 0x64が返される\n",
"\n",
"\n",
"\n",
"一方2回目の読み込みでは、\n",
"\n",
"0x4Cのアドレスに0x10を送って、ここで止まっている。\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 障害の原因\n",
"これまで何回も使っていたLM73::readメソッドにバグがあることが判明しました。 送信用のコマンド0x00をセットするのを忘れていた。\n",
"\n",
"```C++\n",
"int LM73::read()\n",
"{\n",
" char cmd[2];\n",
" // cmdの1バイト目を0をセットし忘れている。2014/11/16発見\n",
" cmd[0] = 0;\n",
" i2c.read( LM73_ADDR, cmd, 2); // Send command string\n",
" int int_val = cmd[0] <<1 | cmd[1]>>7;\n",
" int ceil_val = ((cmd[1] & 0x7f)*200) >>8;\n",
" return (int_val*10 + ceil_val/10);\n",
"}\n",
"```\n",
"\n",
"### 完成したI2Cからシリアルへの送信プログラム\n",
"LPC810では、float型を使用すると急にプログラムサイズが大きくなるため、 温度センサーLM73の戻り値を小数点1桁までの温度を整数とする値に変更しました。\n",
"\n",
"以下にI2Cから読み込んだ値をシリアルに送信するプログラムを示します。 このプログラムは、I2CデバイスLM73から値を読み取り、シリアルに4800ボーで送信する 簡単なものです。\n",
"\n",
"```C++\n",
"#include \"lbed.h\"\n",
"#include \"SoftSerialTxOnly.h\"\n",
"#include \"LPC8xx.h\"\n",
"\n",
"// 4800bps\n",
"#define SERIAL_TIME_PER_BIT1 105\n",
"#define SERIAL_TIME_PER_BIT2 104\n",
"\n",
"SoftSerialTxOnly::SoftSerialTxOnly(PinName pin) : _out(pin) {\n",
"\n",
"}\n",
"\n",
"int SoftSerialTxOnly::_putc(int value) {\n",
" uint8_t data = value;\n",
" _out = 0;\n",
" wait_us(SERIAL_TIME_PER_BIT1);\n",
"\n",
" uint8_t i;\n",
" for (int cnt = 0, i=0x01; cnt < 8; i<<=1, cnt++) {\n",
" if (data & i)\n",
" _out = 1;\n",
" else\n",
" _out = 0;\n",
" wait_us(SERIAL_TIME_PER_BIT2);\n",
" }\n",
" _out = 1;\n",
" wait_us(SERIAL_TIME_PER_BIT1);\n",
"\n",
" return value;\n",
"}\n",
"メインのプログラムは、以下の通りです。\n",
"\n",
"/*\n",
" SoftSerialTxOnly\n",
" I2CデバイスLM73から値を読み取り、シリアルに4800ボーで送信する\n",
" */\n",
"\n",
"#ifdef __USE_CMSIS\n",
"#include \"LPC8xx.h\"\n",
"#endif\n",
"\n",
"#include \n",
"\n",
"#include \"lbed.h\"\n",
"#include \"SoftSerialTxOnly.h\"\n",
"#include \"LM73.h\"\n",
"\n",
"int main(void) {\n",
" // lbedライブラリの初期化\n",
" lbed_setup();\n",
" /* I2C用スイッチマトリックスの設定 */\n",
" I2C_SwitchMatrix_Init();\n",
"\n",
" // 8番ピンSDA, 2番ピンSCL\n",
" LM73lm73(P8, P2);\n",
" // 5番ピンをURARTのRxに接続\n",
" SoftSerialTxOnly pc(P5);\n",
" pc.println(\"Hello World\\n\");\n",
" while(1) {\n",
" pc.print(\"temp=\");\n",
" //pc.print(lm73.read(), 2);\n",
" // floatを使うとサイズオーバーになるので、0.1度までを整数で出力\n",
" int v = lm73.read();\n",
" pc.print(v, DEC);\n",
" pc.println();\n",
" wait_ms(1000);// 1秒待つ\n",
" }\n",
" return 0 ;\n",
"}\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.13"
}
},
"nbformat": 4,
"nbformat_minor": 0
}