
Once the thought arose in my head, but what would be done to cross the old radio in a wooden case and a modern controller for the Internet-things ESP32? Either something is wrong with my head, or I have nothing to do, but it turned out to be crossed. Not stereotyped, in general, although to judge you, dear readers of Habr).
For details, I ask under the cat.
32> 8266
In mathematics this is absurd, but in our case it is. The functionality and capabilities of ESP32 are much greater than ESP8266. In addition to a larger number of GPIO, the microcontroller is more powerful functionally, bluetooth is added to the standard Wi-fi, and in my opinion the most correct thing in it is the presence of two channels of
digital-to-analog conversion (DAC in our DAC for imported). Therefore, nothing complicated is (without resorting to different frills) to directly force the controller to be a generator of various signals or even speak in human language. That's exactly the DAC we need.
The controller 2 channel DAC 25 and 26 conclusions. As I understand it, this is in order to even cut down the stereo sound if necessary. About the ESP32 controller is not enough information that can be taken
here or
here , and for lovers of technical documentation here is a
link to the datasheet. In my case, there was a scarf of the developer of the WEMOS series with a small screen on board, which in itself is quite convenient - you can immediately debug it with the information displayed on the spot or display any data.
')
A handy thing in general, although the price could be more modest. Bought
here .
Get to the point!
Having on board a DAC, we can simulate a “pure” sinusoidal signal of a certain frequency. Analysis of the
datasheet showed that the ESP32 controller DAC sampling rate can reach about 13 MHz, so it remains for us to understand what sine frequency we can get in this case. To do this, it is necessary to approximate the sine by a certain number of time reports - the more reports you take, the more qualitative the signal will look, but this reduces the frequency limit that can be obtained as a result. In this case, the signal amplitude is limited by the bit width of the DAC and is 8 bits.

To approximate four or eight time reports the sine will not be enough, but 16 will be fine.
int sintab[] = {0, 48, 90, 117, 127, 117, 90, 48, 0, -48, -90, -117, -127, -117, -90, -48};
Of course, it would be better to take 32 or 64 reports, but then the frequency of the final signal drops significantly. Thus, with a sampling of 16 time reports and a 13-MHz DAC operation limit, you can get a sine of that kind with a frequency of about 800 kHz (13 MHz / 16 bit). But it already falls into the range of medium-wave household radios, to which it will be possible to transmit a useful signal, for example, speech. The scheme is horribly simple. Does not need to be configured)
To pin 25 of the DAC, we connect a piece of wire (40 centimeters), which serves as an antenna. The radio transmitter is almost ready!
Amplitude modulation
Having received a stable carrier frequency is still not enough to realize the transmission of a useful signal to a radio receiver. It is necessary to modulate the carrier frequency with a low frequency signal, for example, human speech or music, implementing the so-called
amplitude modulation .
We must change the amplitude of the carrier frequency (top) with the information signal (center), providing an acceptable
modulation depth , which ideally should be equal to 1 (or 100%), i.e. the final signal (from below) is a high-frequency signal constantly varying in amplitude. Since it is not always possible to realize the modulation depth clearly at 100 percent - the level of this value at 50 percent is already quite acceptable (approximately as in the figure). The sound quality will be somewhat worse, but it does not matter.
Hi, Habr!
Now our task is to record an audio file in any sound editor in order to receive a sound file, which we will broadcast on a frequency of about 800 kHz and receive on our radio receiver.
So the phrase "Hi, Habr, frequency 835 kHz." From this file we need to generate a report file of the information signal, which can be converted from this
link . The structure of the final output file will be approximately
const unsigned int sampleRate = 44100;
This is essentially an array of amplitudes of the useful signal, which, roughly speaking, we add (if greater than zero) or subtract (if the value is less than zero) from the amplitudes of the high-frequency signal, thereby realizing the amplitude modulation we need.
It remains only to fill in the firmware, connect a piece of wire to pin 25 in the form of an antenna and, having switched the receiver to the AM band, tune into a frequency in the region of 800-850 kHz.
Transmitter power, of course, scanty. Therefore, the antenna is located very close to the receiver.
Actually the final program code takes 70 lines. The converted audio file as a report file
sample.h can be downloaded
here . It is important not to forget to drop this file in the same folder as the program itself.
Program code // #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); }
Stitched and assembled in the ARDUINO IDE. How to make friends ESP32 with him, read, for example,
here . Read more about the source code used in the project
here .
It must be said that there is no practical use for this, but in general it is not stereotyped. In addition, recall the course of radio engineering was so nice. And, of course, a 2-minute
video on how it works is attached.