{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"オリジナルの作成:2016/01/03"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 0T-ESP8266でI2Cを試す\n",
"## LM73\n",
"I2Cの動作確認は、いつも使っている温度センサーLM73でテストしてみることにします。 \n",
"\n",
"LM73は入手が難しいとのご指摘がありますので、後ほど秋月で購入可能な温度センサーADT7410を使った例も示します。\n",
"\n",
"プログラムの動作確認は自分が一番経験のある部品でするのが、良いと思うのです。\n",
"\n",
"\n",
"### ピン接続\n",
"ピンの配置1番ピンから反時計回りに採番\n",
"\n",
" | ピン番号\t | 機能\t | Arduinoのピン | \n",
" |---|---|---|\n",
" | 1\t | 未使用\t | - | \n",
" | 2\t | GND\t | GND | \n",
" | 3\t | 3.3V\t | 3.3V\n",
" | 4\t | SCL\t | A5 (SCL) | \n",
" | 5\t | 未使用\t | - | \n",
" | 6\t | SDA\t | A4 (SDA) | \n",
" \n",
"Arduinoとの接続は以下の様になります。\n",
"\n",
"\n",
"\n",
"### スケッチ\n",
"今回は、 初心者の電子の館 のスケッチを使わせて頂きました。 Wireライブラリは古いバージョンだったので、少し修正しました。\n",
"\n",
"```C++\n",
"#include \"Wire.h\"\n",
"\n",
"#define LM73_ADDR 0x4c // 2進数なら 1 0 0 1 1 0 0\n",
"\n",
"int ret;\n",
"\n",
"void setup() // run once, when the sketch\n",
"{\n",
" Wire.begin();\n",
" Serial.begin(9600);\n",
" delay(1000); // デバック用\n",
" \n",
" Wire.beginTransmission(LM73_ADDR);\n",
" Wire.write((byte)0x04); // Control/Status Registerを選択\n",
" Wire.write(0x60); // 14 bits modeにセットする\n",
" ret=Wire.endTransmission();\n",
"\n",
" Wire.beginTransmission(LM73_ADDR);\n",
" Wire.write(0x00); // 次の通信のため温度レジスターをセットする。\n",
" ret=Wire.endTransmission();\n",
" delay(100); // 次の読み取りまで念のため0.1秒間をあける\n",
" \n",
"}\n",
"\n",
"void loop() // run over and over again\n",
"{\n",
"\n",
" int data=0 ;\n",
"\n",
" Wire.beginTransmission(LM73_ADDR);\n",
" ret=Wire.requestFrom(LM73_ADDR, 2);\n",
" \n",
" data = 0;\n",
" if (Wire.available()) {\n",
" data = Wire.read();\n",
" } else {\n",
" Serial.println(\"Wire not available.\");\n",
" }\n",
" if (Wire.available()) {\n",
" data = (data << 8 )| Wire.read() ;\n",
" }\n",
" \n",
" ret=Wire.endTransmission();\n",
" \n",
" printdata(data); // シリアルへ温度データを送る\n",
" delay(2000);\n",
"\n",
"}\n",
"void printdata(int data){\n",
" \n",
" int data2;\n",
" int data3;\n",
" float data_f;\n",
" \n",
" boolean negative=false;\n",
"\n",
" if (data < 0 ) { // マイナスならbooleanにtrueをセットしプラスに変換\n",
" negative=true;\n",
" data = -data;\n",
" }\n",
"\n",
" data2 = data >> 7; // 小数値切り捨て\n",
"\n",
" data_f = (float)(data >> 2 ) / 32;\n",
" data_f = data_f - data2 ;\n",
"\n",
" data3 = data_f * 100 ;\n",
"\n",
" Serial.print (\"Current temperature is \");\n",
" if (negative) {\n",
" Serial.print(\"-\");\n",
" }\n",
" Serial.print(data2);\n",
" Serial.print(\".\");\n",
" Serial.print(data3/10);\n",
" Serial.print(data3 % 10);\n",
" Serial.println(\" C. \");\n",
"}\n",
"```\n",
"\n",
"どういうわけか、シリアルモニターは9600ボーの半分4800ボーにセットしないと 文字化けしました。\n",
"\n",
"\n",
"\n",
"不思議なことに4800ボーにセットすると正しく読み取れます。\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ESP8266でLM73を使う\n",
"ArduinoでのLM73の動作が確認できたので、LM73をESP8266に接続して同じスケッチを動かしてみます。\n",
"\n",
"\n",
"### I2C用のピンについて\n",
"ネットで調べるとESP8266のI2C用のピンが色々変わっていて混乱していたところ、 macsbugさんの ESP8266 と I2C によると、0,2,4,5,12,13,14のすべてのピンの組み合わせでI2Cが動いたとの記事がありました。\n",
"\n",
"今回は、SCL=IO14、SDA=IO4を使用することにしました。\n",
"\n",
" | ピン番号\t | 機能\t | ESP8266のピンNo | \n",
" |---|---|---|\n",
" | 1\t | 未使用\t | - | \n",
" | 2\t | GND\t | 9 (GND) | \n",
" | 3\t | 3.3V\t | 1 (3.3V) | \n",
" | 4\t | SCL\t | 3(IO14) | \n",
" | 5\t | 未使用\t | - | \n",
" | 6\t | SDA\t | 10(IO4) | \n",
" \n",
"ESP8266のWireを使う場合、最初にI2Cに使用するピンをsetupでセットする必要があります。\n",
"\n",
"```C++\n",
"void setup() {\n",
" Wire.begin(4, 14); // begin(SDA, SCL);のように指定\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ESP8266でLBEDを使ってみる\n",
"Arduino版LBEDは、I2CのWire関連をライブラリの外に出すことにしたので、 ESP8266版Arduino IDEでも使うことができるようになりました。\n",
"\n",
"### 秋月で購入できる温度センサーADT7410を使う\n",
"ADT7410とESP8266との接続には、ESP8266版lbeDuinoのD8(SDA)とD9(SCL)と ADT7410のSDA、SCLをそれぞれ接続します。 ADT7410にモジュール内にプルアップの抵抗が付いていますが、今回はブレッドボードの4.7KΩの抵抗を付けてプルアップしています。\n",
"\n",
"\n",
"\n",
"ADT7410のライブラリには、 Tom Kreycheさんがmbed用に公開されている ADT7410ライブラリ を使わせてもらいます。\n",
"\n",
"ADT7410ライブラリの修正箇所は、ADT7410.hのmbed.hのインクルード文をlbed.hに変更するだけです。\n",
"\n",
"```C++\n",
"// #include \"mbed.h\"\n",
"#include \"lbed.h\"\n",
"スケッチは、以下の様にします。たったこれだけでADT7410温度センサーが使えるようになります。\n",
"\n",
"#include \"Wire.h\"\n",
"#include \"lbed.h\"\n",
"#include \"ADT7410.h\"\n",
"\n",
"ADT7410 healthThemometer(D8, D9, 0x90, 400000);\n",
"\n",
"void setup() {\n",
" Wire.begin(4, 14); // Wire.begin();\n",
" Serial.begin(9600);\n",
" healthThemometer.setConfig(ONE_SPS_MODE);\n",
"}\n",
"\n",
"void loop() {\n",
" float temp = healthThemometer.getTemp();\n",
" Serial.print(\"Current temperature is \");\n",
" Serial.print(temp, 2);\n",
" Serial.println(\" C. \");\n",
" wait_ms(1000);\n",
"}\n",
"```\n",
"\n",
"### I2CLcdシールド\n",
"ESP8266版lbeDuinoは、使えるピンが少ないので、Arduinoピン変換シールドを使って D2をD12に、D3をD5に付け替えて実行します。\n",
"\n",
"\n",
"\n",
"スケッチは、以下のとおりです。\n",
"\n",
"```C++\n",
"#include \"Wire.h\"\n",
"#include \"lbed.h\"\n",
"#include \"AQCM0802.h\"\n",
"\n",
"// D13番ピンにLEDを接続\n",
"DigitalOut led(D13);\n",
"// D8番ピンSDA, D9番ピンSCL. ArduinoではハードI2Cを使用している。\n",
"AQCM0802 lcd(D8, D9);\n",
"// タクトスイッチ\n",
"DigitalIn sw1(D5);\n",
"DigitalIn sw2(D12);\n",
"\n",
"void setup() {\n",
" // ESP8266では、D8に4(SDA), D9に14(SCL)が接続されている\n",
" Wire.begin(4, 14); // Wire.begin(); sw1.mode(PullUp);\n",
" sw2.mode(PullUp);\n",
" lcd.setup();\n",
" lcd.print(\"I2C LCD\");\n",
"}\n",
"\n",
"void loop() {\n",
" led = !led;\n",
" lcd.locate(0, 1);\n",
" \n",
" if (!sw1) {\n",
" lcd.print(\"SW1 On \");\n",
" }\n",
" else if (!sw2) {\n",
" lcd.print(\"SW2 On \");\n",
" }\n",
" else {\n",
" lcd.print(\"All Off\");\n",
" }\n",
" wait_ms(1000);\n",
"}\n",
"```\n",
"\n",
"### BME280温度・湿度・気圧センサ\n",
"I2CLcdが動けば、その他のI2Cセンサも動くはずです。\n",
"\n",
"\n",
"\n",
"```C++\n",
"#include \"Wire.h\"\n",
"#include \"lbed.h\"\n",
"#include \"AQCM0802.h\"\n",
"#include \"BME280.h\"\n",
"\n",
"// D13番ピンにLEDを接続\n",
"DigitalOutled(D13);\n",
"// D8番ピンSDA, D9番ピンSCL\n",
"AQCM0802lcd(D8, D9);\n",
"BME280sensor(D8, D9);\n",
"\n",
"// タクトスイッチ\n",
"DigitalIn sw1(D5);\n",
"DigitalIn sw2(D12);\n",
"\n",
"intlast_mode = 0;\n",
"chardegree = 0xdf;\n",
"void setup() {\n",
" // ESP8266では、D8に4(SDA), D9に14(SCL)が接続されている\n",
" Wire.begin(4, 14); // Wire.begin(); \n",
" sw1.mode(PullUp);\n",
" sw2.mode(PullUp);\n",
" lcd.setup();\n",
" sensor.setup();\n",
" lcd.locate(0, 0); lcd.print(\"BME280\");\n",
" lcd.locate(0, 1); lcd.print(\"Demo\");\n",
" wait_ms(2000);\n",
"}\n",
"\n",
"void loop() {\n",
" led = ! led;\n",
" if (sw1 == 1) {\n",
" if (last_mode == 0)\n",
" lcd.cls();\n",
" lcd.locate(0, 0);\n",
" lcd.print(sensor.getTemperature(), 2);\n",
" lcd.print(degree); lcd.print(\"C\");\n",
" lcd.locate(0, 1);\n",
" lcd.print(sensor.getHumidity(), 2); lcd.print(\"%\");\n",
" last_mode = 1;\n",
" }\n",
" else {\n",
" if (last_mode == 1)\n",
" lcd.cls();\n",
" lcd.locate(0, 0);\n",
" lcd.print(sensor.getTemperature(), 2);\n",
" lcd.print(degree); lcd.print(\"C\");\n",
" lcd.locate(0, 1);\n",
" lcd.print(sensor.getPressure(), 2); lcd.print(\"hPa\");\n",
" last_mode = 0;\n",
" }\n",
" wait_ms(1000);\n",
"}\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## ESP8266版LBEDソース\n",
"ESP8266版で使ったlbedライブラリのソースを添付します。 ユーザのArduino用ディレクトリ/librariesに以下を展開して、 lbeDuino, lbeDuinoUserをコピーしてください。\n",
"\n",
"- [Arduino_lbed.zip](data/Arduino_lbed.zip)"
]
},
{
"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
}