M.C.P.C. (Mamesibori Creation Plus Communication)

印刷屋から五反田のWeb屋に転職したCLのブログです。

(9/5修正済み)アドビの社長ツイッターアカウント紹介ページ修正しないの?

(2016-09-05 11:50追記)現時点で確認したところ、当該ページの佐分利ユージン氏のTwitterアカウント(screen_name)の表示が修正されていました。すばらしい!

〜〜〜

クリエイティブ環境構築サービスを提供するアドビシステムズ社は、一方では自社のサイトにおいてはわりとWebでやられている標準的な作法を守らない暴れん坊きかん坊としても有名で、例えば、自社ソーシャルメディアへのアクセス方法を表示じているページのURLが2016年7月のどこかの時点で404 Not Foundになってしまい、当該情報が得られるページを散々探した結果、別のURLに新しく相当ページができていました。

新しいページはこれ

www.adobe.com

こういうとき、Web制作の教科書的には、ユーザのため古いURLにアクセスしたユーザに新しいURLに自動で案内するように301リダイレクトを設定しろって書いてありますが、アドビはそれを何故かしない。業界のリーディングイノベーター(←?)はユーザの為を思わない冷徹な心を持つ企業だという印象をいまさら再生産してどうするのって思うわけです。

そんで、そのページでアドビシステムズ日本法人社長の佐分利ユージン氏のTwitterアカウントが紹介されているわけですけれども、Twitterへのリンクは正しいのですが表示は間違っているのでございます。

f:id:C_L:20160902154419p:plain

魚拓

  • 誤)@EaugeneSaburi
  • 正)@EugeneSaburi

(↑まあ社長の名前っていちいち覚えたくないっていうのはわかる)

そんで、間違っているって言うことが8月3日に指摘されているわけです。

(↑ぶっちゃけ私が書いたのですが)

んで、1ヶ月が経とうとするAdobe MAX Japan 2016が開催されている9月2日になっても修正されていません。

以前、アドビの岩本さんが、要望とか機能改善があったら複数の人が声を上げないと本社に届かない、みたいなことを言うてたけれども、まさか誤植の指摘でそれはないよね、と思うんですが、いかがなものでしょ?(そもそも複数人が声を上げないと対応しないっつーのは、私達はいつからそんなゲームに自動エントリーさせられていたんだって話である)

おそらく、あそこのページの表記が直る正しい道はアドビチャットサポートだと思うんです。生身の人間が対応するし彼ら上申するって必ず言うから。でも、Twitterの企業アカウントとして開設されているところに、その企業の社長の事案でメンション受信しているのに対応しないって、社長がかわいそうだと思うのです。私だって、届出電気通信事業者の届出を未届出でメールサービスを始めようとしてたのを発見して、社長がしょっぴかれるのを未然で防いだりしているんだから、君らも頑張れよ!(←君らとは)

建前として社長が読んでいるていのアカウントなわけですし、社長あてに来たメンションに対応する作業をソーシャルメディア担当がするんじゃないのかと思う。しないのなら「佐分利ユージンbot(公式)」にしてほしい。

そういうわけで、当該ページの社長アカウントの表記がいつ直るか、私はずうーっとwktkして待っているのです。誤植直さないって選択肢はこの会社の提供するサービスを考えるとありえないわけだしね!

2016年時点で3G-USBモデムは中国から8ドルで買えるが当然技適なし

国内の3G-USBモデムの事情がすこぶる悪く、

  • 新品はSORACOMが販売するABIT AK-020がソラコム直販で¥4,980が最安
  • キャリアから製品がたくさん出た時期とIoTで需要が膨らんだ時期がズレ過ぎて中古端末の価格も新品よりも高い

となり、6年前黒埼のハードオフで500円でL-05Aを入手した頃とは様相が変わりすぎているわけです。

