PIC16F84A スロットゲーム


前回作成した スロットゲーム基板 を使って、プログラムを作成しました。
数字の「777」を揃えるスロットゲームです。

操作はタクトスイッチを押すだけです。
タクトスイッチは2つありますが、ゲームに使用するのは左側で、右側はリセットボタンです。
7セグには0から9の数字が1/3秒間隔で順番に表示され、ビープ音が鳴ります。
スイッチを押すごとに、3桁の7セグの右側から停止し、選んだ数字が表示されます。
**3 -> *23 -> 123
3回押すと、選んだ数字が点滅して、ゲームが終了します。
777が揃ったときは、77Lのように数字が回転する、特別な動作をします。

LEDは1秒間隔で点滅しますが、ゲームの進行とは関係ありません。

プログラム領域の使用量は、99.6%で、限界まで使っています。
7セグの表示、LEDの点滅、ビープ音、ボタンの監視などを行っています。

ソースコードは Github に公開しました。


PIC16F84A 7セグLED


PIC16F84A で7セグLED SND2537 を点灯します。
Arduino で作ったプログラム をベースに、PIC向けに変更しました。

Arduino では、000 から 999 まで 0.1秒刻みでカウントアップする 10秒タイマーでした。
今回は、各セグメントを1つづつ順番に点灯するモードと、012, 123, 234 のように数字がスクロールするモードを、交互に表示するようにしました。

ソースコードは Github に公開しました。


PIC16F84A スロットゲームの基板を作る


20150506_pic_front

概要
Eagle と Sevenmini を使って、PIC16F84A で制御するスロットゲームの基板を作ります。
7セグLEDやタクトスイッチや電磁ブザーなどを搭載します。
元ネタは PICと7セグLEDでスロットマシン です。

基板作成の手順は Eagle と Sevenmini を使って電子基板を作る を参照してください。
データは GitHub で公開しています。

Eagle 側の作業
(1) 回路図 (sch) とボード図 (brd) を作成します。
20150506_pic_sch 20150506_pic_brd

(2) Mirrorにして、ガーバーデータを出力します。
20150506_pic_gerber

FLASH 側の作業
(1) ガーバーデータを読み込みます。
ハンダ面データ (sol) を「フォト表」に、
ドリルデータ (drd) を「穴」に、
外形データ (out) を「外形表」にします。
20150506_pic_flash

(2) 輪郭線抽出を行います。

Sevenmini 側の作業
(1) 配線の加工
基板を両面テープで固定します。
ミリング用のエンドミルを取り付けます。
CAM-Circuit2 アプリから加工を指示します。
(2) 穴の加工
ドリル用のエンドミル 0.6mm に交換します。
CAM-Circuit2 アプリから加工を指示します。
(3) 外形の加工
今回は基板をそのまま使い、加工せず。
20150506_pic_milling

ハンダ付け
(1) 表面の配線を行います。
(2) 部品をつけて、裏面をハンダ付けします。
20150506_pic_front 20150506_pic_rear

動作確認
PICに Lチカのプログラム を書き込みます。
ボタン電池を搭載します。
LEDが点滅すればOKです。

今回は、ゲーム基板を作るところまでです。
ゲームのプログラムは、後ほど作成します。

課題
(1) 表の配線と、抵抗が、同じ穴になってしまった。
意識して設計したつもりが、1ヶ所だけミスった。
(2) 電池のスイッチを付け忘れた。
電池を切るときは、ボックスから外す羽目に。
これが割と面倒。

(3) PIcKit3 が 電池ケースとぶつかってしまった。
ちょっと浮くけど、書き込みには支障なし。
20150506_pic_todo2

参考
PICと7セグLEDでスロットマシン
PIC16F84Aで電子工作 スロットマシーンを作ってみました


PIC16F84A ブザー音 鯉のぼり


YouTube Preview Image

