フォトリフレクタ方式の非接触空間センサーを透明なOLEDディスプレイの下からセンシングすると未来デバイスのような雰囲気で面白いのではないかと思っていました。
ツイッターで見たOLED画像をヒントにネットで検索すると購入できたので早速実験してみました。
デモ動画
ハードウェア
非接触センサー
コントローラ:Raspberry pi pico
website:https://interactive-hand-sensor.com/root/
OLEDディスプレイ
コントローラ:arduino mega
website:https://www.sparkfun.com/products/15079
動作
- 非接触センサーの位置と値をuartで送信
- OLEDディスプレイは受信した位置※の数値を表示
- OLEDディスプレイの数値を一定時間後に消す
※位置は2箇所(0,1)だけ
ソフトウェア
非接触センサー(Raapberry_pi_pico)
from machine import PWM, UART from Sensor_CLED import * uart = UART(0, baudrate=57600, tx=Pin(16), rx=Pin(17)) def makePwm(gpio, freq, duty16): pwm = PWM(gpio) pwm.freq(freq) pwm.duty_u16(duty16) makePwm(pwmCled_gpio, 50, 1<<15) # set pwm def makeIndi(): val = True def closure(dummy): nonlocal val CLed.setIndi(val) val = not val return closure indi = makeIndi() tim = Timer() tim.init(freq=3, mode=Timer.PERIODIC, callback=indi) def makeEla(): val = True def closure(): nonlocal val rev = val val = False return rev def setVal(dummy): nonlocal val val = True return closure, setVal ela, elaSet = makeEla() # elapsed time tim1 = Timer() tim1.init(freq=5, mode=Timer.PERIODIC, callback=elaSet) def getUartLst(lst): CRI_UART = 18 MAX_SIZE = 511 ma = max(lst) if (ma < CRI_UART): return None idx = lst.index(ma) if ma > MAX_SIZE: # ma:9bit ma = MAX_SIZE ch0 = 0x80 | ((idx) << 4) # 1@@@ __$$ @:sel, $:b0(2bit) ch0 |= (ma >> 7) ch1 = ma & 0x7f # 0&&& &&&& &:b1(7bit) # print(ma, hex(ch0), hex(ch1)) return [ch0, ch1] # ***************** main ******************** if __name__ == '__main__': cled = CLed() Sensor.init() # *** initialize Sensor *** print('******************* START ********************') cled.turnOn(5) time.sleep(1) cled.turnOn(0) while True: Sensor.setAd() #cled.turnOn() if ela(): lst = Sensor.getAdLst() uLst = getUartLst(lst) if uLst is not None: uart.write(bytearray(uLst))
OLEDディスプレイ(arduino_mega)
#include <WiseChipHUD.h>
WiseChipHUD myHUD;
const int SHOW_MS = 100;
const int sw = 52;
// #include "Timer.h"
// Timer t;
void setup() {
Serial.begin(57600); // opens serial port, sets data rate to 9600 bps
Serial.println("hello");
myHUD.begin();
clearOLED();
pinMode(sw, INPUT_PULLUP);
}
void display() {
countUp();
showAll();
delay(2000);
clearOLED();
}
byte sel, b0, b1;
// unsigned long lastChange;
void loop() {
if(!digitalRead(sw)) {
display();
sel = 0xff; // sel is not set
}
if (Serial.available()>0) {
char chr = Serial.read();
if (chr & 0x80) { // 1@@@ __$$ @:sel, $:b0(2bit)
sel = (chr >> 4) & 0x07;
b0 = chr & 0x03;
} else if(sel != 0xff){ // 0___ ____ b1(7bit)
b1 = chr & 0x7f;
oledOnOff();
}
}
clearChk();
// t.update(); // Must be called from 'loop
}
int get0_199() {
// int a0 = ((b0 << 7) | b1);
int rev = int(((b0 << 7) | b1) * 0.389) + 1;
// int rev = int( int((b0 << 7) & b1) * 0.78 + 1); // 255->199(max)
Serial.write(b0);
Serial.write(b1);
Serial.print(rev);
return rev;
}
const int STAMP_SIZE = 2;
unsigned long stamp[STAMP_SIZE] = {0};
void (*clearFP[STAMP_SIZE])() = {clear0, clear1};
void oledOnOff() {
// Serial.write(sel);
// Serial.write(b0);
// Serial.write(b1);
if (sel == 0) {
// /************************* Compass Group *************************/
// myHUD.compassCircle(9); // 0 = All Off; 1-8 = All Off Except Selected; 9 = All On; 10-17 = All On Except Selected
// myHUD.compassArrows(9); // 0 = All Off; 1-8 = All Off Except Selected; 9 = All On; 10-17 = All On Except Selected
myHUD.setHeading(get0_199()); // Max 199
stamp[0] = millis();
// t.after(SHOW_MS, clear0, (void*)0);
}
if (sel == 1) {
// /************************* Radar Detector Group *************************/
// myHUD.radarDetector(8); // 0 = No Radar Gun Icon; 1 = Radar Gun Only; 2-8 = Distance Meter
// myHUD.radarDistanceUnits(1); // 0 = Blank; 1 = "m"
myHUD.setRadarDistance(get0_199(),0); // Max 999
stamp[1] = millis();
// t.after(SHOW_MS, clear1, (void*)0);
}
}
void clearChk() {
unsigned long nowTime = millis();
for (int i=0; i<STAMP_SIZE; i++) {
if (nowTime - stamp[i] > SHOW_MS)
(*clearFP[i])();
}
}
void clearOLED() {
myHUD.clearAll(); // Clears all of the segments
}
void clear0() {
// myHUD.compassCircle(0); // 0 = All Off; 1-8 = All Off Except Selected; 9 = All On; 10-17 = All On Except Selected
// myHUD.compassArrows(0); // 0 = All Off; 1-8 = All Off Except Selected; 9 = All On; 10-17 = All On Except Selected
// myHUD.setHeading(0); // Max 199
del_oled(0, 50);
}
void clear1() {
// myHUD.radarDetector(0); // 0 = No Radar Gun Icon; 1 = Radar Gun Only; 2-8 = Distance Meter
// myHUD.setRadarDistance(0,0); // Max 999
// myHUD.radarDistanceUnits(0); // 0 = Blank; 1 = "m"
del_oled(50,90);
}
void del_oled(uint16_t i0, uint16_t i1) {
for(uint16_t i = i0; i<i1; i++){
myHUD.AdjustIconLevel(i, 0x00);
}
}
void showAll() {
/************************* Compass Group *************************/
myHUD.compassCircle(9); // 0 = All Off; 1-8 = All Off Except Selected; 9 = All On; 10-17 = All On Except Selected
myHUD.compassArrows(9); // 0 = All Off; 1-8 = All Off Except Selected; 9 = All On; 10-17 = All On Except Selected
myHUD.setHeading(199); // Max 199
/************************* Radar Detector Group *************************/
myHUD.radarDetector(8); // 0 = No Radar Gun Icon; 1 = Radar Gun Only; 2-8 = Distance Meter
myHUD.setRadarDistance(999,0); // Max 999
myHUD.radarDistanceUnits(1); // 0 = Blank; 1 = "m"
/************************* Exit Group *************************/
myHUD.leftTunnel(1); // 0 = Blank; 1 = Tunnel; Also try leftRoad();
myHUD.middleTunnel(1); // 0 = Blank; 1 = Tunnel; Also try middleRoad();
myHUD.rightTunnel(1); // 0 = Blank; 1 = Tunnel; Also try rightRoad();
/************************* Navigation Group *************************/
myHUD.nav_Group(1); // 0 = Entire Nav Group Off; 1 = Entire Nav Group On
myHUD.setTurnDistance(999,1); // Max 999
myHUD.turnDistanceUnits(2); // 0 = Blank; 1 = "m"; 2 = "km"
/************************* Call Group *************************/
myHUD.setCallIcon(3); // 0 = Blank; 1 = Outline; 2 = Outline + Phone Icon; 3 = All Segments
/************************* TPMS Group *************************/
myHUD.tirePressureAlert(3); // 0 = Blank; 1 = "TPMS"; 2 = "TIRE"; 3 = All Segments
myHUD.setTirePressure(99,1); // Max 99
/************************* Speedometer Group *************************/
myHUD.setSpeedometer(199); // Max 199
myHUD.speedometerUnits(1); // 0 = Blank; 1 = "km/h"
myHUD.setDestinationDistance(999,2); // Max 999
}
void countUp() {
for(int i = 0; i < 200; i += 5){
myHUD.setHeading(i); // Max 199
if (i > 33 * 1)
myHUD.setRadarDistance(i,0); // Max 999
if (i > 33 * 2)
myHUD.setDestinationDistance(i,2); // Max 999
if (i > 33 * 3)
myHUD.setTurnDistance(i,1); // Max 999
if (i > 33 * 4)
myHUD.setTirePressure(i-33 * 4,1); // Max 99
if (i > 33 * 5)
myHUD.setSpeedometer(i); // Max 199
delay(80);
}
delay(500);
clearOLED();
}
終わりに
OLEDディスプレイを通すと赤外線が減衰しセンサーの出力は1/3くらいになりますが検出できました。このディスプレイは車用のブレークアウトボードですがグラフィカルなディスプレイだともっと面白いと思いました。
子供たちのための未来志向開発をテーマにオリジナルの非接触スイッチや非接触制御という新しい分野を研究しています。
テクノロジーはwebsiteから公開しています。
4
投稿者の人気記事
-
3duilab
さんが
2021/07/09
に
編集
をしました。
(メッセージ: 初版)
-
3duilab
さんが
2021/07/09
に
編集
をしました。
-
3duilab
さんが
2022/01/18
に
編集
をしました。
-
3duilab
さんが
2022/02/26
に
編集
をしました。
ログインしてコメントを投稿する