耽るLチカ

投稿日:

 LEDは半導体であるから、電球と違って、光り始める前は抵抗は無限大であり、電流は流れない。ところが電圧がVfを超えて光り始めたら最後、抵抗がなくなって電源をショートさせた状態でぶっ飛び、自分自身も壊れる。従って必ず抵抗を一緒にくっつけてやるのだ。

 その抵抗を選ぶのは簡単で、基本的に E = I\cdot R という、この式のみでよい。LEDを買ってくると、流すべき電流値(If)、光り始める電圧(Vf)がどこかに書いてあるから、それに従って計算する。すなわち、

R = \frac{V - Vf}{If}

ここに、

V 自分が用意する電源の電圧
Vf 買ってきたLEDのVf(順方向電圧)、つまり光り始める電圧
If 買ってきたLEDのIf(順方向電流)、つまり光らせるために必要な電流

 ただ、抵抗は入手可能な数値が決まっており、そのものピタリという抵抗値のものは売っていない。なので、計算した値と一番近い抵抗を選び、その抵抗値で再び電流を計算して、買ってきたLEDのIfを超えていないかどうかを確かめる。

 これが、簡単な計算ではあるけどいちいち面倒くさい。

 それでまあ、抵抗を選ぶのにこういうスプレッドシートを作る。

 それから、これを使ってみよう。

IMG_3181

 これは、「武蔵野電波のプロトタイパーズ第15回『TLC5940で16個のLEDを遊ぶ』」で取り上げられている「TLC5940NT」というICだ。千石電商本店2階、入って左側の、一番奥のほうの抽斗で売られている。武蔵野電波のページでは400~700円とされているが、千石電商の店頭売りでは390円である。

 Arduinoで使うには、GitHubにあるライブラリをダウンロードし、zipを展開して出てくる「tlc5940」というディレクトリをArduino IDEのインストールディレクトリの下にある「libraries」の中にコピーすればよい。

 スペックシートはコレだが、スペックシートを見るより、Arduinoにライブラリを入れると出てくるようになるサンプルスケッチの「BasicUse」を見た方が分かり易いと思う。こんな風にサンプルは書かれている。

/*
    Basic Pin setup:
    ------------                                  ---u----
    ARDUINO   13|-> SCLK (pin 25)           OUT1 |1     28| OUT channel 0
              12|                           OUT2 |2     27|-> GND (VPRG)
              11|-> SIN (pin 26)            OUT3 |3     26|-> SIN (pin 11)
              10|-> BLANK (pin 23)          OUT4 |4     25|-> SCLK (pin 13)
               9|-> XLAT (pin 24)             .  |5     24|-> XLAT (pin 9)
               8|                             .  |6     23|-> BLANK (pin 10)
               7|                             .  |7     22|-> GND
               6|                             .  |8     21|-> VCC (+5V)
               5|                             .  |9     20|-> 2K Resistor -> GND
               4|                             .  |10    19|-> +5V (DCPRG)
               3|-> GSCLK (pin 18)            .  |11    18|-> GSCLK (pin 3)
               2|                             .  |12    17|-> SOUT
               1|                             .  |13    16|-> XERR
               0|                           OUT14|14    15| OUT channel 15
    ------------                                  --------

    -  Put the longer leg (anode) of the LEDs in the +5V and the shorter leg
         (cathode) in OUT(0-15).
    -  +5V from Arduino -> TLC pin 21 and 19     (VCC and DCPRG)
    -  GND from Arduino -> TLC pin 22 and 27     (GND and VPRG)
    -  digital 3        -> TLC pin 18            (GSCLK)
    -  digital 9        -> TLC pin 24            (XLAT)
    -  digital 10       -> TLC pin 23            (BLANK)
    -  digital 11       -> TLC pin 26            (SIN)
    -  digital 13       -> TLC pin 25            (SCLK)
    -  The 2K resistor between TLC pin 20 and GND will let ~20mA through each
       LED.  To be precise, it's I = 39.06 / R (in ohms).  This doesn't depend
       on the LED driving voltage.
    - (Optional): put a pull-up resistor (~10k) between +5V and BLANK so that
                  all the LEDs will turn off when the Arduino is reset.

    If you are daisy-chaining more than one TLC, connect the SOUT of the first
    TLC to the SIN of the next.  All the other pins should just be connected
    together:
        BLANK on Arduino -> BLANK of TLC1 -> BLANK of TLC2 -> ...
        XLAT on Arduino  -> XLAT of TLC1  -> XLAT of TLC2  -> ...
    The one exception is that each TLC needs it's own resistor between pin 20
    and GND.

    This library uses the PWM output ability of digital pins 3, 9, 10, and 11.
    Do not use analogWrite(...) on these pins.

    This sketch does the Knight Rider strobe across a line of LEDs.

    Alex Leone <acleone ~AT~ gmail.com>, 2009-02-03 */

#include "Tlc5940.h"