前回 は、PIC16F84A に圧電ブザーをつけてドレミを鳴らしました。
今回は、楽譜を元に音楽を鳴らします。
スイッチサイエンスさんがゴールデンウィークの企画として Arduinoで童謡「鯉のぼり」を流してみよう を紹介しています。
それに便乗して「鯉のぼり」を演奏します。
楽譜は こいのぼりなど子供の日用の楽譜 を参照しました。

プログラムを Github に公開しました。

参考
Arduinoで童謡「鯉のぼり」を流してみよう
こいのぼりなど子供の日用の楽譜


PIC16F84A ブザー音 ドレミ


20150501_pic_buzzer

PIC16F84A のデジタル出力に 圧電ブザー をつけて、ブザー音を鳴らすことができます。
さらに、ブザー音の周波数を変えることで、疑似的な音楽を鳴らすことができます。
例えば、A(ラ)の音は 440Hz なので、1秒間に440回オンオフを繰り返すことで、Aの音になります。
正確に 440回を刻むために、タイマー割り込みを使用します。

割り込み周期は下記の 計算式 で求められます。
(Fosc / 4) * プレスケーラー分周 * タイマー分周

なお、440回オンオフを繰り返すには、倍の 880Hz の割り込み周期が必要となります。
880Hz にするには、Fosc が 16MHZ のときは、プレスケーラー分周 が 1/32 で、タイマー分周 が 1/142 となります。
同じように、他の音も周波数から分周比も計算して、ドレミの音階を作ります。
周波数は ドレミの音階(平均律)に対応した周波数の表 を参照しました。

音階 周波数 分周比 タイマー値
262 Hz 1/239 17
293 1/213 43
330 1/189 67
ファ 349 1/179 77
392 1/159 97
440 1/142 114
494 1/127 129
高いド 523 1/120 136

プログラムの例

#define DO4 17
#define RE 43
#define MI 67
#define FA 77
#define SO 97
#define RA 114
#define SI 129
#define DO5 136
void tone( int tmr, int t1, int t2 ) {
    tmr0_value = tmr;
    TMR0 = tmr0_value;
    is_tone_enable = true;
    for( ; t1>0; t1-- ) {
        __delay_ms(10);
    }
    noTone( t2 );
}
void noTone( int t ) {
    is_tone_enable = false;
    for( ; t>0; t-- ) {
        __delay_ms(10);
    }
}

プログラムを Github に公開しました。

補足
タイマー割り込みでブザー音を鳴らす方法は、Arudino でも採用されています。
Arudino では、tone関数に周波数を指定すると、関数の中で計算してプリスケーラーとタイマーの値を決めています。
今回のPICでは、予め計算しておいたプリスケーラーとタイマーの値を設定します。

参考
ドレミの音階(平均律)に対応した周波数の表


PIC16F84A タイマー割り込み


PIC16F84Aには、8ビットタイマーが内蔵されています。
これを用いて、タイマー割り込みが利用できます。

20140427_pic_timer0

タイマー割り込みを使用するには、下記の3つのレジスタを設定します。
INTCON
割り込み制御レジスタ
GIE (Global Interrupt Enable)
TMR0IE (TMR0 Overflow Interrupt Enable)

OPTION REG
オプション・レジスタ
T0CS (TMR0 Clock Source Select)
1 = Transition on RA4/T0CKI pin
0 = Internal instruction cycle clock (CLKOUT)
PSA (Prescaler Assignment)
1 = Prescaler is assigned to the WDT
0 = Prescaler is assigned to the Timer0 module
PS2-0 (Prescaler Rate Select)
 Prescaler Rate Select は、000 (1/2) から 111 (1/256) が設定できます。

TMR0
タイマー0 レジスタ
8ビットのアップカウンタです。
255を超えてオーバーフローしたときに割り込みを発生します。
0x00 (1/256) から 0xFF (1/2) が設定できます。
注意:分周比 は 256 – 設定値 です。

割り込み周期
割り込み周期は下記の計算式で求められます。
(Fosc / 4) * プレスケーラー分周 * タイマー分周

