工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduino Pro Miniで赤外線眼球運動トラッキング:LED瞳制御デモ

必要な部品と材料

SparkFun Arduino Pro Mini 328 - 5V/16MHz ×1
Adafruit LiIon/LiPoly Backpack Add-On for Pro Trinket/ItsyBitsy ×1
NeoPixelストリップ ×1
QTR-1A 反射センサー ×1
3.7V LiPoバッテリー ×1

使用するアプリとオンラインサービス

プロジェクト概要

赤外線センサーで眼球運動を検知し、LED瞳を制御するシステムを構築しました。

NeoPixel LEDアイボール

NeoPixel LEDテープ(68個)を使用。ボウル型の台座に両面テープで固定し、以下の順序で配線しています。

Arduino Pro Miniで赤外線眼球運動トラッキング:LED瞳制御デモ
Arduino Pro Miniで赤外線眼球運動トラッキング:LED瞳制御デモ

眼球運動トラッキング

回路図

Arduino Pro Miniで赤外線眼球運動トラッキング:LED瞳制御デモ

センサー配置

QTR-1A反射センサーを2個使用し、目の幅程度の間隔でプラスチックシートに配置します。

Arduino Pro Miniで赤外線眼球運動トラッキング:LED瞳制御デモ

センサー部とマイクロコントローラー部をそれぞれクリップでメガネに固定します。

Arduino Pro Miniで赤外線眼球運動トラッキング:LED瞳制御デモ
Arduino Pro Miniで赤外線眼球運動トラッキング:LED瞳制御デモ

Arduinoコード

虹彩がセンサーに近づくと反射光が減少しセンサー値が増加、離れると反射光が増えセンサー値が減少します。LED瞳の左右動作は片側センサーの増減で制御します。

瞬き時は両センサー値が同時に減少するため、両方が閾値以下になったらLED瞳の瞼を閉じる動作をさせます。

#include <QTRSensors.h>
#include <Adafruit_NeoPixel.h>

#define NUM_SENSORS 2
#define NUM_SAMPLES_PER_SENSOR 10
#define EMITTER_PIN QTR_NO_EMITTER_PIN

int iniSensorValL, sensorValL;
int iniSensorValR, sensorValR;

#define PIN A3
Adafruit_NeoPixel led = Adafruit_NeoPixel(68, PIN, NEO_GRB + NEO_KHZ800);

int blackNum = 24;
int pupilNum = 12;
uint32_t color;
int brightness = 40;
byte eyeColor;
int LR = 7;
boolean lid = false;
int cnt = 0;

