3ピンのDYP-ME007TXをArduino UNOで使う

以前購入したこのセンサ、OUTってかいてるからアナログの値出力してると思ったら、
どうやらシリアルで動いていた様子…ハマった。


下記のコードで動作確認。
OUTピンをD6にさせばいいみたい。

#include <SoftwareSerial.h>

// TX_PIN is not used by the sensor, since that the it only transmits!
#define PING_RX_PIN 6
#define PING_TX_PIN 7

SoftwareSerial mySerial(PING_RX_PIN, PING_TX_PIN);

long inches = 0, mili = 0;
byte mybuffer[4] = {0};
byte bitpos = 0;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
}


void loop() {
  bitpos = 0;
  while (mySerial.available()) {
    // the first byte is ALWAYS 0xFF and I'm not using the checksum (last byte)
    // if your print the mySerial.read() data as HEX until it is not available, you will get several measures for the distance (FF-XX-XX-XX-FF-YY-YY-YY-FF-...). I think that is some kind of internal buffer, so I'm only considering the first 4 bytes in the sequence (which I hope that are the most recent! :D )
    if (bitpos < 4) {
      mybuffer[bitpos++] = mySerial.read();
    } else break;
  }
  mySerial.flush(); // discard older values in the next read

  mili = mybuffer[1] << 8 | mybuffer[2]; // 0x-- : 0xb3b2 : 0xb1b0 : 0x--
  inches = 0.0393700787 * mili;
  Serial.print("PING: ");
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(mili);
  Serial.println("mili");

  delay(100);
}


微調整する部分は、
たまにマイナスの値がくるのでそれを無視するのと、
インチとmiliでしか値が出てないのでcmに変換が必要。



本来の販売元はTindieで出てるこれっぽい。
https://www.tindie.com/products/upgradeindustries/serial-ultrasonic-distance-sensor/

Serial Ultrasonic Distance Sensor (DYP-ME007TX)

Description
This is a fully digital, serial output ultrasonic sensor that uses typical RS-232/UART output signaling. Only one wire required!

This module constantly pumps out readings at 10 Hz which makes it incredibly easy to operate.

Package Contents

1DYP-ME007TX Serial Ultrasonic Sensor
Specifications

Interface: RS-232 / UART (constant output)
Serial Format: 9600 Baud No Parity 8 bits per byte 1 Stop Bit (output)
Range: up to 4m
Accuracy: 1mm
Sound Frequency: 40 kHz
Output Rate: 10 Hz
Response Envelope: &lt; 30 deg
Supply voltage: 5V
Supply current: 15mA typical
Serial output format

The output from this sensor comes in packets of 4-bytes:

Data[0] = 0xFF: Packet Header
Data[1]= 0x0-0xFF: Data Most Significant Byte (MSB)
Data[2]= 0x0-0xFF: Data Least Significant Byte (LSB)
Data[3]= 0x0-0xFF: Data Checksum: = (0XFF + MSB + LSB) & 0xFF
Data is in MILLIMETERS
16 bit value in mm = Data[1] >> 8 | Data[2]


ちなみに、MegaでやるとなぜかSoftwareSerialでDigital Pinを使おうとするとうごかなくて、
A8とかのピンだったら動く様子。ナジェナンディスカ…。


もう一点追記、
SoftwareSerialを複数やる場合、一度に複数ポートをよめないみたいで、
myPort.listen()で切り替える必要がある。
更に、listenして直後はデータ読めないので、ちょっとまってあげる必要がある。
めどい。。。
もろもろ加味したコードが下記。

#include<SoftwareSerial.h>

long showTimer;

#define NUM_SENSORS 7
#define MAX_RANGE 5000

SoftwareSerial mySerial[NUM_SENSORS] = {
  SoftwareSerial(A8,5),
  SoftwareSerial(A9,6),
  SoftwareSerial(A10,7),
  SoftwareSerial(A11,8),
  SoftwareSerial(A12,9),
  SoftwareSerial(A13,10),
  SoftwareSerial(A14,11),
};