例えば、Fosc が 16MHZ で、プレスケーラー分周 が 1/256 で、タイマー分周 が 1/256 のときは、61 Hz (16.4 ms) です。
それより長い周期の割り込みが欲しいときは、プログラムでカウンタを作って、割り込みがN回起きたら、処理を実行するようにします。
例えば、1秒周期のときは、61進カウンタにします。
61 = 1 sec / 16.4 msec

プログラム例
1秒間隔でLEDを点滅させるプログラム

int main(void) {
    TRISA = 0x00;   // PortA all output
    TRISB = 0x00;   // PortB all output
    PORTA = 0x00;   // PortA all low
    PORTB = 0x00;   // PortB all low
    OPTION_REG = 0x07;  // 1/256
    TMR0 = 0;   // 1/256  
    INTCONbits.TMR0IE =1;   // TMR0 Overflow Interrupt Enable
    INTCONbits.GIE = 1; // Global Interrupt Enable
    while(1) {}     // endless loop
}
static void interrupt isr(void) {
    if (INTCONbits.TMR0IF == 1) {   // TMR0 Overflow
        INTCONbits.TMR0IF = 0;  // clear flag
        TMR0 = 0;
        if ( counter >= 61 ) {  // 1sec
            counter = 0; // reset counter
            PORTBbits.RB4 = is_led_on;  // set LED
            is_led_on = !is_led_on; // bit invert
        }
    }
}

プログラムは Github で公開してます。


PIC16F84A のベース基板を作る


20150503_pic_led

概要
Eagle と Sevenmini を使って、PIC16F84A のベース基板を作ります。
発振子、LED、IOピンとPICkit3用のヘッダピンなどを必要最低限なものを実装します。

基板作成の手順は、Eagle と Sevenmini を使って電子基板を作る を参照してください。
データは GitHub で公開しています。

Eagle 側の作業
(1) 回路図 (sch) とボード図 (brd) を作成します。
20150503_pic_sch 20150503_pic_brd

(2) Mirror にしてガーバーデータを出力します。
20150503_pic_gerber

FLASH 側の作業
(1) ガーバーデータを読み込みます。
ハンダ面データ (sol) を「フォト表」に、
ドリルデータ (drd) を「穴」に、
外形データ (out) を「外形表」にします。
20150503_pic_flash

(2) 輪郭線抽出を行います。

Sevenmini 側の作業
(1) 配線の加工
基板を両面テープで固定します。
ミリング用のエンドミルを取り付けます。
CAM-Circuit2 アプリから加工を指示します。
(2) 穴の加工
ドリル用のエンドミル 0.6mm に交換します。
CAM-Circuit2 アプリから加工を指示します。
(3) 外形の加工
フォーミングのエンドミルに交換します。
CAM-Circuit2 アプリから加工を指示します。
20150503_pic_milling

ハンダ付け
(1) 表面の配線を行います。
(2) 部品をつけて、裏面をハンダ付けします。
20150503_pcb_front 20150503_pcb_rear

動作確認
PIC16F84A で Lチカ を実行します。

失敗
RB6とRB7を PICkit を接続すべきが、1ピンずれてRB5とRB6を接続していた。
追加で穴をあけて、修正した。

課題
3端子レギュレータを、よく考えずに配置したため、基板から飛び出してしまった。
向きを変えて、基板に収まるようにしたほうがいいです。


PIC16F84A で Lチカ


20150426_pic_device

PIC16F84A は、マイクロチップ社の8ビットマイコンです。
ひと昔前は、8ビットマイコンの定番的な存在でしたが。
現在では、同社の 18F シリーズや、アトメル社の ATmega が主流になっています。
今回は、無償でまとまった数を入手したので、久しぶりに PIC で遊んでみます。

スペック比較
Arduino Uno に使われているアトメル社の ATmega328P と比べると、かなり見劣りします。

