カテゴリー: ニュース
ニュース
アクティブバンドパスフィルタ1
PCのサウンドライン出力に複数の周波数の信号を混合して出力し受け側で分離すれば1ラインを多重化できそうです。
二段増幅型バンドパスフィルター
1kHz
f0 = 1002.582Hz
Q = 20.788
R1 = 330kΩ
R2 = 15kΩ
R3 = 10kΩ + 6.8kΩ
R4, R5 = 10kΩ
C1, C2 = 0.01μF
6kHz
f0 = 5967.749Hz
Q = 20.788
R1 = 330kΩ
R2 = 15kΩ
R3 = 10kΩ + 6.8kΩ
R4, R5 = 10kΩ
C1, C2 = 1000pF + 680pF
11kHz
f0 = 11022.17Hz
Q = 22.854
R1 = 330kΩ
R2 = 15kΩ
R3 = 10kΩ + 3.9kΩ
R4, R5 = 10kΩ
C1, C2 = 1000pF
16kHz
f0 = 15921.863Hz
Q = 22.449
R1 = 330kΩ
R2, R3 = 10kΩ + 4.7kΩ
R4, R5 = 10kΩ
C1, C2 = 680pF
複数の周波数が混在した信号を利用する時にはフィルタで分離する必要があります。そのフィルタを評価するために指定範囲の周波数をスイープするジェネレーターを作りました。
#include <iostream> #include <windows.h> #include <math.h> #include <MMSystem.h> #pragma comment (lib, "winmm.lib") void createWave(LPWORD lpData, size_t frequency, size_t sampling, WORD amplitude) { size_t wavelength = sampling / frequency; double d = 360.0 / wavelength; double pi = 3.14159265359; for (int i = 0; i < wavelength; i++) { lpData[i] = (WORD)(amplitude * sin(d * (i % wavelength) / 180.0 * pi)); } } int main() { WAVEFORMATEX wfe; static HWAVEOUT hWaveOut; static WAVEHDR whdr; static LPWORD lpWave; static LPWORD lpData; // 最初と最後の1sは出力しないので3以上とする size_t terms = 7; size_t i, j, start, end; size_t frequency = 400; size_t sampling = 384000; size_t wavelength = sampling / frequency; wavelength = sampling / frequency; wfe.wFormatTag = WAVE_FORMAT_PCM; wfe.nChannels = 2; wfe.wBitsPerSample = 16; wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8; wfe.nSamplesPerSec = (DWORD)sampling; wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign; waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL); lpWave = (LPWORD)calloc(sizeof(WORD), wfe.nChannels * sampling * terms); end = sampling * wfe.nChannels * 1; WORD amplitude = 32767; for (i = 0; i < end; i++) { lpWave[i] = 0; } // 最初の1sは出力しない start = sampling * wfe.nChannels * 1; end = wfe.nChannels * sampling * terms; // 最後の1sは出力しない end -= sampling * wfe.nChannels * 1; size_t valWavelength; size_t valFrequency; for (i = start, j = 0; i < end; i += 2) { if (j == 0) { valFrequency = frequency + ((i - start) * (20000.0- frequency)) / (sampling * wfe.nChannels * (terms - 2)); valWavelength = sampling / valFrequency; lpData = (LPWORD)calloc(sizeof(WORD), valWavelength); createWave(lpData, valFrequency, sampling, amplitude); } lpWave[i] = lpData[j]; ++j; if (j >= valWavelength) { j = 0; free(lpData); } } lpData = (LPWORD)calloc(sizeof(WORD), wavelength); createWave(lpData, frequency, sampling, amplitude); for (i = start+1, j = 0; i < end; i += 2) { lpWave[i] = lpData[j]; ++j; if (j >= wavelength) { j = 0; } } free(lpData); whdr.lpData = (LPSTR)lpWave; whdr.dwBufferLength = wfe.nAvgBytesPerSec * terms; whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; whdr.dwLoops = 1; waveOutPrepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, &whdr, sizeof(WAVEHDR)); char str[128]; std::cout << "hello, world\n"; std::cin >> str; }
Flip Flops
ChatGPTに聞いてみた。
User
DM74LS74Nは何ですか。
ChatGPT
DM74LS74Nは、デュアルDフリップフロップ(Dual D Flip-Flop)IC(集積回路)の1つです。このICは、2つのDフリップフロップを持っており、デジタル回路においてデータの格納や信号の同期などに使用されます。
DM74LS74Nは、デュアルインラインパッケージ(DIP)で提供され、14ピンのパッケージングを採用しています。このICには、2つのDフリップフロップがあり、それぞれのフリップフロップには、D入力ピン、クロック入力ピン、セット入力ピン、リセット入力ピン、Q出力ピン、Qバー出力ピンがあります。
DM74LS74Nは、高速なデータの格納や同期、信号のフィルタリングなどに適しています。また、このICは、デジタルシステムにおけるカウンティングやタイミング、シーケンシャルロジック回路の実装などに広く使用されています。
Hex Schmitt Inverter
https://toshiba.semicon-storage.com/info/docget.jsp?did=9945&prodName=TC74HC14AP
ChatGPTに聞いてみた。
User
74HC14APは何ですか。
ChatGPT
74HC14APは、インバータ(Inverter)IC(集積回路)の1つです。このICは、6つのインバータを持っており、入力信号を反転し、出力信号を生成することができます。また、このICは、高速で動作し、低消費電力であるため、多くのデジタルシステムに適しています。
74HC14APは、デュアルインラインパッケージ(DIP)で提供され、14ピンのパッケージングを採用しています。このICには、6つのインバータがあり、それぞれのインバータには、入力ピンと出力ピンがあります。
74HC14APは、高速な信号反転や駆動、多くのデジタルシステムでの信号調整などのアプリケーションに適しています。また、このICは、パルスジェネレーション、クロックドライバ、バッファリングなどのために、広く使用されています。
QuadrupleBus BufferGatesWith 3-StateOutputs
http://www.ti.com/lit/ds/scls104e/scls104e.pdf?ts=1591310379048
ChatGPTに聞いてみた。
User
SN74HC125Nは何ですか。
ChatGPT
SN74HC125Nは、バッファ/ラインドライバ(Buffer/Line Driver)IC(集積回路)の1つです。このICは、4つのバッファを持っており、入力信号を増幅し、出力信号を駆動することができます。また、このICは、高速で動作し、消費電力が少ないため、多くのデジタルシステムに適しています。
SN74HC125Nは、デュアルインラインパッケージ(DIP)で提供され、14ピンのパッケージングを採用しています。このICには、4つのバッファがあり、それぞれのバッファには、入力ピンと出力ピンがあります。また、バッファは、3つのステートメントコントロール入力(G、OE、nOE)を持っています。Gは、全体のICを有効化または無効化するために使用されます。OEは、すべてのバッファの出力を有効化または無効化するために使用されます。nOEは、単一のバッファの出力を有効化または無効化するために使用されます。
SN74HC125Nは、高速な信号増幅や駆動、多くのデジタルシステムでの信号調整などのアプリケーションに適しています。また、このICは、信号増幅、バッファリング、レベル変換などのために、広く使用されています。
Octal Bus TransceiversWith 3-StateOutputs
http://www.ti.com/lit/ds/symlink/sn54ls245-sp.pdf?ts=1591310459915
ChatGPTに聞いてみた。
User
SN74LS245Nは何ですか。
ChatGPT
SN74LS245Nは、バストランシーバ(Bus Transceiver)IC(集積回路)の1つです。このICは、2つのバス間で双方向通信を実現するために使用されます。バスは、データ、アドレス、および制御信号などの複数の信号線のグループです。
SN74LS245Nは、デュアルインラインパッケージ(DIP)で提供され、20ピンのパッケージングを採用しています。このICには、8つの入力/出力(I/O)ピンがあります。それぞれのピンは、片方向の入力または出力として機能することができます。また、このICは、入力と出力を切り替えるために、DIR(方向)ピンを持っています。DIRピンがHIGHの場合、ICは1つのバスからもう一方のバスにデータを送信します。DIRピンがLOWの場合、ICは逆方向に動作します。
SN74LS245Nは、高速で信頼性の高いバス通信を実現するために設計されています。また、このICは、複数のデバイス間で信号を送受信するために広く使用されています。
ChatGPTに聞いてみた。
User
SN74LS153Nは何ですか。
ChatGPT
SN74LS153Nは、デジタル回路に使用される4入力マルチプレクサ(Multiplexer)IC(集積回路)の1つです。このICは、2つの2入力マルチプレクサが統合されており、入力信号の1つを選択し、1つの出力に送信することができます。また、このICは、高速で動作し、低消費電力で動作するため、多くのデジタルシステムに適しています。
SN74LS153Nは、デュアルインラインパッケージ(DIP)で提供され、16ピンのパッケージングを採用しています。このICには、4つのデータ入力、2つの選択入力、1つの出力があります。選択入力は、2つのビットで指定され、4つのデータ入力のうち1つを選択し、選択された入力信号を出力に送信します。SN74LS153Nは、高速なデータスイッチングや遅延の少ない信号伝送などのアプリケーションに適しています。
ChatGPTに聞いてみた。
User
74HC175APは何ですか。
ChatGPT
74HC175APは、デジタル回路に使用される、クアッドDフリップフロップ(Quad D Flip-Flop)IC(集積回路)の1つです。このICは、高速な動作、低消費電力、静的消費電力の低減、入力と出力の保護などの特徴を持っています。また、74HC175APは、単一の電源電圧で動作し、広い動作電圧範囲を持っています。ICのパッケージングには、16ピンのデュアルインラインパッケージ(DIP)が使用されています。
74HC175APは、4つの独立したDフリップフロップを持っており、各フリップフロップには、D入力、クロック入力、セット入力、リセット入力、Q出力、およびQバー出力があります。このICは、高速で信頼性の高いデータ保持や信号同期などの様々なアプリケーションに適しています。
PCのラインからサウンドを出力しその信号をそのままデジタル回路で使用することができるか実験してみました。
その1 矩形波のまま使用
信号のレベルが少し低いのでHighが5V程度になるまでトランジスタやオペアンプで増幅してみましたが次の問題が発生しました。
問題1 一波長でON・OFFの繰り返しを継続して出力する時は波形が乱れない。一波長でOFFのみが間にあると前後の波形が大きく乱れる。
問題2 一定時間だけONの信号が出せない。常に正負交互の交流信号を出力しないと信号が出てこないか前後の波形が乱れる。
問題3 出力の終わりに意図しない波形が出力されデジタル素子が誤動作をしてしまう。
その2 矩形波を止めて正弦波にする
矩形波は多くの高調波を含んでいるので正弦波のみであれば状況が改善すると思い実験してみましたが問題を全て解決できませんでした。
問題1 解決できた。
問題2 波長を低くすればある程度の期間ONにできる。矩形波でも同様。
問題3 改善されない。
その3 常に信号を出している状態にする
AMラジオの様に常に搬送波を出力しそれにデータである信号を乗せてみました。
問題1 再燃した。
問題2 その2と同じ解決できる。
問題3 若干改善した。
結論
PCのサウンド出力はアプリから要求された信号を忠実に送出するのではなく独自の制御を行っているため振幅に意味を持たせる方法ではデジタルデータとしてそのまま使用できないことが解りました。
#include <iostream> #include <string> #include <windows.h> #include <math.h> #include <MMSystem.h> #pragma comment (lib, "winmm.lib") int main() { WAVEFORMATEX wfe1; static HWAVEOUT hWaveOut1; static WAVEHDR whdr1; static LPBYTE lpWave1; static LPBYTE lpDataA; static LPBYTE lpDataB; int i, j, len1, start, end; int f1; size_t terms = 300; int sampling = 192000; size_t size; double pi = 3.14159265359; f1 = 15000; len1 = sampling / f1; wfe1.wFormatTag = WAVE_FORMAT_PCM; wfe1.nChannels = 2; wfe1.wBitsPerSample = 8; wfe1.nBlockAlign = wfe1.nChannels * wfe1.wBitsPerSample / 8; wfe1.nSamplesPerSec = sampling; wfe1.nAvgBytesPerSec = wfe1.nSamplesPerSec * wfe1.nBlockAlign; waveOutOpen(&hWaveOut1, 0, &wfe1, 0, 0, CALLBACK_NULL); size = terms * wfe1.nChannels; lpWave1 = (LPBYTE)calloc(wfe1.nAvgBytesPerSec, size); for (i = 0; i < sampling * terms * wfe1.nChannels; i++) { lpWave1[i] = 128; } start = sampling * wfe1.nChannels * 1; end = start + len1 * wfe1.nChannels * f1 * terms; double d = 360.0 / len1; lpDataA = (LPBYTE)calloc(wfe1.nAvgBytesPerSec, len1); for (i = 0; i < len1; i++) { lpDataA[i] = (BYTE)(70.0 * sin(d * (i % len1) / 180.0 * pi) + 127.5); } for (i = start, j = 0; i < end; i++) { if ((i % 2) == 0) { lpWave1[i] = lpDataA[j]; ++j; if (j >= len1) { j = 0; } } } int a = 300; lpDataB = (LPBYTE)calloc(wfe1.nAvgBytesPerSec, len1*a); for (i = 0; i < len1*a; i++) { lpDataB[i] = (BYTE)(50.0 * sin(d * i / 180.0 * pi / a) + 127.5); } for (i = start, j = 0; i < end; i++) { if ((i % 2) == 1) { if (((i / 2 / len1)+0) % 8 < 8 ) { lpWave1[i] = lpWave1[i-1] + lpDataB[j] - 128; ++j; if (j >= len1*a) { j = 0; } } else { lpWave1[i] = 128; } } } whdr1.lpData = (LPSTR)lpWave1; whdr1.dwBufferLength = wfe1.nAvgBytesPerSec * terms; whdr1.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; whdr1.dwLoops = 1; waveOutPrepareHeader(hWaveOut1, &whdr1, sizeof(WAVEHDR)); waveOutWrite(hWaveOut1, &whdr1, sizeof(WAVEHDR)); char str[128]; std::cout << "hello, world\n"; std::cin >> str; }
パソコンから20Hzの矩形波をライン出力してみました。LEDが8個並んでいるのはいずれシリアルパラレル変換するためです。今回は並列に接続しているので同じように動作します。下記のコードは4CH出力していますが、動画のLEDのボードに接続しているのはデバイス0のLeftです。
#include <iostream> #include <string> #include <windows.h> #include <MMSystem.h> #pragma comment (lib, "winmm.lib") int main() { WAVEFORMATEX wfe; static HWAVEOUT hWaveOut; static WAVEHDR whdr; static LPBYTE lpWave; WAVEFORMATEX wfe2; static HWAVEOUT hWaveOut2; static WAVEHDR whdr2; static LPBYTE lpWave2; int i, len, start, end; int frequency = 20; int terms = 10; int sampling = 192000; wfe.wFormatTag = WAVE_FORMAT_PCM; wfe.nChannels = 2; wfe.wBitsPerSample = 8; wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8; wfe.nSamplesPerSec = sampling; wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign; waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL); lpWave = (LPBYTE)calloc(wfe.nAvgBytesPerSec, terms * wfe.nChannels); wfe2.wFormatTag = WAVE_FORMAT_PCM; wfe2.nChannels = 2; wfe2.wBitsPerSample = 8; wfe2.nBlockAlign = wfe2.nChannels * wfe2.wBitsPerSample / 8; wfe2.nSamplesPerSec = sampling; wfe2.nAvgBytesPerSec = wfe2.nSamplesPerSec * wfe2.nBlockAlign; waveOutOpen(&hWaveOut2, 2, &wfe2, 0, 0, CALLBACK_NULL); lpWave2 = (LPBYTE)calloc(wfe2.nAvgBytesPerSec, terms * wfe2.nChannels); // 立ち上がりは出力を0にする for (i = 0; i < sampling * terms * wfe.nChannels; i++) { lpWave[i] = 128; lpWave2[i] = 128; } len = sampling / frequency; // 最初の8サイクルは出力しない start = len * 8 * wfe.nChannels; start = 0; // 8サイクル波形を出力する end = start + len * 32 * wfe.nChannels; printf("start=%d, end=%d\n", start, end); for (i = start; i < end; i++) { if ((i % 2) == 0) { if ((i/2) % len < len / 2) { lpWave[i] = 228; } else { lpWave[i] = 28; }}} len /= 2; for (i = start; i < end; i++) { if ((i % 2) == 1) { if ((i / 2) % len < len / 2) { lpWave[i] = 228; } else { lpWave[i] = 28; }}} len *= 2; for (i = start; i < end; i++) { if ((i % 2) == 1) { if ((i / 2) % len < len / 2) { lpWave2[i] = 228; } else { lpWave2[i] = 28; } } } len /= 2; for (i = start; i < end; i++) { if ((i % 2) == 0) { if ((i / 2) % len < len / 2) { lpWave2[i] = 228; } else { lpWave2[i] = 28; } } } whdr.lpData = (LPSTR)lpWave; whdr.dwBufferLength = wfe.nAvgBytesPerSec * terms; whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; whdr.dwLoops = 1; waveOutPrepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, &whdr, sizeof(WAVEHDR)); whdr2.lpData = (LPSTR)lpWave2; whdr2.dwBufferLength = wfe.nAvgBytesPerSec * terms; whdr2.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; whdr2.dwLoops = 1; waveOutPrepareHeader(hWaveOut2, &whdr2, sizeof(WAVEHDR)); waveOutWrite(hWaveOut2, &whdr2, sizeof(WAVEHDR)); char str[128]; std::cout << "hello, world\n"; std::cin >> str;
WindowsPCのサウンド出力を使って可聴範囲のジェネレーターを作ることができましたがチャンネルが二つでは足りないので追加してみました。
USBのオーディオ出力を接続しPC本体の出力と合わせてステレオ出力×2=4チャンネルになります。
#include <iostream> #include <string> #include <windows.h> #include <MMSystem.h> #pragma comment (lib, "winmm.lib") int main() { WAVEFORMATEX wfe; static HWAVEOUT hWaveOut; static WAVEHDR whdr; static LPBYTE lpWave; WAVEFORMATEX wfe2; static HWAVEOUT hWaveOut2; static WAVEHDR whdr2; static LPBYTE lpWave2; int i, len, start, end; int terms = 1; int sampling = 192000; int frequency = 500; wfe.wFormatTag = WAVE_FORMAT_PCM; wfe.nChannels = 2; wfe.wBitsPerSample = 8; wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8; wfe.nSamplesPerSec = sampling; wfe.nAvgBytesPerSec = wfe.nSamplesPerSec * wfe.nBlockAlign; waveOutOpen(&hWaveOut, 0, &wfe, 0, 0, CALLBACK_NULL); lpWave = (LPBYTE)calloc(wfe.nAvgBytesPerSec, terms * wfe.nChannels); wfe2.wFormatTag = WAVE_FORMAT_PCM; wfe2.nChannels = 2; wfe2.wBitsPerSample = 8; wfe2.nBlockAlign = wfe2.nChannels * wfe2.wBitsPerSample / 8; wfe2.nSamplesPerSec = sampling; wfe2.nAvgBytesPerSec = wfe2.nSamplesPerSec * wfe2.nBlockAlign; waveOutOpen(&hWaveOut2, 2, &wfe2, 0, 0, CALLBACK_NULL); lpWave2 = (LPBYTE)calloc(wfe2.nAvgBytesPerSec, terms * wfe2.nChannels); // 立ち上がりは出力を0にする for (i = 0; i < sampling * terms * wfe.nChannels; i++) { lpWave[i] = 128; lpWave2[i] = 128; } len = sampling / frequency; // 最初の8サイクルは出力しない start = len * 8 * wfe.nChannels; // 8サイクル波形を出力する end = start + len * 8 * wfe.nChannels; printf("start=%d, end=%d\n", start, end); for (i = start; i < end; i++) { if ((i % 2) == 0) { if ((i/2) % len < len / 2) { lpWave[i] = 228; } else { lpWave[i] = 28; }}} len /= 2; for (i = start; i < end; i++) { if ((i % 2) == 1) { if ((i / 2) % len < len / 2) { lpWave[i] = 228; } else { lpWave[i] = 28; }}} len *= 2; for (i = start; i < end; i++) { if ((i % 2) == 1) { if ((i / 2) % len < len / 2) { lpWave2[i] = 228; } else { lpWave2[i] = 28; } } } len /= 2; for (i = start; i < end; i++) { if ((i % 2) == 0) { if ((i / 2) % len < len / 2) { lpWave2[i] = 228; } else { lpWave2[i] = 28; } } } whdr.lpData = (LPSTR)lpWave; whdr.dwBufferLength = wfe.nAvgBytesPerSec * terms; whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; whdr.dwLoops = 1; waveOutPrepareHeader(hWaveOut, &whdr, sizeof(WAVEHDR)); waveOutWrite(hWaveOut, &whdr, sizeof(WAVEHDR)); whdr2.lpData = (LPSTR)lpWave2; whdr2.dwBufferLength = wfe.nAvgBytesPerSec * terms; whdr2.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP; whdr2.dwLoops = 1; waveOutPrepareHeader(hWaveOut2, &whdr2, sizeof(WAVEHDR)); waveOutWrite(hWaveOut2, &whdr2, sizeof(WAVEHDR)); char str[128]; std::cout << "hello, world\n"; std::cin >> str; }
4チャンネルあればデータに1CH、制御に3CH使えるのでUSBにマイコンをつながなくても様々なデジタル部品の制御ができそうです。