目次

電子サイコロ

概要

いろいろなゲームに使われる、サイコロ(ダイス)を、出来るだけ小さくを目標に、8ピンのPICで実現してみました。

動作原理

8ピンのPICでは、I/O数の制約(電源を除くと6個)が大きいので、当初サイコロには向かないのではと考えました。

このように8個のI/Oが必要となり、2個足りません。18ピンのPICなら、何も問題はないのですが。。。

そこで、次のように考えてみました。

このようにすることで、LED部分は、4個のI/Oで足りることになります。

※この考え方は、電子マスカットさんの「青い電子サイコロ」を参考にしました。

回路図

ソースコード

<プログラム上の工夫>

dice.c
//********************************************************************** 
 
#define		LED_A		GPIO.F0
#define		LED_B		GPIO.F1
#define		LED_C		GPIO.F4
#define		LED_D		GPIO.F5
 
#define		SW			GPIO.F3
 
#define		ON			0
#define		OFF			1
 
//********************************************************************** 
 
static	unsigned	int		seed;
 
void	interrupt(){
	if (INTCON.T0IF == 1) {
		INTCON.T0IF = 0;
		//
		seed++;
	}
}
 
//********************************************************************** 
 
void	Pwm_Change_DutyEx(unsigned int duty_ratio)
{
    CCPR1L = duty_ratio >> 2;
    CCP1CON.F6 = duty_ratio & 0b00000001;
    CCP1CON.F7 = (duty_ratio & 0b00000010) >> 1; 
}
 
//********************************************************************** 
 
void	diceChange()
{
	int		tmp;
	//
	tmp = rand();
	tmp = (((double)tmp) / 32768.0) * 6.0;
	//
	switch (tmp + 1) {
	case 1:
		LED_A = ON;
		LED_B = OFF;
		LED_C = OFF;
		LED_D = OFF;
		break;
	case 2:
		LED_A = OFF;
		LED_B = ON;
		LED_C = OFF;
		LED_D = OFF;
		break;
	case 3:
		LED_A = ON;
		LED_B = ON;
		LED_C = OFF;
		LED_D = OFF;
		break;
	case 4:
		LED_A = OFF;
		LED_B = ON;
		LED_C = ON;
		LED_D = OFF;
		break;
	case 5:
		LED_A = ON;
		LED_B = ON;
		LED_C = ON;
		LED_D = OFF;
		break;
	case 6:
		LED_A = OFF;
		LED_B = ON;
		LED_C = ON;
		LED_D = ON;
		break;
	}
}
 
//********************************************************************** 
 
void main()
{
	char	cnt;
	//
	OSCCON = 0b01111000;	// クロックは8Mhz 
	CMCON0 = 0b00000111;	// コンパレータは使用しない。 
	ANSEL  = 0b00000000;	// A/D変換を使用しない。 
	TRISIO = 0b00001000;
	//TIMER0の設定 
	INTCON.T0IE = 1;
	INTCON.T0IF = 0;
	OPTION_REG.T0CS = 0;
	OPTION_REG.PSA = 0;
	OPTION_REG.PS0 = 0;
	OPTION_REG.PS1 = 0;
	OPTION_REG.PS2 = 0;
	//
	Pwm_Init(1200);
	Pwm_Change_DutyEx((PR2 * 4) / 2);
	//
	LED_A = OFF;
	LED_B = OFF;
	LED_C = OFF;
	LED_D = OFF;
	//
	INTCON.PEIE = 1;	// これ以降の処理で割り込みを許可する。 
	INTCON.GIE = 1;		// これ以降の処理で割り込みを許可する。 
	//スイッチが押されるまで、LEDの点滅を繰り返す。 
	while (SW == OFF) {
		LED_A = ON;
		LED_B = ON;
		LED_C = ON;
		LED_D = ON;
		Delay_ms(100);
		LED_A = OFF;
		LED_B = OFF;
		LED_C = OFF;
		LED_D = OFF;
		Delay_ms(100);
	}
	//スイッチが離されるのを待つ。 
	while (SW == ON) {
		Delay_ms(100);
	}
	//ブザー音を鳴らす。 
	Pwm_Start();
	Delay_ms(200);	
	Pwm_Stop();
	//乱数の種をセットする。 
	srand(seed);
	//
	while (1) {
		//スイッチが押されるまで待つ。 
		if (SW == OFF) {
			Delay_ms(10);
			continue;
		}
		//サイコロの目を切り替える。 
		for (cnt = 0; cnt < 30; cnt++) {
			diceChange();
			//ブザー音を鳴らす。 
			Pwm_Start();
			Delay_ms(100);	
			Pwm_Stop();
			//可変型スリープ 
			Vdelay_ms(50 + (cnt * 10));
		}
	}
}
 
//**********************************************************************

動作確認

ブレッドボードで確認したので、LEDをサイコロの目のように並べていません。
基板等に組み込むときには、並べてください。
向かって左から、(A)(B)(B)(C)(C)(D)(D)の順になります。
右上の大きい丸状のものは、圧電スピーカです。
右下のプッシュスイッチは、スタート用のものです。

起動時には、全LEDが点滅しますので、この間にプッシュスイッチを押してください。
そうすることにより擬似乱数の発生系列が変更されます。

サイコロの目が1~6の時の、LEDの点灯パターンです。


如何ですか?
これを2セット用意するとゲームの幅が広がるかもしれませんね。^_^

著作権表示 copyright notice

このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。詳細
This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.Details