2550コネクタ、またはQIコネクタ

投稿日:

 Raspberry PiのGPIOに何かをつなごうとして、何の用意もしていないと戸惑うのが、

「Raspberry PiのGPIO端子は、オスだ」

……ということかも知れない。

 Raspberry Piの端子は、2.54mmピッチのピンヘッダだ。このピンヘッダには、2550、あるいはQIとも言われるコネクタを使うと接続することができる。

IMG_3290

上段左からQIコネクタメス端子、同オス端子。
下段左から6列のQIコネクタハウジング、同5列、同4列、バラの1列。
もちろん、2列も売られている。

 上の写真はそのQIコネクタ類だが、それで言えば、一番左のメスの端子を切り外し、適切な電線に圧着してハウジングを取り付ければ、それをRaspberry Piに接続できるようになる。

 ところが、どうもこの「QIコネクタ」、情報が少ない。作り方にも多少のコツがある。それで、私が書こうか、と思ったら、既に詳しく紹介されているサイトがあった。

 もう、このサイトが書いておられること以上には付け加えることなどないが、工具については、5年前に私のブログでも紹介しているので、参考にする方がいるならお役立ていただきたい。エントリは5年前のものだが、昨日(平成27年8月15日(土))千石電商本店の1階に立ち寄ったところ、まったく同じ工具がほぼ同じ値段で売られていたことを付け加えておきたい。

 私のエントリで紹介している工具は、大西工業株式会社の「No.150 MINI クリンピングプライヤー」である。この工具を使う場合は、一番手前の「AWG22・0.3mm^2」のダイスで導線をかしめ、被覆は一つ隣の「20・0.5」のダイスで半分だけかしめて、残りを普通のラジオペンチで締めあげるとよい。

その工具(大西工業(株)No.150 MINIクリンピングプライヤー)
IMG_3291

 私のエントリでも触れている通り、QIコネクタは、Raspberry Piや電子工作だけではなく、PCの内部など、いろいろなところで使われている規格なので、覚えておけば何か修理や改造の必要に迫られたときに役立つと思う。

 QIコネクタやそのハウジングは、秋葉原千石電商本店なら、入り口から見て左側の、一番奥より少し手前の小さい抽斗の中段くらいに入っている。

 5年前当時は、使い方が良く分からなかったので、レジの店員さんに「このコネクタ、カシめ方と、使う工具を教えてもらえませんでしょうか」と頼んだら、得たりとばかりの落ち着いた態度で、実際の使い方とコツ、注意点を、店のディスプレイ用にとっておいてある端子だと思うが、それで実演してくれたものであった。若い店員さんだったが、その該博な知識と技に驚嘆したものであった。

 先日、八潮の秋月電子の初老の店員さんは、「これにハウジングみたいなモンは存在しませんよ」と言っていたが、千石電商にはあるので、秋月に行って見つからなければ、千石電商で買うとよいと思う。

 私も、秋月電子八潮店で、「いや、ありますよ」と店員さんに直接教えて上げられればよいのだが、私は素人なので、プロに対してそこまでする義理はないだろう。

Raspberry PiでLチカ

投稿日:

 で、LED1個では寂しいから、同じコードを繰り返して、8個でLチカ。

IMG_3286

 抵抗は8素子9ピンの集合抵抗、各素子330Ω。Vfが3.0~3.4V、Ifが20mAとある青色LEDなのだが、抵抗がこれだけならせいぜい10mAくらいだ。GPIOの各ピンから流せる電流は50mAまでだそうなので、まあ、大丈夫だろう。

 動かすとこんな感じ。

 プログラムは、GPIOのセットアップをするシェルと、Perlのスクリプトだ。

 シェルはこのようなもの。コピペで繰り返しただけ。シェル内の数字がピン番号。

#!/bin/sh
echo  5 >/sys/class/gpio/export
echo  6 >/sys/class/gpio/export
echo 13 >/sys/class/gpio/export
echo 19 >/sys/class/gpio/export
echo 26 >/sys/class/gpio/export
echo 21 >/sys/class/gpio/export
echo 20 >/sys/class/gpio/export
echo 16 >/sys/class/gpio/export
echo out >/sys/class/gpio/gpio5/direction
echo out >/sys/class/gpio/gpio6/direction
echo out >/sys/class/gpio/gpio13/direction
echo out >/sys/class/gpio/gpio19/direction
echo out >/sys/class/gpio/gpio26/direction
echo out >/sys/class/gpio/gpio21/direction
echo out >/sys/class/gpio/gpio20/direction
echo out >/sys/class/gpio/gpio16/direction

 Perlも同じで、コピペで繰り返しただけ。……「配列に書けよ」とかの至極もっともなツッコミはナシの方向でお願いいたしますです(笑)。