一応ソラコムのAK-020がスイッチサイエンスで売っているのでリンク。すごいどうでもいいことなんですけれどもこれに入っているSORACOM AirのSIMの登録有効期限が2016/8/31になっているんでスイッチサイエンスは8月中に販売しきらないと腐るんじゃないですかね(見切り品チラッチラッ

www.switch-science.com

一方、みんな大好きAliExpressだと、$8ぐらいでHSDPA モデムとして売られていわけです。おなじ商品がAmazon.jpだと2,000円ぐらいですね。

※注意! 下記から買っても日本国内では使用が許されていない

仕様としては、HUAWEI E1750互換らしいので、外国のインターネットにいっぱい出ている接続設定情報を流用すれば、国内MVNOの回線でも接続できると思うんですけど、これら日本の技適マークついていないので、日本においては電波暗室以外で使うと違法となっちゃいます

中国からの送料込みで$8ぐらいという単価が知れている状況で、国内の端末が¥4,980っつーのが辛いし、IoTとして大量にプローブ的な子機を準備したいのであれば3G-USBモデムもコンポーネントとして安価に調達できてほしいなあと思いました。Raspberry Pi Zeroが$5で、通信SIMが月298円なのにモデムで5,000円とかなんだこれ。

同様に、USBタイプの3Gモバイルルータに関しても国内事情がいささか辛いですね。USBスティックがWi-Fiアクセスポイントと3Gモデムになっていて、一度PCで設定すると、USBスティックのUSB端子をUSB電源に挿しておくだけでルーターになってくれるタイプ。

国内の製品だと、

ピクセラ LTE対応USBドングル ホワイト  PIX-MT100

ピクセラ LTE対応USBドングル ホワイト PIX-MT100

外国の製品だと、※注意! 下記から買っても日本国内では使用が許されていない

とか。(☝なんか、SIMを入れて一回設定終わっておけば、Wi-Fi経由でなくても、Raspberry Piusb-modeswitch をインストールしてUSBポートに挿すだけで eth0 としてインターネットにつながるらしい。pppとか関係ないのな)

これは、ある見通しの効く空間の中心部(ハブ部)に置いておいて、Wi-Fi搭載のIoT子機のデータを3G経由でインターネット送信をさせたいわけです(楽したい人向け)。これも内外価格差が大きいので、技適のルールさえなんとかなっていればぐぬぬ、という感じです。

以上、個人で電子おもちゃを作り始めて初めてわかる技適の辛さでした。

BOSCH社 温湿度・気圧センサBME280用node.jsパッケージnpmに出来

オシゴトでは10年前のロートルなWeb制作環境にぶっこまれてセッションも知らないとか言いだしたのでさすがに黙っていられずいろいろ口出していたら技術力底上げの担当みたいなのになって言わなきゃよかった的なことになっていて、このままじゃ全然自分の技術つかんのよなーとか思って「わたし何でもできます」だと東京だとほんとに転職できねえのなとか実感しつつしこしこ実家のほうで使うIoT機器でも作んべかなと思っていまして、

秋月電子で売っている温湿度・気圧センサっていうのが、¥1,080 なのに3種類のセンシングできて便利ってんで、買ってみたわけですよ。

秋月電子の。1,080円

akizukidenshi-ogp-injector.dtpwiki.jp

スイッチサイエンスの。1,620円

www.switch-science.com

このセンサ、ガリレオ7でもストロベリーリナックスでも売っていますね。

そんで、こんだけあちこちで売られているセンサーなんだから、node.js で動かす作例ぐらいあるだろうと思って探したがなかった。Pythonの作例ならいっぱいあるわけですが、いまさらPythonもないわけです。 require('child_process').execSync; とかすればPythonをチャイルドプロセスで動かせるんでしょうけれども嫌なのです。Adafruitのライブラリがそんな構成になっている(node-adafruit-bme280)。

そこで、npm を散々探したら、node-bmp-280 という温度と気圧の2種類をとれるセンサ用のモジュールがあったので、改造して、node-bme-280 という名前で npm にアップロードしておきました。なんだこれ、npm は簡単すぎて CPAN よりもカオスな感じがするぞ!

node-bme280

インストールするには、

$ npm i node-bme280 --save

でいけます。サンプルプログラムとして、

var BME280 = require('node-bme280');

var barometer = new BME280({address: 0x76});

barometer.begin(function(err) {
    if (err) {
        console.info('error initializing barometer', err);
        return;
    }

    console.info('barometer running');

    setInterval(function() {
        barometer.readPressureAndTemparature(function(err, pressure, temperature, humidity) {
            console.info(
                'temp:',
                temperature.toFixed(2),
                '℃  pressure:',
                (pressure / 100).toFixed(2),
                'hPa  hum:',
                humidity.toFixed(2),
                '%'
            );
        });
    }, 1000);
});

実行結果

pi@raspberrypi:~/testapp $ node bme280.js
barometer running
temp: 32.62 ℃  pressure: 1005.20 hPa  hum: 69.35 %
temp: 32.59 ℃  pressure: 1005.17 hPa  hum: 69.34 %
temp: 32.59 ℃  pressure: 1005.21 hPa  hum: 69.34 %
temp: 32.58 ℃  pressure: 1005.22 hPa  hum: 69.34 %
temp: 32.58 ℃  pressure: 1005.21 hPa  hum: 69.34 %
temp: 32.57 ℃  pressure: 1005.20 hPa  hum: 69.34 %
temp: 32.56 ℃  pressure: 1005.20 hPa  hum: 69.34 %
temp: 32.54 ℃  pressure: 1005.18 hPa  hum: 69.34 %
temp: 32.55 ℃  pressure: 1005.22 hPa  hum: 69.34 %
temp: 32.55 ℃  pressure: 1005.22 hPa  hum: 69.34 %
temp: 32.53 ℃  pressure: 1005.23 hPa  hum: 69.34 %
temp: 32.52 ℃  pressure: 1005.20 hPa  hum: 69.33 %

て感じです。我が家は熱いですね。

あと、この手のセンサのやつは、校正できないっつーのがつらいかも。Python版の出力値と近いところが出ているから可とした。

これがあると、こんなのを作れるぞ!

これバッテリー駆動でどこからでもGPSと温度・湿度・気圧を DynamoDB に送り続けるやつ。

Raspberry Piにログ記録しないから電源いきなり切ってもOKな気がする。

journald のログのやつは、どうすっかな、 /var/run/systemd/journal ってSDカードのボリューム上だな。確か OverlayFS 使えるからそれで tmpfs で作ったRAMディスクのボリュームを /var/run/systemd/journal に重ねてしまえばいいんじゃないかなーとか思っているんだけど、甘いかな?

秋月電子7セグメントLED DIP化キット10桁をArduino/Raspberry Pi/mbedで点灯

2016/03/04に、秋月電子通商で発売になった、「秋月電子7セグメントLED DIP化キット」を12個入手したので、そのうちの10個を使って点灯させてみます。

7セグメントLED DIP化キットとは?

akizukidenshi-ogp-injector.dtpwiki.jp

この製品は、通常だと点灯するのに手間がかかる7セグメントLEDを容易に駆動できるよう、シフトレジスタIC74HC595と、LED用の抵抗を実装した基板です。

(2016-03-15追記)

7セグLEDセット販売の製品も用意されました。

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

74HC595を使うと、

  • 数珠つなぎにすることで、複数の7セグメントLEDをまとめて操作できる
  • 一度点灯の指示をすると次の指示を出すまで点灯したままにできる
    • ループや割り込みで桁駆動する必要がなくプログラムで楽できる

抵抗が実装されていることで、

  • 1桁ごとに8個の抵抗を用意する必要がなくなる
  • 7セグメントLEDに電流を流し過ぎて故障させる事故が減る

というとてもありがたい基板です。

欠点もあって、

  • 常時点灯なので(=ダイナミック点灯ではない)、LEDの寿命が比較的短くなり、消費電力が大きい
  • マイコンなどで表示パターンをシリアル転送してやらないと点灯しない

となります。

点灯させる前に……消費電流の確認

製品の仕様としては、全セグメント点灯で45mAとのこと。

7セグLEDユニットとしてC-551SRDを載せ、全セグ点灯で5Vで流した場合、7セグLEDユニット5個で0.08A、10個で0.17A(簡易電流計による測定)流れていました。

Adruino Pro Miniには最大12Vの電源から降圧して5Vを作り出すレギュレータがついているのですが、保証されている最大電流値は150mAとなっています。実際のテストでは、オンボードレギュレータの使用では、4個までしか駆動できませんでした(Arduinoにリセットがかかる)。10桁(10個)駆動させるには、5V/450mA程度の電源(USBの電源など)を使う必要があります。

Raspberry Piで3.3Vで点灯させた場合は、簡易電流計によると7セグ10個で0.21Aとなっていましたが、点灯の瞬間は倍以上の電流が流れていました。そもそもGPIOの3.3Vピンからは50mAしか流せないはずなのでやってはいけないです。Raspberry Piの5Vを電源に使い、GPIOは後述しますが3.3V出力を74HC4050で5Vに上げ74HC595に入力しする形で、7セグLED側は5Vとして取り扱います。

Arduinoで点灯させる

早速Arduinoで点灯させます。うちで使うのは、ブレッドボードに乗せやすい、Arduino Pro Mini 5V/16MHzです。

部品名 価格
Arduino Pro Mini 328 5V 16MHz 1243

www.switch-science.com

部品表

部品名 個数 価格
赤色7セグメントLED カソードコモン ボディ黒 C-551SRD 10個 400
7セグメントLED DIP化キット 10個 1600
ブレッドボード BB-102 1枚 300

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

配線

74HC595とのインタフェースとして、3線式シリアル通信用のSPIインタフェースと、ラッチに任意のピンを1ピン分をGPIOの出力モードで利用します。3線式シリアル通信というのは、クロック信号SCK、データ入力信号SDI・データ出力信号SDOの3本の配線でシリアルデータを送受信する方式です。送信だけなら、クロック信号SCK・データ線SDOの2線です。

Arduino 7セグ基板 意味
5V VDD +5V
GND GND Ground(0V)
SCK(pin13) SCK SPI SCK クロック入力
MOSI(pin11)SDO SDI SPI SDI Masterから見たらOut/SlaveからはIn
pin10 LATCH 74HC595 ラッチ(表示を固定)

f:id:C_L:20160308231222p:plain

Arduino Mini Pro

プログラム(Arduino IDE 1.65)

ダイナミック点灯ではないので、ラッチを上げたまま1文字分のビットパターン8bitを10回合計80bitを転送した後、一瞬だけラッチを下してすぐにラッチを上げることで描画が完了します。

ラッチのためのpinにSPIインタフェースでいうところのSSのピンを使っているのは、本当は良くないけれども動くことは動く。

#include <SPI.h>

// SPI: 10(SS)、11(MOSI)、12(MISO)、13(SCK) 
const unsigned char digits[] = {
  0x3f, 0x06, 0x5b, 0x4f,
  0x66, 0x6d, 0x7d, 0x27,
  0x7f, 0x6f,
};

const char str[] = "3.14159265358";
char buf[12];

void setup() {
  //Serial.begin(9600);
  
  SPI.begin() ;                          // SPIを行う為の初期化
  SPI.setBitOrder(MSBFIRST);             // ビットオーダー
  SPI.setClockDivider(SPI_CLOCK_DIV4);   // クロックをシステムクロックの1/4で使用(16MHz機の時は4MHz)
  SPI.setDataMode(SPI_MODE0) ;           // クロック極性0(HIGH) クロック位相1(HIGH)

  char j = -1;
  for ( char i = 0; i < strlen( str ); i++ ) {
    char s = str[i];
    if ( s == '.') {
      buf[j] |= 128;
    }
    else {
      j++;
      buf[j] = s;
    }
    
  }
  show();

}
void show() {
  digitalWrite(SS, HIGH);  // 74HC595 ラッチ On(表示固定)
  for ( char i = 0; i < 10 ; i++ ) {
    char d = buf[i];
    char s = ( d & 128); // 128以上のときは128、127以下のときは0
    d &= 127;            // 下位7bitのみマスク
    s += digits[d-48];   // 文字コードに合わせたパターンを合成
    SPI.transfer(s);        // 74CH595 SPIで8ビット分転送
  }
  digitalWrite(SS, LOW);   // 74HC595 ラッチ Off(表示更新)
  digitalWrite(SS, HIGH);  // 74HC595 ラッチ On(表示固定)
}

void loop() {
}

動作例

あとで写真載せる とりあえずTwitterに上げた写真でも置いておく

Raspberry Piで点灯させる

Raspberry Piでも、SPIを使って点灯します。あと、プログラミング言語node.jsで行きます。

せっかくだからRaspberry Pi Zeroなんか使ってみるといいですね。

部品名 価格
Raspberry Pi Zero $5

www.raspberrypi.org

部品表

部品名 個数 価格
赤色7セグメントLED カソードコモン ボディ黒 C-551SRD 10個 400
7セグメントLED DIP化キット 10個 1600
ブレッドボード BB-102 1枚 300
6回路バッファ CD74HC4050E 1個 40

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

配線

74HC595とのインタフェースには、3線式シリアル通信に適用できるSPIインタフェースと、ラッチ用に任意の1ピンをGPIOの出力モードで利用します。

あと、3.3Vでも光りますが、3.3Vピンの限界超えているので、5Vを使います。

電源として5Vを使うとなると、このままだと信号線が3.3Vなのですが、74HC595のデータシートを見るとVCC=4.5[V]でVIH=3.15[V]となっていて、きわどいです。計算するとVCC=5[V]でVIH=3.5[V]となりますので。

f:id:C_L:20160317003850p:plain

実際にVCC=5[V]を供給して、SPI出力を3.3Vのままで接続してみると、やはりSCLKが5Vまで登り切らないとちゃんとDSIデータpinから状態を正常に取得できないようで、表示が乱れてしまいます。そこで、信号線を5Vにするためにレベルシフタとして使える6chバッファIC74HC4050を使うといいです。

6chバッファIC74HC4050は、マイコンからの出力の場合に限って、レベルシフタとして使えます。安価なので用意しておくと多い日も安心です。

Raspberry Pi 7セグ基板 意味
5V(2pin) VDD +5V
GND(20pin) GND Ground(0V)
SCLK(23pin) SCK SPI SCK クロック入力
MOSI(19pin) SDI SPI SDI Masterから見るとOut/SlaveからはIn
GPIO25(22pin) LATCH 74HC595 ラッチ(表示を固定)

Raspberry-pi-gpio

Pi Zero

f:id:C_L:20160315022416p:plain

プログラム(Raspbian Jessie/node.js)

ダイナミック点灯ではないので、ラッチを上げたまま10文字分のビットパターン80bitを転送した後、一瞬だけラッチを下してすぐにラッチを上げることで描画が完了します。

肝腎のnode.js環境の準備はプログラム冒頭のコメント参照。Raspbian Jessieで最初から入るnode.js環境を取り除くなど破壊的な操作が入りますので、再インストールしても問題がないRaspberry Piで試しましょう。

どうでもいいがpi-spiのコールバックの中ではonoffのGPIO操作とかうまく動かないのを知った。promise使う場面なのかね

'use strict';

// akizuki-7seg-10col.js:
// Usage:
// (Raspberry PiにRaspbian Jessieをインストールして、
// sudo raspi-config で SPI使用を有効にしてリブート後、
// piユーザでログイン)
// sudo apt-get update
// sudo apt-get -y remove nodered nodejs nodejs-legacy
// curl -LO http://node-arm.herokuapp.com/node_latest_armhf.deb
// sudo dpkg -i node_latest_armhf.deb
// mkdir 7seg
// cd $_
// npm install onoff pi-spi
// curl -LO https://gist.githubusercontent.com/CLCL/ab5be8ddc4caa0d72aa5/raw/80600eec8e20584d945c7b249ebb001cd2661b59/akizuki-7seg-10col.js
// sudo node akizuki-7seg-10col.js


//
// #Use libs/Global Objects
//

var SPI  = require('pi-spi');
var Gpio = require('onoff').Gpio;

// SPI初期化
var spi = SPI.initialize('/dev/spidev0.0');
spi.clockSpeed(31250000); // 250MHzの8分周=31.25MHz(実用できる限界速度)

//
// #define
//

// 信号値定義
var HIGH = 1;
var LOW  = 0;
// 信号ピン定義
var LATCH =  25; // GPIO25(22pin):74HC595 LATCH           -> LAT
                 // MOSI(19pin)[変更不可]:SPI DATA OUTPUT -> DAT
                 // SCLK(23pin)[変更不可]:SPI CLOCK       -> CLK

//
// Class
//

var SEG7 = function(f) {
  this.gpio = {
    lat : new Gpio(f.LAT, 'out')
  };
  this.digits = [
    0x3f, 0x06, 0x5b, 0x4f,
    0x66, 0x6d, 0x7d, 0x27,
    0x7f, 0x6f
  ];
  this.gpio.lat.writeSync(LOW);  // ラッチ(LED表示固定)
};

SEG7.prototype = {
  write: function(buf) {
    return new Promise(function(resolve, reject) {
      spi.write( buf, function(e) {
        if (e) console.error(e);
      });
    });
  },
  latch: function() {
    var self = this;
    return new Promise(function(resolve, reject) {
      self.gpio.lat.writeSync(HIGH); // ラッチ解除(シフトレジスタ内容表示)
      self.gpio.lat.writeSync(LOW);  // ラッチ(LED表示固定)
    });
  },
  show: function(f) {
    var self = this;

    var buf = Buffer(f);
    var buf2 = new Buffer(10);
    var j = 0;
    for (var i = 0; i < buf.length; i++) {
      if (buf[i].toString() == '.'.charCodeAt(0)) {
        buf2[j-1] |= 128;
      }
      else {
        buf2[j] = self.digits[buf[i]-48];
        j++;
      }
    }

    self.write(buf2).then(self.latch());
  }

};

//
// Main Routine
//

var seg7 = new SEG7({LAT: LATCH});

var timer = Date.now();
(function loop() {
  var now = Date.now();
  if (now - timer > 16) {
    seg7.show('3.141592653');
    timer = now;
  }
  process.nextTick(loop);
})();

動作例

あとで写真載せる とりあえずツイッターのでお茶を濁す

mbedで点灯する

せっかくなので(このくだりいるのか?)mbedでも光らせます。

今回は、ArduinoマイコンATmega328Pよりも安価なマイコンLPC1114FN28を使ってるmbed LPC1114FN28を使います。これ、プログラム出来上がったらマイコンを外して直接ブレッドボードやら基板やらに設置して動かせるんですよね。

部品名 価格
mbed LPC1114FN28 2160

www.switch-science.com

部品表

部品名 個数 価格
赤色7セグメントLED カソードコモン ボディ黒 C-551SRD 10個 400
7セグメントLED DIP化キット 10個 1600
ブレッドボード BB-102 1枚 300

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

配線

74HC595と通信するLPC1114FN28側のインタフェースには、3線式シリアル通信に適用できるSPIインタフェースと、ラッチ用に任意の1ピンをGPIOの出力モードで利用します。 あと、3.3Vでも光ります。

LPC1114FN28 7セグ基板 意味
VIN 3.3V VDD IC単体で使う時は外部から+3.3V供給
GND GND Ground(0V)
SCLK(dp6) SCK SPI SCK クロック入力
MOSI(dp2) SDI SPI SDI Masterから見るとOut/SlaveからはIn
dp9 LATCH 74HC595 ラッチ(表示を固定)

f:id:C_L:20160312225119p:plain

プログラム(mbed)

ダイナミック点灯ではないので、ラッチを上げたまま1文字分のビットパターン8bitを10回合計80bitを転送した後、一瞬だけラッチを下してすぐにラッチを上げることで描画が完了します。mbedはspi.write()での1回の転送幅を変更できるが、8bitが使いやすいのではないでしょうか。

#include "mbed.h"

const unsigned char digits[] = {
  0x3f, 0x06, 0x5b, 0x4f,
  0x66, 0x6d, 0x7d, 0x27,
  0x7f, 0x6f,
};

const char str[] = "3.14159265358";
char buf[12];

// mbed LPC1114FN28
// SPI: dp2(MOSI)、dp1(MISO)、dp6(SCK) 
SPI spi(dp2, dp1, dp6); // mosi, miso, sck
// LATCH: 9
DigitalOut latch(dp9);

void show() {
    latch = 1; // 74HC595 ラッチ On(表示固定)
    for ( char i = 0; i < 10 ; i++ ) {
        char d = buf[i];
        char s = ( d & 128); // 128以上のときは128、127以下のときは0
        d &= 127;            // 下位7bitのみマスク
        s += digits[d-48];   // 文字コードに合わせたパターンを合成
        spi.write(s);        // 74CH595 SPIで8ビット分転送
    }
    latch = 0;  // 74HC595 ラッチ Off(表示更新)
    latch = 1;  // 74CH595 ラッチ On(表示固定)
}

void main() {
    spi.format(8,0);
    spi.frequency(12000000); // 12MHz
    
    char j = 0;
    for ( char i = 0; i < strlen( str ); i++ ) {
        char s = str[i];
        if ( s == '.') {
            buf[j-1] |= 128;
        }
        else {
            buf[j] = s;
            j++;
        }
    }
    show();
}

動作例

あとで写真載せる

とりまTwitterに貼った写真でお茶濁す

本当にこの製品は有用なの?

8桁ならコンポーネント製品はある。これも常時点灯(74HC595が8個載っている)

akizukidenshi-ogp-injector.dtpwiki.jp

多桁7セグ表示器をダイナミック点灯・ディスクリート部品で作るとこんなにもじゃっとするんやでー

ダイナミック点灯のためループか割り込みでガシガシ桁駆動させる必要があるので、プログラムも割ともじゃっとする。

CentOS6 EPELリポジトリでphpMyAdminを2016/02にアップデートしたらいつもどおりに動かない

CentOS 6用EPELリポジトリphpMyAdminphpMyAdmin.noarch-4.0.10.14-1.el6.rpmになっていますがこれにアップデートすると/etc/phpMyAdminパーミッションが変わってしまって/etc/phpMyAdmin/config.phpに書いていた設定が読めくなるっていう現象が起こっているようです。

具体的には、(社内環境だからね)いままでパスワード無しログイン設定を/etc/phpMyAdmin/config.inc.phpで設定していたら、phpMyAdminアップデート後に、パスワードを要求してくる。

f:id:C_L:20160221184535p:plain

以降操作すべてrootユーザで

アップデート前

# ls -ld /etc/phpMyAdmin/
drwxr-xr-x 2 root apache 4096  2月 17 23:00 2016 /etc/phpMyAdmin/
# ls -l /etc/phpMyAdmin/
-rw-r--r-- 1 root root   7650  2月 17 22:39 2016 config.inc.php
-rw-r----- 1 root apache 7512  5月 14 21:38 2015 config.inc.php.orig

でディレクトリやファイルのパーミッション設定控えておく(drwxr-xr-xのことね、この場合755です)

アップデート

# yum -y --enablerepo=epel update phpMyAdmin
読み込んだプラグイン:fastestmirror
更新処理の設定をしています
Loading mirror speeds from cached hostfile
 * base: mirror.0x.sg
 * epel: ftp.iij.ad.jp
 * extras: ftp.tsukuba.wide.ad.jp
 * updates: ftp.tsukuba.wide.ad.jp
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> Package phpMyAdmin.noarch 0:4.0.10.12-1.el6 will be 更新
---> Package phpMyAdmin.noarch 0:4.0.10.14-1.el6 will be an update
--> 依存性解決を終了しました。

依存性を解決しました

=====================================================================
 パッケージ    アーキテクチャ  バージョン      リポジトリー     容量
=====================================================================
更新:
 phpMyAdmin    noarch          4.0.10.14-1.el6 epel            4.1 M

トランザクションの要約
=====================================================================
アップグレード       1 パッケージ

総ダウンロード容量: 4.1 M
パッケージをダウンロードしています:
phpMyAdmin-4.0.10.14-1.el6.noarch.rpm    | 4.1 MB     00:00
rpm_check_debug を実行しています
トランザクションのテストを実行しています
トランザクションのテストを成功しました
トランザクションを実行しています
  更新          : phpMyAdmin-4.0.10.14-1.el6.noarch     1/2
  整理中        : phpMyAdmin-4.0.10.12-1.el6.noarch     2/2
  Verifying     : phpMyAdmin-4.0.10.14-1.el6.noarch     1/2
  Verifying     : phpMyAdmin-4.0.10.12-1.el6.noarch     2/2

更新:
  phpMyAdmin.noarch 0:4.0.10.14-1.el6

完了しました!

アップデート後

configディレクトリを確認

# ls -ld /etc/phpMyAdmin/
drwxr-x--- 2 root apache 4096  2月 21 18:24 2016 /etc/phpMyAdmin/
# ls -l /etc/phpMyAdmin/
-rw-r--r-- 1 root root   7650  2月 21 18:24 2016 config.inc.php
-rw-r----- 1 root apache 7512  5月 14 21:38 2015 config.inc.php.orig

修復方法

# chmod 755 /etc/phpMyAdmin/

phpMyAdminは最新版使う時も似たような罠があるんですよね……(CentOS 6はMySQLが5.1.73で固定されているため、phpMyAdminもMySQL5.1対応の4.0.10がメンテナンスされているようですね)

あと弊社の謎サーバみたいにApacheの実行ユーザが別人になっているともうちょっと調整しなきゃイカンとかありますのでそこら辺はよしなに(CentOS6でApache実行ユーザをapache以外にするのはトラブりますのでお勧めできません)。

アドビフォーラムに存在した「本名がバレる」ウェブアプリケーション脆弱性について

アドビシステムが提供するユーザコミュニティサイト・アドビフォーラムに存在した、「利用者の本名が、利用者の意図しないところで第三者に知られてしまうという不具合」が、2016年2月4日に修正されました。

不具合の内容

アドビフォーラムのスレッドを閲覧、特定操作で表示される影響評価指標で、そのスレッドを過去に閲覧した多数のユーザの「本名」が表示される。

下図は、事象発生中の第三者へ本名が開示されてしまう様子を再現したものです(実際には、多数の方の本名が表示されておりましたので、スクリーンショットはとらず、再現画像として用意しました)。

f:id:C_L:20160208144116p:plain

本名だけでなく、顔アイコンまで一緒に表示されていました。よって、Web世界で活動が広く知られているユーザであれば、顔アイコンでWebでの人格と本名が紐づけできるため、人によっては大変困ったことになっていました(いわゆるリアル割れ・リアルバレの恐れがあった)。

対応

アドビフォーラムには、要望を書けるフォーラムがあるのですが、不具合の修正前に書き込みが公開されてしまうため、悪用の恐れがありました。そこで、IPA独立行政法人情報処理推進機構)あてに、ウェブアプリケーションの脆弱性関連情報として届出しました。

  • 2016/01/08 申請・届出情報受信
  • 2016/01/14 届出情報受理
  • 2016/02/01 取り扱い開始
  • 2016/02/04 修正完了

