ファンクション・ジェネレータ.出力信号:正弦波,矩形波,矩形波 (5倍波まで).ノイズの付加が可能.
Dependencies: mbed SerialTxRxIntr Random
main.cpp@5:5dca27575a3d, 2018-11-30 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Fri Nov 30 12:50:18 2018 +0000
- Revision:
- 5:5dca27575a3d
- Parent:
- 4:925a2ab34c03
- Child:
- 6:acd06b435799
6
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:d11ff22a164f | 1 | //---------------------------------------------------------------------- |
MikamiUitOpen | 3:e4e95731cab9 | 2 | // ファンクション・ジェネレータ (Function generator) |
MikamiUitOpen | 0:d11ff22a164f | 3 | // |
MikamiUitOpen | 0:d11ff22a164f | 4 | // 設定できる項目 |
MikamiUitOpen | 3:e4e95731cab9 | 5 | // 波形の種類: 正弦波,矩形波,矩形波(フーリエ級数の5倍波までの和) |
MikamiUitOpen | 0:d11ff22a164f | 6 | // 振幅: 0.00 ~ 1.00 倍 |
MikamiUitOpen | 3:e4e95731cab9 | 7 | // 周波数: 10 Hz ~ 5 kHz |
MikamiUitOpen | 0:d11ff22a164f | 8 | // ノイズ付加の有無 |
MikamiUitOpen | 0:d11ff22a164f | 9 | // 標本化間隔:5 μs |
MikamiUitOpen | 0:d11ff22a164f | 10 | // 使用タイマ:TIM7 |
MikamiUitOpen | 3:e4e95731cab9 | 11 | // 信号出力のピン: A3 |
MikamiUitOpen | 3:e4e95731cab9 | 12 | // 同期信号出力のピン: A5 |
MikamiUitOpen | 0:d11ff22a164f | 13 | // |
MikamiUitOpen | 0:d11ff22a164f | 14 | // PC 側のプログラム |
MikamiUitOpen | 0:d11ff22a164f | 15 | // F446_FunctionGenerator |
MikamiUitOpen | 0:d11ff22a164f | 16 | // 端末エミュレータでも使用可能(確認しているのは Tera Term のみ) |
MikamiUitOpen | 0:d11ff22a164f | 17 | // |
MikamiUitOpen | 3:e4e95731cab9 | 18 | // 注意 |
MikamiUitOpen | 3:e4e95731cab9 | 19 | // コマンド等が不正であるかどうかは,PC 側の処理にゆだねられている.そのため, |
MikamiUitOpen | 3:e4e95731cab9 | 20 | // 端末エミュレータから操作する場合,不正なコマンド等に対しては,基本的に無視す |
MikamiUitOpen | 3:e4e95731cab9 | 21 | // るようなプログラムになっている. |
MikamiUitOpen | 3:e4e95731cab9 | 22 | // 端末エミュレータからの Back Space キーの入力には対応していない. |
MikamiUitOpen | 3:e4e95731cab9 | 23 | // |
MikamiUitOpen | 5:5dca27575a3d | 24 | // 2018/11/30, Copyright (c) 2018 MIKAMI, Naoki |
MikamiUitOpen | 0:d11ff22a164f | 25 | //---------------------------------------------------------------------- |
MikamiUitOpen | 0:d11ff22a164f | 26 | |
MikamiUitOpen | 0:d11ff22a164f | 27 | #include "F446_DAC.hpp" |
MikamiUitOpen | 0:d11ff22a164f | 28 | #include "SerialRxTxIntr.hpp" |
MikamiUitOpen | 0:d11ff22a164f | 29 | #include "MyTicker7.hpp" |
MikamiUitOpen | 0:d11ff22a164f | 30 | #include "GaussRand.hpp" |
MikamiUitOpen | 0:d11ff22a164f | 31 | #include <cctype> // isalpha() で使用 |
MikamiUitOpen | 0:d11ff22a164f | 32 | #pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため |
MikamiUitOpen | 0:d11ff22a164f | 33 | |
MikamiUitOpen | 0:d11ff22a164f | 34 | using namespace Mikami; |
MikamiUitOpen | 0:d11ff22a164f | 35 | |
MikamiUitOpen | 0:d11ff22a164f | 36 | const int T0_ = 5; // 出力の標本化間隔: 5 μs |
MikamiUitOpen | 0:d11ff22a164f | 37 | const float TS_ = T0_*1.0e-6; |
MikamiUitOpen | 0:d11ff22a164f | 38 | const float PI2_ = 3.141593f*2; |
MikamiUitOpen | 0:d11ff22a164f | 39 | const float ONE_3_ = 1.0f/3.0f; // フーリエ級数の計算で使用 |
MikamiUitOpen | 0:d11ff22a164f | 40 | const float ONE_5_ = 0.2f; // フーリエ級数の計算で使用 |
MikamiUitOpen | 0:d11ff22a164f | 41 | |
MikamiUitOpen | 0:d11ff22a164f | 42 | DacF446 dac_; // DA 変換器オブジェクト |
MikamiUitOpen | 0:d11ff22a164f | 43 | MyTicker7 timer_; // タイマ割り込み用クラスのオブジェクト,TIM7 を利用 |
MikamiUitOpen | 0:d11ff22a164f | 44 | SerialRxTxIntr rxTx_; // Serial クラスの受送信割込み用オブジェクト |
MikamiUitOpen | 0:d11ff22a164f | 45 | DigitalOut syncOut_(A5); // 同期信号出力用 |
MikamiUitOpen | 0:d11ff22a164f | 46 | |
MikamiUitOpen | 0:d11ff22a164f | 47 | float phi_ = 0; |
MikamiUitOpen | 0:d11ff22a164f | 48 | float dPhi_ = PI2_*1000*TS_; // 周波数決める変数,開始時は 1 kHz; |
MikamiUitOpen | 0:d11ff22a164f | 49 | float volume_ = 0.5f; // 出力の振幅を決める変数,開始時は 0.5 |
MikamiUitOpen | 0:d11ff22a164f | 50 | bool sw_ = false; // 出力 ON/OFF のスイッチ,開始時は off |
MikamiUitOpen | 0:d11ff22a164f | 51 | float volNoize_ = 0.5f; // ノイズの大きさを決める変数 |
MikamiUitOpen | 0:d11ff22a164f | 52 | |
MikamiUitOpen | 0:d11ff22a164f | 53 | // ノイズ付加に関する関数等 |
MikamiUitOpen | 0:d11ff22a164f | 54 | GaussRand rnd(0.3f, 0); |
MikamiUitOpen | 0:d11ff22a164f | 55 | float Noise() { return volNoize_*rnd.Next(); } |
MikamiUitOpen | 0:d11ff22a164f | 56 | float NoiseFree() { return 0; } |
MikamiUitOpen | 0:d11ff22a164f | 57 | float (*fpNoize[])() = { Noise, NoiseFree }; |
MikamiUitOpen | 0:d11ff22a164f | 58 | float (*fpN)() = fpNoize[1]; // 起動時はノイズなし |
MikamiUitOpen | 0:d11ff22a164f | 59 | |
MikamiUitOpen | 0:d11ff22a164f | 60 | // 発生する信号を定義する関数 |
MikamiUitOpen | 0:d11ff22a164f | 61 | // 正弦波 |
MikamiUitOpen | 0:d11ff22a164f | 62 | float Sin(float sinx) { return volume_*sinx + volNoize_*fpN(); } |
MikamiUitOpen | 0:d11ff22a164f | 63 | // 矩形波 |
MikamiUitOpen | 0:d11ff22a164f | 64 | float Rect(float sinx) |
MikamiUitOpen | 0:d11ff22a164f | 65 | { |
MikamiUitOpen | 0:d11ff22a164f | 66 | sinx = (sinx >= 0) ? volume_ : -volume_; |
MikamiUitOpen | 0:d11ff22a164f | 67 | return sinx + volNoize_*fpN(); |
MikamiUitOpen | 0:d11ff22a164f | 68 | } |
MikamiUitOpen | 0:d11ff22a164f | 69 | // 矩形波(5倍波まで) |
MikamiUitOpen | 0:d11ff22a164f | 70 | float Compo(float sinx) |
MikamiUitOpen | 0:d11ff22a164f | 71 | { return volume_*(sinx + ONE_3_*sinf(3*phi_) + ONE_5_*sinf(5*phi_)) |
MikamiUitOpen | 0:d11ff22a164f | 72 | + volNoize_*fpN(); } |
MikamiUitOpen | 0:d11ff22a164f | 73 | |
MikamiUitOpen | 0:d11ff22a164f | 74 | float (*fp[])(float x) = { Sin, Rect, Compo }; |
MikamiUitOpen | 0:d11ff22a164f | 75 | float (*fpS)(float x) = fp[0]; // 起動時は正弦波 |
MikamiUitOpen | 0:d11ff22a164f | 76 | |
MikamiUitOpen | 0:d11ff22a164f | 77 | // タイマ割り込みに対する割込みサービス・ルーチン |
MikamiUitOpen | 0:d11ff22a164f | 78 | void TimerIsr() |
MikamiUitOpen | 0:d11ff22a164f | 79 | { |
MikamiUitOpen | 0:d11ff22a164f | 80 | float sinx = sinf(phi_); // 基本波発生 |
MikamiUitOpen | 0:d11ff22a164f | 81 | float yn = fpS(sinx); // 信号発生 |
MikamiUitOpen | 0:d11ff22a164f | 82 | |
MikamiUitOpen | 0:d11ff22a164f | 83 | // 同期信号出力 |
MikamiUitOpen | 0:d11ff22a164f | 84 | syncOut_ = (sinx >= 0) ? 1 : 0; |
MikamiUitOpen | 0:d11ff22a164f | 85 | |
MikamiUitOpen | 0:d11ff22a164f | 86 | if (sw_) dac_.Write(yn); // 出力:ON |
MikamiUitOpen | 0:d11ff22a164f | 87 | else dac_.Write(0.0f); // 出力:OFF |
MikamiUitOpen | 0:d11ff22a164f | 88 | |
MikamiUitOpen | 0:d11ff22a164f | 89 | phi_ += dPhi_; |
MikamiUitOpen | 0:d11ff22a164f | 90 | if (phi_ >= PI2_) phi_ = phi_ - PI2_; // オーバーフロー防止 |
MikamiUitOpen | 0:d11ff22a164f | 91 | } |
MikamiUitOpen | 0:d11ff22a164f | 92 | |
MikamiUitOpen | 0:d11ff22a164f | 93 | int main() |
MikamiUitOpen | 0:d11ff22a164f | 94 | { |
MikamiUitOpen | 0:d11ff22a164f | 95 | // 以下の割り込み優先順位の設定を忘れないこと |
MikamiUitOpen | 0:d11ff22a164f | 96 | NVIC_SetPriority(TIM7_IRQn, 0); |
MikamiUitOpen | 0:d11ff22a164f | 97 | NVIC_SetPriority(USART2_IRQn, 1); // USART2 割り込み:次に優先 |
MikamiUitOpen | 0:d11ff22a164f | 98 | |
MikamiUitOpen | 1:087c9baf26d0 | 99 | rxTx_.EchobackEnable(); // エコーバックを有効にする |
MikamiUitOpen | 1:087c9baf26d0 | 100 | |
MikamiUitOpen | 3:e4e95731cab9 | 101 | printf("\r\n\n+-------------------------------------------------------------------+\r\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 102 | printf("| Microcontroller-based function generator, (C) MIKAMI, Naoki 2018. |\r\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 103 | printf("| You can alse use with terminal emulator like Tera Term. |\r\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 104 | printf("| You can use lowercase letters as command. |\r\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 105 | printf("+-------------------------------------------------------------------+\r\n\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 106 | printf("<Command>\r\n"); |
MikamiUitOpen | 0:d11ff22a164f | 107 | printf("ON Ountput enabled.\r\n"); |
MikamiUitOpen | 0:d11ff22a164f | 108 | printf("OFF Ountput disabled.\r\n"); |
MikamiUitOpen | 0:d11ff22a164f | 109 | printf("SIN Output: Sinusoidal wave.\r\n"); |
MikamiUitOpen | 0:d11ff22a164f | 110 | printf("RECT Output: Square wave.\r\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 111 | printf("COMPO Output: Square wave (Sum of up to 5th harmonics).\r\n"); |
MikamiUitOpen | 0:d11ff22a164f | 112 | printf("NsOn With noize.\r\n"); |
MikamiUitOpen | 2:46bbe00aecc3 | 113 | printf("NsOff Without noise.\r\n\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 114 | printf("<Command with numeric value (n: 0 to 9)>\r\n"); |
MikamiUitOpen | 0:d11ff22a164f | 115 | printf("#+'n.nn' Relative ampliude of output: 0.00 to 1.00.\r\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 116 | printf("$+'nnnn' Frequency: 10 to 5000 [Hz].\r\n"); |
MikamiUitOpen | 3:e4e95731cab9 | 117 | printf("%%+'n.nn' Relative magnitude of noize: 0.00 to 1.00.\r\n\n"); |
MikamiUitOpen | 4:925a2ab34c03 | 118 | rxTx_.Tx("? "); |
MikamiUitOpen | 0:d11ff22a164f | 119 | |
MikamiUitOpen | 0:d11ff22a164f | 120 | timer_.Attach_us(&TimerIsr, T0_); // タイマ割り込み設定 |
MikamiUitOpen | 0:d11ff22a164f | 121 | |
MikamiUitOpen | 0:d11ff22a164f | 122 | while (true) // PC からの指令に対応する処理 |
MikamiUitOpen | 0:d11ff22a164f | 123 | { |
MikamiUitOpen | 0:d11ff22a164f | 124 | if (rxTx_.IsEol()) // 受信バッファのデータが有効になった場合の処理 |
MikamiUitOpen | 0:d11ff22a164f | 125 | { |
MikamiUitOpen | 0:d11ff22a164f | 126 | string str = rxTx_.GetBuffer(); |
MikamiUitOpen | 3:e4e95731cab9 | 127 | for (int n=0; n<str.size(); n++) str[n] = toupper(str[n]); |
MikamiUitOpen | 0:d11ff22a164f | 128 | if (isalpha(str[0])) // 先頭が A ~ Z, a ~ z の場合 |
MikamiUitOpen | 0:d11ff22a164f | 129 | { |
MikamiUitOpen | 4:925a2ab34c03 | 130 | if (str == "FG") |
MikamiUitOpen | 4:925a2ab34c03 | 131 | rxTx_.Tx("ACK\n"); // PC からの "FG" に対して "ACK" を送信する |
MikamiUitOpen | 0:d11ff22a164f | 132 | |
MikamiUitOpen | 4:925a2ab34c03 | 133 | if (str == "ON") sw_ = true; |
MikamiUitOpen | 4:925a2ab34c03 | 134 | if (str == "OFF") sw_ = false; |
MikamiUitOpen | 0:d11ff22a164f | 135 | |
MikamiUitOpen | 4:925a2ab34c03 | 136 | if (str == "SIN") fpS = fp[0]; |
MikamiUitOpen | 4:925a2ab34c03 | 137 | if (str == "RECT") fpS = fp[1]; |
MikamiUitOpen | 4:925a2ab34c03 | 138 | if (str == "COMPO") fpS = fp[2]; |
MikamiUitOpen | 0:d11ff22a164f | 139 | |
MikamiUitOpen | 4:925a2ab34c03 | 140 | if (str == "NSON") fpN = fpNoize[0]; |
MikamiUitOpen | 4:925a2ab34c03 | 141 | if (str == "NSOFF") fpN = fpNoize[1]; |
MikamiUitOpen | 0:d11ff22a164f | 142 | } |
MikamiUitOpen | 0:d11ff22a164f | 143 | else // 先頭が A ~ Z, a ~ z 以外の場合 |
MikamiUitOpen | 0:d11ff22a164f | 144 | { |
MikamiUitOpen | 0:d11ff22a164f | 145 | char c1 = str[0]; // 先頭の文字を取得 |
MikamiUitOpen | 0:d11ff22a164f | 146 | float x = atof(str.substr(1, str.size()-1).c_str()); |
MikamiUitOpen | 3:e4e95731cab9 | 147 | if (x >= 0.0f) |
MikamiUitOpen | 3:e4e95731cab9 | 148 | { |
MikamiUitOpen | 3:e4e95731cab9 | 149 | if (c1 == '#') // 出力振幅の変更 |
MikamiUitOpen | 3:e4e95731cab9 | 150 | volume_ = (x < 1.0f) ? x : 1.0f; |
MikamiUitOpen | 3:e4e95731cab9 | 151 | if (c1 == '$') // 周波数の変更 |
MikamiUitOpen | 3:e4e95731cab9 | 152 | { |
MikamiUitOpen | 3:e4e95731cab9 | 153 | x = (x < 10) ? 10 : x; |
MikamiUitOpen | 3:e4e95731cab9 | 154 | x = (x > 5000) ? 5000 : x; |
MikamiUitOpen | 3:e4e95731cab9 | 155 | dPhi_ = PI2_*x*TS_; |
MikamiUitOpen | 3:e4e95731cab9 | 156 | } |
MikamiUitOpen | 3:e4e95731cab9 | 157 | if (c1 == '%') // ノイズの大きさの変更 |
MikamiUitOpen | 3:e4e95731cab9 | 158 | volNoize_ = (x < 1.0f) ? x : 1.0f; |
MikamiUitOpen | 3:e4e95731cab9 | 159 | } |
MikamiUitOpen | 0:d11ff22a164f | 160 | } |
MikamiUitOpen | 4:925a2ab34c03 | 161 | rxTx_.Tx("? "); |
MikamiUitOpen | 0:d11ff22a164f | 162 | } |
MikamiUitOpen | 0:d11ff22a164f | 163 | } |
MikamiUitOpen | 0:d11ff22a164f | 164 | } |