SORACOM Summer Challenge 2020参加体験記【ソーシャルディスタンシングバッジ拡張】

ソーシャルディスタンシングバッジ完成品外観(表)




2020年8月3日から8月14日まで「SORACOM Summer Challenge 2020」というSORACOM主催の学生向けハッカソンに参加しました。

この記事ではこのハッカソンでやったことと、最終成果物をご紹介します。

SORACOM Summer Challenge 2020とは

SORACOM-Summer-Challenge-2020

SORACOM Summer Challenge 2020は、IoTプラットフォームを展開するSORACOM(ソラコム)社が主催する学生オンラインハッカソンイベントです。

約2週間かけて、SORACOMプラットフォームを活用して「暮らしを豊かにするIoTシステム」の構築に取り組みます。

そのために、今回SORACOMの「GPSマルチユニットSORACOM Edition」と「SORACOM LTE-M Button Plus」を提供していただきました。

GPSマルチユニットSORACOM Edition
GPSマルチユニットSORACOM Edition
SORACOM LTE-M Button Plus
SORACOM LTE-M Button Plus

これらのSORACOMデバイスや環境を使い倒すことで自分が作りたいものを作っていきます。

(ただし今回私はSORACOM LTE-M Button Plusしか使っていません)

自分のテーマ:ソーシャルディスタンシングバッジ

今回のハッカソンの自由度は非常に高く、自由に発想を膨らませて提案書を書くことができました。

そこで私は今回コロナにまつわる問題を何かしら解決できないという考えから、「ソーシャルディスタンシングバッジ」を提案しました。

ソーシャルディスタンシングバッジとは

実はこのソーシャルディスタンシングバッジについては、以前の記事でもまとめています。

ソーシャルディスタンシングバッジは人との距離をセンサで測定し、その距離をディスプレイに表示する、というバッジです。

今回はすでにあるこのバッジに改善を加え、SORACOMデバイスを組み合わせていきたいと思います。

SORACOM Summer Challenge 2020 利用イメージ図

具体的には、一定距離内に人が入ってきたら密であると判定し、その位置情報を記録し、Slackに通知するといったことを実装していきます。

位置情報を記録することで濃厚接触者をたどることができたり、Slack通知によって自分自身への注意喚起をできると考えています。

使用したもの

ソーシャルディスタンシングバッジには以下のものを使用しています。

HiLetgo 2個セット 12V 1チャンネル リレー モジュール サポート高低レベルのトリガー [並行輸入品]
HiLetgo

ソーシャルディスタンシングバッジ制作過程

簡単にまとめると、前記事の回路に SORACOM LTE-M Button Plusリレーを追加し、さらにSlackと連携できるようにしました。

ただし一筋縄ではいかず、リレーとボタンを既存のものに組み込むのに思いのほか手間取ってしまいました。

回路・ソースコード作成

次の画像のように、回路を作りました。

ソーシャルディスタンシングバッジ完成品

…が、これでは配線がどのようになっているのか伝わりません。

そこで、今回はじめてfritzingというソフトを使ってみました。

電子工作のブログでよく見る、下の図のようなイラストはこのソフトで作っています。

SORACOM Summer Challenge ブレッドボード
LTE-M Button Plusは赤ボタンで代替しています

これを使うと、どこに何がつながっているのかわかりやすく図示できます。

公式サイトからだと現在はダウンロードする際に寄附必須となっているようですが、こちらの記事の下の方にあるリンクからだと無料でできます。

https://qiita.com/twinoze/items/b08b279b40c8dc1ca5c1

また、今回のArduinoのコードは次の通りです。

//*****************************************
//* 簡易距離計プログラム(https://deviceplus.jp/hobby/entry016/)
//*****************************************
#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;

// Uncomment this line to use long range mode. This
// increases the sensitivity of the sensor and extends its
// potential range, but increases the likelihood of getting
// an inaccurate reading because of reflections from objects
// other than the intended target. It works best in dark
// conditions.

#define LONG_RANGE


// Uncomment ONE of these two lines to get
// - higher speed at the cost of lower accuracy OR
// - higher accuracy at the cost of lower speed

//#define HIGH_SPEED
//#define HIGH_ACCURACY


//LED site:(http://happy-arduino.blogspot.jp/2012/08/17_27.html)

//http://tsukutta.hatenablog.com/entry/2014/06/30/180629
const int BUTTON = 11;  // プッシュボタンが接続されているピン
const int led_1  = 9;  // 7segLED the one's place 
const int led_10 = 10;  // 7segLED the ten's place 
const int led_100  = 11;  
const int led_1000 = 12; 

int state = 0;          // LEDの状態(0ならオフ、1ならオン)
int state_1=0;          // the one's digit 
int state_10 =0;        // the ten's digit
int state_100 =0;        
int state_1000 =0;        