なお、ウェブアプリケーションの脆弱性関連情報の場合、修正をもって取扱いが終了となり、IPAとしては特に開示をしないとのことです。また、脆弱性関連情報を公表するかどうかはウェブサイト運営者に委ねられているとしており、Adobe Systemsでは、

Security Bulletins and Advisories

にてアドビ製品全般の「セキュリティ」に関する開示をするとのことなので、参考までに上記リンクを提示しておきます。

感想

IPAから英語でAdobe Systemsに不具合の報告が伝えられ、2/1~2/4の間に修正していただけました。Adobe Systemsと、IPAの担当の方には迅速な対応をしていただけました。

ネット上で本名がほかの人に知られてしまうことに対するリスクは人により違いますので感想は差し控えますが、アドビフォーラムのウェブアプリケーションとしての不具合に関しては今後も真摯に対応をしていただけそうだし、私もアドビ製品のユーザとして、より安心して製品が利用できるようになりました。

補足

問題が解決したので、公開しても差し支えないと判断し、今回IPAに申請したアドビフォーラムのウェブアプリケーション脆弱性の指摘報告の一部を公開しておきます。

 2. 脆弱性関連情報
 
   1) 脆弱性を確認したウェブサイトのURL
      アドビフォーラム
      https://forums.adobe.com/thread/1969854
      (トップページ: https://forums.adobe.com/welcome)
 
   2) 脆弱性の種類
      利用者の意図しない個人情報の漏洩
 
   3) 脆弱性の発見に至った経緯
         当該ページ(https://forums.adobe.com/thread/1969854)にて、
         右ペインの「影響評価指標」の下部の「もっと表示」リンクをクリック
         すると表示されるグラフ下部の閲覧者欄に、ウェブアプリケーション
         設定に関係なく、本名が表示されます。
         ソーシャルネットワークサイトのmixiなどで実装されている「あしあと」
         に近い機能です。
 
   4) 脆弱性であると判断した理由
         当該サイトでユーザ登録時に名前(必須)・苗字(必須)・ユーザ
         名(任意)を登録する仕組みになっています。その後、各ユーザの
         設定ページの「プライバシー」で公開範囲を変更できる仕組みです
         が、本名の公開範囲を「本人のみ」に制限したのに、ログアウト後
         当該ページににアクセス後3)に示した操作をすることで、私の本名
         が表示されます。
         私の個人的な知り合いの方の本名も表示されていたので、連絡を
         取ったのですが、本名を公開設定にはしていないとのことでした。
 
   5) 脆弱性により発生しうる脅威
      (1)当該ウェブサービス提供者は製品利用の利便のためのコミュ
         ニケーションサイトとして運営しているので、提供者は提供
         が販売する製品利用者に対し悪意なく利用者登録を促す
      (2)利用者は、自分の本名が公開されると知らずサービスへ
         利用者登録する。
      (3)利用者が当該ウェブサービス内のコンテンツを閲覧すること
         で、当該コンテンツへのアクセス履歴(mixiのあしあと機能
         みたいな状態で)が記録される
      (4)利用者以外の第三者が秘匿されていない特定手順の操作をす
         ることにより、そのコンテンツ閲覧者の本名が知られてしまう
 
      第三者の操作(悪意ある場合・もしくは過失)によって、下記のような
      被害が発生する可能性があります。
      
        ・個人情報(本名)の漏洩
          本名を秘匿にしておきたい利用者にとって、意図せずに本名
          が漏洩しつづけます。

