realtime process control with RTOS

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

main.cpp

Committer:
ykuroda
Date:
2018-10-18
Revision:
24:e414c7234bcc
Parent:
23:bc5ad77d56bb

File content as of revision 24:e414c7234bcc:

//  mbed-os-io-control
//  I/O制御プログラム(機械工学実験1)
//
//  20161027 ... v1.0 ... originally written by Y.Kuroda for Mechatronics
//  20180917 ... v2.0 ... customised for Jikken1(mbed LPC1768専用)
//  20181004 ... v3.0 ... uses EventQueue
//
#include "mbed.h"

const int DELTA_T = 1;    // mainスレッドの時間間隔の設定[ms](デフォルトは1ms)
int delta_t = DELTA_T;
int qbits = 6;            // 量子化シフト値
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led4(LED4);

// p11,12 サンプリング周期設定ピン(デフォルトは0)
// p11上位ビット,p12下位ビット.0:1kHz, 1: 100Hz, 2: 10Hz, 3: 1Hz
InterruptIn samplingtime_MSB(p11);
InterruptIn samplingtime_LSB(p12);

// p13,14 量子化粒度設定ピン(デフォルトは0)
// p13上位ビット,p14下位ビット.0:10bit, 1:8bit, 2:6bit, 3:4bit
InterruptIn quantization_MSB(p13);
InterruptIn quantization_LSB(p14);

// アナログ入出力ピン(入出力共に0 - 3.3V)
AnalogOut aout(p18);
AnalogIn  ain(p20);

// デジタル入力ピン(割り込みにより実現)
InterruptIn din1(p21);
InterruptIn din2(p22);

// 方形波,パルス波出力ピン
PwmOut squarewave(p23);
PwmOut pulsewave(p24);

const int SIG_ST = 0x1;    // signal番号
Thread* sthread;
EventQueue queue;
int id = 0;

// サンプリング処理をするスレッド(時間管理された処理)
void sampling_job(void* v)
{
    unsigned short a_data  = ain.read_u16(); // AD入力(ADは12ビット)
    aout.write_u16((a_data>>qbits)<<qbits);// DA出力(量子化粒度はピンにより設定)
    led4 = !led4;
}

void setup_thread(void const* arg)     // 設定処理をするスレッド
{
    while(true) {
        Thread::signal_wait(SIG_ST);   // シグナルを待つ

        // ピンの状態を読み取り,2ビット値に変換
        int s_msb = 10, s_lsb = 10;
        int q_msb = 10, q_lsb = 10;
        const int RETRY = 100;  // 100回調べて9割以上1なら1,それ以下なら0とする.
        for(int i=0; i<RETRY; i++) {
            s_msb += samplingtime_MSB;
            s_lsb += samplingtime_LSB;
            q_msb += quantization_MSB;
            q_lsb += quantization_LSB;
        }
        s_msb /= RETRY; s_lsb /= RETRY;
        q_msb /= RETRY; q_lsb /= RETRY;

        int samplingtime = (s_msb<<1)&0x2 | s_lsb&0x1;

        // 制御周期を10^nとする(n=0:1s, n=1:0.1s, n=2:0.01s, n=3:0.001s)
        delta_t = (int)pow(10.0,(double)samplingtime);


        squarewave.period_ms(delta_t);  // 方形波の周期の設定
        pulsewave.period_ms(delta_t);   // パルス波の周期の設定
        squarewave.write(0.5F);         // duty比
        pulsewave.write(0.1F);          // duty比

        // 量子化設定ピン(p13,14)の設定を読んで量子化粒度を決定する
        // 設定ピンの状態を読み取り,2ビット値に変換
        int quantization = (q_msb<<1)&0x2 | q_lsb&0x1;
        qbits = 6+quantization*4;   // 量子化サイズの決定
        // (デジタル出力時の量子化サイズは 0:1024, 1:256, 2:64, 3:16 steps)

        queue.cancel(id);   // 前回のプロセスキューをキャンセル
        printf("delta_t = %d, qbits = %d\n", delta_t, qbits);
        id = queue.call_every(delta_t, sampling_job, (void*)0);
    }
}

// 量子化粒度設定ハンドラ
void qsize_handler(void)
{
    sthread->signal_set(SIG_ST);  // スレッドへ再開シグナルを送る
}

//  サンプリングタイム設定割り込みハンドラ...時間設定ピンの状態が変化した時に呼び出される
void pinstate_handler(void)
{
    sthread->signal_set(SIG_ST);  // スレッドへ再開シグナルを送る
}

//  デジタル入力割り込みハンドラ...デジタル入力信号の状態が変化した時に呼び出される
void din_handler(void)
{
    led1 = din1;    // ピンの状態をそのままLEDの点灯状態にする
    led2 = din2;
}

int main()
{
    sthread = new Thread(setup_thread);   // 設定用スレッドを起動


    squarewave.period_ms(delta_t);  // 初期周期の設定
    pulsewave.period_ms(delta_t);   // 初期周期の設定
    squarewave.write(0.5F);         // 初期duty比(方形波=50%)
    pulsewave.write(0.1F);          // 初期duty比(パルス波=10%)

    samplingtime_MSB.disable_irq();
    samplingtime_MSB.mode(PullDown);
    samplingtime_MSB.rise(pinstate_handler);// 周期設定ハンドラの設定.
    samplingtime_MSB.fall(pinstate_handler);// 設定ピンの状態変化で
    samplingtime_MSB.enable_irq();

    samplingtime_LSB.disable_irq();
    samplingtime_LSB.mode(PullDown);
    samplingtime_LSB.rise(pinstate_handler);// ハンドラが呼び出される
    samplingtime_LSB.fall(pinstate_handler);// ようにする
    samplingtime_LSB.enable_irq();

    quantization_MSB.disable_irq();
    quantization_MSB.mode(PullDown);
    quantization_MSB.rise(qsize_handler);   // 量子化粒度設定ハンドラの設定
    quantization_MSB.fall(qsize_handler);
    quantization_MSB.enable_irq();

    quantization_LSB.disable_irq();
    quantization_LSB.mode(PullDown);
    quantization_LSB.rise(qsize_handler);
    quantization_LSB.fall(qsize_handler);
    quantization_LSB.enable_irq();

    din1.disable_irq();
    din1.mode(PullDown);
    din1.rise(&din_handler);            // デジタル入力ハンドラの設定
    din1.fall(&din_handler);            // din1,2の状態変化でハンドラ
    din1.enable_irq();

    din2.disable_irq();
    din2.mode(PullDown);
    din2.rise(&din_handler);            // が呼ばれる
    din2.fall(&din_handler);
    din2.enable_irq();

    id = queue.call_every(delta_t, sampling_job, (void*)0);
    queue.dispatch();
}