マイクロサーボ(SG92R)を使ってみる

マイクロサーボを試してみました。サーボが動いたときに電源がドロップしてしまうので、VCCは5Vを供給し、サーボの電源も5Vが供給されるように配線しています。マイコン自体は3.3Vを使用していますので、1.7Vぐらいドロップしてしまっても大丈夫です。

サーボへの制御信号は3.3Vでも問題無いようです。このテストでは10kのボリュームにあわせてサーボが連動するようにしています。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

マイクロサーボ Tower Pro Pte Ltd SG92R
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(3.3V仕様)

接続

接続は配線図と写真を参考にして下さい。

ちょっと解説

ライブラリを作るまでも無いと思ったのでメインループに下記のソースを記載しているところがメインの制御ソースです。ちなみにPWMも使っていません。PWMを使うとサーボの接続数が制限されると思うので使ったこと無いです。 counttimer_servo_oneという関数は20msec単位で0以外が割り当てされ、20msec単位でサーボの処理をしています。 0.5msec+アナログ値の時間分を1とし、終わったら0にする。それを20msec単位でループしています。同じ要領で複数用意すればいくつかのサーボが同時に制御できると思います。 また、サーボの制御でdelayを多用してしまうのでシリアルポートはusart1では無く、シリアル信号の割り込みによってサーボへの信号のタイミングが変わってしまうため、usart2のほうがいいと思います。

    if(counttimer_servo_one != 0){
        counttimer_servo_one = 0;
    
        servo_angle = analog_value * 0.176;
        output_bit(PIN_E0,1);
        delay_us(500);
        for(tmp1=0;tmp1<servo_angle;tmp1++){
            delay_us(9);delay_cycles(2);//10.5us
        }
        output_bit(PIN_E0,0);
    }    
    
プロジェクトファイルも含めたサンプル 16f1947_servo.zip
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

電磁石と電磁ソレノイドを使ってみる

4点出力モジュールと組み合わせて電磁石(ZYE1-P20/15)と電磁ソレノイド(ECC412)を動かしてみました。 コイル系の部品は供給後に逆起電力が働き、電磁石のほうでは1.2V4m、ソレノイドのほうではSec1.2V24mSecほどありました。大丈夫と思いますが、気になる人はダイオードを入れたほうが良いでしょう。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

電磁石 中国製 ZYE1-P20/15
電磁ソレノイド(プッシュタイプ) 中国製 PS-12B
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(5V仕様)

接続

接続は下記のとおりです。付属していた引出し線を加工してQIコネクタをつけています。

ちょっと解説

ソフトはREポートを全てLOWのフリッカーで点滅させているだけです。これと言って特殊なことは何もしていないので特に説明もありません。

プロジェクトファイルも含めたサンプル 16f1947_ZYE1-P20_ECC412
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

地磁気センサー(HMC5883L)のテスト

I2C接続地磁気センサーが秋月電子さんから販売されていたので試してみました。コンパスセンサーや方位センサーとも言われ、方位を取得する際に用いられます。正確な方位を取得するには物理的なコンパスと並べてキャリブレーションした方がいいみたいです。 3.3V電源という部分に注意が必要です。

使用機器

 

製品製作の流れ

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

地磁気センサー HMC5883L使用 デジタルコンパスモジュール
3軸地磁気センサ DIP化キット

シリアル変換 USB-USART変換基盤_ZT-FTDI03
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(3.3V仕様)

接続

接続は下記のとおりです。

ちょっと解説