void setup()
{
  /* Call Tlc.init() to setup the tlc.
     You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
  Tlc.init();
}

/* This loop will create a Knight Rider-like effect if you have LEDs plugged
   into all the TLC outputs.  NUM_TLCS is defined in "tlc_config.h" in the
   library folder.  After editing tlc_config.h for your setup, delete the
   Tlc5940.o file to save the changes. */

void loop()
{
  int direction = 1;
  for (int channel = 0; channel < NUM_TLCS * 16; channel += direction) {

    /* Tlc.clear() sets all the grayscale values to zero, but does not send
       them to the TLCs.  To actually send the data, call Tlc.update() */
    Tlc.clear();

    /* Tlc.set(channel (0-15), value (0-4095)) sets the grayscale value for
       one channel (15 is OUT15 on the first TLC, if multiple TLCs are daisy-
       chained, then channel = 16 would be OUT0 of the second TLC, etc.).

       value goes from off (0) to always on (4095).

       Like Tlc.clear(), this function only sets up the data, Tlc.update()
       will send the data. */
    if (channel == 0) {
      direction = 1;
    } else {
      Tlc.set(channel - 1, 1000);
    }
    Tlc.set(channel, 4095);
    if (channel != NUM_TLCS * 16 - 1) {
      Tlc.set(channel + 1, 1000);
    } else {
      direction = -1;
    }

    /* Tlc.update() sends the data to the TLCs.  This is when the LEDs will
       actually change. */
    Tlc.update();

    delay(75);
  }

}

 この最初のほうのコメントにアスキー・アートで書かれている図を見て結線するとよい。こんな感じだ。

IMG_3185

 LEDは秋葉原・千石電商の隣の店、「akiba LEDピカリ館」で売っていた10個入り300円の白色LEDで、Vfが3.0V~3.4V、Ifが20mAとある。電源が5Vならば100Ωばかり抵抗を付けてやればいい理屈だが、全部点灯させるとArduinoがダメになってしまうから、さらに絞って10KΩつけてやる。

 コンパイルして動かすとこうなる。

 10kΩでもこれくらい明るい。

 このICを使うと、パルス幅変調の幅も、Arduinoが256段階であるのに比べ、4096段階と格段に細かくなる。

 アレンジを加えてみよう。昨日買ってきたポテンショメータを使う。アナログの4番ピンと5番ピンに50kΩのポテンショメータと10kΩの抵抗をつなぎ、それぞれを強さと速さにして、「尾を引いたみたいに」明るさ制御をする。

 ポテンショメータの回路はこうする。

IMG_3191

 図の「E1」をアナログ入力で読めばよい。ポテンショメータのつまみの位置は、次の計算でR2を求めれば明らかになる。

E_{0} = I_{0}\cdot(R_{1} + R_{2})
I_{0} = \frac{E_{0}}{R_{1} + R_{2}}…①
I_{0} = \frac{E_{1}}{R_{2}}…②
① = ②
\frac{E_{0}}{R_{1} + R_{2}} = \frac{E_{1}}{R_{2}}
E_{0}\cdot R_{2} = E_{1}\cdot R_{1} + E_{1}\cdot R_{2}
R_{2}(E_{0} - E_{1}) = E_{1}\cdot R_{1}
R_{2} = \frac{E_{1}\cdot R_{1}}{E_{0}-E_{1}}

 組み付けるとこうなる。

IMG_3187

 動かすとこんな感じ。

 スケッチはこんな感じ。

//
//  wPotentio2tlc5940.ino
//    ポテンショメータとTLC5940でLチカ
//    27.08.02(日)0900~
//    佐藤俊夫
//
#include "Tlc5940.h"
//
const float
  R1 = 10000.0,     //  ポテンショメータ前の抵抗10kΩ, 
  E0 = 5.0,         //  電源電圧5V, 
  MAXVR = 50000.0;  //  ポテンショメータの最大抵抗
const unsigned int   VR1 = 4, VR2 = 5;  //  ポテンショメータはアナログピンのA4・A5
const unsigned int MAX_LED = 15;  //  LEDは0~15の16個
//
void setup()
{
  Tlc.init();
  pinMode(VR1, INPUT);
  pinMode(VR2, INPUT);
}

void loop()
{
  float vr1 = 0.0, vr2 = 0.0, e11 = 0.0, e21 = 0.0;
  static unsigned int topLed = 0, tailLen = 10;
  e11 = analogRead(VR1) * (5.0 / 1024);
  e21 = analogRead(VR2) * (5.0 / 1024);
  vr1 = (e11 * R1) / (E0 - e11);  //  明るさ
  vr2 = (e21 * R1) / (E0 - e21);  //  速さ
  if(++topLed > MAX_LED + tailLen)  topLed = 0;
  Tlc.clear();
  int bright = constrain(fmap(vr1, 0.0, MAXVR, 0, 4095), 0, 4095);
  Tlc.set(topLed, bright);
  for(int i = topLed - 1; i >= 0; i--){
    bright -= (4096 / tailLen);
    if(bright < 0) bright = 0;
    Tlc.set(i, bright);
  }
  Tlc.update();
  unsigned int delayTime = constrain(fmap(vr2, 0.0, MAXVR, 100, 10), 10, 100);
  delay(delayTime);
}
//
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;
}

晩夏漫歩

投稿日:

 千石電商と秋月電子で買い物しようと思い、秋葉原へ行った。

 秋葉原UDX下の立体橋のあたりで、向こうから歩いてきた黒ビジネススーツ、まとめ髪にタイトスカートのOLがにわかにこっちへ走り出してきた。

 驚いて成り行きを見守っていると、私の横を並んで歩いていた「サラリーマンの普段着風」の男にはっしと抱きつき、「ありがとうー!」と言っている。多分恋人なのだろう。

「来てくれてありがとうー!」

 OLさん、人目も憚らず、本当に嬉しそうだ。残りは見も聞きもしなかったが、男も嬉しそうだった。

 ちょっと前ならこんな行動はチャラチャラした連中しかしなかったもので、今日のようないずれ劣らぬ大人の男女は街路で抱擁するなど考えられなかったものだ。

 文句を言っているのではない。逆だ。日本は平和で自由で、本当にほがらかで楽しい国になったと思うのみである。良いことだ。

 さておき、今日秋葉原をうろつくのは、LEDで遊びたいからである。それは、私淑するスタパ齋藤大先生が参加運営しておられる「武蔵野電波」で、Arduinoを使用してLEDをチカチカと光らせまくっているのに多大なる影響を受け、そのマネをするためである。

 そもそも、従来スタパ齋藤大先生のマネをするのは極めて困難であった。なんとなれば、デジタルものは、私にとっては高価だからである。スタパ齋藤大先生は数千万円を気絶のうちにつぎ込んでデジタル道を邁進している人なのであって、その求道の姿は到底私ごときにマネできるものではない。

 だが、スタパ齋藤大先生のインタレストが電子工作に指向しだしてからは別だ。炭素抵抗を1個買ったところで5円、ICを1個買っても300円とか、「お前は小学生かい!」と言われかねないほどのあさましい額の微々たる支出である。マネをすることは容易だ。

 今日はさまざまな色のLEDと、武蔵野電波のサイトで紹介されていたLEDドライブIC、テキサス・インスツルメンツの「TLC5940NT」、電圧発生用の抵抗、工具などを買う。いろいろ買っても1500円とかそんな程度の出費だ。ほんと、花火大会見物に行く小学生に渡す小遣い程度のものである。

 秋葉原のメイド通りで冷やし中華の看板が出ていたので食っていく。

 ヨドバシで珍しくカメラ売り場へ行き、買い物をした。

 上野へ寄って、アメ横で鍔広の中折を求める。夏向きの、麻風の黒いもの。

 こんなものを買った。

