前回、3GIMからサーバー側にデータを送信することができましたので、今回は以前利用したセンサ評価キットで実際にデータを取得して、それをサーバーに溜めていく「簡易データロガー」を作成してみます!
今回の電子工作レシピ
完成までの時間目安:60分
必要なパーツ
目次
- センサ評価キットとArduinoでデータを取得
- 取得したデータをサーバーに送信
- グラフ化してみる
- まとめ
1. センサ評価キットとArduinoでデータを取得
今回データロガーを作成するために、センサ評価キットのセンサは「第43回 複数のセンサを組み合わせた照明デバイス制作に挑戦!」で利用した気圧センサと温度センサを利用してみます。

写真1 ロームセンサ評価キット
第43回では温度センサ、気圧センサ、カラーセンサを搭載していますが、今回はカラーセンサを取り外して使います。ちなみに気圧センサと温度センサの電圧は3Vなので、センサ評価キットの電圧を決めるジャンパピンは3Vで設定します。

写真2 第43回では気圧センサとカラーセンサ、温度センサを搭載
温度センサ・気圧センサの取得プログラムは下記のとおりです。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <Wire.h> #include <BD1020.h> //温度センサ用 #include <BM1383GLV.h> //気圧センサ用 BM1383GLV bm1383; //温度センサ用 int tempout_pin = A2; //温度センサ用ピン設定 BD1020 bd1020; //気圧センサ用 void setup() { Serial.begin(9600); while (!Serial); //温度センサ用 bd1020.init(tempout_pin); Serial.println( "BD1020HFV Sample" ); //気圧センサ用 byte rc; Wire.begin(); rc = bm1383.init(); } void loop() { //************************************ //温度センサ用 //************************************ float temp; bd1020.get_val(&temp); Serial.print( "BD1020HFV Temp=" ); Serial.print(temp); Serial.print( " [degrees Celsius], ADC=" ); Serial.println(bd1020.temp_adc); delay(500); //************************************ //気圧センサ用 //************************************ byte rc; float press; rc = bm1383.get_val(&press); if (rc == 0) { Serial.write( "BM1383GLV (PRESS) = " ); Serial.print(press); Serial.println( " [hPa]" ); Serial.println(); } delay(500); } |

図1 気圧と温度が表示
気圧と温度が正常に取得できていることが確認できたら、次はこのプログラムと3GIMの通信処理部分を組み合わせてみます。
2. 取得したデータをサーバーに送信
センサから取得したデータをサーバーに送信する部分を実装していきます。まず、回路に関してはセンサ評価キットシールドをArduinoの上に搭載したので、それを考慮しながら3GIMの配線をする必要があります。といっても、基本的にピン番号などは変える必要がないので、そのままArduinoに対応するセンサ評価キットのピン番号に配線すれば大丈夫です。