ESP-WROOM-02で玄関お出かけ天気カラー照明灯

(この記事内のESP8266用Arduinoスケッチで、livedoor Weather Hacksの8KB程度のJSONをハングアップなしに処理できる方法を募集中です。)

出かけるとき傘を忘れないよう、玄関に置く天気がわかるカラー照明灯を設置しましょう。

f:id:C_L:20151110203422j:plain

これは雨だね。

ESP-WROOM-02開発環境を作る

ESP-WROOM-02の開発環境を用意します。ちなみにこれはESP-WROOM-02ブレイクアウトボードのライターにもなるよ。

f:id:C_L:20151110220746j:plain

まずはブレッドボード

akizukidenshi-ogp-injector.dtpwiki.jp

秋月電子のESP-WROOM-02のブレイクアウトボード。信号引き出し部が300milになっているのでブレッドボードで使うといろいろ部品を載せやすいがESP自体はみ出てしまうのが難点。まさにブレッドボード用だと思う。

akizukidenshi-ogp-injector.dtpwiki.jp

ブレッドボードの真ん中にある部品は、マイコン搭載フルカラーLEDで、ESP-WROOM-02が電源Offになってもそのまま光り続ける便利なやつです。本来5V用だが、3.3Vでも何とか光る。生LEDにありがちな電流制限抵抗が不要で、信号線1本で色や消灯を制御できるので、マイコンを使った電子工作ではとても有用です。

