{ "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 }