#!/usr/bin/perl
#  perl2LEDx8
#    perlで8個Lチカ
#    27.8.16(日)1500~
#    佐藤俊夫
#
use strict;
use warnings;
use Time::HiRes 'sleep';
open(LED1, ">/sys/class/gpio/gpio5/value");
open(LED2, ">/sys/class/gpio/gpio6/value");
open(LED3, ">/sys/class/gpio/gpio13/value");
open(LED4, ">/sys/class/gpio/gpio19/value");
open(LED5, ">/sys/class/gpio/gpio26/value");
open(LED6, ">/sys/class/gpio/gpio21/value");
open(LED7, ">/sys/class/gpio/gpio20/value");
open(LED8, ">/sys/class/gpio/gpio16/value");
LED1->autoflush(1);
LED2->autoflush(1);
LED3->autoflush(1);
LED4->autoflush(1);
LED5->autoflush(1);
LED6->autoflush(1);
LED7->autoflush(1);
LED8->autoflush(1);
while(){
  print LED8 0;
  print LED1 1;
  sleep(0.2);
  print LED1 0;
  print LED2 1;
  sleep(0.2);
  print LED2 0;
  print LED3 1;
  sleep(0.2);
  print LED3 0;
  print LED4 1;
  sleep(0.2);
  print LED4 0;
  print LED5 1;
  sleep(0.2);
  print LED5 0;
  print LED6 1;
  sleep(0.2);
  print LED6 0;
  print LED7 1;
  sleep(0.2);
  print LED7 0;
  print LED8 1;
  sleep(0.2);
}

ノクターンでLチカ

投稿日:

 いやもう、「オッサンとバイエル、ピアノ等」って銘打ってて、長らくなかったこのネタ。ええ、ピアノですよ、ピアノ。

「Arduinoをピアノにつなぎたいッ!」

……すなわちコレである。Arduinoをピアノにつなぎ、LEDをピアノ演奏に合わせて明滅させようというものだ。

 いまや遅しとやってみた。

ノクターンでLチカ

 一つ覚えみたいにノクターンで申し訳ないですが(笑)、すんませんレパートリーがあんまりないもんで。

IMG_3276

 アナログピンからピアノの音声出力を読み、それに合わせてTLC5940NTに接続されたLEDを適宜明滅させるわけである。いかにもピアノ風味に明滅させるにあたっては、乱数によるLED選択と、先日会得した「PWMを十分に使い、余韻をもって各LEDを徐々に消す」という技を遺憾なく使用した。

 これをやるには、アナログピンに上手に音声を入れる必要がある。

 こういう時、電圧レベルを知るのにオシロスコープなどが使えればいいのだが、残念ながら持っていない。そこで、あらかじめテスターのACでテレビ、ラジオ、自分のピアノなどの音声出力端子からだいたいのレベルを推定し、次に十分な抵抗を入れて、Arduinoのアナログピンに入力して読み取った。その結果、だいたい200mVの振幅程度であることがわかった。これならばArduinoに直接入れてもどうということはなさそうだ。ただし、レベルが小さいから、ソフトウェアのほうでうまくやる必要がある。

 次に、音声はアナログ信号だから、プラス・マイナスに振れる。一方、Arduinoのアナログ入力は0~5Vの間を1024分割で読むのだから、ここをうまく工夫しなければならない。

 まず、2.5Vを中心に電圧が振れるよう、2.5Vを生成して合成する。ちょうどTLC5940NTを動かすために5Vの3端子レギュレータを使っているので、ここから抵抗分圧で2.5Vを作り、それを合成する。合成するとき、出力側の音声端子に電流が流れ込んではまずいから、コンデンサを0.1μFばかりつける。周波数は見当がつくが、電圧の見当がつきにくいので、とりあえず0.1μFにして、出来が悪いようなら取り換えることにする。

 まず、大して疑問もない簡素な付加回路。たしか、パルス技術ではこういうの、「クランパ」って言ったっけな……。

