はじめに
今回も前回に引き続き、Squama Ethernetを使います。
テーマはI2C通信です。
ハードウェア
I2Cデバイス
I2Cのテストのため、16bit ADCのADS1115を使いたいと思います。
AdafruitがADS1115の基板を販売しているのでArduinoライブラリもあります。
最近はAmazonでも同等基板が売っているので入手性も良いです。(例えばこちら)
データシートも一応見ましょうね。(日本語訳するなら全部やってほしいですねw こちら)
I2Cアドレス
センシングするデバイス
これは何でも良いのですけれど、手元にあったロードセルを使います。
秋月電子で売っているやつですね。
ブレッドボードによる配線
FritzingにSquama Ethernetが無いので、代わりにArduino Pro Miniで記載していますが、下記のように配線します。
I2CのSDAとSCLは使用する基板ごと適宜読み替えていただければと思います。
Amazonで買ったら2個付いているので、2個使ってしまいましょう。
(また、後述のソフトでは、ロードセルを1つしか接続していません。手元に4つ無くて…すみません…)
ソフトウェア
ADS1115 ライブラリ
Adafruitのライブラリはこちら。
事前にArduinoにインポートしてください。
ソースコード
# include <SPI.h>
# include <Ethernet2.h>
# include <EthernetUdp2.h>
# include <Adafruit_ADS1X15.h>
// ------ADS1115-------
Adafruit_ADS1115 ads_1; /* Use this for the 16-bit version */
Adafruit_ADS1115 ads_2; /* Use this for the 16-bit version */
Adafruit_ADS1115 ads_3; /* Use this for the 16-bit version */
float multiplier_1 = 0.1875F;
float multiplier_2 = 0.1875F;
float multiplier_3 = 0.1875F;
// ------Ethernet-------
byte mac[] = {
0xA8, 0x61, 0x0A, 0xAE, 0x66, 0xC7
};
IPAddress ip(192, 168, 0, 11); // 自身のIPアドレス
unsigned int localPort = 10000;
IPAddress destIP (192, 168, 0, 1); //相手のPCのIPアドレス
int destPort = 20000; //send側ポート
EthernetUDP Udp;
float set_maltiplier(adsGain_t gain) {
float ret = 0;
if (gain == GAIN_TWOTHIRDS) {
ret = 0.1875;
} else if (gain == GAIN_ONE) {
ret = 0.125;
} else if (gain == GAIN_TWO) {
ret = 0.0625;
} else if (gain == GAIN_FOUR) {
ret = 0.03125;
} else if (gain == GAIN_EIGHT) {
ret = 0.015625;
} else if (gain == GAIN_SIXTEEN) {
ret = 0.0078125;
}
return ret;
}
float setup_ads(Adafruit_ADS1115 &ads, int address, adsGain_t gain) {
ads.setGain(gain);
// i2c address
ads.begin(address);
return set_maltiplier(gain);
}
void setup() {
// put your setup code here, to run once:
// ------Ethernet-------
Ethernet.init(10); // CS信号設定. Most Arduino shields
Ethernet.begin(mac, ip);
Udp.begin(localPort);
// ------ADS1115-------
multiplier_1 = setup_ads(ads_1, 0x49, GAIN_SIXTEEN);
multiplier_2 = setup_ads(ads_2, 0x49, GAIN_ONE);
multiplier_3 = setup_ads(ads_3, 0x48, GAIN_ONE);
}
void loop() {
// put your main code here, to run repeatedly:
int16_t results = ads_1.readADC_Differential_0_1();
float multi = results * multiplier_1;
int16_t results_2 = ads_2.readADC_Differential_2_3();
float multi_2 = results_2 * multiplier_2;
int16_t results_3 = ads_3.readADC_Differential_0_1();
float multi_3 = results_3 * multiplier_3;
int16_t results_4 = ads_3.readADC_Differential_2_3();
float multi_4 = results_4 * multiplier_3;
sendUDP(results, multi, results_2, multi_2, results_3, multi_3, results_4, multi_4);
}
void sendUDP(int16_t i_val, float val, int16_t i_val_2, float val_2, int16_t i_val_3, float val_3, int16_t i_val_4, float val_4) {
// UDP SEND
int digit = 4;
Udp.beginPacket(destIP, destPort);
Udp.print(millis() / 1000, DEC);
Udp.write(",");
Udp.print(i_val);
Udp.write(",");
Udp.print(val, digit);
Udp.write(",");
Udp.print(i_val_2);
Udp.write(",");
Udp.print(val_2, digit);
Udp.write(",");
Udp.print(i_val_3);
Udp.write(",");
Udp.print(val_3, digit);
Udp.write(",");
Udp.print(i_val_4);
Udp.write(",");
Udp.print(val_4, digit);
Udp.write("\n");
Udp.endPacket();
}
ほとんどサンプルを利用しています。
1つの基板で2つのゲインを使用したかったので、ads_1
とads_2
で分けていますが、ライブラリの改良で1つにまとめることが出来そうですね。
また、ADS1115の通信機能として、single-shot mode
とcontinuous mode
というのがあります。
今回は1つずつのチャンネルを single-shot mode
にてデータ受信しているため、continuous mode
より時間がかかっています。
continuous mode
のテストも行いましたが、複数chを受け取るため今回使用していないALRT
Pinを使って処理しないといけないっぽいため、諦めました。
1ch分なら雑な設計かもしれませんがALRT
Pinを使わずにcontinuous mode
で受信できます。
ちなみに、UDPのデータレートですが、ADS1115を2つ使って4ch分のデータをUDPでPCに送信しているのをWireSharkで確認したところ、大体20FPSでした。
データの受信と簡単なビジュアライズ
今回もUnityでUDPを受信しています。左上の文字列が受信データとなります。
4chのうち、1chにしかロードセルを付けておらず、それ以外のchは3.3Vをそのまま突っ込んでいたりしていますのでご了承ください。
その1chのロードセルから受けた値を赤線グラフにしているのと、その値で円のScaleを変えています。
ロードセルに加える力に応じて電圧値が変化するので、グラフと円のサイズが変わるのが分かるかと思います。
おわりに
Squama Ethernet でI2C通信してみました。
やはり基板サイズが小さめでイーサネット接続できるSquama Ethernet はイイですね。便利。
課題としては、continuous mode
でしょうか。20FPSではちょっと遅いですもんね。
I2C通信の速度アップで高速に出来るかもしれません。
最後に、ADS1115のゲインのことやUnityの部分など、結構端折って書いているため、備忘録感が強くなってしまっています。
もっとちゃんと書くべきですね…