ファンクション・ジェネレータ.出力信号:正弦波,矩形波,矩形波 (5倍波まで).ノイズの付加が可能.
Dependencies: mbed SerialTxRxIntr Random
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2018-11-30
- Revision:
- 5:5dca27575a3d
- Parent:
- 4:925a2ab34c03
- Child:
- 6:acd06b435799
File content as of revision 5:5dca27575a3d:
//---------------------------------------------------------------------- // ファンクション・ジェネレータ (Function generator) // // 設定できる項目 // 波形の種類: 正弦波,矩形波,矩形波(フーリエ級数の5倍波までの和) // 振幅: 0.00 ~ 1.00 倍 // 周波数: 10 Hz ~ 5 kHz // ノイズ付加の有無 // 標本化間隔:5 μs // 使用タイマ:TIM7 // 信号出力のピン: A3 // 同期信号出力のピン: A5 // // PC 側のプログラム // F446_FunctionGenerator // 端末エミュレータでも使用可能(確認しているのは Tera Term のみ) // // 注意 // コマンド等が不正であるかどうかは,PC 側の処理にゆだねられている.そのため, // 端末エミュレータから操作する場合,不正なコマンド等に対しては,基本的に無視す // るようなプログラムになっている. // 端末エミュレータからの Back Space キーの入力には対応していない. // // 2018/11/30, Copyright (c) 2018 MIKAMI, Naoki //---------------------------------------------------------------------- #include "F446_DAC.hpp" #include "SerialRxTxIntr.hpp" #include "MyTicker7.hpp" #include "GaussRand.hpp" #include <cctype> // isalpha() で使用 #pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため using namespace Mikami; const int T0_ = 5; // 出力の標本化間隔: 5 μs const float TS_ = T0_*1.0e-6; const float PI2_ = 3.141593f*2; const float ONE_3_ = 1.0f/3.0f; // フーリエ級数の計算で使用 const float ONE_5_ = 0.2f; // フーリエ級数の計算で使用 DacF446 dac_; // DA 変換器オブジェクト MyTicker7 timer_; // タイマ割り込み用クラスのオブジェクト,TIM7 を利用 SerialRxTxIntr rxTx_; // Serial クラスの受送信割込み用オブジェクト DigitalOut syncOut_(A5); // 同期信号出力用 float phi_ = 0; float dPhi_ = PI2_*1000*TS_; // 周波数決める変数,開始時は 1 kHz; float volume_ = 0.5f; // 出力の振幅を決める変数,開始時は 0.5 bool sw_ = false; // 出力 ON/OFF のスイッチ,開始時は off float volNoize_ = 0.5f; // ノイズの大きさを決める変数 // ノイズ付加に関する関数等 GaussRand rnd(0.3f, 0); float Noise() { return volNoize_*rnd.Next(); } float NoiseFree() { return 0; } float (*fpNoize[])() = { Noise, NoiseFree }; float (*fpN)() = fpNoize[1]; // 起動時はノイズなし // 発生する信号を定義する関数 // 正弦波 float Sin(float sinx) { return volume_*sinx + volNoize_*fpN(); } // 矩形波 float Rect(float sinx) { sinx = (sinx >= 0) ? volume_ : -volume_; return sinx + volNoize_*fpN(); } // 矩形波(5倍波まで) float Compo(float sinx) { return volume_*(sinx + ONE_3_*sinf(3*phi_) + ONE_5_*sinf(5*phi_)) + volNoize_*fpN(); } float (*fp[])(float x) = { Sin, Rect, Compo }; float (*fpS)(float x) = fp[0]; // 起動時は正弦波 // タイマ割り込みに対する割込みサービス・ルーチン void TimerIsr() { float sinx = sinf(phi_); // 基本波発生 float yn = fpS(sinx); // 信号発生 // 同期信号出力 syncOut_ = (sinx >= 0) ? 1 : 0; if (sw_) dac_.Write(yn); // 出力:ON else dac_.Write(0.0f); // 出力:OFF phi_ += dPhi_; if (phi_ >= PI2_) phi_ = phi_ - PI2_; // オーバーフロー防止 } int main() { // 以下の割り込み優先順位の設定を忘れないこと NVIC_SetPriority(TIM7_IRQn, 0); NVIC_SetPriority(USART2_IRQn, 1); // USART2 割り込み:次に優先 rxTx_.EchobackEnable(); // エコーバックを有効にする printf("\r\n\n+-------------------------------------------------------------------+\r\n"); printf("| Microcontroller-based function generator, (C) MIKAMI, Naoki 2018. |\r\n"); printf("| You can alse use with terminal emulator like Tera Term. |\r\n"); printf("| You can use lowercase letters as command. |\r\n"); printf("+-------------------------------------------------------------------+\r\n\n"); printf("<Command>\r\n"); printf("ON Ountput enabled.\r\n"); printf("OFF Ountput disabled.\r\n"); printf("SIN Output: Sinusoidal wave.\r\n"); printf("RECT Output: Square wave.\r\n"); printf("COMPO Output: Square wave (Sum of up to 5th harmonics).\r\n"); printf("NsOn With noize.\r\n"); printf("NsOff Without noise.\r\n\n"); printf("<Command with numeric value (n: 0 to 9)>\r\n"); printf("#+'n.nn' Relative ampliude of output: 0.00 to 1.00.\r\n"); printf("$+'nnnn' Frequency: 10 to 5000 [Hz].\r\n"); printf("%%+'n.nn' Relative magnitude of noize: 0.00 to 1.00.\r\n\n"); rxTx_.Tx("? "); timer_.Attach_us(&TimerIsr, T0_); // タイマ割り込み設定 while (true) // PC からの指令に対応する処理 { if (rxTx_.IsEol()) // 受信バッファのデータが有効になった場合の処理 { string str = rxTx_.GetBuffer(); for (int n=0; n<str.size(); n++) str[n] = toupper(str[n]); if (isalpha(str[0])) // 先頭が A ~ Z, a ~ z の場合 { if (str == "FG") rxTx_.Tx("ACK\n"); // PC からの "FG" に対して "ACK" を送信する if (str == "ON") sw_ = true; if (str == "OFF") sw_ = false; if (str == "SIN") fpS = fp[0]; if (str == "RECT") fpS = fp[1]; if (str == "COMPO") fpS = fp[2]; if (str == "NSON") fpN = fpNoize[0]; if (str == "NSOFF") fpN = fpNoize[1]; } else // 先頭が A ~ Z, a ~ z 以外の場合 { char c1 = str[0]; // 先頭の文字を取得 float x = atof(str.substr(1, str.size()-1).c_str()); if (x >= 0.0f) { if (c1 == '#') // 出力振幅の変更 volume_ = (x < 1.0f) ? x : 1.0f; if (c1 == '$') // 周波数の変更 { x = (x < 10) ? 10 : x; x = (x > 5000) ? 5000 : x; dPhi_ = PI2_*x*TS_; } if (c1 == '%') // ノイズの大きさの変更 volNoize_ = (x < 1.0f) ? x : 1.0f; } } rxTx_.Tx("? "); } } }