■原理■
同僚さんから、「肩こりがひどいので電子工作で何かできないか」というご相談をいただいて作ってみたシリーズ第二弾です。第一弾は首肩の傾斜で振動するパターンでした。今度は「ふと気がつくとモニタに近づきすぎている。近づいたら警告を」というデバイスです。モニタの上端に貼り付けて使います。
距離計測は超音波とToFを試してみたのですが、超音波は人間の顔だとあまりうまいこと検出できず、手持ちのToFは計測レンジが微妙に遠くてNG。シャープの赤外線距離測定デバイスを使うことにしました。
■製作■
Arduino nanoのパチを使いました。距離センサー
表示にはNeoPixels / WS2812b的なLED
回路は、それぞれのGND同士をつなぎ、ArduinoのVinとセンサーとNeoPixelsの電源同士をつなぎます。距離センサーは最大約2.8vのアナログ出力なのでアナログ入力A0、ArduinoのA1とNeoPixelsのDinをつなぎます。
今回、0.19mmのエナメル線で配線しました。ワイヤリングペンも作ったので、GND-GND-GNDとつながるような場所が大変楽です…と言いたいところですが、所要時間的には架橋ポリエチレン被覆線とあんまり変わらなかったです。
ワイヤリングペン、シャープペンに通すのに例によって30cmほどに切ったワイヤを先端から差し込んで後ろの本体と接合して引っ張り出す作戦を取りました。が、前回は0.3mmだったので突き合わせでハンダ付けできたのですが、今度は0.19mm、さすがに細くて無理だったので、瞬間接着剤使いました。この時期は空気が乾燥しすぎていてなかなか固まらないので困ったもんです。今度、接着促進剤ってのを使ってみたい。
![]() |
見た目は悪いけど使い勝手は良いですw |
■プログラム■
起動したら、5秒間距離を計測して平均値を取ります。これが基準値で、これより近づいたら=値が大きくなったらLEDを点灯させます。loop()ではanalogReadからの値を簡易的な移動平均処理で測定誤差をツブして無駄なチラツキを減らしています。距離センサーからの値は最大で500ぐらいなので、上記の平均値と500との中間点までは黄色、それを越えて近づいたら赤で点灯するようにしました。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Adafruit_NeoPixel.h> | |
#include <TimeLib.h> | |
#ifdef __AVR__ | |
#include <avr/power.h> | |
#endif | |
#define PIN A1 | |
#define Distance A0 | |
#define MaxValue 500 | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_RGB + NEO_KHZ800); | |
int prevSecond = -1; | |
int aveValue = 0; | |
int halfValue = 0; | |
void setup() { | |
// This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket | |
#if defined (__AVR_ATtiny85__) | |
if (F_CPU == 16000000) clock_prescale_set(clock_div_1); | |
#endif | |
// End of trinket special code | |
Serial.begin(115200); | |
strip.begin(); | |
strip.show(); // Initialize all pixels to 'off' | |
int nAverage = 0; | |
while (1) { | |
if (prevSecond != second()) { | |
prevSecond = second(); | |
strip.setPixelColor(0, strip.Color(255, 255, 255)); | |
strip.show(); | |
delay(50); | |
strip.setPixelColor(0, 0); | |
strip.show(); | |
aveValue += analogRead(Distance); | |
nAverage ++; | |
if (nAverage >= 5) break; | |
} | |
delay(10); | |
} | |
aveValue = aveValue / nAverage; | |
halfValue = (MaxValue - aveValue) / 2; | |
} | |
int roundValue = -1; | |
void loop() { | |
// put your main code here, to run repeatedly: | |
if (roundValue == -1) { | |
roundValue = aveValue; | |
} | |
roundValue = (roundValue * 9 + analogRead(Distance)) / 10; | |
int diff = roundValue - aveValue; | |
Serial.print("ave = "); | |
Serial.print(aveValue); | |
Serial.print(", dif = "); | |
Serial.println(diff); | |
if (diff > halfValue) { | |
strip.setPixelColor(0, strip.Color(255, 0, 0)); | |
} else if (diff > 0) { | |
strip.setPixelColor(0, strip.Color(128, 128, 0)); | |
} else { | |
strip.setPixelColor(0, 0); | |
} | |
strip.show(); | |
delay(10); | |
} |
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。