akizukidenshi-ogp-injector.dtpwiki.jp

お天気データを仕入れよう

天気のデータは、昔懐かしいlivedoor Weather HacksからJSONで仕入れます。

昔自分が書いたlivedoor weather hacksのブログ

blog.dtpwiki.jp

しかし、いろいろ試したが8KBのJSONをESP8266で処理するとうまくいかないので、これについては後でStackOverflowで質問するとして、レンタルサーバPHPでカジュアルに処理することにしました。

<?php

//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=010010'; // 北海道
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=020010'; // 青森県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=030010'; // 岩手県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=040010'; // 宮城県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=050010'; // 秋田県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=060010'; // 山形県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=070010'; // 福島県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=080010'; // 茨城県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=090010'; // 栃木県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=100010'; // 群馬県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=110010'; // 埼玉県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=120010'; // 千葉県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=130010'; // 東京都
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=140010'; // 神奈川県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=150010'; // 新潟県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=160010'; // 富山県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=170010'; // 石川県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=180010'; // 福井県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=190010'; // 山梨県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=200010'; // 長野県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=210010'; // 岐阜県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=220010'; // 静岡県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=230010'; // 愛知県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=240010'; // 三重県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=250010'; // 滋賀県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=260010'; // 京都府
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=270010'; // 大阪府
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=280010'; // 兵庫県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=290010'; // 奈良県
$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=300010'; // 和歌山県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=310010'; // 鳥取県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=320010'; // 島根県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=330010'; // 岡山県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=340010'; // 広島県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=350010'; // 山口県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=360010'; // 徳島県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=370010'; // 香川県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=380010'; // 愛媛県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=390010'; // 高知県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=400010'; // 福岡県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=410010'; // 佐賀県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=420010'; // 長崎県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=430010'; // 熊本県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=440010'; // 大分県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=450010'; // 宮崎県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=460010'; // 鹿児島県
//$url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=470010'; // 沖縄県