ATmega328P PIC16F84A
外形 28ピン DIP 18ピン DIP
動作電圧 1.8 – 5.5V 2.0 – 5.5V
クロック 20 MHz 20 MHz
プログラム容量 32KB 1Kword ※1
EEPROM容量 2KB 64B
RAM容量 1KB 68B
AD変換 6個 なし
UART 1個 なし
SPI 1個 なし
I2C 1個 なし
IO電流 40mA 20mA
秋月価格 250円 250円

※1 PIC16F は14ビット命令長です。

開発環境
マイクロチップ社から MPLAB X IDE が無償で提供されています。
Cコンパイラも、8ビット(XC8)、16ビット(XC16)、32ビット(XC32) の無償版が提供されています。
それぞれ、Windows、MAC、Linux に対応しています。

PICライタ
秋月電子には、30種を超える PICライタ が販売されています。
ホビー用の定番は PICkit3 です。

C言語 プログラム
PICの開発環境が、この数年で大きく変わりました。
古い環境やアセンブラで書いた例はいろいろ見つかりましたが。
MPLAB X IDE + XC8 という新しい環境での例は少なかったです。

PIC特有の流儀は、3つくらいです。
(1) チップの品種ごとにマクロが用意されています。
レジスタのアドレスやビット配置などをさほど意識せずに、すっきり書けます。

#include <pic16f84a.h>

(2) config レジスタ用にマクロが用意されています。
main が実行される前に、初期設定を実行してくれます。

#pragma config WDTE = OFF, PWRTE = OFF, CP = OFF, FOSC = HS 

(3) 外部クロック用に周波数定義のマクロ定数が用意されています。
delay など正確な時間が必要な関数が使えます。

#define _XTAL_FREQ 16000000

Lチカのプログラムを書く。
TRISx は、IOポートの出力/入力を設定するレジスタです。
PORTx は、IOポートの値を設定するレジスタです。
今回は、RB4 に LED を付けます。

#include <xc.h>         /* XC8 General Include File */
#include <pic16f84a.h>  /* PIC16F84A */ 
#define _XTAL_FREQ 16000000     // 16MHz
#pragma config WDTE = OFF, PWRTE = OFF, CP = OFF, FOSC = HS 

void main(void)
{
    TRISA = 0x00;   // PortA all output
    TRISB = 0x00;   // PortB all output
    PORTA = 0x00;   // PortA all low
    PORTB = 0x00;   // PortB all low

    while(1)
    {
        PORTBbits.RB4 = 1;  // LED on
        __delay_ms(1000);   // 1sec
        PORTBbits.RB4 = 0;  // LED off
        __delay_ms(1000);   // 1sec
    }
}

MPLAB X IDE 上でコンパイル&ビルドする。
MPLAB X+XC8で__delay_ms関数にエラーマークが表示される問題の解決方法

プログラム転送
PICkit3 を使って、MPLAB X IDE から、PICマイコンにプログラムを転送する。
このとき、PICkit3 から5V電源を供給するようにすると、PICマイコン側は MCLK のプルアップ抵抗だけあればいいです。
20140426_picschematic_pickit3 20150426_pic_pickit3

最低限の回路
PICマイコンの周りに下記を追加します。
(1) 5V電源
(2) 電源コンデンサ
(3) MCLK のプルアップ抵抗
(4) セラミック発振子 ※2
(5) 動作確認用のLED

※2 クロック回路
PIC のクロック回路には、内部発振と、外部クロックの2つの方法があります。
内部発振では、外付けの抵抗とコンデンサが必要です。
外部クロックでは、水晶発振子、セラミック発振子、あるいはクロック源が必要です。
実装的には、セラミック発振子を使うのが簡単です。

20140426_pic_schematic_basic_led

動作確認
上記の回路で、電源を入れれば、LEDが点滅します。
20150426_pic_device

プログラムなどは、Github で公開しています。