int currentSensorIndex = 0;
long millimeters[NUM_SENSORS];
long waitTimer;

void setup () {
  Serial.begin(115200);

  for (int i=0;i<NUM_SENSORS;i++) {
    mySerial[i].begin(9600);
    millimeters[i] = 0;
  }
}

void loop() {
  if (currentSensorIndex < NUM_SENSORS) {
    if (waitTimer == 0) {
      mySerial[currentSensorIndex].listen();
      waitTimer = millis();
    }
    else if (millis() - waitTimer > 100) {
      readSerial(&mySerial[currentSensorIndex], currentSensorIndex);
      waitTimer = 0;
      currentSensorIndex++;
    }
  }
  else {
    currentSensorIndex = 0;
  }

  if (millis() - showTimer > 100) {
    for (int i=0;i<NUM_SENSORS;i++) {
      Serial.print(millimeters[i]);
      Serial.print("\t");
    }
    Serial.println();

    showTimer = millis();
  }
}

void readSerial(SoftwareSerial *s, int idx) {
  if (s->available() > 3) {
    byte myByte = s->read();
    byte myBuffer[2] = {0};
    if (myByte == 0xFF) // Start-Byte erkennen
    {
      myBuffer[0] = s->read(); // HighByte einlesen
      myBuffer[1] = s->read(); // LowByte einlesen
      s->flush();              // Checksumme und ggf. weitere aufgelaufene Messungen verwerfen
    }

    long mm = myBuffer[0] << 8 | myBuffer[1]; // HighByte und LowByte verodern
    if (mm > 0 && mm < MAX_RANGE) {
      millimeters[idx] = mm;
    }
  }
}

FadaCandyことはじめ(Mac OS X Yosemiteにて)


ふつう、USBをさしたらlsコマンドで一覧に出てくるものだと思うし、
ましてやUSBをさしたらジャックの隣のLEDは点灯するもんだと思ってたのだけど、
いずれも反応せず動かない!?って焦ったんだけど、
ちゃんと手順をふんでインストールすると、無事動作を確認できた。
ジャックの隣のLEDは疎通ができてるって意味のLEDだった様子。


手順、メモ。

git clone git://github.com/scanlime/fadecandy
cd fadecandy/server
make submodules
make
sudo mv fcserver /usr/local/bin
fcserver

これをやってから、ブラウザで「http://localhost:7890/」を開いてFadeCandyが接続されてると一覧に出てくる。


チュートリアルはちゃんと読みましょう、ということで。
参考: https://learn.adafruit.com/1500-neopixel-led-curtain-with-raspberry-pi-fadecandy/fadecandy-server-setup


動作テスト

Facebookを1日1時間しかみれないようにしてみた

年明けのリハビリにChromeのExtension書いてみた。
内容は、タイトルの通り「Facebookを1日1時間以上見れないようにする」もの。


①ExtensionをDLする
ここにあります → http://sorauta.net/files/fbFilter.crx


②おもむろにGoogle Chromeをひらき、アドレスバーに「chrome://extensions」とうちこむ。

こんなページが出てくるはず


③DLしたExtensionをDrag & Dropする

ファイル名は「fbFilter.crx」です。
Dropすると、上記のようなアラートがでるので、Add Extensionをおす


④インストールされたか確認するために、おもむろにfacebookをひらいてみる

SSのとおり、残り時間が表示されていればインストール完了です!
おめでとうございます。



経過秒数後どうなるかって?
それは、やってみてのおたのしみということで(特にそんな大したことしてない)




ソースは下記。


manifest.json

{
  "name": "Internet filter",
  "version": "0.1",
  "manifest_version": 2,
  "description": "This Extension is intended to limit the viewing time of Facebook.",
  "icons": {
      "48": "icon128.jpg",
      "128": "icon128.jpg"
  },
  "content_scripts": [{
    "matches": ["https://www.facebook.com/*"],
    "js": ["script.js"]
  }]
}

