人の接近を検知しメロディを鳴らす

概要

SP&PIRリーフに搭載された近距離検出用途の赤外線センサIC(AKM AK9754AE)を使って、人が近づいたらメロディが鳴るシステムを作りましょう。

ir_about

使用するリーフ

以下のリーフを使用します

Type Name Q’ty
AZ62 Connector Cover 1
AI02 SP&PIR 1
AZ01 USB 1
AP01 AVR MCU 1
AV01 CR2032 1
CR2032 coin cell battery 1
M2*15mm screw 2

リーフの組み立て

下図のようにリーフを組み立てましょう。

assemble1

ソースコード

Arduino IDEで下記のプログラムを書きましょう。

//=====================================================================
// Leafony Platform sample sketch
//     Platform     : PIR&SP
//     Processor    : ATmega328P (3.3V /8MHz)
//     Application  : PIR with SP Beep
//
//     Leaf configuration
//       (1) AI02 SP&PIR
//       (2) AP01 AVR MCU
//       (3) AZ01 USB
//
//		(c) 2020  Trillion-Node Study Group
//		Released under the MIT license
//		https://opensource.org/licenses/MIT
//
//      Rev.00 2019/08/01  First release
//=====================================================================
//=====================================================================
// difinition
//=====================================================================
#include <stdio.h>
#include <Arduino.h>
#include <Wire.h>
#include "pitches.h"

#define I2C_PIR_ADDR   0x65
#define I2C_SEND_BUF_LENGTH 10
unsigned char i2c_sendBuf[I2C_SEND_BUF_LENGTH];

#define I2C_RECEIVE_BUF_LENGTH 10
unsigned char i2c_receiveBuf[I2C_RECEIVE_BUF_LENGTH];
unsigned char i2c_receiveLenght;

//------------------------------
// buzzer output = 5pin
//------------------------------
#define BUZZER_OUT 5

byte readReg;
double irData;
double tempData;
char buf[120];

volatile int state = 0;

//=====================================================================
// setup
//=====================================================================
void setup() {
  //pinMode(2, INPUT);
  attachInterrupt(0,catchHuman , FALLING );           //人接近検知割り込み

  Wire.begin();
  Serial.begin( 115200 );
  delay(100);

  //人感センサ設定
  i2c_write_byte(I2C_PIR_ADDR, 0x20, 0xFF); //CNTL1  Resrt
  i2c_write_byte(I2C_PIR_ADDR, 0x2A, 0xF2); //CNTL11 人感アルゴリズム有効/割り込み出力有効
  i2c_write_byte(I2C_PIR_ADDR, 0x25, 0x0F); //CNTL6  センサゲイン205%(最大)
  i2c_write_byte(I2C_PIR_ADDR, 0x2B, 0xFF); //CNTL12 Mode=1 start Meas(連続測定モード)
   delay(1000);
}
//=====================================================================
// Main loop
//=====================================================================
void loop() {
  clearI2CReadbuf();
  i2c_read(I2C_PIR_ADDR, 0x04, 6, i2c_receiveBuf);
  sprintf(buf, "REG = %02X , %02X , %02X , %02X , %02X , %02X", i2c_receiveBuf[0], i2c_receiveBuf[1], i2c_receiveBuf[2], i2c_receiveBuf[3], i2c_receiveBuf[4], i2c_receiveBuf[5]);
  Serial.println(buf);
  sprintf(buf, "Human detection = %d", (i2c_receiveBuf[0] & 0x10) >> 4  );
  Serial.println(buf);

  //IRセンサ測定データ
  irData = clacIR();
  Serial.print("IR   = ");
  Serial.print(irData,2);
  Serial.println(" pA");

  //センサ温度
  tempData = clacTemp();
  Serial.print("TSENS = ");
  Serial.print(tempData,2);
  Serial.println(" deg");
  Serial.println("===================================");
  if (state == 1){
    //------------------------------
    // notes in the melody:
    //------------------------------
    int melody[] = {
      NOTE_C5, NOTE_C5, NOTE_G5, NOTE_G5, NOTE_A5, NOTE_A5, NOTE_G5, NOTE_F5, NOTE_F5, NOTE_E5, NOTE_E5,NOTE_D5,NOTE_D5,NOTE_C5
    };

    //------------------------------
    // note durations: 4 = quarter note, 8 = eighth note, etc.:
    //------------------------------
    int noteDurations[] = {
      4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 2
    };
    //----------------------------------------
    // iterate over the notes of the melody:
    //----------------------------------------
    for (int thisNote = 0; thisNote < 14; thisNote++) {
      //----------------------------------------
      // to calculate the note duration, take one second
      // divided by the note type.
      //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
      //----------------------------------------
      int noteDuration = 1000 / noteDurations[thisNote];
      tone(BUZZER_OUT, melody[thisNote], noteDuration);

      //----------------------------------------
      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      //----------------------------------------
      float pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);

      //-----------------------
      // stop the tone playing:
      //-----------------------
      noTone(BUZZER_OUT);
    }
    state = 0;
  }
  delay(1000);
}