IMG_3164

 私には写真の趣味はないので知らなかったのだが、小さいモノの撮影をするにはこういうものを使うべきなのだそうである。これは小さい写真撮影ブースで、1700円ほどのものだ。傘のような仕組みになっており、テントのような形になる。

IMG_3165

 この中にモノを置いて撮るのである。

 で、さっそく今日買ってきたものなどを撮る。

IMG_3167

 なんだかガラクタをたくさん買ってきているが、まあ、2000円くらいのものである。

 今日の大ヒット買い物は、やはりこれだろう。

IMG_3171

 これも武蔵野電波で紹介されていたもので、ブレッドボード用のジャンプワイヤを加工するためのゲージだ。普段使っているワイヤーストリッパにネジで取り付けて使う。次のような感じだ。

IMG_3173

 他に、3端子レギュレータなど買い込む。

IMG_3174

 東芝のTA7805S。50円くらいのもの。なんでこれを買うかと言うと、ArduinoでLチカをやる際、Arduinoはできれば9Vを給電した方が良いが、LEDに9Vをかけると多少無理が大きいので、LEDには別建てで5Vをかけるためである。これで出力側にセラミックコンデンサを付けて平滑化しておけば手軽に5Vに落とせるのだ。

 次女が小学生の頃使っていた髪留めを徴発し、これに3ミリのドリルで穴をあけ、LEDを埋め込んで、この3端子レギュレータで光らせてみる。なかなかピカピカしてよい。

IMG_3177

ただのLチカがこれまた

投稿日:

 釣りは「へら鮒に始まりへら鮒に終わる」と言うそうだが、「ArduinoはLチカに始まりLチカに終わる」などと誰かが言っていそうで多分誰も言っていない(笑)。

 さておき、けっこう楽しいんだよな、Lチカ。

 で、なんっか、手持ちのものをいろいろとくっつけたくなるのだ。今日目に入ったのはSeeedstudio SIDEKICK BASIC KITに入っていた青いポテンショメータ。私が少年の頃は「バリオーム」「ボリューム」「可変抵抗」と言ったものだが、今はポテンショメータと言うそうな。

 ポテンショメータでLチカのスピードを調整してみよう。

 まず、ポテンショメータのスペックシートなどがなくてはっきりしないから、テスターを当てて抵抗を測る。0Ωから10.5kΩまで変化できることがわかった。

 このまま直列に+5Vを印加してアナログピンに入力してしまいそうだが、0Ωの時に過電流になってしまうから、10kΩの別の抵抗と直列に入れた方がいいだろう。そうするとポテンショメータを最小に回し切っても0.5mAくらいに抑えられる。

 計算はどうなるかというと、こんなようなことになる。

IMG_3161

 式に代入すれば、ポテンショメータを最大抵抗にしたとき2.44V、最小抵抗にしたとき0Vになることがわかる。

 プロトタイピングシールドのブレッドボードは小さくて全部の部品が載らないから、普段使っている普通のブレッドボードにつける。

IMG_3157

 動かすとこんな感じだ。

 スケッチはこんな感じ。

//
//  vr2speed.ino
//    ポテンショメータでLチカ制御
//    27.07.26(日)1300~
//    佐藤俊夫
//
const unsigned int
  STARTPIN  = 2,
  ENDPIN    = 8,
  INPUTPIN  = 9,
  VR        = 0,
  DELAYMIN  = 5,
  DELAYMAX  = 100;
const float
  V0 = 5.0,         //  +5V
  R1 = 10000.0,     //  アナログピンに入れるための電流制限抵抗10kΩ
  VRMIN = 0.0,      //  ポテンショメータの最小抵抗実測値 0Ω
  VRMAX = 10500.0;  //  ポテンショメータの最大抵抗実測値 10.5kΩ
//
void setup() {
  //  330Ωをカソードにそれぞれ入れてデジタル2~8番にLEDを繋いである。
  for(int i = STARTPIN; i <= ENDPIN; i++){
    pinMode(i, OUTPUT);
  }
  //  タクトスイッチは9番に繋いでアースし、内蔵プルアップ抵抗を使っている。
  pinMode(INPUTPIN, INPUT_PULLUP);
  //  ポテンショメータは10kΩ抵抗と直列に繋ぎ、間から出力を取っている。
  pinMode(VR, INPUT);
}

void loop() {
  static int i = STARTPIN, RLdirection = 1, delaytime = DELAYMIN;
  static unsigned long int prevtime = 0;
  if(prevtime + delaytime < millis()){
    digitalWrite(i, LOW);
    i += RLdirection;
    if(i > ENDPIN) i = STARTPIN;
    if(i < STARTPIN) i = ENDPIN;
    digitalWrite(i, HIGH);
    prevtime = millis();
  }
  if(digitalRead(INPUTPIN) == LOW){
    delay(500);
    RLdirection *= -1;
  }
  float v1 = (V0 * R1) / (R1 + VRMAX);
  float vr = analogRead(VR) * (V0 / 1024);
  delaytime = constrain(fmap(vr, v1, 0.0, DELAYMAX, DELAYMIN), DELAYMIN, DELAYMAX);
}

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チカをやるのでも、単線タイプのジャンプワイヤをちゃんと使い、できる限りブレッドボード上を整然と配置してみた。これまではあまりそんなことは考えていなかったからだ。

 とりあえず持っているLEDを持っている330Ωの電流制御抵抗の個数の限り配置した。タクトスイッチをつけて、入力を受け付けるようにする。とりあえず、LEDの点滅が右から左へ流れ、タクトスイッチを押すたびに左右の向きが入れ替わる、というふうにしよう。

IMG_3153

 タクトスイッチの入力にプルダウン抵抗を取り付けるスペースがなくなってしまったので、内蔵プルアップ抵抗を使うことにし、負論理にする。

 動かすとこんな感じだ。

 スケッチはこんな感じ。

//
//  smartBreadboard.ino
//    出来るだけ美しくブレッドボードを作ってみた。
//    27.07.26(日)0800~
//    佐藤俊夫
//
const unsigned int
  STARTPIN  = 2,
  ENDPIN    = 8,
  INPUTPIN  = 9,
  DELAYTIME = 50;
