====== ミニ・シーケンサ(SDカード対応)(PIC18F2550) ======
===== 概要 =====
ある決められた順番や時間で、複数の電気機器のON/OFF制御を、手軽に出来るシーケンサを製作しました。
<仕様>
* 制御ポートは、8チャネルとする。
* シーケンス(動作)は、テキストエディタで簡単に設定できることとする。(SDカードに記録)
* 時間指定は、秒単位とする。(開始時からの相対時間、時分秒で指定)
* アクティブモード(high/low)の指定を可能とする。
===== 動作原理 =====
- シーケンス(動作)を指定するために、テキストエディタ(例えば、メモ帳、秀丸など)で、シーケンス設定ファイルを作成します。(ファイル名は、“sequence.txt" 固定)\\
<アクティブモードの設定>
出力ポートに接続されるインタフェースによっては、アクティブ・ハイ(1)で動作したり、アクティ・ブロー(0)で動作したりするものがあるので、どちらで動作するかを設定します。
$DEF
ON=0,OFF=1。。。。。この例では、アクティブ・ローを指定している。
<初期値の設定>
$INIT
CH0=OFF,CH1=OFF,CH2=OFF,CH3=OFF,CH4=OFF,CH5=OFF,CH6=OFF,CH7=OFF
<シーケンスの開始>
$START
00:00:00,CH0=ON。。。。。この例では、開始直後に、CH0をONにしている。
00:00:10,CH5=ON,CH7=ON。。。。。この例では、開始10秒後に、CH5とCH7をONにしている。
<シーケンスの停止>
$STOP
- SW1を押下すると、シーケンス制御を開始します。(LED2点灯)
- $STOPで、シーケンス制御を停止します。(LED2消灯)
- 制御途中で、シーケンスを停止する場合は、再度SW1を押下します。(LED2消灯)
<処理の流れ>
{{:imgpaste:202004:admin-20200430-191747.png}}
===== 回路図 =====
{{:imgpaste:202004:admin-20200430-191838.png}}
===== ソースコード =====
//**********************************************************************
/*
『ミニ・シーケンサー(SDC対応)』
■機能概要
シーケンス設定ファイルで設定した内容に応じて、出力ポートを制御する。
<設定内容>
・$DEF
出力ポートのアクティブモードの設定(active high/active low)
・$INIT
開始前の出力ポートの初期値の設定
・$START
ポートへの出力時間と、ポートのON/OFFの設定
・$STOP
制御の終了の設定
■シーケンス設定ファイルのフォーマット(設定例)
$DEF
ON=0,OFF=1
$INIT
CH0=OFF,CH1=OFF,CH2=OFF,CH3=OFF,CH4=OFF,CH5=OFF,CH6=OFF,CH7=OFF
$START
00:00:00,CH0=ON
00:00:01,CH1=ON
00:00:02,CH2=ON
00:00:03,CH3=ON
00:00:04,CH4=ON
00:00:05,CH5=ON
00:00:06,CH6=ON
00:00:07,CH7=ON
00:00:08,CH7=OFF
00:00:09,CH6=OFF
00:00:10,CH5=OFF
00:00:11,CH4=OFF
00:00:12,CH3=OFF
00:00:13,CH2=OFF
00:00:14,CH1=OFF
00:00:15,CH0=OFF
00:00:16,CH0=ON
00:00:17,CH1=ON,CH0=OFF
00:00:18,CH2=ON,CH1=OFF
00:00:19,CH3=ON,CH2=OFF
00:00:20,CH4=ON,CH3=OFF
00:00:21,CH5=ON,CH4=OFF
00:00:22,CH6=ON,CH5=OFF
00:00:23,CH7=ON,CH6=OFF
00:00:24,CH7=OFF
00:00:25,CH7=ON
00:00:26,CH7=OFF,CH6=ON
00:00:27,CH6=OFF,CH5=ON
00:00:28,CH5=OFF,CH4=ON
00:00:29,CH4=OFF,CH3=ON
00:00:30,CH3=OFF,CH2=ON
00:00:31,CH2=OFF,CH1=ON
00:00:32,CH1=OFF,CH0=ON
00:00:33,CH0=OFF
00:00:34,CH0=ON,CH1=ON,CH2=ON,CH3=ON,CH4=ON,CH5=ON,CH6=ON,CH7=ON
00:00:35,CH0=OFF,CH1=OFF,CH2=OFF,CH3=OFF,CH4=OFF,CH5=OFF,CH6=OFF,CH7=OFF
$STOP
*/
//**********************************************************************
#define SW PORTC.F0
#define LED1 PORTC.F1
#define LED2 PORTC.F2
#define CR 0x0d
#define LF 0x0a
#define MODE_DEF 0
#define MODE_INIT 1
#define MODE_START 2
#define MODE_STOP 3
#define CH0 PORTB.F2
#define CH1 PORTB.F3
#define CH2 PORTB.F4
#define CH3 PORTB.F5
#define CH4 PORTB.F6
#define CH5 PORTB.F7
#define CH6 PORTA.F0
#define CH7 PORTA.F1
//**********************************************************************
static long clock;
void interrupt()
{
if (PIR1.CCP1IF == 1) {
PIR1.CCP1IF = 0;
//
clock++;
LED1 = ~LED1;
}
}
//**********************************************************************
void init_sdc()
{
static short cnt;
//SDC(MMC)の初期化
Spi_Init_Advanced(MASTER_OSC_DIV64, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);
if (Mmc_Fat_Init(&PORTC, 6)) {
while (1) {
LED2 = 1;
Delay_ms(100);
LED2 = 0;
Delay_ms(100);
}
}
Spi_Init_Advanced(MASTER_OSC_DIV16, DATA_SAMPLE_MIDDLE, CLK_IDLE_LOW, LOW_2_HIGH);
for (cnt = 0; cnt < 5; cnt++) {
LED2 = 1;
Delay_ms(300);
LED2 = 0;
Delay_ms(300);
}
}
//**********************************************************************
void SwitchONcheck()
{
while (Button(&PORTC, 0, 1, 0) == 0)
;
while (Button(&PORTC, 0, 1, 1) == 0)
;
}
//**********************************************************************
void sequenceProc()
{
//変数の定義
static char buf[80], *pnt, tmp[8];
static unsigned long fsize, length;
static unsigned short character, cnt, mode, lineCnt, hh, mm, ss, hhTmp, mmTmp, ssTmp;
static unsigned short onData, offData, outputData;
//変数の初期化
clock = 0;
mode = MODE_STOP;
lineCnt = 0;
onData = 1;
offData = 0;
//MMCのファイルのオープン
Mmc_Fat_Assign("sequence.txt", 0);
Mmc_Fat_Reset(&fsize);
length = 0;
//
while (1) {
//設定ファイルから1行分のデータを読み込む
for (cnt = 0; cnt < 80; cnt++) {
Mmc_Fat_Read(&character);
length++;
if (character == ' ') {
cnt--;
continue;
}
if (character == CR) {
cnt--;
continue;
}
if (character == LF) {
buf[cnt] = 0x00;
break;
}
buf[cnt] = character;
}
lineCnt++;
//定義かを判断する。
pnt = strstr(buf, "$DEF");
if (pnt != 0x00) {
mode = MODE_DEF;
continue;
}
//初期化かを判断する。
pnt = strstr(buf, "$INIT");
if (pnt != 0x00) {
mode = MODE_INIT;
continue;
}
//開始かを判断する。
pnt = strstr(buf, "$START");
if (pnt != 0x00) {
mode = MODE_START;
continue;
}
//停止かを判断する。
pnt = strstr(buf, "$STOP");
if (pnt != 0x00) {
mode = MODE_STOP;
return;
}
//定義の設定
if (mode == MODE_DEF) {
pnt = strstr(buf, "ON=");
if (pnt != 0x00) {
onData = *(pnt + 3) - '0';
}
pnt = strstr(buf, "OFF=");
if (pnt != 0x00) {
offData = *(pnt + 4) - '0';
}
continue;
}
//初期値の設定
if (mode == MODE_INIT) {
tmp[0] = 'C';
tmp[1] = 'H';
tmp[2] = '?';
tmp[3] = '=';
tmp[4] = 0x00;
for (cnt = 0; cnt < 8; cnt++) {
tmp[2] = cnt + '0';
pnt = strstr(buf, tmp);
if (pnt != 0x00) {
if (strncmp((pnt + 4), "ON", 2) == 0) {
outputData = onData;
} else {
outputData = offData;
}
switch (cnt) {
case 0:
CH0 = outputData;
break;
case 1:
CH1 = outputData;
break;
case 2:
CH2 = outputData;
break;
case 3:
CH3 = outputData;
break;
case 4:
CH4 = outputData;
break;
case 5:
CH5 = outputData;
break;
case 6:
CH6 = outputData;
break;
case 7:
CH7 = outputData;
break;
}
}
}
continue;
}
//制御を行う。
if (mode == MODE_START) {
//制御時間を取得する。
if (buf[2] == ':') {
buf[2] = 0x00;
hh = atoi(buf);
buf[2] = ':';
}
if (buf[5] == ':') {
buf[5] = 0x00;
mm = atoi(&buf[3]);
buf[5] = ',';
}
if (buf[8] == ',') {
buf[8] = 0x00;
ss = atoi(&buf[6]);
buf[8] = ',';
}
//制御時間を確認する。
while (1) {
hhTmp = clock / 36000;
mmTmp = (clock - (36000 * (long)hhTmp)) / 600;
ssTmp = (clock - (36000 * (long)hhTmp) - (600 * (long)mmTmp)) / 10;
if ((hh == hhTmp) && (mm == mmTmp) && (ss == ssTmp))
break;
if (SW == 0) {
while (Button(&PORTC, 0, 1, 1) == 0)
;
return;
}
}
//ポートの制御を行う。
tmp[0] = 'C';
tmp[1] = 'H';
tmp[2] = '?';
tmp[3] = '=';
tmp[4] = 0x00;
for (cnt = 0; cnt < 8; cnt++) {
tmp[2] = cnt + '0';
pnt = strstr(buf, tmp);
if (pnt != 0x00) {
if (strncmp((pnt + 4), "ON", 2) == 0) {
outputData = onData;
} else {
outputData = offData;
}
switch (cnt) {
case 0:
CH0 = outputData;
break;
case 1:
CH1 = outputData;
break;
case 2:
CH2 = outputData;
break;
case 3:
CH3 = outputData;
break;
case 4:
CH4 = outputData;
break;
case 5:
CH5 = outputData;
break;
case 6:
CH6 = outputData;
break;
case 7:
CH7 = outputData;
break;
}
}
}
}
}
}
//**********************************************************************
void main()
{
//コンパレータは使用しない。
CMCON = 0b00000111;
//A/D変換の設定
ADCON1.PCFG3 = 1;
ADCON1.PCFG2 = 1;
ADCON1.PCFG1 = 1;
ADCON1.PCFG0 = 1;
//
OSCCON.IRCF2 = 1;
OSCCON.IRCF1 = 1;
OSCCON.IRCF0 = 1;
//ポートの設定
TRISA = 0b0000000000;
TRISB = 0b00000001;
TRISC = 0b00000001;
//
CH0 = 0;
CH1 = 0;
CH2 = 0;
CH3 = 0;
CH4 = 0;
CH5 = 0;
CH6 = 0;
CH7 = 0;
//TIMER1の設定
PIE1.TMR1IE = 0;
PIR1.TMR1IF = 0;
T1CON.T1CKPS0 = 1;
T1CON.T1CKPS1 = 1;
T1CON.NOT_T3SYNC = 1;
T1CON.TMR1CS = 0;
T1CON.TMR1ON = 0;
TMR1L = 0;
TMR1H = 0;
//CCPの設定
PIE1.CCP1IE = 1;
PIR1.CCP1IF = 0;
CCP1CON.CCP1M3 = 1;
CCP1CON.CCP1M2 = 0;
CCP1CON.CCP1M1 = 1;
CCP1CON.CCP1M0 = 1;
CCPR1L = 0xA8; // 0.1sec...(1÷8000000)*4*8*25000
CCPR1H = 0x61; //
//SDC(MMC)の初期化
init_sdc();
// 割り込みを許可する。
INTCON.PEIE = 1;
INTCON.GIE = 1;
//
T1CON.TMR1ON = 1;
//
while (1) {
SwitchONcheck();
LED2 = 1;
sequenceProc();
LED2 = 0;
}
}
//**********************************************************************
===== 動作確認 =====
{{:imgpaste:202004:admin-20200430-192043.png?500}}
出力ポート(CH0~CH7)に、LEDを接続して、動作を確認しました。
右側から、CH0、CH1、CH2、CH3、CH4、CH5、CH6、CH7、未接続、未接続です。
{{:imgpaste:202004:admin-20200430-192105.png?500}}
LED接続時の回路図です。(参考)
アクティブ・ロー(active low)で、LEDが点灯します。
{{:imgpaste:202004:admin-20200430-192116.png?500}}
<シーケンス設定ファイルの例>
$DEF
ON=0,OFF=1
$INIT
CH0=OFF,CH1=OFF,CH2=OFF,CH3=OFF,CH4=OFF,CH5=OFF,CH6=OFF,CH7=OFF
$START
00:00:00,CH0=ON
00:00:01,CH1=ON
00:00:02,CH2=ON
00:00:03,CH3=ON
00:00:04,CH4=ON
00:00:05,CH5=ON
00:00:06,CH6=ON
00:00:07,CH7=ON
00:00:08,CH7=OFF
00:00:09,CH6=OFF
00:00:10,CH5=OFF
00:00:11,CH4=OFF
00:00:12,CH3=OFF
00:00:13,CH2=OFF
00:00:14,CH1=OFF
00:00:15,CH0=OFF
00:00:16,CH0=ON
00:00:17,CH1=ON,CH0=OFF
00:00:18,CH2=ON,CH1=OFF
00:00:19,CH3=ON,CH2=OFF
00:00:20,CH4=ON,CH3=OFF
00:00:21,CH5=ON,CH4=OFF
00:00:22,CH6=ON,CH5=OFF
00:00:23,CH7=ON,CH6=OFF
00:00:24,CH7=OFF
00:00:25,CH7=ON
00:00:26,CH7=OFF,CH6=ON
00:00:27,CH6=OFF,CH5=ON
00:00:28,CH5=OFF,CH4=ON
00:00:29,CH4=OFF,CH3=ON
00:00:30,CH3=OFF,CH2=ON
00:00:31,CH2=OFF,CH1=ON
00:00:32,CH1=OFF,CH0=ON
00:00:33,CH0=OFF
00:00:34,CH0=ON,CH1=ON,CH2=ON,CH3=ON,CH4=ON,CH5=ON,CH6=ON,CH7=ON
00:00:35,CH0=ON,CH1=OFF,CH2=ON,CH3=OFF,CH4=ON,CH5=OFF,CH6=ON,CH7=OFF
00:00:36,CH0=OFF,CH1=ON,CH2=OFF,CH3=ON,CH4=OFF,CH5=ON,CH6=OFF,CH7=ON
00:00:37,CH0=OFF,CH1=OFF,CH2=OFF,CH3=OFF,CH4=OFF,CH5=OFF,CH6=OFF,CH7=OFF
$STOP
上記のシーケンス設定ファイルで動作させて見ました。
$DEF
ON=0,OFF=1
$INIT
CH0=OFF,CH1=OFF,CH2=OFF,CH3=OFF,CH4=OFF,CH5=OFF,CH6=OFF,CH7=OFF
$START
00:00:00,CH0=ON
00:00:01,CH1=ON
00:00:02,CH2=ON
{{:imgpaste:202004:admin-20200430-192230.png}}{{:imgpaste:202004:admin-20200430-192233.png}}{{:imgpaste:202004:admin-20200430-192237.png}}{{:imgpaste:202004:admin-20200430-192242.png}}
00:00:03,CH3=ON
00:00:04,CH4=ON
00:00:05,CH5=ON
00:00:06,CH6=ON
{{:imgpaste:202004:admin-20200430-192248.png}}{{:imgpaste:202004:admin-20200430-192252.png}}{{:imgpaste:202004:admin-20200430-192255.png}}{{:imgpaste:202004:admin-20200430-192258.png}}
00:00:07,CH7=ON
00:00:08,CH7=OFF
00:00:09,CH6=OFF
00:00:10,CH5=OFF
{{:imgpaste:202004:admin-20200430-192305.png}}{{:imgpaste:202004:admin-20200430-192308.png}}{{:imgpaste:202004:admin-20200430-192312.png}}{{:imgpaste:202004:admin-20200430-192315.png}}
00:00:11,CH4=OFF
00:00:12,CH3=OFF
00:00:13,CH2=OFF
00:00:14,CH1=OFF
{{:imgpaste:202004:admin-20200430-192324.png}}{{:imgpaste:202004:admin-20200430-192328.png}}{{:imgpaste:202004:admin-20200430-192331.png}}{{:imgpaste:202004:admin-20200430-192335.png}}
00:00:15,CH0=OFF
00:00:16,CH0=ON
00:00:17,CH1=ON,CH0=OFF
00:00:18,CH2=ON,CH1=OFF
{{:imgpaste:202004:admin-20200430-192346.png}}{{:imgpaste:202004:admin-20200430-192349.png}}{{:imgpaste:202004:admin-20200430-192353.png}}{{:imgpaste:202004:admin-20200430-192356.png}}
00:00:19,CH3=ON,CH2=OFF
00:00:20,CH4=ON,CH3=OFF
00:00:21,CH5=ON,CH4=OFF
00:00:22,CH6=ON,CH5=OFF
{{:imgpaste:202004:admin-20200430-192403.png}}{{:imgpaste:202004:admin-20200430-192406.png}}{{:imgpaste:202004:admin-20200430-192410.png}}{{:imgpaste:202004:admin-20200430-192413.png}}
00:00:23,CH7=ON,CH6=OFF
00:00:24,CH7=OFF
00:00:25,CH7=ON
00:00:26,CH7=OFF,CH6=ON
{{:imgpaste:202004:admin-20200430-192419.png}}{{:imgpaste:202004:admin-20200430-192423.png}}{{:imgpaste:202004:admin-20200430-192426.png}}{{:imgpaste:202004:admin-20200430-192431.png}}
00:00:27,CH6=OFF,CH5=ON
00:00:28,CH5=OFF,CH4=ON
00:00:29,CH4=OFF,CH3=ON
00:00:30,CH3=OFF,CH2=ON
{{:imgpaste:202004:admin-20200430-192438.png}}{{:imgpaste:202004:admin-20200430-192442.png}}{{:imgpaste:202004:admin-20200430-192450.png}}{{:imgpaste:202004:admin-20200430-192454.png}}
00:00:31,CH2=OFF,CH1=ON
00:00:32,CH1=OFF,CH0=ON
00:00:33,CH0=OFF
00:00:34,CH0=ON,CH1=ON,CH2=ON,CH3=ON,CH4=ON,CH5=ON,CH6=ON,CH7=ON
{{:imgpaste:202004:admin-20200430-192503.png}}{{:imgpaste:202004:admin-20200430-192507.png}}{{:imgpaste:202004:admin-20200430-192513.png}}{{:imgpaste:202004:admin-20200430-192519.png}}
00:00:35,CH0=ON,CH1=OFF,CH2=ON,CH3=OFF,CH4=ON,CH5=OFF,CH6=ON,CH7=OFF
00:00:36,CH0=OFF,CH1=ON,CH2=OFF,CH3=ON,CH4=OFF,CH5=ON,CH6=OFF,CH7=ON
00:00:37,CH0=OFF,CH1=OFF,CH2=OFF,CH3=OFF,CH4=OFF,CH5=OFF,CH6=OFF,CH7=OFF
{{:imgpaste:202004:admin-20200430-192523.png}}{{:imgpaste:202004:admin-20200430-192527.png}}{{:imgpaste:202004:admin-20200430-192534.png}}
如何ですか?
今回は、出力機能専用のシーケンサですが、入力機能を取り入れると、更に高度なシーケンサが出来ます。
例えば、入力信号(CH10)が、ONのときに出力信号(CH5とCH8)をOFFにする等。。。
また、時間処理では、内臓のクロック8MHzを使用していますが、RTC(リアルタイムクロック)を実装すれば、精度も向上し、更に開始からの相対時間ではなく、絶対時間での動作も可能となります。時計ユニット(RTC)
このページは稲崎様の閉鎖したHPのコピーで、著作権は稲崎様にあります。[[elechobby:picdic:picdic|詳細]]
This page is a copy of Mr. Inasaki's closed website, and the copyright is held by him.[[elechobby:picdic:picdic|Details]]