使い方としてはhmc5883l_init()をスタート時に実行し、hmc5883l_getval()を定期的に実行するだけで、各変数に値が書き込まれます。

    int hmc5883l_addr_r = 0b00111101;//0x3d
    int hmc5883l_addr_w = 0b00111100;//0x3c
    long hmc5883l_x = 0;//X軸値
    long hmc5883l_y = 0;//Y軸値
    long hmc5883l_z = 0;//Z軸値
    
    void hmc5883l_write(int reg, int val){
        i2c_start();
        i2c_write(hmc5883l_addr_w);//書込みアドレス送信
        i2c_write(reg);//
        i2c_write(val);//
        i2c_stop();
    }
    
    int hmc5883l_read(int reg){
    
        int ans = 0;
    
        i2c_start();
        i2c_write(hmc5883l_addr_w);//書込みアドレス送信
        i2c_write(reg);//
        i2c_start();
        i2c_write(hmc5883l_addr_r);//読み込みアドレス送信
        ans = i2c_read(0);
        i2c_stop();
    
        return ans;
    }
    
    //コンパスモジュールの初期化
    void hmc5883l_init(){
        hmc5883l_write(0x00,0x70);
        hmc5883l_write(0x01,0xA0);
        hmc5883l_write(0x02,0x00);
    }
    
    void hmc5883l_getval(){
        hmc5883l_x = hmc5883l_read(0x03) << 8;hmc5883l_x = hmc5883l_x + hmc5883l_read(0x04);
        hmc5883l_y = hmc5883l_read(0x05) << 8;hmc5883l_y = hmc5883l_y + hmc5883l_read(0x06);
        hmc5883l_z = hmc5883l_read(0x07) << 8;hmc5883l_z = hmc5883l_z + hmc5883l_read(0x08);
    }
プロジェクトファイルも含めたサンプル 16f1947_hmc5883l.zip
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

3軸ジャイロセンサー(L3GD20)のテスト

XYZの角速度を取得できるジャイロセンサーが秋月電子さんから販売されていたので試してみました。I2CとSPI接続に対応しています。電源は3.3Vで5Vに対応していない点が要注意です。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

ジャイロセンサー STマイクロL3GD20使用 3軸ジャイロセンサーモジュール
AE-L3GD20

シリアル変換 USB-USART変換基盤_ZT-FTDI03
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(3.3V仕様)

接続は下記のとおりです。

ちょっと解説

    long l3gd20_x = 0;//X軸値
    long l3gd20_y = 0;//Y軸値
    long l3gd20_z = 0;//Z軸値
    //アドレス設定
    int l3gd20_addr_r = 0b11010101;//0xd5
    int l3gd20_addr_w = 0b11010100;//0xd4
    
    void l3gd20_write(int reg, int val){
        i2c_start();
        i2c_write(l3gd20_addr_w);//書込みアドレス送信
        i2c_write(reg);//
        i2c_write(val);//
        i2c_stop();
    }
    
    int l3gd20_read(int reg){
        int ans = 0;
        i2c_start();
        i2c_write(l3gd20_addr_w);//書き込みアドレス送信
        i2c_write(reg);//
        i2c_start();
        i2c_write(l3gd20_addr_r);//読み込みアドレス送信
        ans = i2c_read(0);
        i2c_stop();
    
        return ans;
    }
    
    int l3gd20_init(){
        //XYZのセンサーを有効にしてパワーダウンをOFFに設定
        l3gd20_write(0x20, 0b00001111);//REG1
        //l3gd20_write(0x21, 0b00001000);//REG2
        //l3gd20_write(0x22, 0b00001000);//REG3
        //l3gd20_write(0x23, 0b10110000);//REG4
        //l3gd20_write(0x24, 0b00000000);//REG5
    }
    
    void l3gd20_getval(){
        l3gd20_x = l3gd20_read(0x29) << 8;l3gd20_x = l3gd20_x + l3gd20_read(0x28);
        l3gd20_y = l3gd20_read(0x2b) << 8;l3gd20_y = l3gd20_y + l3gd20_read(0x2a);
        l3gd20_z = l3gd20_read(0x2d) << 8;l3gd20_z = l3gd20_z + l3gd20_read(0x2c);
    }

プロジェクトファイルも含めたサンプル 16f1947_l3gd20.zip
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

測距モジュール(GP2Y0A02YK)を使ってみる

非接触で距離が測定できるモジュールを使ってみます。赤外線とPSD?を使用しての計測だそうですが、ばらつきも多く、だいたいの計測では使用できそうです。また、反射板も不要で設置は手軽です。正確性を求めるならレーザーをお勧めします。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

測距モジュール シャープ GP2Y0A02YK
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(5V仕様)

接続

接続は下記のとおりです。付属していたハーネスを加工してQIコネクタをつけています。

