秋月のサイトより |
このモジュールは1-3.25MHzのクロックを入れればPDMフォーマットでデジタルデータが取り出せます。PDMなのでローパスフィルタを通せばそのままアナログ信号として使えます。しかも300円。素晴らしい。
…しかし使えなければ意味がありません。結果として動作させることができませんでした。
今週は何をやっても動かないなorz
■追記6/6■
電子工作部の方から「LPFの出力をアンプに繋いでみたら何か信号出てるんじゃない?」というアドバイスをいただき、FPGAで作った1.25Mhzのクロックを入れて、LPF出力をカップリングコンデンサ経由で27dBのアンプにつないでみました。そしたら!
小さいですが確かに音が出ています!! いえええええ!!! アドバイスありがとうございました。うれしー。小さすぎてオシロでは見えなかったけど、信号出てたのね。
というわけで、今週末はデジタルでの処理に再挑戦します。
それまでは以下のマイコンでの試行錯誤からFPGAでのクロック発生回路でアナログとしての取得に成功、最終的にデジタル信号として取り込みDACから音が出るまでのドタバタ劇をお楽しみいただければ幸いですw
■SPIでデジタル入力(失敗)■
今度はSPIです。SPIのクロックを1Mhzに設定し、SPI modeをいろいろ変えたりしてみたのですが、結果は似たようなもので値が123-127の間をパラパラ上下するだけでした。#include <SPI.h>なお、ビットカウントはこちらの記事から使わせていただきました。
const uint8_t BITS_COUNT_TABLE[256] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
};
int numofbits2(uint16_t bits)
{
return BITS_COUNT_TABLE[((unsigned char*)&bits)[0]]
+ BITS_COUNT_TABLE[((unsigned char*)&bits)[1]];
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
SPI.begin();
SPI.setFrequency(1000000);
SPI.setDataMode(SPI_MODE0);
noInterrupts();
}
static int mabiki = 0;
void loop() {
// put your main code here, to run repeatedly:
int num = 0;
for (int i = 0; i < 16; i++) {
num += numofbits2(SPI.transfer16(0xffff));
}
char buf[6];
sprintf(buf, "%4d", num);
if (mabiki == 20) {
Serial.println(buf);
mabiki = 0;
} else {
Serial.print(buf);
}
mabiki++;
}
テーブルを使う方法は思いついたのですが、そのあとに記載されているアルゴリズムは本当にびっくりです。1960年代のコンピュータサイエンスは凄まじいですね。
■GPIOでデジタル入力(失敗)■
GPIOでクロックを生成し、ポートを読み込んで積算する方法を試してみました。帰ってきた値は見事にデタラメでグラフ化しても波形になりませんでした。#include <Arduino.h>
void setup() {
// put your setup code here, to run once:
Serial.begin(230400);
pinMode(14, OUTPUT);
pinMode(12, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
int count = 0;
for (long l = 0; l < 1000; l++) {
digitalWrite(14, HIGH);
if (digitalRead(12) == HIGH) {
count ++;
}
// else {
// count --;
// }
digitalWrite(14, LOW);
}
Serial.println(count);
}
なお、コメントアウトの部分はLOWならデクリメント、というサンプルを見たので試してみたのですが…結果がマイナスに振れただけで同じでしたたたたた。
■マイコン発振 / アナログ出力(失敗)■
1MHz強のクロックを入れ、出力に約20khzのローパスフィルタ(R=1kΩ,1=10nF)を通してマイク前から信号を入れてみました。ローパスフィルタは出力端子>抵抗>コンデンサ>Gndとつないで、抵抗とコンデンサがつながっているところから出力取ります。1MHz強のクロックはESPを160MHzクロックで動かして、以下のプログラムで生成します。デューティー比50%にならないけど、気にしない。デューティー比を考えれば少しでも演算の早いshortの方が良いのですが、shortだと約32mSecごとにシステム?に戻ってしまうのでオシロで波形見るときに邪魔かなと。#include <Arduino.h>
void setup() {
// put your setup code here, to run once:
pinMode(14, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
int count = 0;
for (long l = 0; l < 1000000; l++) {
digitalWrite(14, HIGH);
digitalWrite(14, LOW);
}
}
■FPGA発振 + アナログ出力■
最後にFPGAでちゃんとした1.25 / 2.5MHzのクロックを作って試してみます。でもまだちゃんと作る自信がないので、「FPGA電子工作スーパーキット」のp112ページからの手順やソースをまず動かして見て、そこにクロック生成を追加します(弱気なお、同誌附属の基板はまだ組み立てていないので、BeMicro MAX10を使います。
- Quartus起動
- New Project Wizardでディレクトリ,プロジェクト名ClockGenを入力し、BeMicro搭載デバイスの10M08DAF484C8GESを選び、Finish。
- Fileメニュー>New...からVerilog HDL Fileを選びOK
- Velilogソースを打ち込む
- TasksのAnalysis & Synthesisを右クリックしてStartを選ぶ。エラーが出たら直してもう一度
- Assignmentsメニュー>Pin Plannerを選び、ピンを割り当てる(下図1)
- TasksのCompile Designを右クリックしてStartを選び、コンパイルし、「…Quartus Prime Full Compilation was successful」が出たらOK
- Toolsメニュー>Programmerで、Programmerを起動
- USB-Blasterが選択されていることを確認(表示されていなかったらHardware Setup...ボタンから選択ダイアログへ)
- Add Fileボタンをクリックし、output_filesの中のClockGen.sofを選ぶ。デバイスと書き込みファイルが表示される(下図2)
- Startボタンをクリック、瞬時に書き込みが終わり、LEDがチカチカ。
![]() |
図1 |
![]() |
図2 |
- QuartusのEntity欄でClockGenをダブルクリックしてVerilogソースを開きます。
- ソースを修正して保存します。
- 青の「▶」をクリックすると「変更するか?」と聞いてきますのでYES
- Full Compilation was successfulが出たらToolsメニューからProgrammer
- Startボタンをクリックしてコンフィグ(書き込み)
はい終了。
■FPGAのソース■
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
`define CLOCK_5MH 10 | |
`define CYCLES_1SEC 50000000 | |
// TOP | |
module ClockGen | |
( | |
input wire clk, | |
input wire res_n, | |
output wire [2:0] led, | |
output wire [3:0] mega | |
); | |
// counter for 1sec | |
reg [31:0] counter_1sec; | |
wire period_1sec; | |
always @(posedge clk, negedge res_n) | |
begin | |
if (~res_n) | |
counter_1sec <= 32'h00000000; | |
else if (period_1sec) | |
counter_1sec <= 32'h00000000; | |
else | |
counter_1sec <= counter_1sec + 32'h00000001; | |
end | |
assign period_1sec = (counter_1sec == (`CYCLES_1SEC - 1)); | |
reg[2:0] counter_led; | |
always @(posedge clk, negedge res_n) | |
begin | |
if (~res_n) | |
counter_led <= 3'b000; | |
else if (period_1sec) | |
counter_led <= counter_led + 3'b001; | |
end | |
assign led = ~counter_led; | |
reg[7:0] four_mega_counter; | |
wire four_mega; | |
always @(posedge clk, negedge res_n) | |
begin | |
if (~res_n) | |
four_mega_counter <= 8'b000; | |
else if (four_mega) | |
four_mega_counter <= 8'b000; | |
else | |
four_mega_counter <= four_mega_counter + 8'b001; | |
end | |
assign four_mega = (four_mega_counter == (`CLOCK_5MH - 1)); | |
reg[3:0] mega_output; | |
always @(posedge four_mega) | |
begin | |
mega_output <= mega_output + 4'b0001; | |
end | |
assign mega = mega_output; | |
endmodule |
■最後に■
デジタルマイクは製品として販売されているからには、動くはず。でも何が悪いのかわかりません。もう涙も枯れ果てました…でもFPGAでクロック出すのはうまく行ったから良しとしよう(問題をすり替えてはいけません)。続きはこちらをどうぞ。
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。