$opts = array(
  'http' => array(
    'method' => "GET",
    'header' => "User-Agent: tenki.php/0.1(+http://cl.hatenablog.com/entry/esp-wroom-02-weather-light)\r\n",
  )
);
$context = stream_context_create($opts);

$json = file_get_contents($url, false, $context);
$w    = json_decode($json);
$tenki = $w->{'forecasts'}[0]->{'telop'};

if (preg_match("/晴/", $tenki)) {
  $color = array(
    'red'   => 0,
    'green' => 0,
    'blue'  => 255,
  );
}
if (preg_match("/曇/", $tenki)) {
  $color = array(
    'red'   => 255,
    'green' => 180,
    'blue'  => 0,
  );
}
if (preg_match("/雪/", $tenki)) {
  $color = array(
    'red'   => 255,
    'green' => 255,
    'blue'  => 255,
  );
}
if (preg_match("/雨/", $tenki)){
  $color = array(
    'red'   => 255,
    'green' => 0,
    'blue'  => 0,
  );
}
header('Content-Type: application/json');
print json_encode( array('color' => $color));

exit;

最近やっとPHPを安定ビルドできるようになったのでPHPを使ってみた。上記PHPで、当日の天気の文字列が

  • 晴っぽいなら {"color":{"red":0,"green":0,"blue":255}}
  • 曇っぽいなら {"color":{"red":255,"green":255,"blue":0}}
  • 雪っぽいなら {"color":{"red":255,"green":255,"blue":255}}
  • 雨っぽいなら {"color":{"red":255,"green":0,"blue":0}}