//
void setup() {
  //  330Ωをカソードにそれぞれ入れてデジタル2~8番にLEDを繋いである。
  for(int i = STARTPIN; i <= ENDPIN; i++){
    pinMode(i, OUTPUT);
  }
  //  タクトスイッチは9番に繋いでアースし、内蔵プルアップ抵抗を使っている。
  pinMode(INPUTPIN, INPUT_PULLUP);
}

void loop() {
  static int i = STARTPIN, j = 1;
  static unsigned long int prevtime = 0;
  if(prevtime + DELAYTIME < millis()){
    digitalWrite(i, LOW);
    i += j;
    if(i > ENDPIN) i = STARTPIN;
    if(i < STARTPIN) i = ENDPIN;
    digitalWrite(i, HIGH);
    prevtime = millis();
  }
  if(digitalRead(INPUTPIN) == LOW){
    delay(500 );
    j *= -1;
  }
}

いよいよ多機能リモコン

投稿日:

 LEDを強力に光らせることが出来たので、いよいよWebサーバつき多機能リモコンを作成する。卓上などに置いておき、ネットワークにつないで、スマホなどから複数の電化製品を操作できるというものだ。

 ここでは、いくつかのテクニックを使った。

 一つは、フォームが大きくなってしまい、ハードコーディングするとメモリが足りなくなる。そこで、SDカード内にHTMLを置き、これを読み出すようにした。

 同様に、リモコンから読み取った数値データが大きくなって、普通にハードコーディングしたのではメモリが不足する。そこで、「PROGMEM」というキーワードを使って、フラッシュメモリ内にデータを置き、これを読み出すようにした。

IMG_3134 ETHERNET SHIELD 2を遺憾なく使う。SDカードを取り付けられるから、そこにHTMLを書き込んでおけばよい。FETをつけたブレッドボードと一緒に、買っておいたSparkfunの基盤に固定する。

 SDカード内には、次のようなHTMLを置き、ファイル名を「irform.htm」とする。

<html>
 <head>
  <meta name="Editor" content="Notepad.exe">
  <meta http-equiv="Content-Type" content="text/html;charset=Shift_JIS">
  <title>Webリモコン</title>
  <basefont size=4>
 </head>

 <body bgcolor="#ddffdd">
  <center>
   <h1><b>Webリモコン</b></h1>
     <table>
      <tr><td> 作成者   </td>
       <td align="right">佐藤俊夫</td></tr>
      <tr><td> 作成日時 </td>
       <td align="right">27.07.19 (日) 1835</td></tr>
     </table>
  </center>
  <hr>
  <center>
    <form method="get" name="irremote">
    <table border=1>
      <tr><th>機器</th><th>ボタン</th></tr>
      <tr>
        <td rowspan=4>扇風機</td>
        <td><input submit type="submit" value="入/風量" name="fan_on"></td>
      </tr>
        <tr><td><input submit type="submit" value="タイマー" name="fan_timer"></td></tr>
        <tr><td><input submit type="submit" value="首振" name="fan_swing"></td></tr>
        <tr><td><input submit type="submit" value="切" name="fan_off"></td></tr>
      </tr>
      <tr>
        <td rowspan=5>テレビ</td>
        <td><input submit type="submit" value="入/切" name="tv_on_off"></td>
      </tr>
        <tr><td><input submit type="submit" value="音量大" name="tv_volup"></td></tr>
        <tr><td><input submit type="submit" value="音量小" name="tv_voldown"></td></tr>
        <tr><td><input submit type="submit" value="チャンネル>" name="tv_chup"></td></tr>
        <tr><td><input submit type="submit" value="チャンネル<" name="tv_chdown"></td></tr>
    </table>
    </form>
  </center>
 </body>
</html>

irform 上のHTMLの見た目はこんな感じだ。

 スケッチは次のようになる。

