enebular x 전도성 천으로 빈 좌석 감지

이 기사는 2020년 12월 1일에 개최된 【온라인】enebular developer meetup 에서 발표한 내용을 베이스로 하고 있습니다.

소개



UX 디자이너의 따뜻한입니다.

평상시는 UI 설계나 UX 개발등의 일의 옆, 취미로 프로토 타입등을 만들거나 하고 있습니다.
요전날, E텍스타일을 사용한 인풋 모듈 「 nüno 」를 nanbwrks씨와 만들었습니다.
nüno의 최신 버전은 ver.2이지만,
이번에는 남아있는 nüno ver.1을 사용하여 공석 통지 시스템을 만들어 보았습니다.

nüno에 대해서는 2018년 12월의 기사 「enebular로 천 센서로부터 LINE에 통지 할 수있게했다. 」도 참고해 주세요! !

할 수 있는 것



궁극적으로 할 수있는 동영상은 여기입니다.

nuno의 데모! #enebular 피 c. 라고 r. 이 m/G7W tFYqt4 — 노라 해크(자키) (@Zakkiea) 2020년 12월 1일


알기 어렵지만, 제일 오른쪽 하단의 이불이 노란색이 되어 있네요. (되어 있습니다!)

여기에 대해 설명합니다.



전체 구성



구성으로 빈 자리 데이터 전송은 nüno에서 M5Stack을 통해 Wifi를 사용하여 enebular에 연결,

enebular에서 Firebase로 감지 정보를 보냅니다.



그리고 공석 정보를 표시하기 위한 데이터 취득은 PC(스마트 폰)로부터 enebular에 리퀘스트를 송신,

enbular가 Firebase에서 데이터 꼬리를 가져와 PC에 빈 자리 정보를 표시하는 흐름입니다.





하드웨어



프로토타입 느껴지지만, 하드웨어는 이쪽.



무인 양품의 이불에 nüno를 접속해, M5Stack Core2를 사용하고 있습니다.

M5Stack Core2와 nüno의 통신은 I2C를 사용합니다.



Arduino



우선 Arduino에서

또한, nüno에서는 MTCH6102라는 정전 터치 센서를 사용하고 있으므로,

프로그램과 같은 계층에 여기 에서 빌려왔다

- MTCH6102.h

- MTCH6102.cpp

사용하고 있습니다.



#include <M5Core2.h>
#include <Arduino.h>
#include <Wire.h>
#include "MTCH6102.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>

#define ADDR 0x25
#define ScreenWidth 320
#define ScreenHeight 240

MTCH6102 mtch = MTCH6102();

const int len = 8;//感知ポイント数
int nuno_mode = 2;
int cnt; //ループ用変数
uint32_t chipId = 0;


const bool ONLINE = true;//オンラインモード
const char* WIFI_SSID ="SSID";
const char* WIFI_PASSWORD = "PASSWORD";
const char* POST_URL = "URL";

WiFiClient client;

void setup() {
  delay(1000);

  // Initialize the M5Stack object
  M5.begin();
  //M5.Power.begin();
  M5.Lcd.fillScreen(TFT_BLACK);
  Serial.begin(115200);
  //mtch6102
  mtch.begin(ADDR);
  delay(100);
  mtch.writeRegister(MTCH6102_NUMBEROFXCHANNELS, 0x08);
  mtch.writeRegister(MTCH6102_NUMBEROFYCHANNELS, 0x03);//最低3点必要なため
  mtch.writeRegister(MTCH6102_MODE, MTCH6102_MODE_FULL);
  mtch.writeRegister(MTCH6102_HORIZONTALSWIPEDISTANCE, 0x04);
  mtch.writeRegister(MTCH6102_MINSWIPEVELOCITY, 0x02);
  mtch.writeRegister(MTCH6102_TAPDISTANCE, 0x02);
  mtch.writeRegister(MTCH6102_SWIPEHOLDBOUNDARY, 0x04);

  mtch.writeRegister(MTCH6102_BASEPOSFILTER, 0x00);
  mtch.writeRegister(MTCH6102_BASENEGAFILTER, 0x00);

  mtch.writeRegister(MTCH6102_CMD, 0x20);
  delay(500);

  //chipID
  for(int i=0; i<17; i=i+8) {
    chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
  }
  Serial.print("chip Id:");
  Serial.println(chipId);

  //WIFI
  if (ONLINE) {
    WiFi.mode(WIFI_STA);
    WiFi.disconnect(true);
    delay(1000);
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    Serial.println("connecting");
    M5.Lcd.print("========== WIFI connecting ==========\n\n");

    while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(500);
      Serial.print(WiFi.status());
      Serial.print(",");
    }
    Serial.println();
    Serial.print("connected: ");
    Serial.println(WiFi.localIP());
    M5.Lcd.print("========== WIFI connected ==========\n\n");
  }
}