※付属のハーネスを使用していますが、5Vが黒になっている事にご注意ください。

ちょっと解説

取得値に単純な計算をしているだけですのでだいたいの値となります。実際、取得値は放物線の様ですのでもう少し複雑な計算式が必要と思います。が、値のばらつきも多いため、労力掛けて作っても意味がないと思ったので下記の様な単純な計算式だけでとりあえず使用しています。

    length_mm = (3000-analog_value)*0.4;
    if(length_mm >= 1500){
        length_mm = 1500;
    }else if(length_mm <= 200){
        length_mm = 200;
    }
        

プロジェクトファイルも含めたサンプル 16f1947_GP2Y0A02YK0F
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

高精度温度計(LM61)を使ってみる

2.7~10Vの電源を供給するだけで温度を電圧出力してくれる便利な温度計を試してみました。0.6Vのオフセット電圧があるので0度の時は0.6Vが出力されます。同じく有名な温度センサーを言うとLM35が有りますが、あちらはマイナス温度が検出できない、3.3V回路で使えないなどのデメリットがあります。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

高精度IC温度センサー Texas Instruments LM61CIZ
有機ELキャラクターディスプレイモジュール Sunlike Display Tech. Corp. SO2002AWYB-UC-WB-U
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(5V仕様)

接続

接続は下記のとおりです。

ちょっと解説

取得値は大きくて1.6Vという事で、アナログのリファレンス電圧は2048vとしています。オシロで見てみると1mSec毎にp-p値40mV以上のノイズが出ています。気になる方はコンデンサを入れたほうが良いかもしれません。

プロジェクトファイルも含めたサンプル 6f1947_lm61
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

AM2321による温度・湿度計測

マイコンで温度の計測例はよくあるネタだが湿度の計測はあまり見かけない。というわけでサンプルを作ってみたので紹介したいと思います。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

温度センサーモジュール Aosong Guangzhou Electronics Co., Ltd. AM2321
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(3.3V仕様)
USB-USART変換基盤 ZEATEC co.,ltd. ZT-FTDI03

接続

接続に関してはいたって簡単。CPUボードにあらかじめ必要回路が実装されているため4本の足を伸ばして接続するだけ。今回はデュポン(QIコネクタ)コネクタを使用して配線した。センサーの足が1.27ピッチなので基板実装でなければ少々難しい。 センサーのほうは記入する都合で不規則に並んでいるので要注意です。

プログラミング

コンパイラはCCS社のPCM Ver.4.132を使用しました。センサー用のライブラリを作りましたのでインクルードすることですぐに使用できます。注意点としてはセンサーがスリープからの復帰や応答待ちなどがあるためハードウェアI2Cを使用する事と一定間隔で読み込む事ぐらいです。ライブラリファイルと内容は以下のとおり。メインソースに#include “am2321.c”と記述してインクルードしてください。

AM2321のリファレンス AM2321_e.pdf
AM2321用ライブラリ am2321.zip
プロジェクトファイルも含めたサンプル zt-16f194701_am2321.zip
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