写真3 Arduinoの上にセンサ評価キットシールドを載せて、3GIMと接続
データを送信するプログラムは、前回のものをベースにして、データロガー自体の処理の流れとしては
- 各種センサから値を取得
- データを送信
- 一定時間待ってループ(1へ戻る)
となります。これを基本にして、センサの種類を増やしたり、データの送信部分を改良したり拡張を考えていくのがよいと思います。
センサデータ送信プログラム
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | // 3GIM(V2) sample sketch -- httpGET #include <SoftwareSerial.h> #include "a3gim.h" #include <Wire.h> #include <BD1020.h> //温度センサ用 #include <BM1383GLV.h> //気圧センサ用 BM1383GLV bm1383; //温度センサ用 int tempout_pin = A2; //温度センサ用ピン設定 BD1020 bd1020; //気圧センサ用 SoftwareSerial Serial3g(4,5); #define baudrate 9600UL const int powerPin = 7; // 3gim power pin(If not using power control, 0 is set.) const char *server = "deviceplus.jp" ; const char *path = "" ; int port = 80; char res[a3gsMAX_RESULT_LENGTH+1]; int len; String imei = "" ; int rssi = 0; float lat = 0; float lng = 0; int height = 0; int utc = 0; int number = 0; int quality = 0; String date = "" ; // setup AGPS function void setupAGPS() { char apn[20], user[20], password[20]; if (a3gs.getDefaultProfile(apn, user, password) == 0) { char atwppp[50]; sprintf (atwppp, "at+wppp=2,4,\"%s\",\"%s\"" ,user,password); Serial.println(atwppp); a3gs.enterAT(2); a3gSerial.println(atwppp); delay(200); Serial.println( "Assisted GPS set OK" ); } else Serial.println( "NG: getDefaultProfile(), can't use AGPS.." ); } void setup() { Serial.begin(baudrate); Serial3g.begin(38400); delay(3000); // Wait for Start Serial Monitor Serial.println( "Ready." ); //温度センサ用 bd1020.init(tempout_pin); Serial.println( "BD1020HFV Sample" ); //気圧センサ用 byte rc; Wire.begin(); rc = bm1383.init(); } void loop() { //************************************ //1.センサからデータを取得する //************************************ //温度センサのデータを取得 float temp; bd1020.get_val(&temp); Serial.print( "BD1020HFV Temp=" ); Serial.print(temp); Serial.print( " [degrees Celsius], ADC=" ); Serial.println(bd1020.temp_adc); delay(500); //気圧センサのデータを取得 byte rc; float pressure; rc = bm1383.get_val(&pressure); if (rc == 0) { Serial.write( "BM1383GLV (PRESS) = " ); Serial.print(pressure); Serial.println( " [hPa]" ); Serial.println(); } delay(500); //************************************ //2.3GIMでデータをサーバーに送信 //************************************ Serial.print( "Initializing.. " ); if (a3gs.start(powerPin) == 0 && a3gs.begin(0, baudrate) == 0) { Serial.println( "Succeeded." ); delay(25000); // ウェイトを持たせる Serial.println( "httpGET() requesting.. " ); len = sizeof (res); //*************************************************** //get rssi //*************************************************** if (a3gs.getRSSI(rssi) == 0) { Serial.print( "RSSI = " ); Serial.println(rssi); if (rssi > 0 || rssi <= -113 ){ //電波強度が取得できない場合は最初から Serial.println( "retry." ); return ; } } else { //電波強度が取得できない場合は最初から Serial.println( "retry." ); return ; } //*************************************************** //get imei //*************************************************** char imei[a3gsIMEI_SIZE]; if (a3gs.getIMEI(imei) == 0) { Serial.print( "IMEI: " ); Serial.println(imei); } //*************************************************** //get time //*************************************************** char date[a3gsDATE_SIZE], time [a3gsTIME_SIZE]; if (a3gs.getTime(date, time ) == 0) { Serial.print( "DATE:" ); Serial.print(date); Serial.print( " " ); Serial.println( time ); } //*************************************************** //GPS-location //*************************************************** setupAGPS(); char lat[15], lng[15], utc[7], height[8]; if (a3gs.getLocation2(lat, lng, height, utc, &quality, &number) == 0) { Serial.print( "OK: " ); Serial.print(lat); Serial.print( "," ); Serial.print(lng); Serial.print( "," ); Serial.print(height); Serial.print( "," ); Serial.print(utc); Serial.print( "," ); Serial.print(quality); Serial.print( "," ); Serial.println(number); } String pathStr = "/api.php?imei=" ; String tempS = String(temp); //温度センサの値 String pressureS = String(pressure); //気圧センサの値 String imeiS = String(imei); String rssiS = String(rssi); String latS = String(lat); String lngS = String(lng); String utcS = String(utc); String qualityS = String(quality); String numberS = String(number); String heightS = String(height); String dateS = String(date); String timeS = String( time ); pathStr = pathStr+imeiS+ "&rssi=" +rssiS+ "&rssi=" +tempS+ "&=" +pressureS+ "&utc=" +utcS+ "&lat=" +latS+ "&lng=" +lngS+ "&quality=" +qualityS+ "&number=" +numberS+ "&height=" +height+ "&datetime=" +dateS+ "%20" +timeS; int rst = a3gs.httpGET(server, port, pathStr.c_str(), res, len); Serial.print( "URL:" ); Serial.println(server); Serial.println( "" ); Serial.print( "PATH:" ); Serial.println(pathStr); Serial.print( "RESULT:" ); Serial.println(rst); if (rst == 0) { Serial.println( "OK!" ); Serial.print( "[" ); Serial.print(res); Serial.println( "]" ); } else { Serial.print( "Can't get HTTP response from " ); Serial.println(server); } } else { Serial.println( "Failed." ); } Serial.println( "Shutdown.." ); a3gs.end(); a3gs.shutdown(); } // END |

図2 温度センサと気圧センサの値を送信
シリアルモニタで正常に送信できていることが確認できました。ただ、今回コンパイルをした際に「スケッチで使用できるメモリが少なくなってしまっています。動作が不安定になる可能性があります」との表示がArduinoのソフトウェアに表示されました。
プログラムが処理が多くArduino内のメモリが少なくなると、Arduinoの実行時にメモリを多く使う処理などが走った際にArduinoが正常に動作しなくなってしまう可能性があります。このような場合は、メモリの多い別のArduinoを利用するか、無駄な処理をできるだけ削除してメモリを軽くするかどちらかの対策をとると良いです。
3. グラフ化してみる
せっかくなので、前回は表で表示するだけだったサーバー側も、少し手を加えてグラフで表示してみます。サーバーサイドでの表示は、プログラムや方法がいろいろあるので、自分がやりやすい方法を選択してもらえればよいのですが、手軽にグラフを表示できるサービスとして、Google Chartsを今回使ってグラフ化してみました。Google Chartsはjavascriptでシンプルな表記で様々な種類のグラフを表示することができるので、簡単にデータを表示したい場合などに適しています。

図3 Google Charts
Google Chartsのページで紹介されているサンプルコードを見ていただくとわかるのですが、javascriptのプログラム部分に表示したいデータやグラフの設定を行い、表示したいタグのIDを指定することでグラフの表示が可能です。
実際に取得した気圧、温度をグラフにしたのが下記の図です。

図4 気圧・温度をグラフで表示
グラフで表示されるとわかりやすくなりますね(今回の例ではあまり変動がありませんでしたが)。
まとめ
簡易的ですがデータロガーが完成しました。これでいつでも好きな場所でセンサデータを取得できるようになりましたが、まだ大きな課題が残されています。それはやはり「電源」。常時データロガーをオンにしておくと、電源が常に必要になってしまい、せっかく3G通信でどこでも通信できても電源の確保が必要になってしまいます。次回はデータロガーの電源周りの対策について考えてみます。
■関連記事
SORACOM Air×3GIMによるArduinoの3G通信〜センサ評価キットと組み合わせてデータロガー作成(3)
SORACOM Air×3GIMによるArduinoの3G通信〜Arduinoで3G通信をする方法(2)
SORACOM Airを使ってArduinoで通信できる?~Arduinoで3G通信をする方法(1)
ラズベリーパイとSORACOM Airでインターネット接続!(1)登録編