const int log_max = 10;
JSONVar move_log;
int move_current = 0;

//動作ログ送信
void SendLog() {
  if (!ONLINE) return;
  if (WiFi.status() != WL_CONNECTED) return;

  HTTPClient http;
  Serial.print("[HTTP] begin...\n");
  http.begin(POST_URL); //HTTP
  http.addHeader("Content-Type", "application/json");
  String jsonString = JSON.stringify(move_log);
  int httpCode = http.POST(jsonString);
  http.end();
}


void loop() {

    M5.update();
    M5.lcd.clear();
    M5.Lcd.setCursor(0, 70);

    byte data;
    int sensVals[len];

    for (int i = 0; i < len; i++) {
      data = mtch.readRegister(MTCH6102_SENSORVALUE_RX0 + i);
      sensVals[i] = data;
      M5.Lcd.fillRect(30 + (i * 35), ScreenHeight - 20, 30, 10, TFT_BLACK);
      M5.Lcd.setCursor(30 + (i * 35), ScreenHeight - 20);
      M5.Lcd.print(data);
    }

    Serial.println(String(chipId));
    for (int j = 0; j < len; j++) {
      move_log["chipId"] = String(chipId);
      move_log["value"][j] = sensVals[j];
      Serial.print(sensVals[j]);
      Serial.print(",");
    }
    Serial.println();
    //ログ投げる


    M5.Lcd.setCursor(0, 70);
    //背景ライン
    for (int i = 0; i < len; i++) {
      M5.Lcd.drawLine((i + 1) * 35, ScreenHeight - 40, (i + 1) * 35, 0, 0x0000cc);
    }
    for (int i = 1; i < 11; i++) {
      M5.Lcd.drawLine(0, i * 20, ScreenWidth, i * 20, 0x0000cc);
    }
    //グラフ線の描画
    for (int i = 0; i < len + 1; i++) {
      float prev = 0;
      float current = 0;
      if (i == 0) {
        prev = 0;
      }else{
        prev = sensVals[i - 1];
      }
      if (i == len) {
        current = 0;
      } else {
        current = sensVals[i];
      }
      M5.Lcd.drawLine(i * 35, 200 - (prev / 255) * 200, ((i + 1) * 35), 200 - (current / 255) * 200, TFT_WHITE);
    }

  SendLog();
  delay(5000);//10秒に1回投げる
}


미래에 여러 기기가 실행될 것으로 예상하므로

chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;


여기서 칩 ID를 얻어서 어떤 장치에서 보낸 값을 결정할 수 있습니다.



Firebase



Firebase 측에서는 Realtime 데이터베이스를 사용하고 있습니다.

Realtime 데이타베이스로서는 여기 의 기사를 참고로 해 달라고 설정했습니다.



enebular



enebularn의 흐름은 여기입니다.



상이 송신용, 아래가 취득하는 플로우입니다.

매우 간단하지만 Firebase 노드이 편리하고 즉시 Firebase와의 협력을 실현할 수있었습니다.



1 점 집계 포인트로서 데이터 취득시 CORS의 에러가 표시되었으므로,

http response 노드에 CORS의 와일드 카드를 설정하여 일이 없었습니다.





javascript



이번에는 간편한 구현이므로 jQuery를 사용하고 있습니다.

nüno의 데이터는 0~255의 정전 용량값이 8점 되돌아오므로,

그 8점 가운데 1개라도 150 이상의 값이 있는 경우는 착석 상태로서 seated 클래스를 부여해 상태를 변경하고 있습니다.



$(document).ready(function(){

    setInterval(function(){     
        $.ajax({
            url: 'https://nuno-seat2.herokuapp.com/get-data',
            success: function(result) {
                refreshChair(result);
            }
        })
    }, 1000);

    function refreshChair(data){
        $.each(data,function(index, value){
            if(index == "value"){
                console.log(value);
                var m = Math.max.apply(null, value);
                if(m > 150){
                     $('#seat_8481756').addClass('seated');  
                 }else{
                     $('#seat_8481756').removeClass('seated');   
                 }
             }

        });
    }

});


완성!



이것으로 공석 감지가 가능합니다.

간단한 시스템이라면 하루 정도로 만들 수 있으므로 매우 좋네요!



여러분, 좋은 enebular 생활을 ~!


좋은 웹페이지 즐겨찾기