/*****************************************************************************************
温度・湿度センサー(AM2321)用ライブラリ 2015/2/10作成

□提供元
ZEATEC co.,ltd. 

□ご利用について
転載・無断使用可です。このライブラリを使用した上での不具合等に関しては、いかなる内容におい
ても一切の責任を追わないものとします。

□使用方法
read_am2321()を1.5msec以上のタイマーに入れ、2回に1回の割合でデータを取得する。
I2Cはハードウェア制御を推奨とし、宣言例は下記のとおり。

#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,SLOW,FORCE_HW)//FAST=400kbps SLOW=100kbps
ピンアサインはPIC16F1947で使用した場合で、スピードは100kbpsとする。400kbpsは使用不可。

温度はtemperature、湿度はhumidityに10倍の値で格納される。表記する際には1/10で表記すること。

*****************************************************************************************/
int i2c_buff_am2321[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
int am2321_status = 0;//0.待機 1.機能コード送信 2.応答値読み込み
long temperature = 0;//温度
long humidity = 0;//湿度

void read_am2321();

//センサーからデータ読み込み
void read_am2321(){
    if(am2321_status == 1){
        am2321_status = 2;

        //スリープから起こす
        i2c_start();
        i2c_write(0xb8);
        //delay_us(800);//ハードウェアI2Cの場合は不要
        i2c_stop();

        //温度と湿度を読み込みコマンド送信
        i2c_start();
        i2c_write(0xb8);//書込みアドレス送信
        i2c_write(0x03);//機能コード送信
        i2c_write(0x00);//読み込みレジスタの先頭アドレス
        i2c_write(0x04);//読み込みレジスタ数
        i2c_stop();
    }else if(am2321_status == 2){
        am2321_status = 1;
        //機能コード送信されてから1.5msec以上経過していれば読み込み

        //読み込み開始
        i2c_start();
        i2c_write(0xb9);//読み込みアドレス送信
        //delay_us(30);//ハードウェアI2Cの場合は不要
        i2c_buff_am2321[0] = i2c_read(); //機能コードの返し
        i2c_buff_am2321[1] = i2c_read(); //返信してくるレジスタ数

        i2c_buff_am2321[2] = i2c_read(); //湿度の上位バイト
        i2c_buff_am2321[3] = i2c_read(); //湿度の下位バイト
        humidity = i2c_buff_am2321[2] << 8;//湿度
        humidity = humidity + i2c_buff_am2321[3];//湿度

        i2c_buff_am2321[4] = i2c_read(); //温度の上位バイト
        i2c_buff_am2321[5] = i2c_read(); //温度の下位バイト
        temperature = i2c_buff_am2321[4] << 8;//温度
        temperature = temperature + i2c_buff_am2321[5];//温度

        i2c_buff_am2321[6] = i2c_read(); //巡回冗長符号 下位バイト
        i2c_buff_am2321[7] = i2c_read(0); //巡回冗長符号 上位バイト
        i2c_stop();
    }else{
        am2321_status = 1;
    }
}

動作テスト

USB-USARTで接続して値を表示したところ問題なく取得できています。

MP3プレイヤー(KT403A)を使ってみる

音源として使えるプレイヤーはあってもファイル指定が出来なかったり再生終了が取得できなかったりシリアル制御できなかったりといまいちな製品が多い中、安価で多機能、しかもワンチップのプレイヤーを入手しました。チップは中国製のKT403Aでなかなかの優れものです。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

MP3プレイヤー Seeed Studio Grove – MP3 v2.0
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(5V仕様)

接続

接続は下記のとおりです。付属していたハーネスを加工してQIコネクタをつけています。

ちょっと解説

ライブラリを作るまでも無いと思ったので関数をちょっと追加しました。使用例の様にkt403_play()を記載するだけです。同じ要領でコマンド0x06を変更することでボリューム調整なども可能です。 シリアルの設定はMP3プレイヤーに合わせ、9600bpsにしています。また、USART2のほうを使用していますので、お間違いなく。

使用例
再生後3秒後に停止しています。

    kt403_play(0x1);//0001.mp3を再生
    delay_ms(1000);
    delay_ms(1000);
    delay_ms(1000);
    kt403_play(0x0);//停止

再生停止関数
よく使うと思われる再生コマンドと停止コマンドしか用意していません。また、再生終了時のフェードバックコマンドもコメントとして記載していますのでシリアルの受信を監視しておけば再生完了を取得できます。

  
    //KT403の制御
    void kt403_play(int play_no){
    
        //再生完了後のフィードバック
        //7E FF 83 4F 40 20 90 B8 EF
        
        if(play_no==0){
        //停止
        fprintf(c2,"%c%c%c%c%c%c%c%c",0x7E,0xFF,0x06,0x11,0x00,0x00,00,0xEF);
        }else{
        //再生
        fprintf(c2,"%c%c%c%c%c%c%c%c",0x7E,0xFF,0x06,0x03,0x00,0x00,play_no,0xEF);
        }
    }

プロジェクトファイルも含めたサンプル 16f1947_KT403A.zip
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132

RTCモジュール(RX6110SA)の時間取得

マイコンボードZT-PIC16F194701にはあらかじめRTCが搭載している物もあり、別途時計チップを試す必要も無いかもしれませんが、RX6110SAはバッテリー接続用のピンもあり、時計を保持させる面に関しては優れています。 そこであえて時計無しのマイコンボードを使用し、時間を取得します。

今回の試作ではバッテリーを付けていません。バッテリーを接続する場合はマニュアルのP.3をご確認ください。 接続に関してはライブラリの説明文をご確認ください。

OLYMPUS DIGITAL CAMERA

UARTポートに接続したシリアルからコマンドを入力することで時間取得が確認できるようにしています。

RTCについてちょっと一言・・・
元々マイコンボードに乗せているRTC-8564JEは使い慣れているという点から採用しました。しかし、バッテリー用端子が無く、電気二重層コンデンサでの時計の保持について少々いまいちな気もしてました。 そこで時折、他にいいチップは無いかと思い、条件としては時計用クロックは内蔵で時間を刻む事に対してチップ以外の部品が必要でない事、I2C接続な事で探していました。気になる毎に探していましたが、最近バッテリー用端子付きがあることに気が付き、今回試してみる事に至りました。RTCのICは色々ありますがクロック内蔵というのはなかなか無いと思います。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

I2CリアルタイムクロックIC Epson RX6110SA カタログ マニュアル
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(5V仕様)
プロジェクトファイルも含めたサンプル zt-16f194701_rx6110sa.zip
接続ハーネスの図面 Harness_RX6110SA.zip Harness_RX6110SA.pdf
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132
※VBAT端子からコンデンサへ電源を供給する場合は80mAまでです。
(セイコーエプソン株式会社TD営業グループより回答)

使用機器

RX6110SA用ライブラリ「rtc_rx6110sa.c」の中身です。使用方法等、も記載しています。

///////////////////////////////////////////////////////////////////
//  リアルタイムクロックライブラリ
//■対応RTC IC:Seiko Epson Corp. RX6110SA
//■使用デバイス番号:書込みモード=0x64,読込みモード=0x65
//■通信方式:I2C
//■通信速度:100kHz or 400kHz
//■製作:2016年12月31日 ZEATEC co.,ltd. S.Hirai
///////////////////////////////////////////////////////////////////
//
//■事前準備
//ヘッダー部分で先にI2Cと、このファイルの読み込みが必要です。
//#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,SLOW,FORCE_HW)//FAST=400kbps SLOW=100kbps
//#include "rtc_rx6110sa.c"
//
//■使い方
//rtc_date_setに12桁または13桁の数字を割り当てることで日時を更新します。
//12桁入力の場合:param1 = 160323101840(2016年03月23日10時18分40秒)
//13桁入力の場合:param1 = 1603233101840(2016年03月23日水曜日10時18分40秒)
//rtc_date_set(param1);
//曜日は数字に置き換えると下記のようになります。
//0=日曜日 1=月曜日 2=火曜日 3=水曜日 4=木曜日 5=金曜日 6=土曜日
//時刻を読み込むには、rtc_date_read()を実行するだけで各変数(sec,minなど)の値が更新される。
//fprintf(c1," %02x:%02x:%02x\r\n",hour,min,sec);とする事で時間が表示できます。
//各値を10進数に変換したい場合は下記の計算例を元に変換してください。
//sec = ((sec >> 4)*10)+ (sec & 0x0f);
//
//■接続
//1.CLK/SCL →SCL
//2.DI/SDA  →SDA
//3.DO/FOUT →クロック出力
//4.CE/FOE  →GND
//5.SPISEL  →GND
//6.GND  →GND
//7./IRQ2   →タイマー出力②
//8.N.C.    →空き
//9.Vbat    →電池のプラス
//10.Vdd    →VCC
//11.Vio    →VCC
//12./IRQ1  →タイマー出力②
//13.N.C.   →空き
//14.N.C.   →空き

int year,month,week,day,hour,min,sec;// 現時刻
char c_week[] = "xxx";
int rtc_flag = 0;

void rtc_init(){
    delay_ms(40);//ウェイクアップウェイト
    //初期化設定
    i2c_start();
    i2c_write(0x64); // デバイス番号(書き込みモード)
    i2c_write(0x1e); // 
    i2c_start();
    i2c_write(0x65); // デバイス番号(読込みモード)
    rtc_flag = i2c_read(0); // 
    i2c_stop();
    if(bit_test(rtc_flag,1) == 1){
        i2c_start();
        i2c_write(0x64); // デバイス番号(書き込みモード)
        i2c_write(0x1d); // Extention Register
        i2c_write(0b01000010); // 設定値(動作設定前にTEビットをゼロクリア)
        
        i2c_write(0x1b); // Timer Counter0
        i2c_write(0b00000001); // 設定値
        i2c_write(0x1c); // Timer Counter1
        i2c_write(0b00000000); // 設定値
        i2c_write(0x1f); // Control Register
        i2c_write(0b00111000); // 設定値      
        i2c_write(0x31); // Reserved
        i2c_write(0b00011100); // 設定値
        i2c_write(0x32); // IRQ Control
        i2c_write(0b00010100); // 設定値

        i2c_write(0x1d); // Extention Register
        i2c_write(0b01010010); // 設定値(動作設定後TEビットをセット)
        i2c_stop();
    }
}

//日時設定
int rtc_date_set(int *data) {

    int tmp_update = 0;
    int tmp_week = 0;
    int ans = 0;
    //fprintf(c1, "%02x\r\n", strlen(data));

    //RTC初期化(RX6110SA)
    rtc_init();

    if(strlen(data) == 13){
        //パラメータを分割して書き込み
        //設定例:time,160323101840(2016年03月23日10時18分40秒)
        //曜日指定なし
        year = ((data[0] - 0x30)*16) + (data[1] - 0x30);
        month = ((data[2] - 0x30)*16) + (data[3] - 0x30);
        day = ((data[4] - 0x30)*16) + (data[5] - 0x30);
        hour = ((data[6] - 0x30)*16) + (data[7] - 0x30);
        min = ((data[8] - 0x30)*16) + (data[9] - 0x30);
        sec = ((data[10] - 0x30)*16) + (data[11] - 0x30);

        tmp_update = 1;
        ans = 1;
        //fprintf(c1,"time set ok.\r\n");
    }else if(strlen(data) == 14){
        //パラメータを分割して書き込み
        //設定例:time,1603234101840(2016年03月23日水曜日10時18分40秒)
        //曜日指定あり
        year = ((data[0] - 0x30)*16) + (data[1] - 0x30);
        month = ((data[2] - 0x30)*16) + (data[3] - 0x30);
        day = ((data[4] - 0x30)*16) + (data[5] - 0x30);
        week = data[6] - 0x30;
        hour = ((data[7] - 0x30)*16) + (data[8] - 0x30);
        min = ((data[9] - 0x30)*16) + (data[10] - 0x30);
        sec = ((data[11] - 0x30)*16) + (data[12] - 0x30);

        tmp_update = 1;
        ans = 1;
        //fprintf(c1,"time set ok.\r\n");
    }else{
        ans = 2;
        //fprintf(c1,"Parameter error.\r\n");
    }

    if (tmp_update == 1) {
        //先に曜日のデータを変換
        if (week == 0x0) {
            tmp_week = 0x1;
        }else if (week == 0x1) {
            tmp_week = 0x2;
        }else if (week == 0x2) {
            tmp_week = 0x4;
        }else if (week == 0x3) {
            tmp_week = 0x8;
        }else if (week == 0x4) {
            tmp_week = 0x10;
        }else if (week == 0x5) {
            tmp_week = 0x20;
        }else if (week == 0x6) {
            tmp_week = 0x40;
        }

        i2c_start();
        i2c_write(0x64); // デバイス番号(書き込みモード)
        i2c_write(0x10); // 秒のアドレス

        i2c_write(sec);  // 秒の値 0-59
        i2c_write(min);  // 分の値 0-59
        i2c_write(hour); // 時の値 0-23
        i2c_write(tmp_week); // 曜の値 日月火水木金土 week
        i2c_write(day);  // 日の値 1-31
        i2c_write(month);// 月の値 (C:MSB)1-12   Cは1のとき21世紀
        i2c_write(year); // 年の値 00-99

        i2c_stop();
    }

    return ans;
}

//日時の読み出し
void rtc_date_read() {
    int tmp_week = 0;

    i2c_start();
    i2c_write(0x64); // デバイス番号(書き込みモード)
    i2c_write(0x10); // 秒のアドレス(読み出し先頭アドレス)
    i2c_start();
    i2c_write(0x65); // デバイス番号(読込みモード)

    sec = i2c_read(1); // 秒の値
    min = i2c_read(1); // 分の値
    hour = i2c_read(1); // 時の値
    tmp_week = i2c_read(1); // 曜の値
    day = i2c_read(1); // 日の値
    month = i2c_read(1); // 月の値
    year = i2c_read(0); // 年の値
    i2c_stop();
    bit_clear(month, 7);
    bit_clear(month, 6);
    bit_clear(month, 5);
    bit_clear(day, 7);
    bit_clear(day, 6);
    bit_clear(hour, 7);
    bit_clear(hour, 6);
    bit_clear(min, 7);
    bit_clear(sec, 7);
    if (tmp_week == 0x01) {
        week = 0; c_week = "SUN";
    }else if (tmp_week == 0x02) {
        week = 1; c_week = "MON";
    }else if (tmp_week == 0x04) {
        week = 2; c_week = "TUE";
    }else if (tmp_week == 0x08) {
        week = 3; c_week = "WED";
    }else if (tmp_week == 0x10) {
        week = 4; c_week = "THU";
    }else if (tmp_week == 0x20) {
        week = 5; c_week = "FRI";
    }else if (tmp_week == 0x40) {
        week = 6; c_week = "SAT";
    }else {
        week = 7; c_week = "ERR";
    }
}

RTCモジュール(DS1307)の時間取得

OLYMPUS DIGITAL CAMERA

マイコンボードZT-PIC16F194701にはあらかじめRTCが搭載している物もあり、別途時計チップを試す必要も無いかもしれませんが、DS1307はバッテリー接続用のピンもあり、時計を保持させる面に関しては優れています。 そこであえて時計無しのマイコンボードを使用し、時間をLCDに表示させます。尚、LCD表示に関しては別途記事を参照願います。

RTCとLCDを接続するためにI2Cのコネクタを二つに分け、並列に接続しています。RTCのBATコネクタをアナログ値として取得したいところですが、そのまま接続するとバッテリーの電力をマイコンが消費してしまい、時計の保持が出来ないため、何らかの回路が無いと無理と思われます。
※注意:RTCモジュール側でI2Cのプルアップ抵抗があるため、マイコンボード側のプルアップは外す必要があります。基板上の赤いマークのある2.2kチップ抵抗です。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。

I2Cリアルタイムクロックモジュール SainSmart SKU-20-019-108*WB
マイコンボード(PIC16F1947搭載) ZEATEC co.,ltd. ZT-PIC16F194701(5V仕様)

プロジェクトファイルも含めたサンプル zt-16f194701_ds1307.zip
開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132
配線図:DS1307_wiring.zip

ちょっと解説・・・
rtc_date_read()を実行するだけで各変数に値が取得され、使うことが出来ます。

    so1602awxb_cmd(0x80);
    rtc_date_read();
    printf(so1602awxb_puts,"ZEATEC 20%02x/%02x/%02x  %c",year,month,day,life_char[life_index]);
    //2行目表示
    so1602awxb_cmd(0xa0);
    if(week == 1){
        printf(so1602awxb_puts,"Sunday   ");//SUN
    }else if(week == 2){
        printf(so1602awxb_puts,"Monday   ");//MON
    }else if(week == 3){
        printf(so1602awxb_puts,"Tuesday  ");//TUE
    }else if(week == 4){
        printf(so1602awxb_puts,"Wednesday");//WED
    }else if(week == 5){
        printf(so1602awxb_puts,"Thursday ");//THU
    }else if(week == 6){
        printf(so1602awxb_puts,"Friday   ");//FRI
    }else if(week == 7){
        printf(so1602awxb_puts,"Saturday ");//SAT
    }else{
        printf(so1602awxb_puts,"Error    ");//
    }
    printf(so1602awxb_puts,"   %02x:%02x:%02x",hour,min,sec);