JSON文書が出ます。雨が優先度高く、晴れが優先度低い。晴れのち雨とかだと雨、つまり赤となる。livedoor Weather Hacksはたまに暴風雪とかよくわかんない予報出ますが、まあしょうがないよね。

ESP-WROOM-02をArduino IDEでプログラミング

お天気APIJSONを簡略化するJSON APIを作ったので、先ほど作っておいたテスト環境でプログラムします。プログラミング環境は今回はArduino IDE 1.6.5にESP8266用設定を追加したものを使います。

追加で、Arduino用ライブラリ

を入手します。また、このプログラムは10分間ごとに起動して、待ち時間は超低消費電力モード(deep-sleepモード)に入るので、IO16RSTはジャンプワイヤでつないでおきます。詳しくは文末の参考文献で。

f:id:C_L:20151110221359j:plain

#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <ArduinoJson.h>

#define RGBREDPIN 14

// 5mm版NEOPixel LEDの場合
//Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, RGBREDPIN, NEO_RGB + NEO_KHZ800);
// チップ版NEOPixel LEDの場合
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, RGBREDPIN, NEO_GRB + NEO_KHZ800);

const char ssid[]     = "yourssid";
const char password[] = "yourpassword";

char url[] = "http://labo.dtpwiki.jp/tenki.php";

const int BUFFER_SIZE = JSON_OBJECT_SIZE(4) + JSON_ARRAY_SIZE(1);
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;

void setup() {
  // シリアル通信準備
  Serial.begin(115200);
  // NeoPixelLED準備

  pixels.begin();
  delay(10);
 
  // Wi-Fiに接続
  Serial.println();
  Serial.print  ("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    showNeoPixel(0, 3, 0);
    delay(250);
    showNeoPixel(0, 0, 0);
    Serial.print(".");
  }

  Serial.println();
  Serial.println("WiFi connected");
  
  Serial.print  ("IP address: ");
  Serial.println(WiFi.localIP());
  delay(100);
  
  // メインルーチン(loopに置かなくてもよい)
  String resBody = wget(url);
  char json[resBody.length() + 1];
  resBody.toCharArray(json, sizeof(json));
  Serial.println(json);
  JsonObject& root = jsonBuffer.parseObject(json);
  if (!root.success()) {
    Serial.println("parseObject() failed");
  }
  JsonObject& color = root["color"];
  const char* red   = color["red"];
  const char* green = color["green"];
  const char* blue  = color["blue"];

  showNeoPixel( atoi(red), atoi(green), atoi(blue));

  Serial.println("closing connection");
  
  //1:μ秒での復帰までのタイマー時間設定  2:復帰するきっかけの設定(モード設定)
  ESP.deepSleep(600 * 1000 * 1000 , WAKE_RF_DEFAULT);

  //deepsleepモード移行までのダミー命令
  delay(1000);
}

void loop() {
  // (2016-01-14プログラム変更)
  // deepsleepモードで運用するので、loop関数は空でよい
  // 詳しくは参考文献で
}