script.js

var STOP_THRESHOLD = 3600; // 1日あたり、この秒数以上Facebookをみていたら閲覧制限がかかる
var TIMER_INTERVAL = 1000; // loop関数を実行する周期、ミリ秒で表記

var watchTimer;
var fbClosed = false;
var isViewer = false;

/**
 * 初期処理を行う関数
 *  ページをひらくとまずこの関数が実行されます
 */
var setup = function() {
  console.log('setup fbTiler');

  // ブラウザ上に保存されていたデータを読みだす
  var storedTimestamp = Number(localStorage.getItem("storedTimestamp"));
  // もしブラウザ上にデータが保存されていなかった場合、初期化する
  if (storedTimestamp == null) {
    console.log("initialize local storage");

    var cDate = new Date();
    storedTimestamp = Math.floor(cDate.getTime() / 1000);
    saveToStorage(storedTimestamp, 0);
  }

  // loop関数を定期的に実行するようにセット
  watchTimer = setInterval(loop, TIMER_INTERVAL);

  // 残り時間をFacebook上に表示するようにする
  var mPattern = location.href.match("/messages/([0-9a-z\.\_\-]+)");
  if ((location.pathname == "/" || (mPattern.length > 0 && mPattern[1].length > 0)) &&
      document.title && document.title.length > 0) {
    var element = document.createElement('div');
    element.id = "timeLimitView";
    element.innerHTML = "&nbsp;";
    element.style.position = 'fixed';
    element.style.bottom = '5px';
    element.style.left = '5px';
    document.body.appendChild(element);

    isViewer = true;
  }
}

/**
 * 定期的に実行される関数
 *  閲覧時間の確認、表示制限の処理などを行う
 */
var loop = function() {
  // タイムスタンプ(long型)を、処理しやすいように連想配列に整形する
  var cDate = new Date();
  var cHash = getDateHash(Math.floor(cDate.getTime() / 1000));
  var storedTimestamp = Number(localStorage.getItem("storedTimestamp"));
  var sHash = getDateHash(storedTimestamp);

  // 日付が更新されたか確認
  var keys = ['Y', 'M', 'D'];
  var isDifferentDate = false;
  for (var i in keys) {
    if (cHash[keys[i]] != sHash[keys[i]]) {
      isDifferentDate = true;
      break;
    }
  }

  // 日付が更新されていた場合、閲覧秒数のカウントをリセット
  if (isDifferentDate == true) {
    cTimestamp = Math.floor(cDate.getTime() / 1000);
    console.log("update stored data", cTimestamp);
    saveToStorage(cTimestamp, 0);
  }
  // 経過時間をチェックする
  else {
    var storedViewSec = Number(localStorage.getItem("storedViewSec"));

    // 閲覧時間が、本日の制限時間を超えていた場合、表示をブロック
    if (storedViewSec > STOP_THRESHOLD) {
      //console.log("shut down facebook");
      document.body.innerHTML = '<center><img src="http://serif.hatelabo.jp/images/cache/2b0a04a1636b501e0ad202e672039491b05690d9/f9d7755e1c8f7abead4c76b1a4c5e2225aba1080.gif" style="margin:10px auto;text-align:center;" /></center>';
      fbClosed = true;
    }
    // 残り時間を更新
    else {
      if (isViewer == true) {
        document.getElementById('timeLimitView').innerHTML = (STOP_THRESHOLD - storedViewSec) + " sec";
      }
      //console.log("only " + (STOP_THRESHOLD - storedViewSec) + " second, you can enjoy facebook");
      saveToStorage(storedTimestamp, storedViewSec + (TIMER_INTERVAL / 1000));

      // TODO: test here
      //if (fbClosed == true) {
      //  location.reload();
      //}
    }
  }
}

