「えだまめ」しているラズパイ

30年ぶりに半田ごて握ってラズパイ勉強中。

ATTiny85 モーションセンサー付 クリスマスツリーの製作

◯やりたい事

ATTiny85でモーションセンサー付クリスマスツリーを作るためのハード・ソフト開発。

◯やった事

・回路図作成

無料の回路図CADを使って、初めて回路図を書いてみました。

たったこれだけを書くのに1週間もかかりました。もう大変。

ただ回路的には単純明快、簡単なものです。
赤外線センサー(アクティブH)の出力を微分してワンショットパルスを作成し、FETのNAND回路を通してAT85にリセットをかけるというものです。センサーはアクティブHであれば基本どんなものでも使えます。微分回路はパルス立ち下がり時にマイナス電位が発生しますので、使用するFETのゲート定格には注意です。

モーションセンサーのアクティブ時間が短い場合、クリスマスチカの最中やミュージック演奏中に再リセットがかかってしまいますのでNAND回路で制限しています。起動後すぐにリセットを禁止し処理を終えた後リセットを許可してスリープに入ります。

RGB-LEDはWS2012を内蔵した4ピン砲弾型LED PL9823を使用しました。秋月電子さんのページにあるデータシートによると、動作電圧4.5〜6VとなっていますがLiPo電池でもなんとか動作してくれるようです。

・実験回路組み立て

回路図に基づいてブレッドボードに回路を組んでみました。

ちょうどミニブレッドに収まります。
センサー出力(微分出力)とリセットパルスの関係をハンディオシロで測定してみたところ


(青:センサー 黄:リセット)

約70msの実測値でした。
ちなみにブレッドボードのトップビューも参考に載せておきます。

直接スピーカーを駆動してくれるのが助かります。

・スケッチ作成

上記を基にスケッチを作成。

/*
 *      CPU     : ATtiny85
 *       D0/PWM : -
 *       D1/PWM : SP
 *       D2/A1  : WS2811 Data Pin
 *       D3/A3  : -
 *       D4/A2  : EN
 *       D5     : Reset
*/

// include
#include <avr/sleep.h>  // スリープライブラリ
#include <FastLED.h>

// ピン定義
#define SP           1  // D1 Speaker
#define DATA_PIN     2  // D2 WS2811,2812 Data Pin
#define EN           4  // D4 Reset Enable
#define RESET        5  // D5 Reset

// RGB LED
#define NUM_LEDS     3  // 系統1 LED 接続数
CRGB leds[NUM_LEDS];

// RGB LED Color  0xRRGGBB
uint32_t black  = 0x000000;  // color #0
uint32_t red    = 0x800000;  // #1
uint32_t yellow = 0x404000;
uint32_t green  = 0x008000;
uint32_t cyan   = 0x004040;
uint32_t blue   = 0x000080;
uint32_t purple = 0x400040;
uint32_t white  = 0x303030;  // #7
uint32_t LED_COLOR[] = {black,red,yellow,green,cyan,blue,purple,white};

// 音階定数
const int Note_C  = 239;  // ド
const int Note_CS = 225;
const int Note_D  = 213;  // レ
const int Note_DS = 201;
const int Note_E  = 190;  // ミ
const int Note_F  = 179;  // ファ
const int Note_FS = 169;
const int Note_G  = 159;  // ソ
const int Note_GS = 150;
const int Note_A  = 142;  // ラ
const int Note_AS = 134;
const int Note_B  = 127;  // シ

// 割込みベクタ
ISR (PCINT0_vect) {}

// 初期化
void setup() {
  // 8MHzモードに設定
  CLKPR = 0x80;
  CLKPR = 0x00;

  // ピンモード設定 事前に出力データを確定させておく
  digitalWrite(EN, LOW);  // リセット禁止
  digitalWrite(SP, LOW);
  pinMode(EN, OUTPUT);
  pinMode(SP, OUTPUT);

  // WS2811 setup
  FastLED.addLeds<WS2811, DATA_PIN,  RGB>(leds,  NUM_LEDS);
}

// メインルーチン
void loop() {
  // リセット禁止
  digitalWrite(EN, LOW);

  // LED点灯後 ミュージックスタート
  led_on();
  ply_mus(1);

  // ループ開始
  for (int8_t j=0; j<125; j++) {
    // LED 点灯
    led_on();
    delay(800);
  }

  // 電源off(スリープ)
  while (true) {
    // 全消灯,リセット許可 
    led_off();
    digitalWrite(EN, HIGH);
    delay(100);

    // sleep モード,割込起動ピン設定
    GIMSK = 0x20; // set GIMASK PCIE bit.
    PCMSK = 0x08; // enable PCINT3 (PB3)
    //PCMSK = 0x10; // enable PCINT4 (PB4)

    // sleep 開始
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_cpu();
          
    // 割込み発生 sleep 終了 
    sleep_disable(); 
    return;
  }
}

/* LED Control */
// Get Random Color
int32_t  led_color() {
  if (random(2)==0) return 0;
  return LED_COLOR[random(8)+1];
}
// LED 点灯
void led_on() {
  for (int8_t i=0; i<NUM_LEDS; i++) leds[i] = led_color();
  FastLED.show();
}

// 全消灯
void led_off() {
  for (int8_t i=0; i<NUM_LEDS; i++) leds[i] = CRGB::Black;   
  FastLED.show();
}

/* Tiny Tone */
void TinyTone(unsigned char divisor, unsigned char octave, unsigned long duration)
{
  //TCCR1 = 0x90 | (8-octave); // for 1MHz clock
  TCCR1 = 0x90 | (11-octave); // for 8MHz clock
  OCR1C = divisor-1;         // set the OCR
  delay(duration);
  TCCR1 = 0x90;              // stop the counter
}

// Play a scale
void ply_mus(int fun) {
  unsigned long D=300;
  unsigned long Dw=D*2;
  unsigned long Dh=D/2;
  unsigned long Dq=D/4;
  switch (fun) {
    case 1:  // 赤鼻のトナカイ
      TinyTone(Note_G, 4, D);
      TinyTone(Note_A, 4, Dh);
      TinyTone(Note_G, 4, Dh);
      TinyTone(Note_E, 4, D);
      TinyTone(Note_C, 5, D);
      TinyTone(Note_A, 4, D);
      TinyTone(Note_G, 4, Dw);
      delay(300);
      TinyTone(Note_G, 4, Dh);
      TinyTone(Note_A, 4, Dh);
      TinyTone(Note_G, 4, Dh);
      TinyTone(Note_A, 4, Dh);
      TinyTone(Note_G, 4, D);
      TinyTone(Note_C, 5, D);
      TinyTone(Note_B, 4, Dw);
      break;
    default:
      TinyTone(Note_C, 4, Dq);
      break;
  }
}

Tone発生は http://www.technoblogy.com/show?KVO さんを参考にさせて戴きました。(感謝)

リセットで起動し、真っ赤なお鼻の〜♪を演奏した後RGB-LEDを7色乱数で一定時間表示して終了と言う一本道スケッチです。RGBチカ終了後は再リセットを許可してスリープに入ります。

○やってみて

いまだブレッドボード上で稼働中で、もみの木へ飾り付けられていません。というのもせっかく作ったものをクリスマスだけで終わるのがもったいなくなってしまい、時節によって曲を変えながら使い続けているためです。一年を通して置いておける外観はないがいいだろうと、まだ結論が出ていませんでした。
演奏可能曲は月ごとに増え、赤ハナのトナカイ、ジングルベル〜♪、もーいくつ寝ると〜♪、鬼は外〜♪、春のうららの〜♪と増殖中です。