String wget(char *url) {
  // URLからhostとRequestPathとportを作る
  String str_host;
  String requestPath;
  uint16_t port;
  makePath(url, &str_host, &requestPath, &port);
  int str_host_len = str_host.length() + 1;
  char host[str_host_len];
  str_host.toCharArray(host, str_host_len);

  Serial.print  ("connecting to ");
  Serial.print(host);
  Serial.print  (":");
  Serial.println(port);
 
  // Use WiFiClient class to create TCP connections
  WiFiClient client;

  if (!client.connect(host, port)) {
    Serial.println("connection failed");
    return String("");
  }
 
  Serial.print  ("requestPath: ");
  Serial.println(requestPath);
 
  // サーバにリクエストを送信
  String requestHeader = makeRequestHeader(host, requestPath);
  //Serial.print(requestHeader);
  client.print(requestHeader);
  delay(300);

  // レスポンスを処理
  String resHeader = "";
  String resBody   = "";
  httpGet(&client, &resHeader, &resBody);
  /*
  Serial.println("response header:");
  Serial.println(resHeader);
  Serial.println();
  Serial.print  ("response body:");
  Serial.println(resBody);
  Serial.print  ("Length: ");
  Serial.println(resBody.length());
  Serial.println();
  */
  return resBody;
}

void httpGet(WiFiClient *client, String *resHeader, String *resBody) {
  while((*client).available()) {
    String line = (*client).readStringUntil('\r');
    if ( line.equals("\n")) {
      break;
    }
    else {
      (*resHeader).concat(line);
    }
  }
  while((*client).available()) {
    String line = (*client).readStringUntil('\r');
    (*resBody).concat(line);
  }
}

void makePath(String url, String *host, String *requestPath, uint16_t *port) {
  String urlStr = String(url);
  if ( !urlStr.startsWith("http://") ) {
    Serial.println('URL Parse Error');
  }
  String urlStr2 = urlStr.substring(7);
  uint8_t p = urlStr2.indexOf("/");
  *host = urlStr2.substring(0,p);
  *requestPath = urlStr2.substring(p);
  *port = 80;
}

String makeRequestHeader( String host, String requestPath ) {
  String res = String("GET ") + requestPath + " HTTP/1.1\r\n"
   + "Host: "+ host +"\r\n"
   + "User-Agent: ESP8266WiFi.h (+http://cl.hatenablog.com/entry/esp-wroom-02-weather-light)\r\n" +
   + "Connection: close\r\n"
   + "\r\n";
  return res;
}

void showNeoPixel(uint8_t r, uint8_t g, uint8_t b) {
  pixels.setPixelColor(0, r, g, b);
  pixels.show(); 
}

いろいろ試行錯誤して、試作ボード上で納得いく動作が出来ましたか?

CerevoのESP-WROOM-02のボードにプログラムを書き込む

先ほどのブレッドボードは、実はCerevoのESP-WROOM-02ブレイクアウトボード用の書き込み環境でもあったのです。サクッと書き込みます。

f:id:C_L:20151110222608j:plain

書き込んだ後、このまま動作テストもできます。

ミニブレッドボード上で動くよう組み立てる

部品表

品名 価格 コメント
ミニブレッドボード BB−601(白) 130 生け花におけるオアシスみたいなもん
電池ボックス 単3×2本用(Bスナップ)BH−321−1B 40 006Pスナップがかっこよくて電極なめてみたくなる
ジャンパーワイヤー付バッテリースナップ(縦型) 40 ブレッドボードにリードが挿せて便利
マイコン内蔵RGB 5mmLED PL9823-F5 40 砲弾型はチップ型と色配列違うので注意
Cerevo CDP-ESP8266 842 小型ESP-WROOM-02ブレイクアウトボード。要はんだ付け
TPS63000 昇降圧DC-DCモジュール(3.3V/5V) 900 2.4Vや3.0Vや5Vを3.3Vにしてくれる。要はんだ付け

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

akizukidenshi-ogp-injector.dtpwiki.jp

f:id:C_L:20151110222908j:plain

ミニブレッドボードに部品を全部乗せるのが大変。なお、ここで使用したTPS63000搭載DCDCコンバータモジュールは昇圧・降圧の両方対応なので、1.8V~5.5V、具体的に言うとエネループ2本(2.4V)・アルカリ乾電池2本(3V)・USB電源(5V)でも動かせるようになります。

動作確認

ミニブレッドボード上に組み立てた構成で、実際に動くかどうか確認します。

マイコン内蔵5mmLEDなのですが、マイコン自体はチップ型LEDと互換性があるのですが、色が赤と緑とで反転しています。マイコン内蔵型なのでピンを入れ替えて対応するとかできませんので、プログラム側でRGB三色の順番を入れ替えられるようになっています。そこを書き換えましょう(プログラムの前方でコメントアウトしているところ)。

f:id:C_L:20151110222936j:plain

イオンのソーラーステンレスライトに組み込む

一軒家の玄関わきにさしてある太陽電池で光るLEDライトを買ってきます。

f:id:C_L:20151110223533j:plain

2個入っているので多い日も安心です。

f:id:C_L:20151110223656j:plain

イオンが近くにない場合は4個入りですがAmazon

分解した蓋側(写真右)には、太陽電池と単四型ニッケル水素乾電池と、LEDドライバIC CL0116 が入っていてこれはこれで面白いのですが、今回は使いません。

f:id:C_L:20151110223817j:plain

筒側のほうは、下の蓋と接着されていて外れませんが、ペグ(地面に挿す杭)が差し込まれるように穴が開いています。

f:id:C_L:20151110223942j:plain

ミニブレッドボードの制作物を中に入れ、下の穴から電源ケーブルを外に出します。

f:id:C_L:20151110224058j:plain

あとは、蓋をします。頑張れるのならば、LEDを蓋側から生えている導光管にはめ込めるとベストです。

f:id:C_L:20151110224603j:plain

電池をつなぐと、Wi-Fi経由でJSONを取得して、天気によって決まった色で光ります。

f:id:C_L:20151110224737j:plain

晴れの日はこんな感じです。

f:id:C_L:20151110225307j:plain

色がJenkins CIっぽくていやっていう場合は、PHP側で変更できるんですね。RGB値で好きな色にしましょう。

参考

qiita.com

qiita.com

(2016-01-29追記)

LIGで似たようなの作り始めてた

liginc.co.jp

LIGといえば現職の会社のブログがLIGのオウンドメディアをパクっていてつらい