ファンクション・ジェネレータ.出力信号:正弦波,矩形波,矩形波 (5倍波まで).ノイズの付加が可能.

Dependencies:   mbed SerialTxRxIntr Random

Committer:
MikamiUitOpen
Date:
Mon Jan 07 11:06:16 2019 +0000
Revision:
7:5d1c170065d8
Parent:
6:acd06b435799
8

Who changed what in which revision?

UserRevisionLine numberNew 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 7:5d1c170065d8 24 // 2019/01/07, 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 6:acd06b435799 42 DacF446 dac_; // DA 変換器オブジェクト
MikamiUitOpen 6:acd06b435799 43 MyTicker7 timer_; // タイマ割り込み用クラスのオブジェクト,TIM7 を利用
MikamiUitOpen 6:acd06b435799 44 SerialRxTxIntr rxTx_; // Serial クラスの受送信割込み用オブジェクト
MikamiUitOpen 6:acd06b435799 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 6:acd06b435799 49 float volume_ = 0.5f; // 出力の振幅を決める変数,開始時は 0.5
MikamiUitOpen 6:acd06b435799 50 bool sw_ = false; // 出力 ON/OFF のスイッチ,開始時は off
MikamiUitOpen 6:acd06b435799 51 float volNoize_ = 0.5f; // ノイズの大きさを決める変数
MikamiUitOpen 0:d11ff22a164f 52
MikamiUitOpen 0:d11ff22a164f 53 // ノイズ付加に関する関数等
MikamiUitOpen 6:acd06b435799 54 GaussRand rnd_(0.3f, 0); // 標準偏差:0.3, 平均値:0
MikamiUitOpen 6:acd06b435799 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 6:acd06b435799 66 float x = (sinx >= 0) ? volume_ : -volume_;
MikamiUitOpen 6:acd06b435799 67 return x + 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 6:acd06b435799 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 }