// 黒目左右アニメーションパターン
int blackLED[15][24] = {
  {12,32,35,55,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
  {12,13,31,36,54,55,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68,68},
  // ...(省略)
};

// 瞳孔左右アニメーションパターン
int pupilLED[15][12] = {
  {33,34,68,68,68,68,68,68,68,68,68,68},
  {32,33,34,35,68,68,68,68,68,68,68,68},
  // ...(省略)
};

// 瞬きアニメーションパターン
int eyelid = 0;
int eyelidNum[8] = {0,4,8,16,24,34,44,56};
int eyelidLED[56] = {64,65,66,67,58,59,60,61,56,57,62,63,49,50,51,52,47,48,53,54,38,39,40,41,46,55,36,37,42,43,26,27,28,29,35,44,24,25,30,31,15,16,17,18,34,45,23,32,13,14,19,20,6,7,8,9};

QTRSensorsAnalog qtra((unsigned char[]){0, 1}, NUM_SENSORS, NUM_SAMPLES_PER_SENSOR, EMITTER_PIN);
unsigned int sensorValues[NUM_SENSORS];

void blink(int eyelid, int LR) {
  if (eyelid != 8) {
    // 瞳全体を薄いグレーに
    for(uint16_t i=0; i<led.numPixels(); i++) {
      led.setPixelColor(i, led.Color(66, 66, 66));
    }
    // 黒目表示
    for(uint16_t i=0; i<blackNum; i++) {
      led.setPixelColor(blackLED[LR][i], color);
    }
    // 瞳孔表示
    for(uint16_t i=0; i<pupilNum; i++) {
      led.setPixelColor(pupilLED[LR][i], led.Color(0, 0, 66));
    }
    // 瞼表示
    for(int i=0; i < eyelidNum[eyelid]; i++) {
      led.setPixelColor(eyelidLED[i], 0);
    }
  } else {
    led.clear();
  }
  led.show();
}

void setup() {
  Serial.begin(115200);
  led.begin();
  led.setBrightness(brightness);
  led.show();
  color = led.Color(0, 177, 55);  // 瞳色
  delay(100);
  qtra.read(sensorValues);
  iniSensorValL = sensorValues[0];
  iniSensorValR = sensorValues[1];
  blink(eyelid, LR);
}

void loop() {
  qtra.read(sensorValues);
  sensorValL = sensorValues[0];
  sensorValR = sensorValues[1];
  
  double rasioL = (double)sensorValL / iniSensorValL;
  double rasioR = (double)sensorValR / iniSensorValR;
  
  Serial.print(rasioL); Serial.print(" "); Serial.println(rasioR);
  
  // 右方向視線
  if(rasioL > 0.985 && rasioR < 0.985) {
    for(int i = LR; i < 12; i++) {
      blink(0, i); delay(40); LR = i;
    }
  }
  // 左方向視線
  else if(rasioL < 0.985 && rasioR > 0.985) {
    for(int i=LR; i>2; i--) {
      blink(0, i); delay(40); LR = i;
    }
  }
  // 瞬き(閉じる)
  else if(lid == false && rasioL < 0.96 && rasioR < 0.96) {
    for(int i = 1; i < 9; i++) {
      blink(i, LR); delay(40); lid = true;
    }
  }
  // 瞬き(開く)
  else if(lid == true && rasioL > 0.96 && rasioR > 0.96) {
    for(int i = 8; i > 0; i--) {
      blink(i, LR); delay(40); lid = false;
    }
  }
  // 通常時(中央復帰)
  else if(lid == false && rasioL > 0.96 && rasioR > 0.96) {
    if(LR <= 7) {
      for(int i=LR; i<=7; i++) { blink(0, i); delay(40); LR = i; }
    } else {
      for(int i=LR; i>=7; i--) { blink(0, i); delay(40); LR = i; }
    }
    Serial.println("通常時");
  }
  
  // 基準値の定期リフレッシュ
  if (cnt > 10) {
    iniSensorValL = sensorValL;
    iniSensorValR = sensorValR;
    cnt = 0;
  }
}

動作

センサー値の比率変化に基づき、LED瞳の左右移動と瞬きをリアルタイムで再現します。

製造プロセス

  1. プロダクトデザインで自然素材への回帰が進む理由
  2. Raspberry PiでTMP006赤外線温度センサーを使う – Pythonライブラリとセットアップガイド
  3. Raspberry PiとPythonでリモート温度センサーを構築 – ステップバイステップガイド
  4. Raspberry Piでライントラッキングセンサー – シンプルなKY-033ドア/ライン検出器
  5. Home Assistant on Raspberry Piで安全なホーム監視 – モーション、アラーム、ビデオ撮影
  6. Raspberry Pi用DIY赤外線モーションセンサー構築 - ステップバイステップガイド
  7. Raspberry PiでPIRモーションセンサーとLEDを制御
  8. Leap Motionで操作するレーザー戦車の製作 – Arduino、Raspberry Pi、RGB LED
  9. Arduinoで作る赤外線心拍センサー:低コスト・リアルタイム波形表示のステップバイステップガイド
  10. 色感度プロセス向け高精度赤外線温度センシング
  11. パルス光センサー:LED光パルスを増幅して可聴音に変換