//
//  Web2IRremote.ino
//    リモコンをウェブで操作する。
//    27.07.25(日) 1930
//    佐藤俊夫
//
#include <SPI.h>
#include <Ethernet2.h>
#include <SD.h>
#include <IRremote.h>
#include <avr/pgmspace.h>
//
byte mac[] = {  0x90, 0xA2, 0xDA, 0x0F, 0xF6, 0x74 };
IPAddress ip(192, 168, 1, 129);
EthernetServer SERVER(80);
EthernetClient CLIENT;
IRsend irsend;
PROGMEM
  const unsigned int
    fan_on[]     = {4500,2150, 600,500, 650,500, 600,500, 600,500, 600,1650, 600,1600, 650,1550, 650,500, 600,1600, 650,1600, 600,1600, 650,450, 600,1600, 650,500, 600,500, 650,500, 600,1600, 600,500, 650,500, 600,500, 600,500, 600,500, 600,1650, 600,500, 600,500, 600,500, 650,1600, 600,1600, 600,1650, 600,1600, 600,500, 650,500, 600,0},
    fan_timer[]  = {4500,2150, 550,550, 550,600, 550,550, 600,500, 550,1700, 500,1700, 550,1650, 550,600, 550,1650, 550,1700, 500,1700, 550,600, 500,1700, 550,550, 550,550, 550,600, 500,1700, 550,600, 500,600, 500,600, 500,600, 550,550, 550,1700, 550,600, 450,600, 550,550, 550,600, 500,1700, 550,1650, 550,1700, 550,1650, 550,600, 500,0},
    fan_swing[]  = {4450,2200, 600,550, 550,500, 600,550, 550,550, 550,1700, 550,1650, 550,1700, 550,550, 550,1650, 550,1700, 550,1650, 550,550, 600,1650, 550,550, 550,550, 550,550, 600,1650, 550,550, 550,550, 600,550, 550,550, 550,550, 600,1600, 600,550, 550,550, 550,1650, 600,1550, 650,1700, 550,1650, 550,550, 550,550, 600,550, 550,0},
    fan_off[]    = {4450,2250, 550,550, 600,550, 550,500, 600,550, 550,1650, 600,1650, 550,1650, 600,550, 550,1650, 550,1650, 600,1650, 550,550, 550,1700, 550,550, 550,550, 550,550, 550,1700, 550,550, 550,550, 550,550, 600,550, 550,550, 550,1650, 550,550, 600,550, 550,1650, 600,1650, 550,550, 550,1700, 550,500, 600,550, 550,1650, 600,0},
    tv_on_off[]  = {3400,1750, 400,500, 350,1350, 400,500, 350,500, 400,500, 350,500, 400,500, 350,450, 400,500, 400,500, 350,500, 400,500, 350,500, 350,1350, 400,500, 400,500, 350,450, 400,500, 400,500, 350,450, 400,500, 400,500, 350,500, 400,1300, 400,500, 400,450, 400,500, 400,500, 350,500, 350,500, 400,450, 400,450, 400,1350, 400,500, 400,1300, 400,1350, 400,1350, 400,1350, 400,450, 400,500, 400,1300, 400,500, 400,1300, 400,1350, 400,1350, 400,1350, 400,500, 350,1350, 400,0},
    tv_volup[]   = {3400,1750, 400,500, 400,1300, 400,500, 400,500, 350,500, 450,400, 400,500, 350,500, 400,500, 350,500, 350,500, 400,500, 350,500, 400,1300, 400,500, 400,450, 400,500, 350,500, 400,500, 350,500, 400,500, 350,500, 350,500, 400,1300, 450,450, 400,500, 350,500, 400,500, 350,500, 400,450, 400,500, 350,500, 400,500, 350,450, 400,500, 400,500, 350,500, 450,1250, 400,500, 400,500, 350,500, 400,450, 400,500, 350,500, 400,500, 350,1350, 400,450, 400,1350, 400,0},
    tv_voldown[] = {3400,1750, 400,500, 350,1350, 400,500, 400,450, 400,500, 350,500, 400,450, 400,500, 400,500, 350,500, 350,500, 400,500, 350,500, 350,1300, 450,500, 400,500, 350,450, 400,500, 450,450, 350,500, 400,450, 400,450, 400,500, 400,1300, 450,500, 350,500, 350,500, 400,500, 350,450, 400,500, 400,500, 350,500, 400,1300, 400,500, 400,450, 400,500, 400,500, 350,1350, 400,500, 350,500, 400,1300, 400,500, 400,500, 350,500, 350,500, 400,1300, 450,500, 350,1350, 400,0},
    tv_chup[]    = {3400,1750, 400,500, 400,1350, 450,400, 400,450, 400,500, 450,400, 400,450, 400,500, 450,450, 450,400, 450,450, 400,400, 400,500, 450,1250, 450,500, 350,450, 500,400, 450,400, 400,500, 350,500, 450,450, 350,500, 450,450, 450,1250, 400,500, 450,400, 400,500, 400,450, 450,400, 450,450, 350,500, 450,400, 450,450, 350,500, 450,1250, 400,500, 450,1250, 500,1250, 500,400, 450,450, 350,500, 450,450, 350,1350, 450,450, 400,1300, 450,1250, 500,450, 400,1250, 450,0},
    tv_chdown[]  = {3500,1650, 450,500, 400,1300, 400,500, 450,400, 350,500, 400,450, 500,400, 450,450, 350,450, 400,500, 400,500, 350,500, 400,450, 450,1300, 450,450, 350,450, 450,500, 350,500, 450,400, 450,400, 400,500, 350,500, 450,400, 400,1350, 450,400, 500,400, 450,450, 450,400, 400,500, 350,500, 350,500, 400,500, 350,1350, 450,450, 350,1350, 400,500, 350,1350, 500,1250, 450,450, 450,400, 450,1250, 500,400, 450,1300, 450,450, 400,1300, 450,1250, 450,500, 350,1350, 450,0};
////
void setup() 
{ 
  const int chipSelect = 4;
  Ethernet.begin(mac, ip);
  SERVER.begin();
  if (!SD.begin(chipSelect)) {
    return;
  }
} 
 