音声入力のためのクランパ
「voice2tlc」の回路図

 それで、TLCなどと一緒にLEDを植え込む。

IMG_3273

 ミニジャックを接続するために、秋月電子の「ステレオミニジャックDIP化キット」を取り付けた。

ミニジャックの部分
IMG_3274

 で、スケッチはこうなった。

//
//  voice2tlc.ino
//    アナログピンに音声を入れ、TLC5940NTを使ってLEDを光らせる。
//    27.08.13(木)1000~
//    佐藤俊夫
//
#include "Tlc5940.h"
#include <stdio.h>
//
const int
  AUDIO = 0, //  アナログ0ピン
  THRESH = 8;  //  8単位以上のレベルならLEDを点灯
//
void setup() {
  Tlc.init();
  Tlc.clear();
  Tlc.update();
}

void loop() {
  int v = 0, l = 0;
  static long int prevtime = 0.0;
  static int prevv = 0;
  v = abs(analogRead(AUDIO) - 512);
  l = constrain(fmap(v, 0, 15, 0, 4095), 0, 4095);
  if(millis() >= prevtime + 10){
    prevtime = millis();
    for(int i = 0; i <= 15; i++){
      Tlc.set(i, Tlc.get(i) * 0.9);
    }
  }
  for(int i = 0; i <= 15; i++){
    if(random(0, 16) == 1 && prevv != v && v >= THRESH){
      Tlc.set(i, l);
    }
  }
  Tlc.update();
  prevv = v;
}
//
float fmap(float x, float in_min, float in_max, float out_min, float out_max) {
  //  もともとの「map()」がlong int型でこの用途に合わないので、float型を定義
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

とにかく目一杯

投稿日:

 実用的なモノというとネット便器ぐらいしか作らず、Lチカばかりやっている今日この頃であるが、Lチカは楽しいので仕方がない。というか、「ネット便器のどこが実用的なのか?」というツッコミに極めて脆弱な文章をついつい書いてしまっているところもなかなか痛いが、さておき、昼間の「亀の子ブレボー」に、いつぞや大量生産したビーズ付きLEDを目一杯大量に植え込み、TLC5940NTでゴンゴンドライブしてみた。

 前回TLC5940NTを使ったときは、単純に右から左へ光るだけだったが、今度と言う今度は、もう、今思いつくだけあらん限りいろんな光らせ方をさせてみた。

 亀の子ブレッドボードは、なかなか省スペースで、うまく組み付けられる。

TLC5940NTを亀の子ブレボー(笑)に設置した状況
IMG_3259

 LEDをタップリ植え込むとこうなる。

IMG_3261

 動かすとこんな感じだ。

 スケッチはこうなった。はじめはタクトスイッチで手動切り替えをしていたが、面倒臭くなり、乱数で切り替えるようにした。

//
//  tlcVariation.ino
//    TLC5940NTにつないだLED、ランダムにいろんな光らせ方をしてみる。
//    27.08.11(火) 1515~
//    佐藤俊夫
//
#include "Tlc5940.h"
//
const int switchInterval = 5000;
//
void setup() {
  Tlc.init();
  Tlc.clear();
  Tlc.update();
}
//
void loop() {
  static int mode = 0;
  static long int prevtime = 0;
  if(millis() > prevtime + switchInterval){
    mode = random(0, 8);
    prevtime = millis();
    //  今のエフェクトを徐々に消す。
    int maxlum = 0;
    do{
      maxlum = 0;
      for(int i = 0; i <= 15; i++){
        Tlc.set(i, Tlc.get(i) * 0.9);
        maxlum = Tlc.get(i) > maxlum ? Tlc.get(i) : maxlum;
      }
      Tlc.update();
      delay(20);
    }while(maxlum > 0);
  }
  switch(mode){
    case 0:
      sinCurve_diff();
      break;
    case 1:
      inOrder_left();
      break;
    case 2:
      toCenter();
      break;
    case 3:
      inOrder_tail();
      break;
    case 4:
      left_right();
      break;
    case 5:
      left_right_tail();
      break;
    case 6:
      allAtOnce_tail();
      break;
    case 7:
      inOrder_right();
      break;
    default:
      sinCurve_diff();
      break;
  }
}
//
void inOrder_right(){
  //  0.1秒おきに右から切り替えていく。
  static long int prevtime = 0.0;
  static int led = 15;
  Tlc.clear();
  if(millis() >= prevtime + 100){
    Tlc.clear();
    Tlc.set(led--, 4095);
    led = led < 0 ? 15 : led;
    Tlc.update();
    prevtime = millis();
  }
}
//
void allAtOnce_tail(){
  //  一斉に点灯して徐々に消える。
  static long int prevtime = 0;
  if(millis() > prevtime + 100){
    prevtime = millis();
    if(Tlc.get(0) <= 0){
      for(int i = 0; i <= 15; i++){
        Tlc.set(i, 4095);
      }
    }else{
      for(int i = 0; i <= 15; i++){
        Tlc.set(i, Tlc.get(i) * 0.8);
      }
    }
    Tlc.update();
  }
}
    
//
void left_right_tail(){
  //  尾を引きながら右へ行ったり左へ行ったり。
  static long int prevtime = 0.0;
  static int led = 0, order = 1;
  if(millis() >= prevtime + 100){
    for(int i = 0; i <= 15; i++){
      Tlc.set(i, (int)((float)Tlc.get(i) * 0.5));
    }
    led = led + order;
    Tlc.set(led, 4095);
    order = (led >= 15) || (led <= 0) ? order * -1 : order;
    Tlc.update();
    prevtime = millis();
  }
}
//
void left_right(){
  //  右へ行ったり左へ行ったり
  static long int prevtime = 0.0;
  static int led = 0, order = 1;
  if(millis() >= prevtime + 100){
    Tlc.clear();
    led = led + order;
    Tlc.set(led, 4095);
    order = (led >= 15) || (led <= 0) ? order * -1 : order;
    Tlc.update();
    prevtime = millis();
  }
}
//
void inOrder_tail(){
  //  尾を引きながら0.1秒おきに左から切り替えていく。
  static long int prevtime = 0.0;
  static int led = 0;
  if(millis() >= prevtime + 100){
    for(int i = 0; i <= 15; i++){
      Tlc.set(i, (int)((float)Tlc.get(i) * 0.5));
    }
    Tlc.set(led++, 4095);
    led = led > 15 ? 0 : led;
    Tlc.update();
    prevtime = millis();
  }
}
//
void toCenter(){
  //  中央付近のLEDから外へ光らせる。
  static long int prevtime = 0.0;
  static int ledleft = 7, ledright = 8;
  if(millis() >= prevtime + 100){
    for(int i = 0; i <= 15; i++){
      Tlc.set(i, (int)((float)Tlc.get(i) * 0.5));
    }
    Tlc.set(ledright++, 4095);
    Tlc.set(ledleft--,  4095);
    ledright = ledright > 15 ? 8 : ledright;
    ledleft = ledleft < 0 ? 7 : ledleft;
    Tlc.update();
    prevtime = millis();
  }
  
}
//
void inOrder_left(){
  //  0.1秒おきに切り替えていく。
  static long int prevtime = 0.0;
  static int led = 0;
  Tlc.clear();
  if(millis() >= prevtime + 100){
    Tlc.clear();
    Tlc.set(led++, 4095);
    led = led > 15 ? 0 : led;
    Tlc.update();
    prevtime = millis();
  }
}
//
void sinCurve_diff(){
  //  呼ぶたびにサインカーブをちょっとづつずらしながら光らせる。
  static float x[16] = {
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
  };
  for(int i = 0; i <= 15; i++){
    x[i] = x[i] >= (2.0 * PI) ? 0.0 : x[i] + ((2.0 * PI) / 1000.0) * (1.0 + (float)i / 10.0);
    Tlc.set(i, (int)(((sin(x[i]) + 1.0) / 2.0) * 4095));
  }
  Tlc.update();
}

ブレボー亀の子

投稿日:

 ブレッドボードに小さいプロトタイプを作るとき、この「プロトタイピングシールド」も捨てがたい。だが、しばらく使ってみての感想なのだが、小さくて不便だ。また、電源ラインもどうも使いづらい。シールド上の赤ソケットには実は5Vは到達していないので、自分で配線しなければならないのだ。

便利だが、小さいところが難
IMG_3031

 と言って、大きい方だと、Arduinoに重ねるわけにもいかず、昨日のようになってしまう。

たかが7セグLED2個のためにゴチャつくブレッドボード(笑)
IMG_3240

 何かいいことないかな、と思ってネットを漁っていたら、ある方がブレッドボードの脇に直接Arduino用のピンヘッダを接着剤で取り付けて、目的を達成しておられるのを見つけた。ほほー、なるほどなるほど……。

 つまり、大抵のブレッドボードは、同じメーカーの物なら、こういうふうに脇を取り外したり組み合わせたりできるのだが、電源ラインを一つ外すと、Arduinoの上下のピン幅とピッタリなのである。

IMG_3252
IMG_3253

 チナミに、このようにバラしたり組み合わせたりするには、ブレッドボード裏の両面テープの、つけ外しする部分をカッターナイフでスーッと切ると良い。

 しかし、接着剤でピンソケットを付けてしまう、てのも、なあ……。他のことにブレッドボードが使えなくなってしまうし……。

 で、考えてみたら、私は次の写真のようなArduino用のプラスチックケースを使っているが……

IMG_3254

……この上に電源ラインを一本外したブレッドボードを亀の子にし、輪ゴムか何かで縛っておけば、目的は達成できるではないか。

IMG_3255

 どうして今までこうしなかったかと言うと、そのままだとプラスチックケースの上下に細く開けてあるピンソケットにアクセスするためのスリットがふさがり、Arduinoから信号線が出せないからである。しかし、電源ラインを外すと、上下ともちょうどピッタリ、スリットが隠れずにすむのだ。

 ほうほう、なるほど、というわけで、この前作ったビーズのLEDなど植えてみる。Arduinoの「Arduino AT HEART♥」みたいな感じで、ハートですな、男のくせにw。

IMG_3256

 動かすとこんな感じ。

 このLチカはシンプルで、スケッチはこう。

//
//  differSin.ino
//    サインカーブをちょっとづつずらしてLチカ
//    佐藤俊夫
//    27.08.11(火) 1100~
//    
void setup() {
  pinMode( 9, OUTPUT);
  pinMode(10, OUTPUT);
}

void loop() {
  static float x1 = 0.0, x2 = 0.0;
  x1 = x1 > (2.0 * PI) ? 0.0 : x1 + (2.0 * PI / 1000.0);
  x2 = x2 > (2.0 * PI) ? 0.0 : x2 + (2.0 * PI / 1100.0);
  analogWrite( 9, (int)((sin(x1) + 1) * 128));
  analogWrite(10, (int)((sin(x2) + 1) * 128));
  delay(2);
}

 そう言えば、以前、「なんとっ!Arduinoって3項演算子ないのかッ!?」「ううっ、あったらなあ」などと書いたことがあったが、これは早とちりで、私の間違い。ちゃんとありました。上記スケッチでご覧のとおり(苦笑)

2桁順番

投稿日:

 次に、TLC5940NTを使って、数字をちゃんと表示させる。

 前と同じ回路で、スケッチは次のようにする。

//
//  tlc594027segmentLED.ino
//    7セグメントLEDをTLC5940NTで制御
//    27.08.10(月)1800~
//    佐藤俊夫
//
#include "Tlc5940.h"
//
void setup()
{
  Tlc.init();
}

void loop()
{
  Tlc.clear();
  static int n = 0;
  disp7LED(n++);
  if(n >= 100) n = 0;
  delay(1000);
}
//
void disp7LED(int n){
  const int on = 4095, off = 0;
  const int pat[10][8] = {
    // 0    1    2    3    4    5    6    7pin   num
    { on,  on,  on, off,  on,  on,  on, off},  //  0
    {off, off,  on, off,  on, off, off, off},  //  1
    { on,  on, off, off,  on,  on, off,  on},  //  2
    {off,  on,  on, off,  on,  on, off,  on},  //  3
    {off, off,  on, off,  on, off,  on,  on},  //  4
    {off,  on,  on, off, off,  on,  on,  on},  //  5
    { on,  on,  on, off, off,  on,  on,  on},  //  6
    {off, off,  on, off,  on,  on,  on, off},  //  7
    { on,  on,  on, off,  on,  on,  on,  on},  //  8
    {off,  on,  on, off,  on,  on,  on,  on}   //  9
  };
  //  一旦消す
  Tlc.clear();
  //  10の位
  int n10 = n / 10, i = 0;
  for(i = 0; i <= 7; i++){
    Tlc.set(i, pat[n10][i]);
  }
  // 1の位
  int n1 = n % 10;
  for(i = 0; i <= 7; i++){
    Tlc.set(i + 8, pat[n1][i]);
  }
  Tlc.update();    
}

 次のようにカウントアップしていく。

 そういえば昔の刑事ドラマなんかで、時限爆弾のカウントって、こんな感じで、電線がゴチャゴチャしてたっけなあ。ふふっ、爆発しそうだな、これじゃ(笑)。

次に2桁を

投稿日:

 7セグメントLEDの1桁の制御の基礎がわかったので、今度は2桁だ。

 当然、ArduinoのI/Oはこれでは足りない。

 したがって、ドライバICを使う。この前買ったテキサス・インスツルメントの定番IC、「TLC5940NT」を使うのである。秋葉原千石電商で390円だ。

IMG_3240

 16本のカソードを全部ICに入れてあるので、配線はだいぶゴチャつく。ブレッドボードも2連結だ。

 この配線は、ArduinoのTLC5940用ライブラリをインストールすると使えるようになるサンプルスケッチ「BasicUse」のコメントの冒頭にアスキーアートで詳しく図示されている。

 とりあえず、この「BasicUse.ino」を動かしてみた。次のようになって面白い。

 

お稽古

投稿日:

 7セグメントLEDのお稽古をする。意味のあるなしはどうだってよろしい。レッツゴー。

 私は古株ぶっているが、実は若い頃に7セグLEDを扱ったことがない。子供の頃の電子工作はもっぱらラジオなどのトランジスタ回路、長じてからは仕事関係で5極真空管やマイクロ波の発振管などを扱っていた。

 数値表示のためには、その頃の仕事関係では「ニキシー管」という数値表示のための真空管を扱っていた。これは放電管で、数字の形をした陰極が赤く光るものだ。

 そういうわけで、7セグLEDを知らないのである。いや、無論、当時から7セグメントLEDは世の中にあったが、私の職場が特殊だったのである。

 で、これが昨日秋月電子八潮店で買ってきた、1個60円の7セグLEDである。

IMG_3234
IMG_3236
OSL10561-IRA

 さて、まずは点灯からだ。データシートから、抵抗と電流っ。

 各素子I_F = 20mA, V_F = 2.1V……とあるから、V_0 = 5Vとして、

I_R = \frac{V_0 - V_F}{I_F} = \frac{5 - 2.1}{20mA} = 181.25\Omega

……まず、200Ωばかりつけておいてやればよいのだろう。この前買った集合抵抗の手持ち、8素子9ピンで330Ωのがあるから、それを付ければ多少暗いが10mA前後で光るだろう。

 さっそく、全点灯で光らせてみよう。単に電源をくれてやって、抵抗に結線するだけだ。

7セグLED全点灯
回路図

 光らせてみると、計算上の抵抗の倍近い抵抗値なのに、なかなかどうして、結構明るく光る。

IMG_3237
単純全点灯で光らせてみたところ

 次に、Arduinoをつないで、数字を表示させる。全点灯で電流を測ってみると67mAほど流れているので、電源はこのまま別建てのほうがいいだろう。

 アノードコモンのLEDであるから、カソード側で制御しなければならない。集合抵抗では一本づつ制御できないので、330Ωの電流制御抵抗をバラで8本とりつける。それぞれの足をArduinoのデジタル2ピンから9ピンまで取り付ける。

 スケッチをこう書く。点灯のパターンは配列に書くのが手早いだろう。

//
//  7segmentLED_1.ino
//    7セグメントLEDを1個動かす。
//    27.08.10(月) 1300~
//    佐藤俊夫
//
//    LED「OSL10561-IRA」
//    LED 1 -> Digital 2
//    LED 2 -> Digital 3
//    LED 4 -> Digital 4
//    LED 5 -> Digital 5
//    LED 6 -> Digital 9
//    LED 7 -> Digital 8
//    LED 9 -> Digital 7
//    LED10 -> Digital 6
//
void setup() {
  for(int i = 2; i <= 9; i++){
    pinMode(i, OUTPUT);
  }
}

void loop() {
  for(int i = 0; i <= 9; i++){
    lighting(i);
    delay(1000);
  }
}

void lighting(int n){
  const int pat[10][8] = {
    { LOW,  LOW,  LOW, HIGH, HIGH,  LOW,  LOW,  LOW},  //  0
    {HIGH, HIGH,  LOW, HIGH, HIGH, HIGH, HIGH,  LOW},  //  1
    { LOW,  LOW, HIGH, HIGH,  LOW, HIGH,  LOW,  LOW},  //  2
    {HIGH,  LOW,  LOW, HIGH,  LOW, HIGH,  LOW,  LOW},  //  3
    {HIGH, HIGH,  LOW, HIGH,  LOW,  LOW, HIGH,  LOW},  //  4
    {HIGH,  LOW,  LOW, HIGH,  LOW,  LOW,  LOW, HIGH},  //  5
    { LOW,  LOW,  LOW, HIGH,  LOW,  LOW,  LOW, HIGH},  //  6
    {HIGH, HIGH,  LOW, HIGH, HIGH,  LOW,  LOW,  LOW},  //  7
    { LOW,  LOW,  LOW, HIGH,  LOW,  LOW,  LOW,  LOW},  //  8
    {HIGH,  LOW,  LOW, HIGH,  LOW,  LOW,  LOW,  LOW}   //  9
  };
  int i = 0;
  for(i = 0; i <= 7; i++){
    digitalWrite(i + 2, HIGH);
  }
  for(int i = 0; i <= 7; i++){
    digitalWrite(i + 2, pat[n][i]);
  }
}

 アノードコモンなので、論理は負論理だ。

 Arduinoとブレッドボードをこういうふうにする。

IMG_3238

 動かすと、ゆっくりカウントアップする。

ネット便器

投稿日:

 時代はIoTである。モノをネットに接続することは、もはや正義を通り越して神の啓示であるとすら言えるほどだ(笑)。

 やろうやろうと思ってやっていない一事はこのことだ。すなわち、「Arduino」を使用して、直接モノにツイートさせること、これである。モノがツイートするのはきっと面白いに違いない。

 「Twitter Arduino」あたりで検索すると、ライブラリが出てくる。今回はこれ(Tweet Library 1.3)をありがたく使わせていただく。

 さて、そうと決まれば何をネットに接続するか、である。ここはやはり、自宅の便器をネットに接続するという、これを一度やってみるべきであろう。

 やはり、IoT時代であるから、便器もネットにつないでやらなければ面白くないだろう。便器だって平等に扱ってやらねば、他の物品との差別感を覚えてひがむようになり、性格が曲がってしまうかもしれない。このように性格の歪んだ便器は、人間様が用を足すときに局部に噛みついてくるようなことが万に一つはないとも限らない。便器にも時々はインターネットと会話をさせてやるべきだ。

 とりあえず、便所のフタの開閉を検知するため、「チルトスイッチ」を使用する。

チルトスイッチ
IMG_3218

 これは、傾けるとスイッチが入るというもので、Arduinoを買ったときに一緒に買った「Seeedstudio SIDEKICK BASIC KIT」というセットに入っていたものだ。

 回路は簡単である。下図のように、行儀よく10kΩほどプルダウンしておけば誤動作は少ない。

チルトスイッチ回路図

 スケッチのほうは、ライブラリの導入に多少手間取った。使用させていただいた「Tweet Library」は、「ETHERNET SHIELD」のほうに対応しており、私が持っている「ETHERNET SHIELD 2」にはそのままでは対応していない。

 基本的にヘッダファイルのインクルードを「#include <Ethernet.h>」から「#include <Ethernet2.h>」に書き換えるだけでいいのでは、と思ったのだが、どうもうまくいかない。さっぱりお手上げだったのだが、いろいろといじくりまわしているうち、エラーメッセージをよく見てみると、「クラスの2重定義」という意味のエラーが出ていることがわかった。なぜか、「libraries\Ethernet2\srcの下にあるやつと重なっている」みたいなメッセージが出ている。ハテ、とライブラリのあるディレクトリを見てみると、「libraries\Ethernet2\src」の下に、なぜか「Twitter.h」と「Twitter.cpp」がある。

 なんだかわかんないけどいいや、消しちゃえ!と、それをぞんざい適当に消したら、うまくコンパイルできるようになった。しかし、そのことで5~6時間ほどハマッてしまった。

 ETHERNET SHIELD 2とプロトタイプシールドを、先日買った「継ぎ足しピンヘッダ」を介して積み重ね、次のようにしていつもの100円ショップのアクリル枠にねじ止めする。

IMG_3213

 手前に緑色のチルトスイッチが取り付けられていることがわかるだろう。

 Twitterに専用アカウントをとり、Tweet Libraryの説明にしたがってトークンを取得する。専用アカウントは、その名も「佐藤家の物」である(笑)。

 それから、スケッチを次のように書く。

//
//  つぶやき便所 tweetToilet.ino
//    27.08.08(土) 1000~
//    佐藤俊夫
//    チルトスイッチで便所のふたの動きを検出し、呟かせる。
//
#include <SPI.h>
#include <Ethernet2.h>
#include <Twitter.h>
#include <stdio.h>
//
byte MAC[] = { 0x90, 0xA2, 0xDA, 0x0F, 0xF6, 0x74 };
IPAddress IP(192, 168, 1, 129);
Twitter TWITTER("hogehogehoge-hagehagehagehage......");  //  トークン
const int TILTSW = 9;
//
void setup()
{
  pinMode(TILTSW, INPUT);
  delay(1000);
  Ethernet.begin(MAC, IP);
  delay(1000);
}

void loop()
{
  static int tiltSwStatus = LOW, prevStatus = LOW;
  int i = 0;
  tiltSwStatus = tiltSw();
  if(tiltSwStatus != prevStatus){
    prevStatus = tiltSwStatus;
    tweetMsg(tiltSwStatus);
    delay(1000);
  }else{
    ;
  }
}
//
int tiltSw(){
  //  チルトスイッチの読み取りを安定させるため、100回連続して同じ値が返るまで読む。
  int i = 0, prevStatus = LOW, nowStatus = LOW;
  prevStatus = digitalRead(TILTSW);
  do{
    nowStatus = digitalRead(TILTSW);
    if(nowStatus == prevStatus){
      i ++;
    }else{
      i = 0;
    }
    prevStatus = nowStatus;
  }while(i < 100);
  return(nowStatus);
}
//
void tweetMsg(int tiltStatus){
  const char
    openMsg[] = "%e3%82%84%e3%81%82%e3%80%82%e4%bf%ba%e3%81%af%e4%bd%90%e8%97%a4%e5%ae%85%e3%81%ae%e4%be%bf%e5%99%a8%e3%81%a0%e3%80%82%e4%bb%8a%e3%83%95%e3%82%bf%e3%81%8c%e9%96%8b%e3%81%84%e3%81%a6%e3%81%84%e3%82%8b%e3%80%82",
    //  'やあ。俺は佐藤宅の便器だ。今フタが開いている。'    
    closeMsg[] = "%e4%bf%ba%e3%81%af%e4%bd%90%e8%97%a4%e5%ae%85%e3%81%ae%e4%be%bf%e5%99%a8%e3%81%a0%e3%80%82%e4%bb%8a%e3%83%95%e3%82%bf%e3%81%8c%e9%96%89%e3%81%be%e3%81%a3%e3%81%9f%e3%80%82";
    //  '俺は佐藤宅の便器だ。今フタが閉まった。'
  char tweetStr[256];
  if(tiltStatus == HIGH){
    sprintf(tweetStr, "%s  \r\n %ld", openMsg, millis());
    //  Twitterは同じ文字列を繰り返し書き続けられないので、起動時間を付けて書き、重複を防ぐ。
  }else{
    sprintf(tweetStr, "%s  \r\n %ld", closeMsg,  millis());
  }
  TWITTER.post(tweetStr);
  TWITTER.wait();
}

 うまく動くようになったら、ホット・グルーでプロトタイプを便器のフタに取り付ける。

IMG_3216IMG_3215

 便所にLAN工事を施しておしまいだ。

IMG_3214
 

 上記動画のように便器のふたを開け閉めすると、やおら便器が次のように呟きだすのである。