/**
 * タイムスタンプを処理しやすいように連想配列に変換する
 */
var getDateHash = function(timestamp) {
  var d = new Date(timestamp * 1000);

  var hash = {
    Y  : d.getFullYear(), // year
    M  : d.getMonth() + 1, // month
    D  : d.getDate(), // date
    h  : d.getHours(), // hour
    m  : d.getMinutes(), // min
    s  : d.getSeconds(), // sec
    t  : Math.floor( d.getTime() / 1000 ), // unix time
  };

  for (var k in hash) {
    if (k != 'Y' && k != 't') {
      hash[k] = ('0' + hash[k]).slice(-2);
    }
  }

  return hash;
}

/**
 * ブラウザ上に現在の閲覧時間などを保存する
 */
var saveToStorage = function(st, sv) {
  localStorage.setItem("storedTimestamp", st); // unix time
  localStorage.setItem("storedViewSec", sv); // sec
}

///////////////////////////////////
// 初期化する関数を実行
setup();

gitにもあげたので、なにか更新があればこちらのリポジトリでやってきます
https://github.com/rin1024/Internet-filter-on-Chrome

11月


■ タカシマヤ タイムズスクウェアのイルミネーション演出
新宿高島屋のイルミネーションを総合演出させていただきました。
なんだかで、これも3月くらいから提案していたので、
半年以上かけて実現したプロジェクトでした(長い...)。
名も無きベンチャーがまさか新宿高島屋のイルミネーションやれるとか
数年前までは想像すらしてませんでしたが、
世の中何が起きるかわからないなぁと。笑

イルミネーションはおかげさまで好評なようで、
来年はもっとアップデートしていきたいです。



■ 大分 イルミネーション
間違いなく、今年を総括するであろう一大プロジェクト。
ラボをやめてから、大分で仕事したい!って言ってまわっていたら、
まさかの一発目に滅茶苦茶デカイ仕事きてしまったパターン(良い意味で)。


これまで、大規模なイルミネーションが行われてこなかった 大分での「初」開催。
更に、今年、新たに開業した大分駅の「初」となるイルミネーション。
地元のばーちゃん達に、自分がやってる仕事を見てもらえる絶好の機会。


普段から作品を作るときも、これ失敗したら死ぬなーとか
超ビビリながらやっているのですが、
今回は、失敗したらマジで地元帰れなくなるなーとか思って、
いつもとはまた違った感覚のなか、お仕事してました。


企画内容もかたまり、
11月に入り、施工が始まるにつれ、
これ実際に間に合うの!?みたいなレベルで出てくる山のような問題。
それらと日々格闘しつつ、演出のプログラム調整を開始できたのは、
イルミネーション点灯式のほんの数日前。。。
本当は調整期間3週間で見てたんだけど、、、
いつもソフトは最後の尻拭いするとはいえ、、、
今回の規模では死ぬ、、、、
とか思いながら、ひたすら楽曲から演出イメージを膨らませながら、
深夜の誰もいない駅前で、テスト、テスト、またテスト。
そして迎えた点灯式。
。。。個人的には、全然満足できなくて、
もう死にたいくらいに課題だらけでしたが、
結果をどうこういってもしょうがないので、
この悔しさと反省点は全て洗い出して、
来年への改善に向けてまた一から進んでいこうと思います。


このお仕事も、本当に色んな人からのご好意で、
つながって、つながって、形になりました。


このお仕事に関わってくれた皆さん、
直接ではなくとも、応援してくださっていたみなさまが、
少しでも笑顔になってくれるような形にできていたのであれば、
幸いです。





今年も本当に多くの素敵な方々に会えて、
(Facebook上だけでも95人つながりが増えておりました。笑)
たくさんのお仕事に恵まれて感謝の1年でした。


相変わらず、空間演出から基板設計、スマホアプリとか、
ひろーくあさーくやっておりますが、
来年はもう少し絞れてくるといいなぁと。