void loop() 
{ 
  //  Webサーバの動作
  char c;
  String rstr = "";
  CLIENT = SERVER.available();
  if (CLIENT) {
    while (CLIENT.connected()) {
      if (CLIENT.available()) {
        c = CLIENT.read();
        rstr += c;
        if(rstr.endsWith("\r\n")){
          break;
        }
      }
    }
    if(rstr.indexOf("fan_on=") >= 0){
      unsigned int buf[sizeof(fan_on) / sizeof(*fan_on)];
      for(int i = 0; i < sizeof(fan_on) / sizeof(*fan_on); i++){
        buf[i] = pgm_read_word(fan_on + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("fan_timer=") >= 0){
      unsigned int buf[sizeof(fan_timer) / sizeof(*fan_timer)];
      for(int i = 0; i < sizeof(fan_timer) / sizeof(*fan_timer); i++){
        buf[i] = pgm_read_word(fan_timer + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("fan_swing=") >= 0){
      unsigned int buf[sizeof(fan_swing) / sizeof(*fan_swing)];
      for(int i = 0; i < sizeof(fan_swing) / sizeof(*fan_swing); i++){
        buf[i] = pgm_read_word(fan_swing + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("fan_off=") >= 0){
     unsigned int buf[sizeof(fan_off) / sizeof(*fan_off)];
     for(int i = 0; i < sizeof(fan_off) / sizeof(*fan_off); i++){
        buf[i] = pgm_read_word(fan_off + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("tv_on_off=") >= 0){
     unsigned int buf[sizeof(tv_on_off) / sizeof(*tv_on_off)];
     for(int i = 0; i < sizeof(tv_on_off) / sizeof(*tv_on_off); i++){
        buf[i] = pgm_read_word(tv_on_off + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("tv_volup=") >= 0){
     unsigned int buf[sizeof(tv_volup) / sizeof(*tv_volup)];
     for(int i = 0; i < sizeof(tv_volup) / sizeof(*tv_volup); i++){
        buf[i] = pgm_read_word(tv_volup + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("tv_voldown=") >= 0){
     unsigned int buf[sizeof(tv_voldown) / sizeof(*tv_voldown)];
     for(int i = 0; i < sizeof(tv_voldown) / sizeof(*tv_voldown); i++){
        buf[i] = pgm_read_word(tv_voldown + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("tv_chup=") >= 0){
     unsigned int buf[sizeof(tv_chup) / sizeof(*tv_chup)];
     for(int i = 0; i < sizeof(tv_chup) / sizeof(*tv_chup); i++){
        buf[i] = pgm_read_word(tv_chup + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    else if(rstr.indexOf("tv_chdown=") >= 0){
     unsigned int buf[sizeof(tv_chdown) / sizeof(*tv_chdown)];
     for(int i = 0; i < sizeof(tv_chdown) / sizeof(*tv_chdown); i++){
        buf[i] = pgm_read_word(tv_chdown + i);
      }
      irsend.sendRaw(buf, sizeof(buf) / sizeof(buf[0]), 38);
    }
    rstr = "";
    sendform();
    delay(1);
    // close the connection:
    CLIENT.stop();
  }
  delay(20);
}
void sendform(){
  //  フォームを送る。
  CLIENT.println("HTTP/1.1 200 OK");
  CLIENT.println("Content-Type: text/html");
  CLIENT.println("Connection: close");
  CLIENT.println();
  CLIENT.println("<!DOCTYPE HTML>");
  File html = SD.open("irform.htm");
  if (html) {
    while (html.available()) {
      CLIENT.write(html.read());
    }
    html.close();
  } 
}

IMG_3135 勿論、ただのWebであるから、このようにスマホの他、タブレットなどからも操作可能である。また、ルータでポートフォワードすれば、外出先からの操作も可能である。

赤外線LEDをもっとビカビカ光らせる

投稿日:

 さて、前回のこのエントリでは、赤外線LEDでリモコンを作る基礎が整ったが、50mA定格のLEDに5mAしか流していないので、いまいち光り方に根性がなく、電気製品の受光部にかなり近づけないと厳しい。

 そこで、どっぷり50mA近くまで電流を流し、赤外線LEDをして「ご主人様もうお腹いっぱいゲフォア」と言わしめたい。

 運よく、以前にソレノイドを動かした時のFET「2SK2232」がある。

 50mA近く流すには

R=\cfrac{5V}{50mA}=100\Omega

……ということで、100Ωかましてやればいいが、ちょうど100Ωの抵抗は持っていない。で、330Ωがあるから、これを3本並列にして

\cfrac{1}{\cfrac{1}{330\Omega}\times 3}=110\Omega

 110Ωに5V流せば

\cfrac{5V}{110\Omega}\fallingdotseq 45mA

……というわけで、じゃぶじゃぶ流せる。2SK2232のドレイン電流は25Aなので、余裕でオッケーである。

IMG_3133 と、いうわけで、回路図とブレッドボードはこうなる。

 スケッチは前回と同じでいい。

 動かしてデジカメのモニタで観察すると、もう、ビカビカにLEDが光る光るッ!。そんなに受光部に近づけなくても、ばりばり扇風機のスイッチがオンオフできるようになった。

赤外線LEDでリモコンごっこ

投稿日:

IMG_3128 他の方のサイトでも、赤外線LEDを買ってきてArduinoで便利なリモコンを作る、ということをやっているので、私も真似したく、赤外線LEDを買ってきた。

 10個も入っていて100円である。

 受信機はこの前800円で買ったリモコンと受信モジュールのセットがあるから、これでよい。

 この赤外線LEDは50mA流す規格なので、20mAしか流せないArduinoで光らせるには少し大き過ぎる。1kΩばかり抵抗をつけて5mAくらいにする。暗くてリモコンが反応しないのじゃないかな、とも思ったが、受光部に近づければ大丈夫だ。しかし、デジカメで観察するとかなり暗い。もし、ちゃんとしたものを組み立てるのなら、FETなどでリレーして、他の電源から50mA流したほうがいいだろう。

 今回は遊びなので、5mAで光らせる。

 先達のサイトでは、スクラッチビルドのコードで市販のリモコンの信号を受信し、ミリ秒単位でオンオフ時間を計測して記録し、その通りに赤外線LEDを光らせてうまく行っている方が多いようだ。

 一方、Arduinoには、「IRremote」というライブラリをGitHubで公開しておられる方がいるので、これを使えば簡単である。

 GitHubのページからzip玉をもらって解凍し、できたディレクトリ(IRremote)をArduinoのインストールディレクトリの「libraries」の下にコピーすればよい。

 今日は私の家のリビングの扇風機のリモコンで試してみよう。

 リビングの扇風機のリモコン信号をコピーしてテストするには、ライブラリをインストールするとできるサンプルスケッチのうち、「IRrecord」というのを使う。コマンドメニューは「ファイル→スケッチの例→IRremote→IRrecord」と辿る。

 これは、「1回こっきりの学習リモコン」のスケッチだと思えばよい。市販のリモコンを受信して記憶し、次いでボタンを押すとそのままそっくり信号のコピーを赤外線LEDから送出するスケッチだ。

 赤外線LEDは1kΩの抵抗と直列にしてデジタル3番ピンに、受信機は11番ピンに、タクトボタンを12番ピンにつなぐ。タクトボタンの入力側は10kΩの抵抗できちんとプルダウンしておくのが行儀がいい。そうしないと、手を触れたくらいのことでスイッチが入ってしまう。

 ブレッドボードが出来たら、使いたいリモコンを受信機に近づけ、ボタンを押す。

 それから今度は、ブレッドボード上の赤外線LEDを電気製品に近づけ、タクトボタンを押す。

 そっくりコピーされた信号が送出され、扇風機が動く。

 これで、ハードウェアは正しく動くことが分かったので、今度は単純にデータをハードコーディングで配列に書き出し、これを送出して扇風機のスイッチをオンオフさせる。

 まず、データを記録する。それにはサンプルスケッチの「IRrecvDumpV2」を使う。今度は受信機を6番ピンにつなぎ換え、シリアルモニタを起動してデータを観測する。そうすると、そのまま使える形の配列の初期化定義の格好でダンプが出てくる。

 これをクリップボードにコピーして、今度はサンプルスケッチの「IRSendDemo」にペーストし、送出してやればよい。

 ところが、ここでハマッた、ハマッた。そのままではうまくいかないのである。

 はじめ、私の扇風機では、「IRrecvDumpV2」のダンプはこうなった。

Encoding  : UNKNOWN
Code      : 1FB3782D (32 bits)
Timing[68]: 
     -22598
     +4500, -2150     + 650, - 500     + 600, - 500     + 500, - 600
     + 550, - 550     + 650, -1600     + 600, -1600     + 550, -1700
     + 600, - 500     + 550, -1700     + 600, -1600     + 600, -1650
     + 550, - 550     + 600, -1600     + 600, - 500     + 650, - 500
     + 600, - 500     + 600, -1600     + 650, - 500     + 600, - 500
     + 600, - 500     + 600, - 500     + 600, - 500     + 650, -1600
     + 600, - 500     + 600, - 500     + 550, - 600     + 600, -1600
     + 600, -1600     + 550, -1700     + 600, -1600     + 650, - 500
     + 500, - 600     + 550, 
unsigned int  rawData[69] = {9627, 90,43, 13,10, 12,10, 10,12, 11,11, 13,32, 12,32, 11,34, 12,10, 11,34, 12,32, 12,33, 11,11, 12,32, 12,10, 13,10, 12,10, 12,32, 13,10, 12,10, 12,10, 12,10, 12,10, 13,32, 12,10, 12,10, 11,12, 12,32, 12,32, 11,34, 12,32, 13,10, 10,12, 11,0};  // UNKNOWN 1FB3782D

そこで私は、この「rawData[69]」をコピペし、次のようにした。

#include <IRremote.h>

IRsend irsend;

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

void loop() {
  static unsigned int  rawData[] = {9627, 90,43, 13,10, 12,10, 10,12, 11,11, 13,32, 12,32, 11,34, 12,10, 11,34, 12,32, 12,33, 11,11, 12,32, 12,10, 13,10, 12,10, 12,32, 13,10, 12,10, 12,10, 12,10, 12,10, 13,32, 12,10, 12,10, 11,12, 12,32, 12,32, 11,34, 12,32, 13,10, 10,12, 11,0};  // UNKNOWN 1FB3782D
  if (Serial.read() != -1) {
    for (int i = 0; i < 3; i++) {
      irsend.sendRaw(rawData,sizeof(rawData) / sizeof(rawData[0]), 38); // Sony TV power code
      delay(40);
    }
  }
}

 ところが、これではまったくダメなのである。

 最初は赤外線LEDの電流が足りないのかなあ、などと思い、半日ほどあっちこっちをいじくりまわして、ダメだった。

 「IRrecord」での丸ごと信号コピーはうまく行っているのだから、電流が足りないわけではないらしい。

 そこで、「IRrecord」のダンプ部分にコードを書き足し、「sendRaw()」関数にどんな値を渡しているかを見てみた。

  else if (codeType == UNKNOWN /* i.e. raw */) {
    // Assume 38 KHz
    irsend.sendRaw(rawCodes, codeLen, 38);
    Serial.println("Sent raw");
    Serial.println(codeLen);
    for(int cnt = 0; cnt <= codeLen; cnt++){
      Serial.print(rawCodes[cnt]);
      Serial.print(",");
    }
    Serial.println("\n");
  }

 そうしたら、どうも、ダンプされた値の50倍が渡されているらしい。

4400,2250,550,600,500,600,500,600,500,600,550,1700,500,1700,500,1750,500,600,400,1800,550,1700,500,1650,550,600,550,1700,500,600,500,600,550,600,500,1700,550,550,450,650,550,600,500,600,500,600,450,1800,550,550,550,550,550,600,500,1700,550,1650,550,1700,500,1700,650,500,500,600,500,0,

 そこで、「IRrecvDumpV2」のダンプ出力部分を次のようにカスタマイズした。

  // Dump data
  for (int i = 0;  i < results->rawlen;  i++) {
//    Serial.print(results->rawbuf[i], DEC);
    Serial.print(results->rawbuf[i] * 50, DEC);
    Serial.print(",");
    if (!(i&1))  Serial.print(" ");
  }

 そうすると、ダンプは……

ncoding  : UNKNOWN
Code      : FBB100E8 (32 bits)
Timing[68]: 
     -24324
     +4550, -2150     + 650, - 450     + 650, - 450     + 650, - 500
     + 650, - 450     + 650, -1550     + 650, -1600     + 650, -1550
     + 650, - 450     + 650, -1600     + 650, -1550     + 700, -1550
     + 650, - 450     + 650, -1550     + 650, - 500     + 650, - 450
     + 650, - 450     + 650, -1600     + 600, - 500     + 650, - 450
     + 650, - 500     + 600, - 450     + 700, - 450     + 650, -1550
     + 650, - 500     + 650, - 450     + 650, - 450     + 650, -1600
     + 600, -1600     + 650, -1550     + 650, -1600     + 650, - 450
     + 650, - 450     + 650, 
unsigned int  rawData[69] = {24324, 4550,2150, 650,450, 650,450, 650,500, 650,450, 650,1550, 650,1600, 650,1550, 650,450, 650,1600, 650,1550, 700,1550, 650,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,500, 650,450, 650,500, 600,450, 700,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,1600, 650,1550, 650,1600, 650,450, 650,450, 650,0};  // UNKNOWN FBB100E8

……となる。

 で、この先頭の「24324」は送信前の空き時間なので、捨ててよいようだ。「IRsendDemo」のほうにこれをコピペし、先頭の24324は消す。

#include <IRremote.h>

IRsend irsend;

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

void loop() {
  static unsigned int  rawData[] = {4550,2150, 650,450, 650,450, 650,500, 650,450, 650,1550, 650,1600, 650,1550, 650,450, 650,1600, 650,1550, 700,1550, 650,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,500, 650,450, 650,500, 600,450, 700,450, 650,1550, 650,500, 650,450, 650,450, 650,1600, 600,1600, 650,1550, 650,1600, 650,450, 650,450, 650,0};  // UNKNOWN 1FB3782D
  if (Serial.read() != -1) {
    for (int i = 0; i < 3; i++) {
      irsend.sendRaw(rawData,sizeof(rawData) / sizeof(rawData[0]), 38); // Sony TV power code
      delay(40);
    }
  }
}

 これで、赤外線LEDを扇風機に近づけ、シリアルモニタの「送信」ボタンをクリックすると、扇風機がオン・オフされる。

IMG_3129 ブレッドボードは結局、最後はこんな感じ。

リモコンでLEDコントロール

投稿日:

 秋月電子で買ったリモコン、せっかくだから、これでLEDを点けたり消したりしてみよう。ただ単に点滅ではいまいち芸がないから、3色LEDの照度を多段階に変えたり、色をいろいろに変えたりしてみようではないか。

 買ってきたリモコン

 IR受信ライブラリを使ってみたが、どうも安定しない。リモコンからはコードが連続送出されるようなのだが、受信ごとに違う値が返ってきて困る。

 調べてみると、0xffffff、すなわち24ビットを超える値が返ってくるときはどうやら受信がうまく行っていないことがわかったので、これを排除してみたところ、うまくいくようだ。

 そこを通り抜けると、今度はどうも、使用するピンの組み合わせに約束があるようだ。はっきりとはわからないのだが、PWMを9・10・11、IRリモコン受信モジュールを12で使うと、さっぱりうまく行かない。

 いろいろと変えて、LEDのためのPWMをR・G・Bそれぞれ9・5・6に割り付けるとうまくいくことがわかった。……理由がなんだかよくわからないのだが(笑)。

 スケッチは結局こうなった。

//
//  IR2LED.ino
//    赤外線リモコン「DFR0107」(DFROBOT社)でLEDをコントロールする。
//    https://satotoshio.net/blog/?p=1490
//    27.7.11(土) 1755~
//    佐藤俊夫
//    
#include <IRremote.h>

const int LEDR = 9, LEDG = 5, LEDB = 6, IRR = 12;
IRrecv irrecv(IRR);
decode_results results;

void setup()
{
  irrecv.enableIRIn(); // Start the receiver
  pinMode(LEDR, OUTPUT);
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);
  pinMode(IRR, INPUT);  
}

void loop() {
  if (irrecv.decode(&results)) {
    if(results.value <= 0xffffff && results.value > 0xfd0000){
      processValue(results.value);
    }      
    irrecv.resume(); // Receive the next value
  }
}

void processValue(long int value){
  static boolean ledOn = true;
  static unsigned int r = 255, g = 255, b = 255, combi = 0x07;
  switch(value){
    case 0xfd00ff:  //  vol+
      if(ledOn == true){
        ledOn = false;
      }else{
        ledOn = true;
      }
      break;
    case 0xfd807f:  //  vol-
      if(r < 255 - 10) r += 10;
      if(g < 255 - 10) g += 10;
      if(b < 255 - 10) b += 10;
      break;
    case 0xfd906f:
      if(r > 0 + 10) r -= 10;
      if(g > 0 + 10) g -= 10;
      if(b > 0 + 10) b -= 10;
      break;
    case 0xfd609f:  // >>|
      if(combi < 0x07){
        combi++;
      }else{
        combi = 0x01;
      }
      break;
    case 0xfd20df:  // |<<
      if(combi > 0x01){
        combi --;
      }else{
        combi = 0x07;
      }
      break;
    default:
      break;
  }
  controlLED(ledOn, r, g, b, combi);

}

void controlLED(const boolean on, const int r, const int g, const int b, const int combi){
  unsigned int ron = 0, gon = 0, bon = 0;
  
  ron = (0x04 & combi) > 0;
  gon = (0x02 & combi) > 0;
  bon = (0x01 & combi) > 0;
  delay(20);
  if(on){
    analogWrite(LEDR, (255 - r * ron));
    analogWrite(LEDG, (255 - g * gon));
    analogWrite(LEDB, (255 - b * bon));
  }else{
    analogWrite(LEDR, 255);
    analogWrite(LEDG, 255);
    analogWrite(LEDB, 255);
  }
}

焦電センサで遊ぶ

投稿日:

 秋月電子に行ったら、「焦電センサ」が売られていた。付加回路のついたモジュールで、800円。秋月電子のサイトを見ると、他にも安いものはあるが、店頭にあるものではこれが一番安かった。

IMG_3096

 「焦電センサ」という言い方は随分通ぶった言い方で、一般的には「赤外線人感センサ」と言った方が通りがよかろう。

 買ったものは5V・TTLの負ロジックで、35度くらいのものがセンサ前面の角度120°の範囲2メートル以内で動くと、出力が「負」になる。ロジック端子にプルアップ抵抗をつけて、5Vくらいをくれておいてやるとよいわけだ。

 そこで、早速こんなふうにする。ブレッドボードシールド上にはプルアップ抵抗と、リード線を伸ばして3色LEDを取り付けるだけでいい。

IMG_3097
IMG_3098

 スケッチをこんなふうに書けば、即席人感ランプの出来上がりである。

//
//  Pir2Led.ino
//  焦電センサで遊ぶ。
//    秋月電子焦電センサモジュール「SE-10」使用
//    https://satotoshio.net/blog/?p=1471
//    27.7.11 1100~
//    佐藤俊夫
//
const int PIR = 8, LEDR = 9, LEDG = 10, LEDB = 11, LIGHTTIME = 5000, DULL = 100;
//  DULL  過敏さを抑えるため、100回くらい人感しないと点灯させない。
//  LEDはアノードコモン、焦電センサは負論理なので、どっちも「負 LOW」で点灯
void setup() {
  pinMode(PIR, INPUT);
  pinMode(LEDR, OUTPUT);
  pinMode(LEDG, OUTPUT);
  pinMode(LEDB, OUTPUT);
  digitalWrite(LEDR, HIGH);
  digitalWrite(LEDG, HIGH);
  digitalWrite(LEDB, HIGH);
}

void loop() {
  static int pcount = 0;
  boolean p = HIGH;
  delay(20);
  p = digitalRead(PIR);
  if(p == LOW){
    pcount++;
  }
  if(pcount >= DULL){
    digitalWrite(LEDR, LOW);
    digitalWrite(LEDG, LOW);
    digitalWrite(LEDB, LOW);
    pcount = 0;
    delay(LIGHTTIME);
  }else{
    digitalWrite(LEDR, HIGH);
    digitalWrite(LEDG, HIGH);
    digitalWrite(LEDB, HIGH);
  }
}

自然風もどき扇風機

投稿日:

 1000円ほどで買った安物の扇風機にArduinoその他をつなぎ、自然風もどきの送風機能を実装してみる。

 先週作った「AC100Vオン・オフモジュール」と、1/fゆらぎエフェクトをかけたランプのスケッチをそのまま使う。

 先週のLチカの、赤色LEDの線をそのままSSRの+5Vロジック・インへ、それから、Lチカはアノード・コモンのLEDを使ったためにArduinoの+5Vに接続していたから、これをGNDにつなぎかえてSSRの+-0Vへ入れる。

 これを試そうという方がいたら、使う扇風機についてご注意いただきたい。必ず、ここで使っているような、電子的な制御がかかっていない、AC100Vがモーターに直接かかるような、安物の簡素な扇風機を使わないといけない。