2017年3月18日土曜日

I2C通信で動かす顔モジュール 一度形にしてみる

どうも
前回MatrixLEDドライバ,HT16K33を使用し,いくつかの表情を作成してみました.
今回はサーボ,サーボマウント,USBカメラを使用し一旦,顔として構築してみる
ことにしました.

使用したもの一覧
LOGICOOL ウェブカム HD画質 120万画素 C270
SG90用カメラマウント
マイクロサーボ SG90
マトリックスLEDドライバHT16K33
青色マトリックスLED8*8

完成したのがこれ





テープ等を使い,適当にマウントに取り付けました.
マウントは作りが甘かったため,すぐに首が取れてしまいます.
このあたりは自作する必要があるのでしょうか.
制御用のマイコンは予定通りArduinoを使用しました.
今回はボードを使用しましたが,ゆくゆくは素子単体で動作させます.

とりあえず,喜ぶ・怒る・悲しむの動作を作成し,PCからのコマンドで
動作するプログラムを作成しました.ほんちゃんのI2Cを通信に使用するため,
LEDドライバとの通信はソフトウェアI2Cライブラリを使用.
サーボは標準ライブラリのままでは速すぎるため自作関数でゆっくり
動くようにしています.ついでに使わないときは電源を切るようにしました.

メモ代わりにスケッチを載せます.
このほかにface.hにビットパターンを書き込んでいます

cam_mount.ino

//====ソフトウェアI2C関連マクロ====
#define SCL_PIN  2                 // SCLは2番ピンとする
#define SCL_PORT PORTD
#define SDA_PIN  3                 // SDAは3番ピンとする
#define SDA_PORT PORTD
#define I2C_TIMEOUT 100
#define I2C_FASTMODE 1
//=================================

#include <SoftWire.h>   //ソフトウェアI2C
#include<Servo.h>       //サーボ
#include"face.h"

#define HT16K33 (0x70)   //LEDドライバーHT16K33 アドレス

Servo servo_pan;    //サーボ宣言パン軸
Servo servo_tilt;   //サーボ宣言チルト軸
byte recv_data[256];

const char blink_Hz = 0;
const char on_off  = 1;
const char brightness = 1;

SoftWire Wire = SoftWire();   //ソフトI2C

//===============サーボ角度制御================
void Servo_move(int ang_pan, int ang_tilt, int wait_ms){
    int pan_palse = map(ang_pan, 0, 180, 800, 2300);
    int pan_now = servo_pan.readMicroseconds();
    int tilt_palse = map(ang_tilt, 0, 180, 800, 2300);
    int tilt_now = servo_tilt.readMicroseconds();
    int flg_pan=1,flg_tilt=1;
 
    while(flg_pan || flg_tilt){
      if(pan_palse > pan_now) pan_now++;
      else if(pan_palse < pan_now) pan_now--;
      else flg_pan = 0;
   
      if(tilt_palse > tilt_now) tilt_now++;
      else if(tilt_palse < tilt_now) tilt_now--;
      else flg_tilt = 0;

      servo_pan.writeMicroseconds(pan_now);
      servo_tilt.writeMicroseconds(tilt_now);
      delay(wait_ms);
    }
 
  }

//===============サーボセット================
void Servo_set(int deg_pan,int deg_tilt){
  servo_pan.attach(8, 800, 2300);
  servo_tilt.attach(9, 800, 2300);
  Servo_move( deg_pan, deg_tilt, 2);
  servo_pan.detach();
  servo_tilt.detach();
  }

//===============LEDドライバ初期化================
void matrixLED_init(void){

  //HT16K33システムオシレータON
  Wire.beginTransmission(HT16K33);
  Wire.write(0x20 | 1);
  Wire.endTransmission();

  //blink_Hz=0 点滅off, 1は2Hz, 2は1Hz, 3は0.5Hz, on_off=0は消灯、1は点灯 
  Wire.beginTransmission(HT16K33);
  Wire.write(0x80 | (blink_Hz<<1) | on_off);
  Wire.endTransmission();

  // brightness= 0~15
  Wire.beginTransmission(HT16K33);
  Wire.write(0xE0 | brightness);
  Wire.endTransmission();

  //マトリックスLED初期化
  Wire.beginTransmission(HT16K33);
  Wire.write(0x00);
  for(int i=0;i<8;i++){
    Wire.write(B00000000);                   //1つ目の8x8LED初期化
    Wire.write(B00000000);                   //2つ目の8x8LED初期化
  }
  Wire.endTransmission();
}

//================マトリックスLED出力================
void LED_Driver_DisplayOutput(byte LD_addrs, byte* DotB, byte* DotB2)
{
  int i,j;
        Wire.beginTransmission(LD_addrs);
        Wire.write(B00000000); //これは必要
        for(i = 0; i<8; i++){
          Wire.write(DotB[i]);
          Wire.write(DotB2[7-i]);
        }
        Wire.endTransmission();
}

//================action happy================
void action_happy(void){
  LED_Driver_DisplayOutput(HT16K33, dots_happy, dots_happy);
  Servo_set(90, 90);
  delay(250);
  Servo_set(110, 90);
  delay(250);
  Servo_set(90, 90);
  delay(250);
  Servo_set(110, 90);
  delay(250);
  Servo_set(90, 90);
}

//================action angry================
void action_angry(void){
 LED_Driver_DisplayOutput(HT16K33, dots_angry, dots_angry);
 Servo_set(70, 110);
 delay(250);
 Servo_set(90, 90);
}

//================action sad================
void action_sad(void){
 LED_Driver_DisplayOutput(HT16K33, dots_sad, dots_sad);
 Servo_set(110, 90);
 Servo_set(110, 70);
 delay(250);
 Servo_set(110, 110);
 delay(250);
 Servo_set(90, 90);
}

void setup()
{
  Serial.begin(115200);
  Wire.begin();
  matrixLED_init();
  LED_Driver_DisplayOutput(HT16K33,dots_usual, dots_usual);
  Servo_set(90,90);
  delay(1000);
  Serial.println("arduino_i2c_face");
  Serial.println("please_input_command:");
}

void loop()
{
   byte recv_char = Serial.read();
   switch(recv_char){
    case 'h':action_happy();
             Serial.println("happy!");
             break;

    case 'a':action_angry();
             Serial.println("angry!");
             break;

    case 's'://LED_Driver_DisplayOutput(HT16K33, dots_sad, dots_sad);
             action_sad();
             Serial.println("sad!");
             break;
           
    default:break;
   }
   LED_Driver_DisplayOutput(HT16K33, dots_usual, dots_usual);
}



動いている動画



形にはなっていますが,結構ガタガタした動作です.
仮組みしてわかったことは,ハードはもっとかっちり組んだほうが
いいということです.
Raspberry piなどと接続するのはまだまだ先になりそうです.


参考にさせていただいたサイト.
http://www.geocities.jp/zattouka/GarageHouse/micon/I2C/I2C_5.htm
http://tetsuakibaba.jp/index.php?page=workshop/ServoBasis/main
https://www.mgo-tec.com/blog-entry-ada-ledmatrix01.html

0 件のコメント:

コメントを投稿