//=====================================================================
void catchHuman(){
  state = 1;
  Serial.println("!! Interrupt !!");      //人の接近を検知
}

//=====================================================================
double clacTemp(){
  double ret;
  unsigned short val = (unsigned short)((i2c_receiveBuf[4] << 8) |  i2c_receiveBuf[3]);
  if ( (val & 0x8000) == 0x8000)  {
     val = ~val + 1;
     ret = (double)((val) *   0.0019837 ) * -1;
  }
  else  {
    ret = (double)val * 0.0019837;
  }
  return ret + 25;
}

//=====================================================================
double clacIR(){
  double ret;
  unsigned short val = (unsigned short)((i2c_receiveBuf[2] << 8) |  i2c_receiveBuf[1]);
  if ( (val & 0x8000) == 0x8000)  {
    val = ~val + 1;
    ret = (double)(val *   0.4578 ) * -1;
  }
  else  {
    ret = (double)(val *  0.4578 );
  }
  return ret;
}
/**********************************************
* I2C スレーブデバイスに1バイト書き込む
**********************************************/
void i2c_write_byte(int device_address, int reg_address, int write_data){
  Wire.beginTransmission(device_address);
  Wire.write(reg_address);
  Wire.write(write_data);
  Wire.endTransmission();
}
/**********************************************
* I2C スレーブデバイスから1バイト読み込む
**********************************************/
unsigned char i2c_read_byte(int device_address, int reg_address){

  int read_data = 0;

  Wire.beginTransmission(device_address);
  Wire.write(reg_address);
  Wire.endTransmission(false);

  Wire.requestFrom(device_address, 1);
  read_data = Wire.read();

  return read_data;
}
/**********************************************
* I2C スレーブデバイスに複数バイト書き込む
**********************************************/
void i2c_write(int device_address, int reg_address, int lengrh, unsigned char* write_byte){

  Wire.beginTransmission(device_address);
  Wire.write(reg_address);
  for (int i = 0; i < lengrh; i++){
    Wire.write(write_byte[i]);
  }
  Wire.endTransmission();
}
/**********************************************
* I2C スレーブデバイスから複数バイト読み込む
**********************************************/
void i2c_read(int device_address, int reg_address, int lengrh, unsigned char* read_byte){

  Wire.beginTransmission(device_address);
  Wire.write(reg_address);
  Wire.endTransmission(false);

  Wire.requestFrom(device_address, lengrh);
  for (int i = 0; i < lengrh; i++){
    read_byte[i] = Wire.read();
  }
}
/**********************************************
* I2C 受信バッファクリア
**********************************************/
void clearI2CReadbuf(){
  memcpy(i2c_receiveBuf, 0x00, I2C_RECEIVE_BUF_LENGTH);
}

PIR_Melody_test.ino

実行結果

人が近づくとメロディが鳴ります。


最終更新 September 14, 2020