メニュー
▼ アクセス(地図)
▼ Windowsアプリ開発 ▼ マイコン開発 ▼ CGI・PHP制作 |
▼ サイトマップ(全投稿記事)
▼ タイトル(画像一覧) ▼ 事業内容 |
お問い合わせメールフォームが開きます。
2013年10月25日
Raspberry Pi でエレキー
Raspberry Pi でエレキーを作ってみました。
【概要】
C library for Broadcom BCM 2835 を利用させて頂きました。
http://www.airspayce.com/mikem/bcm2835/index.html
ポートの入出力設定
bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_INPT);
ポートのプルアップ設定
bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP);
ポートの読み込み
uint8_t value = bcm2835_gpio_lev(PIN);
タイマ割り込みは使わず、ディレイライブラリで対応
bcm2835_delayMicroseconds(1000); // 1msec待ち
ブザーは下記のPWMライブラリを使用
http://www.airspayce.com/mikem/bcm2835/pwm_8c-example.html
速度調整はロータリエンコーダをを使用
(RaspberryPiにA/Dコンバータ機能がないため)
コンパイルは下記の通りです。(ソースコード名:Elekey.c)
gcc -o Elekey -l rt Elekey.c -l bcm2835
【接続】
・DOT入力 P1_11 (内部プルアップ)
【接続】
・DOT入力 P1_11 (内部プルアップ)
・DASH入力 P1_15 (内部プルアップ)
・LED出力 P1_07 (抵抗→LED→GNDへ)
・LED出力 P1_07 (抵抗→LED→GNDへ)
・ブザー出力 P1_12
・エンコーダA P1_22 (内部プルアップ)
・エンコーダB P1_24 (内部プルアップ)
【動作の様子】
【ソースコード】
・エンコーダA P1_22 (内部プルアップ)
・エンコーダB P1_24 (内部プルアップ)
【動作の様子】
【ソースコード】
#include <stdio.h>
#include <stdlib.h>
#include <bcm2835.h>
//----------------------------------------------------------------------------
// マクロ定義
//----------------------------------------------------------------------------
#define PIN_DOT RPI_V2_GPIO_P1_11
#define PIN_DASH RPI_V2_GPIO_P1_15
#define PIN_LED RPI_V2_GPIO_P1_07
#define PIN_BUZZ RPI_V2_GPIO_P1_12
#define PIN_ENC_A RPI_V2_GPIO_P1_22
#define PIN_ENC_B RPI_V2_GPIO_P1_24
#define PWM_CHANNEL 0 // PWM channel 0
#define RANGE 1024 // Max range of the PWM signal
// LED出力状態を設定
#define LED_ON() (bcm2835_gpio_write(PIN_LED, HIGH))
#define LED_OFF() (bcm2835_gpio_write(PIN_LED, LOW))
// ブザー出力状態を設定
#define BUZZ_ON() (bcm2835_pwm_set_data(PWM_CHANNEL, RANGE/2))
#define BUZZ_OFF() (bcm2835_pwm_set_data(PWM_CHANNEL, 0))
// Dot/Dashポートチェック(負論理)
#define ChkDotPort() (bcm2835_gpio_lev(PIN_DOT) == LOW)
#define ChkDashPort() (bcm2835_gpio_lev(PIN_DASH) == LOW)
// Encoderポートチェック(負論理)
#define ChkEncA() (bcm2835_gpio_lev(PIN_ENC_A) == LOW)
#define ChkEncB() (bcm2835_gpio_lev(PIN_ENC_B) == LOW)
//----------------------------------------------------------------------------
// 定数定義
//----------------------------------------------------------------------------
typedef enum
{
PARA_ALL_OFF = 0x00,
PARA_DOT_ON,
PARA_DOT_OFF,
PARA_DASH_ON,
PARA_DASH_OFF
} PARA; // Dot/Dash状態遷移
typedef enum
{
ENC_STS_NO = 0x00,
ENC_STS_PLUSE,
ENC_STS_MINUS,
ENC_STS_MAX
} ENC_STS; // エンコーダ状態
#define LIMIT_VALUE (0x03) // チャタリングフィルタ用
#define MAX_SPEED (20) // 最大速度
#define MIN_SPEED (255) // 最小速度
//----------------------------------------------------------------------------
// ユーザメモリと初期化
//----------------------------------------------------------------------------
unsigned int ParaTime = 0x0000;
unsigned int ADCData= MIN_SPEED;
unsigned char ParaCode = PARA_ALL_OFF;
unsigned char CntDotOn = 0x00;
unsigned char CntDashOn = 0x00;
unsigned char ENC_Pluse = 0;
unsigned char ENC_Minus = 0;
//----------------------------------------------------------------------------
// エンコーダのプラス側ステータスセット
//----------------------------------------------------------------------------
static void ENC_SetPluse( void )
{
ENC_Pluse = 1;
ENC_Minus = 0;
}
//----------------------------------------------------------------------------
// エンコーダのマイナス側ステータスセット
//----------------------------------------------------------------------------
static void ENC_SetMinus( void )
{
ENC_Pluse = 0;
ENC_Minus = 1;
}
//----------------------------------------------------------------------------
// エンコーダのチャタリング吸収
//----------------------------------------------------------------------------
void ENC_ChkPort( void )
{
static unsigned char BakEncSts;
if( !ChkEncA() && !ChkEncB() )
{
BakEncSts = 0x00;
}
else if( ChkEncA() && !ChkEncB() )
{
if( BakEncSts == 0x00 )
{
ENC_SetMinus();
}
BakEncSts = 0x01;
}
else if( !ChkEncA() && ChkEncB() )
{
if( BakEncSts == 0x00 )
{
ENC_SetPluse();
}
BakEncSts = 0x02;
}
else if( ChkEncA() && ChkEncB() )
{
BakEncSts = 0x03;
}
}
//----------------------------------------------------------------------------
// エンコーダ速度設定
//----------------------------------------------------------------------------
void GetSpeedValue(void)
{
if( ENC_Pluse== 1 )
{
ENC_Pluse = 0;
if( ADCData > MAX_SPEED )
{
ADCData -= 8;
}
}
if( ENC_Minus == 1 )
{
ENC_Minus = 0;
if( ADCData < MIN_SPEED )
{
ADCData += 8;
}
}
}
//----------------------------------------------------------------------------
// パラメータセット: Dash
//----------------------------------------------------------------------------
char SetParaDash(void)
{
if(CntDashOn >= LIMIT_VALUE)
{
CntDashOn = 0;
ParaCode = PARA_DASH_ON;
ParaTime = ADCData;
ParaTime <<= 1;
ParaTime += ADCData;
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
// パラメータセット: Dot
//----------------------------------------------------------------------------
char SetParaDot(void)
{
if(CntDotOn >= LIMIT_VALUE)
{
CntDotOn = 0;
ParaCode = PARA_DOT_ON;
ParaTime = ADCData;
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
// 入力ポートチャタリング処理
//----------------------------------------------------------------------------
void ChkInputPort( void )
{
// for Dot
if(ParaCode != PARA_DOT_ON)
{
if(ParaCode == PARA_DOT_OFF && ParaTime >= (ADCData >>3))
CntDotOn = 0;
else if(ParaCode == PARA_DASH_ON && ParaTime >= ADCData)
CntDotOn = 0;
else if(CntDotOn < LIMIT_VALUE)
{
if( ChkDotPort() )
CntDotOn ++;
else
CntDotOn = 0;
}
}
// for Dash
if(ParaCode != PARA_DASH_ON )
{
if(ParaCode == PARA_DASH_OFF && ParaTime >= ADCData>>3)
CntDashOn = 0;
else if(ParaCode == PARA_DOT_ON && ParaTime >= (ADCData >>1))
CntDashOn = 0;
else if(CntDashOn < LIMIT_VALUE)
{
if( ChkDashPort() )
CntDashOn ++;
else
CntDashOn = 0;
}
}
}
//----------------------------------------------------------------------------
// 出力ポート設定
//----------------------------------------------------------------------------
void SetOutput(void)
{
if((ParaCode == PARA_DASH_ON) || (ParaCode == PARA_DOT_ON))
{
BUZZ_ON(); // ブザーポートOn/Off
LED_ON(); // LEDポートOn/Off
}
else
{
BUZZ_OFF();
LED_OFF();
}
}
//----------------------------------------------------------------------------
// メイン関数
//----------------------------------------------------------------------------
int main(int argc, char *argv)
{
if( !bcm2835_init() ) return 1;
// In/Out設定
bcm2835_gpio_fsel(PIN_DOT, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(PIN_DASH, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(PIN_ENC_A, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(PIN_ENC_B, BCM2835_GPIO_FSEL_INPT);
bcm2835_gpio_fsel(PIN_LED, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(PIN_BUZZ, BCM2835_GPIO_FSEL_OUTP);
// Pullup設定
bcm2835_gpio_set_pud(PIN_DOT, BCM2835_GPIO_PUD_UP);
bcm2835_gpio_set_pud(PIN_DASH, BCM2835_GPIO_PUD_UP);
bcm2835_gpio_set_pud(PIN_ENC_A, BCM2835_GPIO_PUD_UP);
bcm2835_gpio_set_pud(PIN_ENC_B, BCM2835_GPIO_PUD_UP);
// PWM設定など
bcm2835_gpio_fsel(PIN_BUZZ, BCM2835_GPIO_FSEL_ALT5);
bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_32);
bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1);
bcm2835_pwm_set_range(PWM_CHANNEL, RANGE);
bcm2835_pwm_set_data(PWM_CHANNEL, 0);
while( 1 )
{
bcm2835_delayMicroseconds(1000); // 1msec待ち
ChkInputPort(); // 入力ポートチャタリング処理
ENC_ChkPort();
GetSpeedValue(); // エンコーダ値取得
if(ParaTime > 0)
{
ParaTime --;
if(ParaTime == 0)
{
switch(ParaCode)
{
case PARA_DOT_ON:
ParaCode = PARA_DOT_OFF;
ParaTime = ADCData;
break;
case PARA_DASH_ON:
ParaCode = PARA_DASH_OFF;
ParaTime = ADCData;
break;
case PARA_DOT_OFF:
if(!SetParaDash()) // スクイズ動作のためDashを見る
ParaCode = PARA_ALL_OFF;
break;
case PARA_DASH_OFF:
if(!SetParaDot()) // スクイズ動作のためDotを見る
ParaCode = PARA_ALL_OFF;
}
}
}
if(ParaCode == PARA_ALL_OFF)
{
if(!SetParaDot())
{
SetParaDash();
}
}
SetOutput(); // 出力ポート設定
}
}