給電ユニット(秋月電子#114405、400円)により、電磁誘導方式でワイヤレスLED(秋月電子#117031など、5個入りで240円程度)に無接点で給電を行い、LEDを点灯させることができる。
給電ユニットの仕様は、
駆動電源として、スイッチ付きCR2032x2ボタン電池ホルダー(秋月電子#112666、150円)と、給電ユニットのケースとして百均のプラケース(66x62x21mm、2個セット)、PH-2Pコネクタポスト(秋月電子#117259、70円)を揃えた。
なお、給電ユニットは両面テープで1.2mm厚のプラ板(大きさ57mm角)に固定し、プラ板の下に5mm高の樹脂スペーサを両面テープで4隅に取り付けた。
単に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);
}
}
}
|
※プログラムのリストをハイライト付きのスタイルで見る場合はここをクリック
※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。