3duilab が 2022年07月20日07時10分57秒 に編集
コメント無し
本文の変更
# 概要 赤外線の反射を利用した非接触空間センサーで、手の動き、方向、高さを検出しテープLED、NeoPixelで表示するシステムを創りました。AIカメラより速く3次元で検出する世界でも珍しい動作検出システムについて解説します。 website 動作検出システム Arduino Nano Every(https://interactive-hand-sensor.com/root/motion-detection-arduino-nano-every) # 動画 @[youtube](https://youtu.be/tvV6aWiNObM) # 双方向ハンドセンサーの原理 **原理は赤外線の反射**です。約1.2mS毎に出る8個の距離データを分析しています。赤外線LEDを瞬間的に強く発光させ反射光の強さをADコンバータで数値化しています。 参考記事:スイッチングフォトリフレクタ(非接触空間センサー)(https://elchika.com/article/b6785113-f812-4b39-bf32-891fa1cc0da1/) ![キャプションを入力できます](https://camo.elchika.com/2a44bb7ad866c995eeb8f43adb80854b1f251edb/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31383164613832352d646330322d343939302d626461342d3362323431386663646437372f31386163376562382d396564332d343132382d393537312d633962653564363166663565/) # 配線 双方向ハンドセンサーの接続はこちらArduino Nano Every Example(https://interactive-hand-sensor.com/root/arduino-nano-every-example) カラーLEDはNeoPixel(https://www.switch-science.com/catalog/1861/)を使っています。
![キャプションを入力できます](https://camo.elchika.com/d719f2aa5af93ee2cf0d1ea06d16050f522e0a02/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31383164613832352d646330322d343939302d626461342d3362323431386663646437372f64393932633434632d646166662d343464632d613033322d306566346162616262303665/)
![配線図NeoPixel](https://camo.elchika.com/d719f2aa5af93ee2cf0d1ea06d16050f522e0a02/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31383164613832352d646330322d343939302d626461342d3362323431386663646437372f64393932633434632d646166662d343464632d613033322d306566346162616262303665/) ![キャプションを入力できます](https://camo.elchika.com/226b50e31876ef9d4f6c1dc33ac9c62d1c41368a/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31383164613832352d646330322d343939302d626461342d3362323431386663646437372f66663765383462612d653066342d346463352d393730642d646332633130643934623862/)
# ソフトウェア ![フローチャート](https://camo.elchika.com/10c3d9714d3c1087f5e94dbe44a4ac699bcf6499/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f31383164613832352d646330322d343939302d626461342d3362323431386663646437372f62626261613763352d646163642d343664372d393465632d386331613431663430303562/) センサーの距離データ最大値が基準値を超えると、**その最大値**と**そのインデックス**(センサー番号)を**配列に保存**していきます。最大値が基準値以下になると配列の情報から速度、長さ、色を計算し、テープLED NeoPixelを回します。 - **遅延時間(1/速度)**:配列長さ✕定数 /(インデックス最大値 ー インデックス最小値)) - **長さ** :インデックス最大値 ー インデックス最小値 - **色** :距離データ最大値の平均→6段階の色に変換 # コード ```arduino:IHS11_Nano_Every_Motion.ino #include "CLED.h" #include "MotionNeoPixel.h" #include <SPI.h> Sensor sensor(0); // 40:smaller -> high sense CLED cled(0); // IHSxx MotionNeoPixel mt; NeoPixel np(1); // D1 or TX:NeoPixel // ************************** setup ******************************** void setup() { Serial.begin(57600); sensor.init(); cled.set(5); // init blink np.clr(); delay(2000); } // *************************** loop ******************************** void loop() { sensor.setAd(); if (mt.exec(sensor)) { // mt.pm.print(); np.drift(mt.pm); } } ``` ```arduino:MotionNeoPixel.cpp #include "MotionNeoPixel.h" int getMaxIdx(int* ary) { int rev = 0; int Idx = 0; for (int i=0; i<COL_LEN; i++) { if (ary[i] > rev) { rev = ary[i]; // max Value Idx = i; // max Index } } return Idx; } int ad2val(int ad) { // div6 true:1~6 false:1~12 int cri[NEO_CRI_LEN] = {450,700,850,1200,1650,1950}; for (int i = 0; i < NEO_CRI_LEN; i++) if (ad < cri[i]) return i; return NEO_CRI_LEN; } template <class X> void Sprint(X out, int lf = 0) { Serial.print(out); Serial.print(", "); if (lf) Serial.println(""); } // ******************* class MotionNeoPixel ****************** MotionNeoPixel::MotionNeoPixel(){ init(); } void MotionNeoPixel::init() { isOn = false; idx = 0; } bool MotionNeoPixel::exec(Sensor& sen) { const int CRI = 300; // criteria sen.getColAd(adVal); // get sensing data int max_idx = getMaxIdx(adVal); bool isBig = (adVal[max_idx] >= CRI); // max Value >= CRI if (isBig) { // continue isOn = true; // starting copy2Ary(max_idx); } else if (isOn) { // stopping return result(); } return false; } void MotionNeoPixel::copy2Ary(int max_idx) { maxAd[idx] = adVal[max_idx]; // max Value maxIdx[idx] = max_idx; // max Index if (idx < ARY_SIZE) idx++; } bool MotionNeoPixel::result() { // direction length delay(ms) RGB int plus = 0; int minus = 0; for (int k=1;k<idx;k++) { int delt = maxIdx[k] - maxIdx[k - 1]; if (delt > 0) plus++; else if (delt < 0) minus++; } bool dir = (plus > minus); // direction true: Cw int deltIdx = maxIdx[idx - 1] - maxIdx[0]; if (deltIdx < 0) deltIdx *= (-1); bool isEdge = (deltIdx==0) && ((maxIdx[idx - 1] == 7) || (maxIdx[idx - 1] == 0)); if (isEdge) { deltIdx = 2; dir = (maxIdx[0] == 0); } if ((idx <= 2) || (deltIdx==0)) { init(); return false; } int len = deltIdx; const int RATIO = 2; int waitMs = idx * RATIO / deltIdx; int color = ad2val(getAvg(maxAd)); pm.set(dir, waitMs, len, color); init(); return true; } int MotionNeoPixel::getAvg(int* ary) { long addVal = 0; for (int i=0; i<idx; i++) { addVal += ary[i]; } return addVal / idx; } ``` ```arduino:MotionNeoPixel.h #ifndef MOTION_NEOPIXEL_H #define MOTION_NEOPIXEL_H #include "Sensor.h" #include "NeoPixel.h" class MotionNeoPixel { public: MotionNeoPixel(); bool exec(Sensor& sen); Param pm; private: static const int ARY_SIZE = 1024; int maxAd[ARY_SIZE]; int maxIdx[ARY_SIZE]; int adVal[COL_LEN]; bool isOn; int idx; // 0 ~ ARY_SIZE void init(); void copy2Ary(int max_idx); bool result(); int getAvg(int* ary); }; #endif ``` ```arduino:NeoPixel.cpp #include "NeoPixel.h" NeoPixel::NeoPixel(uint16_t pin) : pixels(NUMPIXELS, pin, NEO_GRB + NEO_KHZ800) { #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000) clock_prescale_set(clock_div_1); #endif pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) } void NeoPixel::drift(int idx) { idx = idx % NUMPIXELS; pixels.clear(); pixels.setPixelColor(idx, pixels.Color(150, 150, 0)); pixels.show(); // Send the updated pixel colors to the hardware. } void NeoPixel::drift(Param& p) { int delta = 0; for (int i = 0; i < NUMPIXELS+p.len; i++) { pixels.clear(); int idx = (p.isCw) ? i : -i; if (i >= NUMPIXELS) delta++; for (int k = 0; k < p.len - delta; k++) { int m = (idx + NUMPIXELS +((p.isCw) ? -k : k)) % NUMPIXELS; pixels.setPixelColor(m, pixels.Color(p.r(), p.g(), p.b())); } pixels.show(); // Send the updated pixel colors to the hardware. delay(p.mSec); } } void NeoPixel::clr() { pixels.clear(); pixels.show(); } ``` ```arduino:NeoPixel.h #ifndef NEO_PIXEL #define NEO_PIXEL #include <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> // Required for 16 MHz Adafruit Trinket #endif const int NUMPIXELS = 60; // NeoPixel ring size const int NEO_CRI_LEN = 6; struct Param { bool isCw; // direction int mSec; // delay(mS) int len; // length int colIdx; const int ColorAry[NEO_CRI_LEN][3] = { {255,0,0}, // Red {100,100,0}, // Yellow {0,255,0}, // Green {0,100,100}, // light blue {0,0,255}, // blue {150,0,50} // purple }; uint8_t r() {return ColorAry[colIdx-1][0];} // Red uint8_t g() {return ColorAry[colIdx-1][1];} // Green uint8_t b() {return ColorAry[colIdx-1][2];} // Blue void set(bool cw, int ms, int le, int col) { isCw = cw; mSec = ms; len = le; colIdx = col; } void print() { int ary[4] = {isCw, mSec, len, colIdx}; for (int i=0; i<8; i++) { if (i % 2) Serial.print(", "); else { Serial.print(ary[i >> 1]); } } Serial.println(""); } }; class NeoPixel { public: NeoPixel(uint16_t pin); void drift(int idx); void drift(Param& p); void clr(); private: Adafruit_NeoPixel pixels; }; #endif ``` # 終わりに 双方向ハンドセンサーは約2年前に開発し発売しました。現在まであまり売れていませんが、電機産業が総崩れとなりつつある現状でこのような世界でも珍しいセンサーが突破口となる期待をこめて投稿しました。一人で開発しましたが今まで品質問題など致命的な問題がありません。特許は取らず、回路図、ソフトウェアはユーザーガイド(https://interactive-hand-sensor.com/root/user-guide)から公開しています。動作検出の他、非接触スイッチ、非接触タッチパネル、動的展示、侵入検知、マウスなど応用範囲が広く清潔です。世界に売れる現代的な製品を創りたい。みなさんも協力してもらえませんか。 # リンク 双方向ハンドセンサーwebsite:https://interactive-hand-sensor.com/root/ 双方向ハンドセンサー発売中:https://www.switch-science.com/catalog/6495/ download(双方向ハンドセンサーArduino Nano Every Example):https://drive.google.com/drive/folders/1apqLGDlBQQrGnEpgINgA0En2ZdTqqJnb download(動作検出システム Arduino Nano Every):https://drive.google.com/drive/folders/1nEYjUnJgwbNl6JxprOL8BeTMk-m_75uz Instagram:https://www.instagram.com/3duilab/?hl=ja ツイッター:https://twitter.com/TakahiroMaeda3