また今年とは一歩、生活形態を変えて、
2016年も引き続き楽しいことやっていけたらなーと思っています!


それでは、良いお年を。

10月


■ スマートイルミネーション横浜にて「ある海辺」展示
昨年ChAirを展示したスマートイルミネーション横浜にて、
今年も再び手塚くんと参戦。
今回は、そのむかし、横浜が海だったころの景色を彷彿させるようなサウンドインスタレーションで、
「ある海辺」というタイトルで出展しました。
象の鼻にある石のベンチ全てをつかった、
規模でいうと50m x 50mの個人製作では過去最大のサイズでの展示を行いました。


相変わらず、めんどくさがりなのに真面目な手塚くんの根性は凄いなーと感心しつつ、
今回楽曲制作で携わってくださった野口さんも、
展示期間中もほぼ毎日足を運んでくださって、常に楽曲のアップデートをしまくってました。
音響に関しても、
超有名なアーティストのレコーディングなどを行っている方に参加していただいたり、
記録撮影も、いつもお世話になってる方に来ていただいたりと、
割りとオールスターな感じで制作を行うことができました。
個人ワークは、自分たちの裁量でどこまでもアレンジできて、作り込めるのがいいとこだなと。
相変わらず、10月末の横浜は寒かったけれども、楽しく作品制作できました。


あとは展示期間中、東京から足を運んで来てくれたり、
神戸に隔離されてた大学院時代の友人とかが来てくれたりと、久々に再開ができたしたのも嬉しかった。
作品展示のいいところは、
作品を通して色んな人とコミュニケーションとれることなんだろうなーと。
ある種の、冠婚葬祭みたいな感じがする。

6〜9月

色々と仕込みやデモなどはしてはいたのだけど、
この期間は表に出せるリリースが特になかったかも。
来年は、この時期を勉強にあてるでもいいので、うまく使えるようにしたい。



■ うまログ リリース(7月)
むかーし、大山さんと適当に作って適当に個人的に遊んでいたサービスを、
リニューアルした。
サービス内容は、ワンタップで自分がいる場所の美味しいお店を
スコアが高い順にだしてくれるというもの。
サービスはこちら
スマホから見ると良いです。



■ Art Hack Day(8月)
Art Hack Dayという3日間で、異なる分野のアーティストやデザイナーと即興的に作品を作り上げるハッカソンに参加。
今まで、どんな満足できなかったものでも作ったものは発表するようにしてきたのですが、
今回のは悔しい通り越して、
ちょっと反省ってレベルじゃすまねーぞって感じのものになってしまい、
発表できずじまいでした。
素敵な人が集まっていた分、もったいないコトしたなーと。



■ SENSORSにて「あ」が放映(9月)
大学院時代に制作していた「あ」という作品が、
SENSORSというテレビ番組の「SENSORS WONDER」という、
「なんだかよくわからないけど、将来世の中で役に立つかも!?」な
研究などを特集している企画で放映いただきました。
担当のディレクターさんがとても情熱的な方で、
より正確に「あ」のよさが伝わるようにと、きめ細かく熱心に取材していただきました。
良いものを作ろうとしてる人って、余計なことを語らずとも、
その姿勢で伝わってくる。これもタイトだったけど、楽しかった。
ちなみに、番組放映後に開発秘話についてまでまとめていただきました。感謝。

5月


■ 月間事業構想に取材記事掲載
月間事業構想という雑誌に、インタビュー記事を掲載いただきました
「クリエイターの発想術」という連載の中で、
普段どんなことを考えながら作品をつくっているかについてのお話をさせていただきました。
読み返して、たいてい僕はぼーっとしてるんだろーなと思った。


■ 某外車のクローズドイベントの空間演出
(こちらも)大人の都合により写真は掲載できませんが、
某外車のクローズドイベントの空間演出を一部担当させていただきました。
この車を買うクラスタの人は、こういう人たちが集まるんだなーというのを、
イベント通して観察していました。