「Hello、Habr」、周波数835 kHz

かつて私の頭の中に考えが浮かんだが、木製のケースにある古いラジオと、モノのインターネットESP32用の最新のコントローラーを通過させるにはどうすればよいでしょうか? 私の頭に何か問題があるか、または私は何の関係もないが、私はそれをなんとか越えた。 ステレオタイプではありません、一般的に、あなたを判断しますが、親愛なるHabrの読者)。



猫の下で詳細を尋ねます。



32> 8266



数学では、これはばかげていますが、私たちの場合はそうです。 ESP32の機能と機能は、ESP8266よりもはるかに大きいです。 多数のGPIOに加えて、マイクロコントローラーの機能がより強力になり、Bluetoothが標準Wi-fiに追加されました。私の意見で最も正しいのは、 デジタルアナログ変換の2つのチャネルの存在です(DACは、インポートグレードのDACです)。 したがって、コントローラをさまざまな信号の生成者に直接強制したり、人間の言語を話すことさえ、複雑なことではありません(さまざまなトリックに頼ることなく)。 必要なのはこのDACです。









コントローラには、25ピンと26ピンの2つのDACチャネルがあります。 私が理解しているように、これは必要に応じてステレオサウンドをカットするためです。 ESP32コントローラーに関する多くの情報がここまたはここで入手できます。技術文書のファンのために、ここにデータシートへのリンクがあります。 私の場合、ボード上に小さな画面を備えたWEMOSシリーズの開発者用ハンカチがありました。それ自体は非常に便利です。その場で情報を表示したり、データを表示してすぐにデバッグできます。











一般的には便利なものですが、価格はもっと控えめかもしれません。 ここで買っ



要点をつかもう!



DACを搭載すると、特定の周波数の「純粋な」正弦波信号をシミュレートできます。 データシートの分析により、ESP32コントローラーのDACのサンプリング周波数は約13 MHzに達することがあるため、この場合に得られるサイン周波数を理解する必要があります。 これを行うには、一定数の時間レポートで正弦波を近似する必要があります。取得するレポートが多いほど、信号の外観は良くなりますが、最終的に取得できる制限周波数は減少します。 この場合、信号振幅はDAC容量によって制限され、8ビットです。







4つまたは8つの一時レポートでサインを近似するだけでは十分ではありませんが、16で十分です。



int sintab[] = {0, 48, 90, 117, 127, 117, 90, 48, 0, -48, -90, -117, -127, -117, -90, -48};
      
      





もちろん、32個または64個のレポートを取得する方が適切ですが、最終的な信号の周波数は大幅に低下します。 したがって、16時間レポートでサンプリングし、13 MHzのDAC動作の制限範囲を使用すると、約800 kHz(13 MHz / 16ビット)の周波数でこのような正弦波を得ることができます。 しかし、これはすでに家庭用無線の中波範囲に該当し、音声などの有用な信号を送信することが可能になります。 スキームは非常にシンプルです。 構成する必要はありません)









25個のDACの出力に、アンテナとして機能するワイヤ(40センチメートル)を接続します。 無線送信機はほとんど準備ができています!



振幅変調



安定した搬送周波数を受信しただけでは、無線受信機への有用な信号の送信を実現するには不十分です。 いわゆる振幅変調を実装する、人間の音声や音楽などの有用な低周波信号で搬送波周波数を変調する必要があります。











キャリア周波数の振幅(上)を情報信号(中央)で変更し、許容できる変調度を提供する必要があります。理想的には1(または100%)である必要があります。 最終信号(下)は、振幅が絶えず変化する高周波信号です。 変調度を100パーセントで明確に実現できるとは限らないため、この値の50パーセントのレベルはすでに十分に受け入れられます(ほぼ図のように)。 音質は少し悪くなりますが、問題ではありません。



こんにちは、Habr!



ここでのタスクは、約800 kHzの周波数でブロードキャストし、ラジオで受信するサウンドファイルを取得するために、サウンドエディターでオーディオファイルを録音することです。