unsigned long time;
unsigned long init_time;

//*****************************************
//* タイマー(https://garretlab.web.fc2.com/arduino/introduction/beginning_with_7segment_led/)
//*****************************************

#include <MsTimer2.h> // タイマー割り込みを利用する為に必要なヘッダファイル

// LEDをオン・オフする際の出力
#define DIGIT_ON LOW
#define DIGIT_OFF HIGH
#define SEGMENT_ON HIGH
#define SEGMENT_OFF LOW

const int digitPins[] = {9, 10, 11, 12};                                       // ディジット(コモン)に接続するArduinoのピン
const int segmentPins[] = {13, 3, 5, 7, 8, 1, 4};                              // セグメントピンに接続するArduinoのピン
const int numberOfDigitPins = sizeof(digitPins) / sizeof(digitPins[0]);        // ディジットの数
const int numberOfSegmentPins = sizeof(segmentPins) / sizeof(segmentPins[0]);  // セグメントの数
int numbersToDisplay = 0;                                                      // LEDに表示する数字を保持する変数


// 数字と表示させるセグメントの関係
const int digits[] = {
    0b00111111,  // 0
    0b00000110,  // 1
    0b01011011,  // 2
    0b01001111,  // 3
    0b01100110,  // 4
    0b01101101,  // 5
    0b01111101,  // 6
    0b00100111,  // 7
    0b01111111,  // 8
    0b01101111,  // 9
};

// 数字を表示する
void displayNumber(int n) {
  // digits[n]の各ビットを調べて対応するセグメントを点灯・消灯する
  for (int i = 0; i < numberOfSegmentPins; i++) {
    digitalWrite(segmentPins[i], digits[n] & (1 << i) ? SEGMENT_ON : SEGMENT_OFF);
  }
}

// セグメントをすべてオフにする
void clearSegments() {
  for (int j = 0; j < numberOfSegmentPins; j++) {
    digitalWrite(segmentPins[j], SEGMENT_OFF);
  }
}

// 4桁の数字を表示する
void displayNumbers() {
  int n = numbersToDisplay;                  // numberToDisplayの値を書き換えないために変数にコピー
  
  for (int i = 0; i < numberOfDigitPins; i++) {  // 右の桁からディジットを選択する
    digitalWrite(digitPins[i], DIGIT_ON);        // ディジットをオンにする
    displayNumber(n % 10);                       // 10で割った余りを求めて、1の位を求め、表示する
    delayMicroseconds(100);
    clearSegments();                        // セグメントをすべてオフにする
    digitalWrite(digitPins[i], DIGIT_OFF);  // ディジットをオフにする
    n /= 10;                                // 10で割り、次に表示する数字を、1の位に移す
  }
}

// 表示する数字をセットする
void setNumbers(int n) {
  numbersToDisplay = n;
}

//SORACOM LTE-M Button Plus//
//リレー
int relayIn = 2;
void relaySwitch() {
  digitalWrite(relayIn, HIGH);
  delay(500);
  digitalWrite(relayIn, LOW);
  delay(1000);
}


void setup() {
  Serial.begin( 9600 ); 
  Wire.begin();

  //SORACOM LTE-M Button Plus//
  //リレー
  pinMode(relayIn, OUTPUT);
  digitalWrite(relayIn, LOW);

  if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1) {}
  }
  
  #if defined LONG_RANGE
  // lower the return signal rate limit (default is 0.25 MCPS)
  sensor.setSignalRateLimit(0.1);//0.1
  // increase laser pulse periods (defaults are 14 and 10 PCLKs)
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 18);//18
  sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 14);//14
  #endif

  #if defined HIGH_SPEED
  // reduce timing budget to 20 ms (default is about 33 ms)
  sensor.setMeasurementTimingBudget(20);//20
  #elif defined HIGH_ACCURACY
  // increase timing budget to 200 ms
  sensor.setMeasurementTimingBudget(200000);//200000
  #endif

  /////////
  for (int i = 0; i < numberOfDigitPins; i++) {
    pinMode(digitPins[i], OUTPUT);  // digitPinsを出力モードに設定する
    digitalWrite(digitPins[i], DIGIT_OFF);
  }
  for (int i = 0; i < numberOfSegmentPins; i++) {
    pinMode(segmentPins[i], OUTPUT);  // segmentPinsを出力モードに設定する
  }

  MsTimer2::set(1, displayNumbers);  // displayNumbers()を1ミリ秒ごとに呼び出す
  MsTimer2::start();                 // タイマを開始する
}

void loop() {
  int sensorData = sensor.readRangeSingleMillimeters();
  setNumbers(sensorData);
  Serial.println(sensorData);

  //SORACOM LTE-M Button Plus//
  //距離センサの値が100未満のときにスイッチを入れる
  if (sensorData < 100) {
    relaySwitch();
  }
}

