Vol.894 10.May.2024

ワイヤレス給電LED PICミニBB(4)_I2C接続ロータリーエンコーダ

E 電子おもちゃ  〜ワイヤレス給電LED

by fjk

 給電ユニット(秋月電子#114405、400円)により、電磁誘導方式でワイヤレスLED(秋月電子#117031など、5個入りで240円程度)に無接点で給電を行い、LEDを点灯させることができる。
 給電ユニットの仕様は、

動作電圧 : DC5〜9V、
出力電流 : 500mA(DC9V時)、
駆動周波数: 60kHz、
誘導距離 : 10mm(9V時)

 駆動電源として、スイッチ付きCR2032x2ボタン電池ホルダー(秋月電子#112666、150円)と、給電ユニットのケースとして百均のプラケース(66x62x21mm、2個セット)、PH-2Pコネクタポスト(秋月電子#117259、70円)を揃えた。
 なお、給電ユニットは両面テープで1.2mm厚のプラ板(大きさ57mm角)に固定し、プラ板の下に5mm高の樹脂スペーサを両面テープで4隅に取り付けた。
 単にLEDを点灯させるだけのオモチャだが、LEDユニットは見た目には見分けにくそうなので、給電ユニットにLEDを置いて、「同じ色のものがあればゲットできる」というルールでゲームができそう。


給電ユニットとワイヤレスLED

スイッチ付きボタン電池ホルダー

百均のプラケース

ワイヤレスLEDの点灯テスト


P PICミニBBシリーズ(4)  〜I2C接続ロータリーエンコーダー

by fjk

 ロータリーエンコーダー(RE)は24クリックタイプ(秋月電子 106357、100円)で、さらにロータリーエンコーダDIP化基板(秋月電子 107241、60円)を用いた。
 RE出力をそのままメインPIC(PIC-BASE14)の入力としても良いが、汎用入力ユニットとしたいので、I2C接続スレーブPICでデータを処理後、メインPICにI2CでREデータを送ることにした。I2CマスターPICはPIC16F1825、RE用I2CスレーブPICはPIC12F1840とし、RE用ブレッドボードはabc893で作成(配線)したアナログ入力ユニットを用いた。
 さらに、アナログ入力ユニット上の可変抵抗器の電圧(AD)もPIC12F1840で取得し、I2Cマスターからの指示により、AD(mode=0)かRE(mode=1)のどちらのデータをI2C送信するか選択できるようにした。modeの指示はUSB接続パソコン端末から、'0'または'1'を入力。modeを変更(再指定)するとREのカウンタは0にクリアされる。


I2C接続RE/ADボード回路図

RE/ADボードの配線

RE/AD動作中(REは灰色つまみ)

 また、PIC12F1840へのプログラムの書込みにはabc824で作成した「PIC書込みアダプタ」を使用した。
 PIC12F1840(ROM:4Kbyte)の使用メモリは17%(0.7Kbyte)以下なので、代わりにPIC12F1822やPIC16F18313(ROM:2Kbyte)などが使えそう。


PIC12F1840書込み中

 
PIC12F1840の使用メモリ状態

パソコン端末(テラターム)画面例

 なお、slaveI2CのPIC12F1840のMCC設定は以下のとおり。


RE/ADボード(PIC12F1840)のsystem Module
 

Pin Module

MSSP
 

ADC

 プログラムには、abc893で紹介した "i2cLCD_ST7032i.c/h"および"my_stdlib.c/h"が必要。

【プログラム】 abc894-1825.c(zip)
   (PIC16F1825のMCC設定などはabc893参照) (BFSIZEはeusart.hで宣言、 abc889を参照)

/*********************** (abc894-1825.c)**************
 *  I2C_RE・ADC入力  (mode=0:ADC、mode=1:RE)
 *****************************************************/
#include "mcc_generated_files/mcc.h"
#include "stdio.h"
#include "i2cLCD_ST7032i.h"
#include "my_stdlib.h"
#define  SLVADR 0x42

/* -----  Variables  ----- */
char     	sBuf[BFSIZE];  		// 文字列作業エリア
char     	rBuf[BFSIZE];   	// シリアル受信バッファ
uint8_t  	sFlg;           	// シリアル受信フラグ

/*----  disp mode -----------*/
void dsp_md(uint8_t md){
    LCD_cursor(3,0);
    if(md){
        puts("\n> RE Mode\r");
        LCD_str("RE Mode");
        IO_RA4_SetLow();
    }else{
        puts("\n> AD Mode\r");
        LCD_str("AD Mode");
        IO_RA4_SetHigh();
    }
}

/*------ main application ----*/
void main(void)
{
    static uint16_t rDat = 0;
    static uint8_t  mode = 0;
    SYSTEM_Initialize();
    LCD_init();              // LCD初期化
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
    LCD_str("=  ready");    
    dsp_md(mode);
    
    while (1)
    {
        if(sFlg){              // USB受信データがあれば
            LCD_clr();
            LCD_str(rBuf);
            if(rBuf[0] % 2)    // bit0のみで判断
                mode = 1;
            else
                mode = 0;
            dsp_md(mode);      // モード変更表示

            //--- スレーブへ送信
            I2C_Write1ByteRegister(SLVADR, 0, mode);
            sFlg = 0;
        }

        //---   スレーブから受信
        I2C_ReadNBytes(SLVADR, (uint8_t *)&rDat, 2);
        if(mode){                    // REモードなら
            if(rDat & 0x8000){       // 負数か?
                rDat = ~rDat + 1;    // 負数処理
                sBuf[0] = '-';
                my_itoa(sBuf+1,rDat);
            }else{
                my_itoa(sBuf, rDat);
            }          
        }else{                       // ADモード
            my_itoa(sBuf, rDat);
        }
        LCD_cursor(0,1);
        LCD_str("      ");
        LCD_cursor(0,1);
        LCD_str(sBuf);
        puts(sBuf);
        putch('\r');
        __delay_ms(500);
    }
}

 
【I2Cスレーブ(RE/AD)】 abc894-1840.c(zip)

/*********************(abc894-1840.c)***********
 *  アナログ&REデータ送信(I2Cスレーブ)
 *  Slave Address = 0x42 (66)
 ***********************************************/
#include "mcc_generated_files/mcc.h"

uint8_t  	wState;      	// I2C書込みステート番号
uint8_t  	rState;      	// I2C読込ステート番号
uint16_t 	sDat;        	// I2C送信16ビットデータ
uint8_t		reg;         	// レジスタ番号(未使用)
uint8_t  	mode = 0;    	// 1:RE / 0:ADC
int16_t  	count = 0;

/*****  I2C Read Callback  ****************/
void I2C_ReadProcess(void) {
    switch (rState) {    	// ステートで進む
        case 0:
            reg = I2C_Read();
            rState++;    	// 1byte目読込、次へ
            break;
        case 1:
            mode = I2C_Read();
            rState = 0;   	// 2byte目読込、最初に
            count = 0;    	// countデータクリア
            break;
        default:
            break;
    }
}

/*****  I2C Write Callback *****************/
void I2C_WriteProcess(void) {
    switch (wState) {
        case 0:
            I2C_Write((uint8_t)sDat);
            wState++;     	// sDatの下位送信、次へ
            break;
        case 1:
            I2C_Write((uint8_t)(sDat >> 8));
            wState++;     	// sDatの上位送信、次へ
            break;
        case 2:           	// 送信完了
            wState = 0;   	// 最初に戻る
            break;
        default:
            break;
    }
}

/*------ main application ----*/
void main(void)
{
    uint16_t aDat;
    SYSTEM_Initialize();
    I2C_Open();
    I2C_SlaveSetReadIntHandler(I2C_ReadProcess);
    I2C_SlaveSetWriteIntHandler(I2C_WriteProcess);    

    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

    while (1)
    {
        if(mode){
            if(IO_RA4_GetValue() == 0){
                __delay_ms(5);
                if(IO_RA5_GetValue())  count--;
                else                   count++;
                while(IO_RA4_GetValue() == 0);
                __delay_ms(5);
            }
            sDat = (uint16_t)count;
        }else{
            sDat = ADC_GetConversion(AN0);
            __delay_ms(100);
        }
    }
}


※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。


ワイヤレス給電LED PICミニBB(4)_I2C接続ロータリーエンコーダ