これは「こんにちは、Habr、周波数835 kHz」というフレーズです。 このファイルから、このリンクを使用して変換できる情報信号レポートファイルを生成する必要があります。 最終的な出力ファイルの構造は次のようになります



 const unsigned int sampleRate = 44100; //      const unsigned int sampleCount = 289728; //     .    44100   .    6 . const signed char samples[] = { -2, -4, -7, -10, -12, -13, -13, -14, -13, -12, -11, -11, -9, -8, -6, -5, -4, -2, -2, -3, -4, -6, -10, -15, -21, -27, -34, -39, -41, -40, -38, -34, -28, -22, -19, -15, -13, -13, -16, -18, -21, -24, -27, -29, -31, -33, -35, -36, -36, -37, -38, -39, -38, -37, -36, -33, -31, -30, -30, -31, -32, -34, -35, -35, -35, -35, -34, -34, -33, -32, -31, -31, -31, -31, -31, -31, -29, -27, -25, -22, ......       ...... -20, -18, -16, -14, -13, -11, -9, -8, -7, -6, -5, -4, -3, -3, -2, -1, 0, 2, 6, 10, 14, 19, 23, 27, 28, 28, 26, 24, 21, 20, 20, 21, 23, 25, 28, 30, 32, 34, 36, 37, 38, 39, 40, 41, 41, 42, 43, 43, 42, 40, 38, 36, 35, 36, 38, 40, 42, 43, 43, 42, 39, 37, 34, 31, 30, 29, 30, 31, 32, 33, 33, 32, 29, 26, 22, 19, 17, 15, 14, 15};
      
      





これは基本的に有用な信号の振幅の配列であり、大まかに言えば、高周波信号の振幅から加算(ゼロより大きい場合)または減算(値がゼロより小さい場合)することで、必要な振幅変調を実現します。



ファームウェアを埋め、アンテナの形でワイヤを25番目のピンに接続し、レシーバをAMレンジに転送して、800〜850 kHzの周波数に調整するだけです。











もちろん、送信機の電力はわずかです。 したがって、アンテナは受信機の非常に近くに配置されます。



実際、プログラムの最終コードは70行を占有します。 sample.hレポートファイルとして変換されたオーディオファイルは、 ここからダウンロードできます 。 このファイルをプログラム自体が置かれているのと同じフォルダーにドロップすることを忘れないことが重要です。



プログラムコード
 //    #include "sample.h" #include <soc/rtc.h> #include "driver/i2s.h" static const i2s_port_t i2s_num = (i2s_port_t)I2S_NUM_0; // i2s //  i2s static const i2s_config_t i2s_config = { .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN), .sample_rate = 1000000, .bits_per_sample = (i2s_bits_per_sample_t)I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, .communication_format = I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 2, .dma_buf_len = 1024 }; void setup() { rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M); //   cpu i2s_driver_install(i2s_num, &i2s_config, 0, NULL); // i2s i2s_set_pin(i2s_num, NULL); //   i2s_set_sample_rates(i2s_num, 1000000); // ,        ~ 13  SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_A_V, 1, I2S_CLKM_DIV_A_S); SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_B_V, 1, I2S_CLKM_DIV_B_S); SET_PERI_REG_BITS(I2S_CLKM_CONF_REG(0), I2S_CLKM_DIV_NUM_V, 2, I2S_CLKM_DIV_NUM_S); SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_TX_BCK_DIV_NUM_V, 2, I2S_TX_BCK_DIV_NUM_S); } //     short buff[1024]; //,   16 .    13  //     800-850  int sintab[] = {0, 48, 90, 117, 127, 117, 90, 48, 0, -48, -90, -117, -127, -117, -90, -48}; unsigned long long pos = 0; unsigned int posLow = 0; //  -  .  , 835  unsigned long long posInc = ((unsigned long long)sampleRate << 32) / 835000; void loop() { //       for(int i = 0; i < 1024; i+=16) { if(posLow >= sampleCount) posLow = sampleCount - 1; int s = samples[posLow] + 128; //   for(int j = 0; j < 16; j += 4) { buff[i + j + 1] = (sintab[j + 0] * s + 0x8000); buff[i + j + 0] = (sintab[j + 1] * s + 0x8000); buff[i + j + 3] = (sintab[j + 2] * s + 0x8000); buff[i + j + 2] = (sintab[j + 3] * s + 0x8000); } pos += posInc; posLow = pos >> 32; if(posLow >= sampleCount) pos = posLow = 0; } //       i2s_write_bytes(i2s_num, (char*)buff, sizeof(buff), portMAX_DELAY); }
      
      





ARDUINO IDEでステッチおよびアセンブル。 彼とESP32を友達にする方法は、例えばここを読んでください 。 プロジェクト使用されるソースコードの詳細については、 こちらをご覧ください



これには実際的な利点はないと言う必要がありますが、一般的にはステレオタイプではありません。 さらに、無線工学のコースを思い出すことはとても楽しく快適でした。 そして、もちろん、その仕組みに関する2分のビデオを添付します。



All Articles