LiLaCプログラムの変更(pic147)
中学の技術授業からは離れてしまったけれど、夏休みの一研究として以前から考えていた変更に着手した。
それは、LiLaCのプログラムを中学生が自分でできないかということ。
LiLaCは本来 Learn intelligence of Logic and Circuitry として論理と回路について学ぶのものという位置づけで考えていた。
それでも、なんとか学習指導要領が求めている「計測と制御のプログラミング」にも使えないかとは思っていた。なかなか難しいかもしれないけれど、一応あがいてみようかなと思って取り組んだ。
LiLaC自体は、PCでプログラムしてコンパイルしたものを書き込み機でワンチップマイコンに書き込んでいる。
上の写真は、LiLaC ver.2として開発しているプロトタイプ基板。書き込み自体も直接接続して転送出来るように考えている。
完全にお金が発生せずに公開出来るよう、C言語を用いて一から自分でプログラムをおこしていたが、独学で学習しながらなのでちょっとしたことで何度もつまづいていた。
今回娘が結婚した旦那さんがエンジニアだったこともあって助言を受けることができたので、プログラムを「生徒が自分で構成する簡単な部分」だけを取り出してソースコードを書けるようにして、それ以外の部分は別ファイルで見えないようにするよう変更した。
とりあえず、メインの部分はすごく簡単になった。
下は、そのメインプログラムを無料の開発環境であるマイクロチップ社のMPLAB IDEで表示させているところ。
ここから、分岐や繰り返しの部分を簡単にできるように、メインへ戻すような作業をしていこうと考えている。
さらに、スタート時にスイッチで選択して、センサーの計測値をサーボモーターによって針のメーターで示すようにすればいいかな。
といいつつ、夏休みはもう終わりになるので、ここからは少しずつ進めていくようにしたい。(その他の宿題がたくさんたまっているのは、学生時代からかわらない)
ちなみに外に出した部分のソースコード(現時点で以前と同じ動作をするもの)は以下
LiLaC-functions.h
/*
* File: LiLaC-v22functions.h
* Author: dai_a
*
* Created on 2022/08/13, 6:45
*/
// PIC12F683 Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown Out Detect (BOR disabled)
#pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#define _XTAL_FREQ 1000000
/*ピンの定義をしておく*/
#define OUTPUT1 GP5
#define OUTPUT2 GP4
#define SW1 GP3
#define MOTOR GP2
#define INPUT1 AN0
#define INPUT2 AN1
/*状態の定義をしておく*/
#define ON 1
#define OFF 0
void content(short int Thre1, short int Thre2, short int Tim_sec);
LiLaC-functions.c
#include "LiLaC-v22functions.h"
#include
#include
void content(short int Thre1, short int Thre2, short int Tim_sec){
/*切り替えスイッチの値はSW_fとして 1=and 2=or に割り当てる*/
short int SW_f=0;
/*入力ポートの値はadc1 adc2 として 10bitの値を用いる*/
short int adc1,adc2;
/*入力結果(オンかオフか)は 2つのポートを in1_f in2_f として どちらも0か1が入る*/
short int in1_f,in2_f;
short int tim_cnt; /*ウエイトに使うカウンタ変数*/
/*内部クロックの設定 1MHzに設定*/
OSCCON = 0b01000000;
/*ポートの入出力の設定 4と5を出力 2と3を機能切り替えスイッチ 0と1をアナログ入力 データシート36pより
1が入力、0が出力*/
TRISIO =0b00001011;
/*AD変換クロック>2Tosc アナログ入力ピンの設定 0と1をアナログ入力 */
ANSEL = 0b00000011;
/*コンパレータはオフ*/
CMCON0 = 0b00000111;
/*切り替えスイッチはポートを内部でプルアップに設定(オプションレジスタを0で有効に)*/
OPTION_REGbits.nGPPU = 0;
/*切り替えスイッチはSW1=GP3 SW2=GP2 なのでそこをプルアップする >どうやらGP3は内部プルアップができないらしい>10KΩで*/
WPUbits.WPU2=1;
/*タイマー2の動作設定ポストスケーラ回数:毎回1 プリスケーラ分周比1:16 */
T2CON = 0b00000110;
/*PWMモードの指定 PWMオン */
CCP1CON = 0b00001100;
/*サーボモータ パルス周期 T=15ms T=(PR2設定値+1)×プリスケーラ分周比×クロック周期×4×ポストスケーラ回数
上記変形により PR2=233
角度(変数:angle)を 0?180°とすると angle×233÷180 によってホーンの位置が決定する。*/
PR2 = 255;
while(1){
/*INPUT1のデータを読み込んでadc1に入力*/
/*INPUT1 ADC初期設定*/
ADCON0 = 0b10000001;//右詰め|基準電圧は電源Vdd)|空白|空白||AN0|ADC終了|ADC有効
__delay_us(4);//ADC充電時間
GO = 1;//ADC変換開始
while(GO);//ADC変換終了までループ待機
adc1 = ADRESH*256 + ADRESL;//adc1にADC 0>1024段階の値を入れる
/*INPUT2のデータを読み込んでadc2に入力*/
/*INPUT2 ADC初期設定*/
ADCON0 = 0b10000101;//右詰め|基準電圧は電源Vdd)|空白|空白||AN1|ADC終了|ADC有効
__delay_us(1);//ADC充電時間
GO = 1;//ADC変換開始
while(GO);//ADC変換終了までループ待機
adc2 = ADRESH*256 + ADRESL;//adc2にADC 0>1024段階の値を入れる
/*AD変換した結果をデジタルのオンオフデータに*/
if(adc1 > Thre1){ /*INPUT1の値*/
in1_f = 1; /*しきい値より大きければ 1 */
}
else{
in1_f = 0; /*しきい値より小さければ 0 */
}
if(adc2 > Thre2){ /*INPUT2の値*/
in2_f = 1; /*しきい値より大きければ 1 */
}
else{
in2_f = 0; /*しきい値より小さければ 0 */
}
/*論理回路選択スイッチの値(SW_f)をセットする SW1 on=0 off=1 */
/*プルアップしているため このスイッチは オンが0 オフが1 */
if (SW1 == 0){
SW_f = 1;
}
if (SW1 == 1){
SW_f = 2;
}
/*論理選択スイッチの値によって分岐する*/
switch(SW_f){
case 1:
/*AND回路 sw1>ON */
if (in1_f & in2_f){ /*AND演算*/
OUTPUT1 = ON;
OUTPUT2 = ON;
CCPR1L = 23;
tim_cnt = 0; /*onになっている指定時間を待つ*/
while(Tim_sec > tim_cnt){
__delay_ms(1000);
tim_cnt++;
}
}
else{
OUTPUT1 = OFF;
OUTPUT2 = OFF;
CCPR1L = 7.5;
}
break;
case 2:
/*OR回路 sw1>off */
if (in1_f | in2_f){ /*OR演算*/
OUTPUT1 = ON;
OUTPUT2 = ON;
CCPR1L = 38;
tim_cnt = 0; /*onになっている指定時間を待つ*/
while(Tim_sec > tim_cnt){
__delay_ms(1000);
tim_cnt++;
}
}
else{
OUTPUT1 = OFF;
OUTPUT2 = OFF;
CCPR1L = 7.5;
}
break;
}
}
}