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

2017年3月14日火曜日

MatrixLEDドライバHT16K33を使ってみる

お久しぶりです.
最近大学が忙しく,趣味の電子工作をする時間がめっきり減っています.
それでも日々少しずつ前進したいところです.

さて,今回はMatrixLEDドライバ,HT16K33を使ってみました.
このドライバはI2C接続で16×16のマトリックスLEDを2つ制御することができます.
秋月でドライバモジュールとカッコつけて青色マトリックスLEDを購入し,
ユニバーサル基盤で回路を作成しました.



配線は,A0-A15をLEDのアノード(Col),C-0-C7をLEDのカソード(Row)
に接続し,電源,GND,SDA,SCLをそれぞれ引き出します.
回路は単純ですが,数が多いため内部はカオスです笑

ちょっと顔らしい動作をさせてみたいと思い,標準・喜ぶ・怒る・
悲しむ・疑問・驚き・寝るの表情を作ってみました.



アナログチックでちょっとかわいいですね.

今回のモジュールとサーボ,カメラを用いて「I2C通信で動かす
顔モジュール」を作って,Raspberry pi等から動かそうと計画しています.
ソフトウェア等はまたある程度出来上がってから紹介したいと思います.