参考
PIC 久しぶり – PIC16F84A XC8 LED
LEDを点滅させる - TMR0割込み -(PIC16F84A XC8)
16F84A XC8開発例 – カウンタ回路(7セグメントLEDの制御)
XC8:コンフィグレーションワード記述書式について
MPLAB X+XC8で__delay_ms関数にエラーマークが表示される問題の解決方法


PIC-ADK を Android 4.1 対応にする


Android 4.1 から ADK の protocol version が1から 2 にバージョンアップしました。
それに伴い PIC-ADK も protocol version 2 に対応にする必要があります。
変更するのは下記の2つのファイルです。

main.c

 
BOOL USB_ApplicationEventHandler( BYTE address, USB_EVENT event, void *data, DWORD size )
{
	...
	case EVENT_ANDROID_DETACH:
		device_attached = FALSE;

		// Reinit the device if a detach is detected
		USBInitialize(0);
		AndroidAppStart(&myDeviceInfo);
 
		return TRUE;
		break;

usb_host_android.c

 
static ANDROID_PROTOCOL_VERSION protocolVersions[] =
{
	{
		1,
		...
	},
	{
 		2,
		AndroidAppWrite_Pv1,
		AndroidAppIsWriteComplete_Pv1,
		AndroidAppRead_Pv1,
		AndroidAppIsReadComplete_Pv1,
		AndroidInitialize_Pv1,
		AndroidTasks_Pv1,
		AndroidAppEventHandler_Pv1,
		AndroidAppDataEventHandler_Pv1
	}
};

BOOL AndroidAppEventHandler( BYTE address, USB_EVENT event, void *data, DWORD size )
{
	...
	case EVENT_TRANSFER:
		...  
		if(j >= (sizeof(protocolVersions)/sizeof(ANDROID_PROTOCOL_VERSION)))
		{
			//If we don't support that protocol version, use the next best version

			//Override the protocol version specified by the device                       
			devices[i].protocol = protocolVersions[j-1].versionNumber;                       

			devices[i].state = READY;                       
			devices[i].protocolHandle = protocolVersions[j-1].init(devices[i].address,devices[i].flags, devices[i].clientDriverID);                   
		}

修正したファイルは code.google にあります。

参考
PIC24F ADK device not working on Android Jelly Bean (Nexus 7 Tablet)
ADK 1.0 devices fail to work with Jelly Bean, why?

関連
PIC24FJ64GB002のADK開発環境
ADK 2012


横浜ロボット部のADK温度センサ


横浜ロボット部 ADK製作実習 の続きです。

yokorobo ボードに温度センサをつける。
ADK製作実習では、プログラムは原田さんに書き込んで頂いたが、今回は自分で作成する。
方法は Android ADK プログラミング&電子工作バイブル に掲載されています。
プログラムは ソシム社のサイト からダウンロードできます。

1. yokorobo ボード側
1-1. プロジェクトの作成
PIC-ADK開発環境 と同様に、ADKのプロジェクトを作成する。

1-2. プロジェクトの変更
温度センサに変更する
下記を2つのファイルを変更する。
– main.c (変更)
– HardwareProfile.h (変更)

※ main.c はダウンロードした chap5/ADK_Thermometer/ に入っている。

1-3. プロジェクトのビルド
Clean and Build Main Porject を実行する。
エラーなく終了した。(^o^)

1-4 PIC に書き込む
yokorobo ボードに PICKit3 を接続する。
Run Main Porject を実行する。

2. Android側
2-1 Eclipse 環境
Eclipse に ダウンロードした chap5/Thermometer/ をインポートする。
Androrid アプリケーションを実行(Run) する。
エラーなく終了した。(^o^)

2-2 Android にインストールする
Android端末を接続して、再度 実行する。

3. 実機確認
(1) yokorobo ボードに温度センサをつける
(2) yokorobo ボード と Android を接続する
(3) yokorobo ボード の電源を入れる
(4) Android に「このUSBアクセサリーが接続されたときに…」という表示がでる
(5) Android に室温が表示された。(^o^)