IFTTTでSlack連携

IFTTT

SORACOMデバイスをSlackと連携させたい場合、IFTTT(イフト)を使うことになります。

IFTTTとは、TwitterやSlackなど、この世に存在するさまざまなWebサービスの連携を可能にしてくれるサービスです。

IFTTTについては下のページに詳しい説明が載っています。

https://www.atmarkit.co.jp/ait/articles/1711/22/news031.html

肝心のSORACOMデバイスとの連携は、基本的に下のページの手順に沿ってやれば問題ありません。

https://soracom.github.io/iot-recipes/door-monitoring-by-soracom-lte-m-button/#4

ただし最後の「SORACOM Beamの連携設定」のところで、パスの値が /trigger/button/with/KEY_ID となっていますが、正しくは /trigger/button/with/key/KEY_ID です。

実証実験

実際にこのソーシャルディスタンシングバッジを使ってみた記録を書いていきます。

本当は外で人とすれ違ったときに試してみたかったのですが、当初想定していたサイズより大きくなってしまったことに加え、首掛け型の予定が手持ち型になってしまったため、これをもって人にセンサを向けると不審者っぽくなってしまうことを恐れ、家の中で実験することにしました…笑

完成品

ソーシャルディスタンシングバッジ完成品外観(表)
ソーシャルディスタンシングバッジ完成品外観(裏)

ブレッドボードの表側に距離センサと4桁7セグメントLEDとリレーを配置し、裏側にArduinoとSORACOM LTE-M Button Plusを固定しています。

ArduinoとSORACOM LTE-M Button Plus は両面テープ固定に加え、まさかの毛糸で固定しています。

当初は両面テープだけの固定だったのですが、両面テープの粘着力だけでは不足してArduinoやボタンが落下しまくったため、急遽家にあった手ごろなひもである毛糸を使用しました…。

これが毛糸テックです笑

デモ動画

手が一定距離内に入るとSORACOM LTE-M Button Plusのスイッチが入ります。

その後ややタイムラグがありますが、Slackに「密です!」とのメッセージが流れています(見にくいのですが動画の最後にちゃんと流れています)。

SORACOMデバイスからのSlack通知

上の画像がSlackの画面です。

愛犬でもためしてみました(かわいい)

近づくとカチッと音がなって、ボタンのスイッチがオンになっているのがわかります(このとき同時にSlackに密です!と警告が入っています笑)

SORACOM Harvestの画面

SORACOM Harvestの画面

このように一定距離内に人(など)が近づいたときの位置情報がプロットされていきます。

失敗した点・改善すべき点

最後に、今後のために失敗したことや今後改善したいこと、やってみたいことを記録しておきます。

Arduinoの1番ピンを理解していなかった

今回使用したArduino Uno R3の場合、1番ピンはUART(Serial)のピンとして使われるため、リレーが正しく動作しませんでした。

//SORACOM_Summer_Challenge.ino 一部抜粋
int relayIn = 1; //ここが1だとダメ
void relaySwitch() {
  digitalWrite(relayIn, HIGH);
  delay(500);
  digitalWrite(relayIn, LOW);
  delay(1000);
}

シフトレジスタを使いこなせなかった

シフトレジスタを使ってArduinoのピンを減らそうと思ったのですが、配線がうまくいかない&コードをうまく書けず時間的に断念…。

自作基板作成に失敗した

はんだ付けが初心者過ぎて、ユニバーサル基板上に配線するのに失敗しました…笑

恥を忍んで、今後の成長を感じるためにここに残しておきます…。

失敗したはんだ付け
裏はもっと悲惨です涙

時間的にも厳しかったので、今回は自作基板作成は諦めてブレッドボード上に配線しましたが、今後はんだ付けスキルを上げていきたいと思います。

一定距離以内であれば人以外にも反応してしまった

一定距離内にある物すべてに反応してしまうため、人感センサを組み合わせるのもよかったかなと思ったりしました。

もっと高度な「密」判定機能を作りたかった

時間の概念を入れて、一定時間以上&一定距離以内に(同じ)人がいたらアウト、という判定機能をつけたかったです。

SORACOM Summer Challenge 2020 まとめ

今回のSORACOM Summer ChallengeではSORACOMのIoTデバイスを使って、試行錯誤しながらシステムを作っていくことができました。

このソーシャルディスタンシングバッジはまだまだブラッシュアップしていきたいところではありますが、今回はひとまずこれで完成とします。

自分のスキル不足も痛感したため、今後も手を動かして学びながら、IoTの可能性を広げていくようなモノを作っていきたいと思います。

最後に、手厚くサポートしてくださったSORACOMのメンターの皆様、誠にありがとうございました!




コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です