В этом тексте я покажу, как из подручных материалов на основе микроконтроллера, аудиокодека и SD карты запрограммировать самый настоящий диктофон. Покажу принципы работы звукозаписывающей аппаратуры. Но обо всем по порядку...

Постановка задачи
Разработать прототип диктофона на основе микроконтроллера STM32F407VG и аудио кодека WM8731. Написать прошивку для записи звука в wav файлы. Звук передавать по интерфейсу I2S2. Аудиокодек конфигурировать по интерфейсу I2C2. Использовать фирменный HAL SDK от производителя микроконтроллера STM. Записанные файлы хранить на SD карте, подключенной по интерфейсу SDIO. Использовать DMA потоки для интерфейса I2S2_RX, SDIO и UART2_TX. Внутри SD карты должна быть файловая система FAT16. В прошивке использовать функции из API файловой системы FatFS. Обеспечить возможность записывать в wav файлы через интерфейс командной строки поверх UART2. Указывать длительность записываемого файла аргументами командной строки. Обеспечить возможность работать со стерео WAV файлом на частоте дискретизации 96kHz, семплами разрешением 16-бит. Вот, пожалуй, и все требования к прототипу диктофона.

Аппаратная часть

Итак, танцуем от печки... Из чего же я буду собирать диктофон? Основа диктофона - это учебно-тренировочная электронная плата DevEBox STM32F4XX_M_V3. PCB хороша тем, что она миниатюрна и на ней построен гараж для microSD карты. Вот так она выглядит.

DevEBox STM32F4XX_M_V3
DevEBox STM32F4XX_M_V3

Вот блок-схема DevEBox STM32F4XX_M_V3.

Аудиокодек - это ASIC WM8731 и модуль на его основе.



WM8731 - это по сути 2xADC + 2xDAC с торчащим наружу I2S и с управлением по I2C.

Надо учинить вот такой прототип. Следует установить всего 12 перемычек. Вот так, просто и незатейливо:

Микрофон я выбрал первый попавшийся под рукой. Это оказался микрофон aceline AMIC-7.

микрофон aceline AMIC-7
микрофон aceline AMIC-7

Блок-схема диктофона получается такая

В качестве накопителя я выбрал микро SD карту на 128 MByte.

Теория цифровой звукозаписи

Главная трудность записи звука на микроконтроллерах заключается в том, что в микроконтроллерах нет столько много RAM памяти, чтобы за раз записать привычный нам звуковой файл. Одна песня в WAV формате может занимать 60MByte. Для решения этой проблемы существует классическое решение на основе двух массивов. Суть проста. Пока по I2S записывается в RAM память фрагмент 1, микроконтроллер сохраняет из RAM памяти в FAT16 файл фрагмент 2. Пока по I2S записывается в RAM память фрагмент 2, микроконтроллер сохраняет из RAM памяти в файл фрагмент 1. Таким образом становится возможным непрерывно записывать файлы, размер которых в тысячи раз превышает количество RAM памяти в микроконтроллере.


Для контролирования процесса записи внутри прошивки должен работать вот такой простой конечный автомат. Состояние автомата можно переключать прямо внутри обработчика прерываний по DMA каналам. А непосредственную запись в SD карту делать в супер цикле функции main по командам конечного автомата записи.

Реализация

Настройка GPIO

Для работы диктофона надо активировать альтернативные функции на I2S2, I2C2, SDIO, UART2. Плюс добавить несколько GPIO пинов для отладки на логическом анализаторе или осциллографе.

-->
-->gl
+-----+-------+---------+------+------+-----+-----+---------------+
| No  |  pad  |  mode   | dir  | pull |MuxS |MuxG |     name      |
+-----+-------+---------+------+------+-----+-----+---------------+
|   0 |   PA8 |    Out  |  Out |  Air |   0 |   0 |   I2S2_TX_DMA |
|   1 |   PA4 |    Out  |  Out |  Air |   0 |   0 |   I2S2_RX_DMA |
+-----+-------+---------+------+------+-----+-----+---------------+
|   2 |  PB13 |   ALT1  |  Out | Down |   5 |   5 |       I2S2_CK |
|   3 |  PB12 |   ALT1  |  Out | Down |   5 |   5 |       I2S2_WS |
|   4 |  PB15 |   ALT1  |   In | Down |   5 |   5 |       I2S2_SD |
+-----+-------+---------+------+------+-----+-----+---------------+
|   5 |  PB10 |   ALT1  |  Out |   Up |   4 |   4 |      I2C2_SCL |
|   6 |  PB11 |   ALT1  |   Io |   Up |   4 |   4 |      I2C2_SDA |
+-----+-------+---------+------+------+-----+-----+---------------+
|   7 |   PA2 |   ALT1  |  Out |  Air |   7 |   7 |     USART2_TX |
|   8 |   PA3 |   ALT1  |   In |   Up |   7 |   7 |     USART2_RX |
+-----+-------+---------+------+------+-----+-----+---------------+
|  10 |  PC12 |   ALT1  |  Out |  Air |  12 |  12 |        SD_CLK |
|  11 |   PD2 |   ALT1  |  Out |   Up |  12 |  12 |        SD_CMD |
|  12 |   PC8 |   ALT1  |   Io |   Up |  12 |  12 |         SD_D0 |
|  13 |   PC9 |   ALT1  |   Io |   Up |  12 |  12 |         SD_D1 |
|  14 |  PC10 |   ALT1  |   Io |   Up |  12 |  12 |         SD_D2 |
|  15 |  PC11 |   ALT1  |   Io |   Up |  12 |  12 |         SD_D3 |
+-----+-------+---------+------+------+-----+-----+---------------+
|  9  |   PA1 |    Out  |  Out |  Air |   0 |   0 |      LedGreem |
+-----+-------+---------+------+------+-----+-----+---------------+
-->

Настройка I2S трансивера
Для работы я выбрал I2S2. I2S2 трансивер надо сконфигурировать на режим записи. Микроконтроллер должен выступать в роли мастера. Есть два варианта для пина I2S2_SD: PC3 и PB15.

GPIO

Dir

MCU pin

PinMux

Connector

Connector

PC3

out

18

AF5

J3.35

--

PB15

in

54

AF5

J2.8

J4.3


В STM32 каждый отдельный I2S трансивер может либо записывать, либо отправлять звук через пин I2Sx_SD. Поэтому для записи и последующего воспроизведения вам придется пере инициализировать I2S трансивер. Есть и отдельный режим полного дуплекса, но он требует еще одного экземпляра I2S трансивера. Полный дуплекс достигается за счет тандемной работы двух трансиверов, но это тема для отдельной статьи.

Запись звука должна происходить на таких настройках GPIO.

PinMux

GPIO

DIR

Pull

PIN

PinMux

Connector

Connector

I2S2_SD

PB15

in

down

54

AF5

J2.8

J4.3

GPIO

PC3

in

down

18

0

J3.35

--

I2S2_CK

PB13

out

down

47

5

J3.13

--

I2S2_WS

PB12

Out

down

51

5

J3.11

J4.5

Синтез WAV файла

Как только поступит запрос на запись надо понять сколько вообще надо семплов звука. Для простоты положим, что в запросе на запись задается продолжительность записи в секундах. Известна частота дискретизации, размер одного семпла, количество каналов. Надо определить сколько памяти потребуется для поля данных. Это можно рассчитать по простой формуле:

MemNeed [byte] = SampleFreq [Hz] x SampleSize [byte] x Channels [Num] x RevDuration [s]

Зная параметры предстоящей записи надо синтезировать заголовок WAV файла. Этот заголовок прописывается в WAV файл и после этого дается отмашка DMA на пуск I2S_RX .

Настройка каналов DMA

Записывать звук следует через DMA канал для I2S2_RX. Должен быть включен циклический режим, активированы DMA прерывания, выравнивание 16 бит. Тут надо сразу вспомнить что в STM32 микроконтроллерах I2S - это режим SPI. Поэтому настройки каналов DMA надо тоже копировать от SPI.

Для I2S2 настройки каналов DMA получаются такие

Flow

DMA

Stream

Channel

Mode

Direction

I2S2_RX

DMA1

Stream_3

Channel_0

CIRCULAR

PERIP->MEM

I2S2_TX

DMA1

Stream_4

Channel_0

CIRCULAR

MEM->PERIP

В коде это выглядит так

#define DMA_CHANNEL_I2S_COMMON                      \
        .memory_burst = DMA_BURST_SINGLE,           \
        .periph_burst = DMA_BURST_SINGLE,           \
        .aligment_per = DMA_ALIGNMENT_WORD,         \
        .aligment_mem = DMA_ALIGNMENT_WORD,         \
        .interrupt_on = true,                       \
        .block_count = 1,                           \
        .valid = true,                              \
        .mode = DMA_MODE_CIRCULAR,                  \
        .fifo = DMA_FIFO_OFF,                       \
        .priority = DMA_PRIOR_VERY_HIGH,


#define DMA_CHANNEL_I2S2_RX                                 \
    {                                                       \
        .DmaChPad = { .dma_num = 1, .stream=3, .channel = 0,  .name = "I2S2_RX", },      \
        DMA_CHANNEL_I2S_COMMON                              \
        .per_inc = DMA_INC_OFF,                             \
        .mem_inc = DMA_INC_ON,                              \
        .dir = DMA_MCAL_DIR_PERIPH_TO_MEMORY,               \
        .name = "I2S2_RX",                                  \
        .num = DMA_CHANNEL_NUM_I2S2_RX,                     \
        .base_addr_source = (uint32_t) fromArray,           \
        .base_addr_destination = (uint32_t) &(I2S2ext->DR), \
        .block_size = (uint32_t) DMA_MEMCPY_SIZE,           \
        .CallBackHalf = CallBackHalfI2s2Rx,                 \
        .CallBackDone = CallBackDoneI2s2Rx,                 \
    },

Настройка и интерфейса SDIO

В экспериментах я работал на частоте тактирования SDIO равной 12 MHz (фактическое значение по осциллографу). Повышение частоты до 24MHz не оказало существенного прироста производительности. SDIO интерфейс надо настроить на работу с DMA каналами.

Flow

DMA

Stream

Channel

Mode

Direction

SDIO_RX

DMA2

Stream_3

Channel_4

PFCTRL

PERIP->MEM

SDIO_TX

DMA2

Stream_6

Channel_4

PFCTRL

MEM->PERIP

В коде это выглядит так

#ifndef DMA_CHANNEL_SDIO_CONFIG_H
#define DMA_CHANNEL_SDIO_CONFIG_H

#ifdef __cplusplus
extern "C" {
#endif

#include "std_includes.h"
#include "dma_channel_types.h"
#include "dma_channel_config.h"

#ifndef MIN
#define MIN(n, m) (((n) < (m)) ? (n) : (m))
#endif

bool CallBackDoneSdio1Rx(void);
bool CallBackDoneSdio1Tx(void);
bool CallBackHalfSdio1Rx(void);
bool CallBackHalfSdio1Tx(void);
bool CallBackErrorSdio1Rx(void);
bool CallBackErrorSdio1Tx(void);

/*DMA_PFCTRL DMA_PFCTRL DMA_PFCTRL DMA_PFCTRL*/
#define DMA_CHANNEL_SDIO_COMMON                      \
        .block_size = (uint32_t) MIN( sizeof(toArray) ,sizeof(fromArray))  ,    \
        .per_inc = DMA_INC_OFF,                      \
        .mem_inc = DMA_INC_ON,                       \
        .aligment_mem = DMA_ALIGNMENT_DWORD,         \
        .aligment_per = DMA_ALIGNMENT_DWORD,         \
        .memory_burst = DMA_BURST_INC4,              \
        .periph_burst = DMA_BURST_INC4,              \
        .fifo = DMA_FIFO_ON,                         \
        .priority = DMA_PRIOR_VERY_HIGH,             \
        .mode = DMA_MODE_PFCTRL,                     \
        .valid = true,                               \
        .interrupt_on = true,

#define DMA_CHANNEL_SDIO_RX                          \
    {                                                \
        .DmaChPad = { .dma_num = 2, .stream = 3, .channel = 4, .name = "SDIO1_RX",  },      \
        .dir = DMA_MCAL_DIR_PERIPH_TO_MEMORY,        \
        DMA_CHANNEL_SDIO_COMMON                      \
        .name = "SDIO1_RX",                          \
        .num = DMA_CHANNEL_NUM_SDIO_RX,              \
        .CallBackHalf = CallBackHalfSdio1Rx,         \
        .CallBackDone = CallBackDoneSdio1Rx,         \
        .base_addr_source = (uint32_t) fromArray,    \
        .base_addr_destination = (uint32_t) toArray, \
        .block_count = 1,                            \
        .mux = 0,                                    \
    },

#define DMA_CHANNEL_SDIO_TX                         \
    {                                               \
        .DmaChPad = { .dma_num = 2,  .stream = 6,  .channel = 4, .name = "SDIO_TX",},      \
        .dir = DMA_MCAL_DIR_MEMORY_TO_PERIPH,       \
         DMA_CHANNEL_SDIO_COMMON                    \
        .num = DMA_CHANNEL_NUM_SDIO_TX,             \
        .name = "SDIO_TX",                         \
        .CallBackHalf = CallBackHalfSdio1Tx,        \
        .CallBackDone = CallBackDoneSdio1Tx,        \
        .base_addr_source = (uint32_t)fromArray,    \
        .base_addr_destination =(uint32_t) toArray, \
        .block_count = 1,                           \
        .mux = 0,                                   \
    },

#define DMA_CHANNEL_SDIO \
    DMA_CHANNEL_SDIO_TX  \
    DMA_CHANNEL_SDIO_RX



#ifdef __cplusplus
}
#endif

#endif /* DMA_CHANNEL_SDIO_CONFIG_H  */

Настройка SD карты

Может так получиться, что вы нашли SD карту на 2GB, установили в PC и вам показывает 7 MByte. Дело в том что на ней уже прописана какая-н linux-овая файловая система и win это не видит. Надо удалить старые разделы и заново отформатировать карту памяти. Это можно сделать утилитой DISKPART. Для пуска утилиты DISKPART потребуются админские права.



Microsoft DiskPart version 10.0.19041.3636
Copyright (C) Microsoft Corporation.
On computer: LAPTOP-xxxxxx

DISKPART>
DISKPART> list disk
list VDISK
  Disk ###  Status         Size     Free     Dyn  Gpt
  --------  -------------  -------  -------  ---  ---
  Disk 0    Online          476 GB  1024 KB        *
  Disk 1    Online         7600 MB  7592 MB
DISKPART> select disk 1
Disk 1 is now the selected disk.
DISKPART>
DISKPART> list part
  Partition ###  Type              Size     Offset
  -------------  ----------------  -------  -------
  Partition 1    Primary           7568 KB    31 KB
DISKPART>
DISKPART> select part 1
Partition 1 is now the selected partition.
DISKPART>
DISKPART> delete part
DiskPart successfully deleted the selected partition.
DISKPART>
DISKPART>  create part pri
DiskPart succeeded in creating the specified partition.
DISKPART>
DISKPART> format fs=fat32 quick
  100 percent completed
DiskPart successfully formatted the volume.
DISKPART>
DISKPART> exit

Затем перед установкой SD карты в устройство надо проверить, что карта в самом деле поддерживает нужную битовую скорость на запись. Для этого есть другая утилита, называется H2testw.exe. Скачать H2testw можно по ссылке.  Утилита H2testw не стирает данные с карты. Эта утилита по частям пишет , читает и проверяет прочитанное с записанным. И так по всей памяти.

утилита H2testw проверяет SD карту
утилита H2testw проверяет SD карту

Утилита H2testw проверяет SD карту в случае успеха утилита выдает строку Test finished without errors. Тут же есть отчет по битовой скорости записи и чтения.

Результат тестирования SD карты положительный. Фактическая скорость получилась 13.8 MByte/s. Это в 37.68 раз превышает необходимую скорость записи звука.

Warning: Only 3758 of 3820 MByte tested.
Test finished without errors.
You can now delete the test files *.h2w or verify them again.
Writing speed: 13.8 MByte/s
Reading speed: 67.4 MByte/s
H2testw v1.4

Однако может попасться и бракованная SD карта. В этом случае утилита H2testw выдаст примерно такое красное сообщение

Отрицательный тест SD карты
The media is likely to be defective.
951.9 MByte OK (1949692 sectors)
2 KByte DATA LOST (4 sectors)
Details:0 KByte overwritten (0 sectors)
0 KByte slightly changed (< 8 bit/sector, 0 sectors)
2 KByte corrupted (4 sectors)
0 KByte aliased memory (0 sectors)
First error at offset: 0x000000000df64e00
Expected: 0x000000000df64e00
Found: 0x000000000df24e00
H2testw version 1.3
Writing speed: 6.47 MByte/s
Reading speed: 20.9 MByte/s
H2testw v1.4

У каждой SD карты есть регистры: CSD, CID и прочие. Вот значения регистров той SD карты с которой я делал эксперименты.

 3.191-->sdio_diag_ll

4.299,308,W,[SDIO],
CardCSD...
4.300,309,I,[SDIO],CSD_CRC:119 ,ECC:0,FileFormat:0,TempWrProtect:0
,PermWrProtect:0,CopyFlag:0,FileFormatGroup:0,ContentProtectAppli:0
,WriteBlockPaPartial:0,MaxWrBlockLen:9,WrSpeedFact:5,ManDeflECC:0
,WrProtectGrEnable:1,WrProtectGrSize:3,EraseGrMul:127,EraseGrSize:0
,DeviceSizeMul:4,MaxWrCurrentVDDMax:5,MaxWrCurrentVDDMin:5,MaxRdCurrentVDDMax:5
,MaxRdCurrentVDDMin:5,DeviceSize:3879,DSRImpl:0,RdBlockMisalign:0
,WrBlockMisalign:0,PartBlockRead:1,RdBlockLen:9,CardComdClasses:501
,MaxBusClkFrec:50,NSAC:0,TAAC:94,SysSpecVersion:0,CSDStruct:0

CID...
4.327,343,I,[SDIO],ManID:29 0x1d AData
4.328,344,I,[SDIO],OemAppId:16708 0x4144 DA
4.328,345,I,[SDIO],ProdName1:1297293344 0x4d532020 MS
4.331,346,I,[SDIO],ProdRev:0x10=0.1
4.331,347,I,[SDIO],ProdSN:939530821 0x38001a45
4.333,348,I,[SDIO],ManufactDate: Month:11 Year:2000
4.334,349,I,[SDIO],CID_CRC:55=0x37
4.337,350,W,[SDIO],
DsCardInfo...
4.337,351,I,[SDIO],CardVersion:0
4.337,352,I,[SDIO],Class:501
4.340,353,I,[SDIO],RelCardAdd:45928
4.340,354,I,[SDIO],BlockNbr:248320
4.340,355,I,[SDIO],BlockSize:512
4.343,356,I,[SDIO],TotalSize:127139840 Byte=124160 kByte=121.25 MBytes
4.344,357,I,[SDIO],LogBlockNbr:248320
4.346,358,I,[SDIO],LogBlockSize:512
4.346,359,I,[SDIO],CardType:0
4.347,360,I,[SDIO],1 CardState ?

Отформатировать SD карту в файловую систему FAT16. Назначить Allication Unit size равным 16 kбайт.

Диктофоны - это устройства hi-load обработки. Сейчас объясню почему... Для записи набегающего потока двухканальных 16-битных аудио семплов на частоте дискретизации 96kHz надо чтобы в SDIO, скорость записи превышала 384000 байт в секунду. Это не мало. Каждый семпл дает Вам в WAV файле 4 байта: левый и правый каналы по 16 бит каждый. Внутри прошивки я измерил фактическую битовую скорость записи в файловую систему FAT16 и получил такую справку. Понял, что надо заняться оптимизацией и ускорить запись в файл.

SDIO clock, MHz

kByte/s

Byte/s

ratio

режим, bit

5

159

162847

0,42

1

16.6

262

269003

0.70

1

12

737

754883

1.9*

4

25

292

299304

0,77

1

Для увеличения скорости записи пришлось принять ряд совсем неочевидных мер:

  1. Увеличить частоту ARM Cortex-M4 ядра до максимума: 168MHz (было 100 MHz). Так системная шина тактирует SDIO MAC с максимальной частотой 84MHz.

  2. Установил подтяжки к питанию для всех SDIO проводов кроме тактирования.

    -->gl sd
    +-----+-------+--------+-------+------+------+-----+-----+---------+
    | No  |  pad  |  mode  | level | dir  | pull |MuxS |MuxG |  name   |
    +-----+-------+--------+-------+------+------+-----+-----+---------+
    |   3 |  PC12 |   ALT1 |   L   |  out |   Air|  12 |  12 |  SD_CLK |
    |   4 |   PD2 |   ALT1 |   H   |  out |   Up |  12 |  12 |  SD_CMD |
    |   5 |   PC8 |   ALT1 |   H   |  io  |   Up |  12 |  12 |   SD_D0 |
    |   6 |   PC9 |   ALT1 |   H   |  io  |   Up |  12 |  12 |   SD_D1 |
    |   7 |  PC10 |   ALT1 |   H   |  io  |   Up |  12 |  12 |   SD_D2 |
    |   8 |  PC11 |   ALT1 |   H   |  io  |   Up |  12 |  12 |   SD_D3 |
    +-----+-------+--------+-------+------+------+-----+-----+---------+
  3. Записывать блоки размером 4k Byte за раз.

  4. Перевести SDIO на 4-битный режим. То есть задействовать параллельную шину.

  5. Работать в SDIO в режиме DMA2.

  6. Закомментировать отладочное логирование в коде SDIO операций чтения и записи.

  7. Повысить приоритет DMA каналов для SDIO до максимума.

  8. Повысить приоритет прерываний для DMA каналов SDIO до максимума.

  9. Отформатировать SD карту в файловую систему FAT16. Назначить Allocation Unit size равным 16 kбайт.

  10. Увеличил тактирование на SDIO тактировании до 24 MHz (максимальное).

  11. Увеличил стековую RAM память до 16k Byte.

    После этих мер скорость записи файлов заметно увеличилась и стала доходить до 853 kByte/s. Можно провернуть модульный тест fat_fs_write для измерения фактической скорости записи в файл.

Отладка диктофона

Чтобы начать запись надо открыть программу PuTTY, подключиться к главной консоли управления на UART2 и выполнить команду sound_recorder_restc DurationS. Первый аргумент задает продолжительность записи. В CLI это выглядит так

То же в виде текста

7:44-->sound_recorder_restc 10

465.426,431,I,[SoundRecorder],Duration,Ok
465.427,432,I,[WAV],File:R_4096_UT462732_10000Ms.wav,state:0,state:3,i2s_error_cnt:0,
                    rec_cnt:4,sample_cnt:960000,ErrCnt:0,total_file_size:3840044,
                    start_rec_ms:462753,stop_rec_ms:459991,data_size:3840000,
                    Spin:6871236,cur_save_size:0,Init:On,
465.429,433,I,[WAV],ChunkId:RIFF,ChunkSize:1920036 Byte,Format:WAVE,Subchunk1Id:fmt ,
                    Subchunk1Size:16,AudioFormat:0x0001,NumChannels:2,
                      SampleRate:96000 Hz,
                     ByteRate:384000 Byte,BlockAlign:4 Byte,BitsPerSample:16 bit,
                       Subchunk2Id:data,DataSize:1920000 Byte
465.440,434,I,[I2S],I2S_2,Set,Operation:Rx
465.441,435,I,[I2S],2 init
465.442,436,W,[DmaChannel],N:3=I2S2_RX
465.442,437,W,[Dma],3,DMA1,Stream_3,Init
465.443,438,I,[Dma],Init Id:3 Dma:1 Stream:3 Ok!
465.443,439,I,[I2S],I2S2 initOk
465.444,440,I,[GPIO],Init,PA0,IN
465.444,441,I,[GPIO],Init,PC3,IN
465.445,442,W,[GPIO],PB12,DrvSel:?,I2S2_WS,Dir:Out,Mode:ALT1,Mux:5,LL:H,Pull:Down,
                       Speed:High,Pin:0,
465.446,443,W,[GPIO],PB13,DrvSel:?, I2S2_CK,Dir:Out,Mode:ALT1,Mux:5,LL:H,Pull:Down,
  Speed:High,Pin:0,
465.447,444,W,[GPIO],PB15,DrvSel:?,I2S2_SDEXT,Dir:In,Mode:ALT1,Mux:5,LL:H,Pull:Down,
  Speed:High,Pin:0,
465.447,445,I,[SoundRecorder],RecStart...
7:45-->
7:48-->
7:49-->
7:49-->475.277,446,I,[I2S],DmaStopOk!
475.277,447,I,[SoundRecorder],I2sDmaStop,Ok
475.281,448,I,[SoundRecorder],CloseFile:[R_4096_UT465427_10000Ms.wav]Ok
475.281,449,I,[SoundRecorder],RecDuration:9833 ms
475.282,450,I,[SoundRecorder],WrOkCnt:938
475.283,451,I,[SoundRecorder],errorCnt:0
475.283,452,I,[SoundRecorder],WrSzErrorCnt:0
475.283,453,I,[SoundRecorder],longWriteErrorCnt:0

После появления в консоли строки RecDuration на SD карте кристаллизуется уникальный WAV файл, содержащий запись звуковой дорожки.

Этот файл можно проиграть любой мультимедийной утилитой. Например стандартной программой Media Player.

Архитектура прошивки получилась вот такой

В чем трудность создания диктофона?

Сделать прошивку прототипа диктофона оказалось не такой уж и тривиальной задачей. От записи к записи возникали всяческие неожиданные загвоздки:

  1. Как это ни странно, но в FatFS API не всегда отрабатывает функция f_write(). Да... Особенно в режиме FAT32. Иной раз f_write выдает OK и правильную записанную длину, а по факту уже на PC в HexViewer выяснятеся, что местами прошивка просто пишет в wav файл вкрапления непрерывных нулей. Согласно наблюдениям нули в WAV файле образуются как раз тогда, когда функция f_write не успевает записать половинчатый массив семплов между прерываниями I2S DMA (RxHalf и RxDone). При этом, в случае работы на файловой системе FAT16 эта ошибка не воспроизводится.

  2. FatFS функция f_write() при записи сваливается в ошибку FR_INT_ERR. В этом случае файловая система на SD карте рушится и laptop PC потом не узнает файловую систему на этой SD карте. Увеличение стека прошивки в два раза частично решило проблему, но не полностью. Есть набор SD карт где FR_INT_ERR вообще не появляется, при этом прошивка на STM32F407VG та же самая.

  3. Функция f_write иной раз может просто заклинить. Возвращает, что записано ноль байт и последующие записи тоже выводят 0 байт. При этом код ошибки возвращается FR_OK. Обычно такое происходит, когда в SD карте просто больше нет свободного места. Это особенно актуально на картах объёмом 128MByte. Поэтому перед созданием файла надо убедиться, что на SD карте есть свободное место.

  4. Функция f_write работает относительно быстро только, если записывать блоки по 4kByte. Другие размеры обычно не проходят тест на производительность (384000 Byte/s) и запись в SD карту происходит слишком медленно. В результате происходит срыв потока, запись просто теряет свою непрерывность и смысл.

  5. FatFS на файловой системе FAT16 работает стабильнее, чем на FAT32. В случае с FAT32 так и не прошел модульный тест на запись 1MByte с последующей проверкой записанных байт.

  6. При включенном цифровом фильтре нижних частот аудиокодек на левый канал выдает помехи. При этом правый канал формируется с нормальным сигналом.

    левый канал с помехами
    левый канал с помехами
  7. По непонятным мне причинам, самая стабильная работа диктофона наблюдается на SD карте размером 128MByte (форматирование FAT16). Даже не знаю откуда у меня такая реликтовая SD карта.

  8. В финальной WAV записи на левый канал эпизодически просачиваются вкрапления подозрительных одиночных пиков.

    Водянистый звуковой сигнал
    Водянистый звуковой сигнал

Итог

В результате мне удалось написать STM32F407VG-прошивку для I2S - совместимого диктофона c возможностью записывать WAV файлы на SD карту по SDIO с файловой системой FAT16 на основе широко распространенной учебной платы dev_ebox_stm32f4x и такого же распространенного отладочного аудиокодека WM8731. Бинари микропрограммы представлены на github. Исходный код прошивки диктофона тут же.

Думаю не требуется перечислять все те возможные приложения, где может потребоваться запись звука. Надеюсь этот текст поможет кому-нибудь добавить возможность звукозаписи в свои проекты.

Ссылки

Название

URL

Диктофоны для книги рекордов

https://habr.com/ru/articles/94553/

Диктофон и медицина
@555www555

https://habr.com/ru/articles/876326/

Проигрыватель WAV файлов на STM32

https://habr.com/ru/articles/1051842/

Обзор диктофона Edic Weeny A110 с функцией «чёрного ящика»
@EgorKotkin

https://habr.com/ru/articles/467935/

Подключение SD карты по SPI (Капсула памяти)
@karenic

https://habr.com/ru/articles/974076/

Конечный Aвтомат Аппаратного I2C-Трансивера

https://habr.com/ru/articles/856548/

Медленная работа SD карточек — кто виноват и что делать?
@GarryC

https://habr.com/ru/articles/220433/

Пуск I2S трансивера на Artery

https://habr.com/ru/articles/830184/

Audacity

https://www.audacityteam.org/

Запуск I2S Трансивера на Artery [часть 2] (DMA, FSM, PipeLine)

https://habr.com/ru/articles/834304/

FatFs - Generic FAT Filesystem Module

https://elm-chan.org/fsw/ff/

Сравнение микросхем аудио кодеков

https://docs.google.com/spreadsheets/d/1r7tuNrQ8PPfIVcM2FeGpwa1eeWjyq41CD0MGq_Q_VV8/edit?gid=0#gid=0

STM32 - uSD - SDIO 4bit - DMA

https://github.com/dtiziano/stm32_uSD_SDIO4bit/tree/main

Исходный код прошивки диктофона

https://github.com/aabzel/trunk/tree/main/source/projects/dev_ebox_stm32f4x_sound_recorder_gcc_m

Чип AudioСodec(а) WM8731 (или (ADC/DAC)*2 из iPod(а))

https://habr.com/ru/articles/703588/

Wave File Format - формат звукового файла WAV

https://microsin.net/programming/pc/wav-format.html

Разбор I2S трафика в программе Logic 2

https://habr.com/ru/articles/758188/

Цифровой звук на STM32: подключаем аналоговый микрофон через SAI и NAU88C22

@a3x

https://habr.com/ru/companies/selectel/articles/892852/

Обзор Aппаратного Aудио кодека MAX9860 (2x ADC+DAC)

https://habr.com/ru/articles/758140/

Как Работать с UART на Микроконтроллерах (UART + FIFO = LOG) @danil_12345

https://habr.com/ru/articles/981028/

Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB

https://habr.com/ru/articles/673522/

Формат WAV-файлов

http://solidstate.karelia.ru/p/tutorial/asni/Glava 2/Index3.htm

Отладка STM32 программатором J-LINK по SWD
@danil_12345

https://habr.com/ru/articles/995996/

Обзор AудиоКодека NAU8814YG

https://habr.com/ru/articles/808499/

dev_ebox_stm32f4x_sound_recorder_gcc_m

https://github.com/aabzel/Artifacts/tree/main/dev_ebox_stm32f4x_sound_recorder_gcc_m

утилита H2testw.exe для испытания SD карт

https://www.softportal.com/getsoft-45617-h2testw-1.html

Вопросы

  1. Что если реальная звуковая дорожка не совпадает с тем, что указано в заголовке WAV файла?

  2. Существует ли формат аудиозаписи, который в бинарном виде хранит такие метаданные как точное время начала записи и геолокацию места, где была инициирована данная запись звука?

  3. Как на Си изменить конкретный массив в середине бинарного файла, зная отступ от начала файла, размер заменяемого фрагмента и новое значение размера массива? В качестве API файловой системы используется Fat-FS.

  4. Как измерить реальную поддерживаемую скорость записи данной конкретной microSD карты?

  5. Существуют ли в продаже готовые отладочные платы с ARM Cortex M4 микроконтроллером (STM32F4X), каким-н простым аудиокодеком как WM8731, audio-jack портов для наушников, микрофона (и желательно LineIn), гаражом для microSD карты подключаемой по интерфейсу SDIO (или SPI), LEDом и желательно графическим дисплеем? Чтобы можно было полноценно прототипировать и отлаживать прошивки диктофонов и плейеров.

  6. Как проверить, что диктофонная запись звука в самом деле получилась непрерывная? Как убедиться, что звукозаписывающая аппаратура не пропустила 10-30 миллисекунд (или не добавила лишние семплы) ?

  7. Существует ли win утилита для чтения регистров SD карты: Card-specific data, Card IDentification register, SD Status register, Card Status Register, operation conditions register, SD Card Configuration register, Drive stage register , relative card address register, при её подключению к персональному компьютеру с операционной системой Windows 10?

  8. Поддерживают ли microSD карты “горячее подключение”?

Комментарии (40)


  1. Mikhail_Abiht
    06.07.2026 11:35

    Очень основательный подход! Следующим этапом было бы: своя печатная плата с расширением памяти и другими фишками под задачи(аппаратное отключение -например...)


    1. aabzel Автор
      06.07.2026 11:35

      Следующим этапом было бы: своя печатная плата с расширением памяти и другими фишками под задачи(аппаратное отключение -например...)

      Проше взять готовую отладочную плату STM32F746G-DISCO . Где всё это добро уже есть


      1. Coder007
        06.07.2026 11:35

        STM32F746G-DISCO микроконтроллерная плата jiaboroo за 11 596,23 ₽

        Как мне кажется - дороговатая плата для диктофона.

        Цифровой диктофон ockic WAV/MP3 128ГБ за 1 436,21 ₽

        А вот сколько стоит диктофон, цифровой.

        И то и другое с алиэкспресса.


    1. aabzel Автор
      06.07.2026 11:35

      плата с расширением памяти 

      Что Вы подразумеваете под расширением памяти?
      SDRAM? SPI-NAND? Другое?


      1. Mikhail_Abiht
        06.07.2026 11:35

        |Главная трудность записи звука на микроконтроллерах заключается в том, что в микроконтроллерах нет столько много RAM памяти| -у вас так написано...


  1. rukhi7
    06.07.2026 11:35

    Для этого есть утилита H2testw.exe.

    это вы под Windows на десктопе проверяете -

    что карта в самом деле поддерживает нужную битовую скорость на запись

    интересно? Если да, то как вы проверяете скорость записи на СТМ-ке, мне кажется у вас не очень понятно написано, а было бы интересно понять.

    Не знаю это только я не понял есть ли у вас проверка при переключении буферов, что очередной буфер для записи свободен, то есть что данные из него полностью ушли на карту?


    1. aabzel Автор
      06.07.2026 11:35

      то как вы проверяете скорость записи на СТМ-ке, мне кажется у вас не очень понятно написано, а было бы интересно понять.

      Вот такой модульный тест я написал для проверки скорости записи

      Код измерения скорости записи в FAT-FS
      
      /*
        tr fat_fs_write
      */
      static uint8_t wrData[WRITE_PART_SIZE+1]={0};
      bool test_fat_fs_write(void) {
          LOG_INFO(TEST, "%s():", __FUNCTION__);
          bool res = true;
          static uint32_t sn=0;
          FRESULT ret;
          sn++;
      
          memset(wrData, 0xAA, sizeof(wrData));
          FIL File = {0};
          uint32_t i = 0;
          uint32_t total_size = 0;
          uint32_t start_ms = time_get_ms32();
          char file_name[80]="";
          snprintf(file_name,sizeof(file_name),"TWP%u.bin", sn);
          LOG_INFO(TEST,"sizeof:%s ",file_name );
          BYTE mode = FA_WRITE | FA_CREATE_NEW |FA_OPEN_ALWAYS;
          FRESULT reto = f_open((FIL*)&File, (const TCHAR*) file_name, mode);
          LOG_INFO(TEST,"file_name:[%s],ret:%s ",file_name , FatFsResToStr(reto ));
          if(FR_EXIST==reto ) {
              ret = f_unlink(file_name);
              LOG_INFO(TEST,"DeleteFile:[%s],ret:%s ",file_name , FatFsResToStr(ret ));
              reto = f_open((FIL*)&File, (const TCHAR*) file_name, mode);
          }
      
          while(total_size < WAV_WRITE_SIZE) {
              UINT written = 0;
              ret = f_write(&File, wrData, WRITE_PART_SIZE, &written);
              EXPECT_EQ(FR_OK, ret);
              EXPECT_EQ(WRITE_PART_SIZE, written);
              if( FR_OK != ret ) {
                  LOG_ERROR(TEST,"%u,WrError:%s",i, FatFsResToStr(ret ));
                  break;
              }
              if(WRITE_PART_SIZE!=written) {
                  break;
              }
              total_size += written;
              i++;
          }
      
          ret = f_close(&File);
          LOG_INFO(TEST,"CloseCode:%s " , FatFsResToStr(ret ));
          ASSERT_EQ(FR_OK, ret);
          uint32_t stop_ms = time_get_ms32();
          uint32_t diff_ms = stop_ms - start_ms;
          uint32_t data_rate= (1000*total_size) / (diff_ms);
          LOG_INFO(TEST,"totalSize:%u Byte,Duration:%u ms,WriteSpeed:%u Byte/s=%f kByte/s",
                   total_size,
                   diff_ms,
                   data_rate,
                   BYTES_2_KBYTES(data_rate));
      
          float ratio =((float) data_rate / (float) WAV_WRITE_SPEED);
          LOG_INFO(TEST,"ratio:%f ",ratio );
          ASSERT_GR(WAV_WRITE_SPEED, data_rate);
      
          EXPECT_EQ(WAV_WRITE_SIZE, total_size);
          return res;
      }


      1. rukhi7
        06.07.2026 11:35

        так это не тест должен быть, это должна быть встроенная диагностика при переключении буферов в рантайме! Надо обязательно проверять что буфер свободен при переключении, иначе вы и будете ловить артефакты от наложений и не поймете откуда они у вас берутся.

        Кстати в этом коде очень странно что вы время на открытие и закрытие файла и всякую другую дребедень тоже охватили:

            uint32_t start_ms = time_get_ms32();
            char file_name[80]="";
            snprintf(file_name,sizeof(file_name),"TWP%u.bin", sn);
            LOG_INFO(TEST,"sizeof:%s ",file_name );
            BYTE mode = FA_WRITE | FA_CREATE_NEW |FA_OPEN_ALWAYS;
            FRESULT reto = f_open((FIL*)&File, (const TCHAR*) file_name, mode);
            LOG_INFO(TEST,"file_name:[%s],ret:%s ",file_name , FatFsResToStr(reto ));
        // ...
        // ...
        // ...
        
        
        ret = f_close(&File);
        // ...
        // ...
        // ...
        
            uint32_t stop_ms = time_get_ms32();

        Зачем вы все это учитываете как время записи?


        1. aabzel Автор
          06.07.2026 11:35

          Кстати в этом коде очень странно что вы время на открытие и закрытие файла и всякую другую дребедень тоже охватили:

          Потому, что FATFS фактическую запись как раз и делает внутри f_close.
          Внутри f_close вызывается f_sync для фактической загрузки в накопитель.


    1. aabzel Автор
      06.07.2026 11:35

      Не знаю это только я не понял есть ли у вас проверка при переключении буферов, что очередной буфер для записи свободен, то есть что данные из него полностью ушли на карту?

      У меня есть проверка на срыв потока.
      Если длительность записи фрагмента превысила таймаут REC_PART_TIMEOUT_US , то происходит аварийная остановка записи.

      static inline bool sound_rec_save_part_offset(SoundRecorderHandle_t* Node, 
                                                    uint32_t offset, 
                                                    uint32_t need_size) {
          bool res = false;
          if(Node->cur_save_size < Node->total_file_size) {
              UINT written = 0;
              uint32_t start_save_us = time_get_us32();
              void* buff = (void* )    ( (   (uint32_t ) Node->RxSampleArray) +  offset     );
              FRESULT ret = f_write(&Node->FileToRec, buff, need_size, &written);
              uint32_t end_save_us = time_get_us32();
              if(FR_OK == ret) {
                  if(need_size == written) {
                      Node->cur_save_size += written;
                      Node->wr_ok_cnt++;
                      res = true;
                  } else {
                      Node->error_size_cnt++;
                      //LOG_ERROR(SOUND_RECORDER,"WriteSmall:%u Byte", written);
                      res = sound_recorder_stop_ll(Node);
                  }
                  Node->action = SOUND_RECORDER_ACTION_NOPE;
              } else {
                  Node->error_cnt++;
                  Node->action = SOUND_RECORDER_ACTION_NOPE;
                  res = sound_recorder_stop_ll(Node);
              }
              uint32_t diff_us = end_save_us-start_save_us;
              if (REC_PART_TIMEOUT_US < diff_us) {
                  Node->long_write_error_cnt++;
                  res = sound_recorder_stop_ll(Node);
              }
          } else {
              res = sound_recorder_stop_ll(Node);
          }
          return res;
      }


      1. rukhi7
        06.07.2026 11:35

        ну вот здесь у вас один f_write

                uint32_t start_save_us = time_get_us32();
                void* buff = (void* )    ( (   (uint32_t ) Node->RxSampleArray) +  offset     );
                FRESULT ret = f_write(&Node->FileToRec, buff, need_size, &written);
                uint32_t end_save_us = time_get_us32();

        измеряется, и получается он измеряет непонятно что если

        FATFS фактическую запись как раз и делает внутри f_close

        Но с точки зрения проверки что буфер свободен это корректно, тем не менее.

        Но получается вы используете двойную буферизацию - одна своя, вторая от файловой системы. Это как минимум не очень эффективно, а как максимум будет иметь всякие странные эффекты, которые и приводят к артефактам в записанных данных и которые вы не отладите пока в конце концов не влезете с ногами в код реализации этой файловой системы и ее буферизации. Чужая реализация файловой системы в эмбеддед это почти всегда беда, такая черная дыра в которой размножаются баги безконтрольно. В эмбеддед Операционная Система (ОС) практически не бывает полноценная, там куча ограничений которые еще фиг все найдешь-отловишь. Фактически вы вместо того чтобы заниматься отладкой своего кода вынуждены заниматься исследованием кода этой ОС большую часть времени.


  1. DrGluck07
    06.07.2026 11:35

    Не, ну на кодеке любой сделает. А вот ежели через ADC и DAC микроконтроллера...


    1. aabzel Автор
      06.07.2026 11:35

      У аудиокодека шире динамический диапазон: 24 бит вместо 12 на MCU. Плюс есть аналоговые предусилитель для микрофона, цифровой фильтр нижних частот.

      Звук получается чище и разборчивее.


      1. Sdima1357
        06.07.2026 11:35

        Все нормально там со звуком у STM32. Используте i2s microphone и sigma delta.
        https://habr.com/ru/articles/662141/
        Здесь сигма дельта на тaймерах stm32f401

        https://www.youtube.com/watch?v=8jB26_xrSuw


  1. Sun-ami
    06.07.2026 11:35

    Зачем диктофону частота дискретизации 96 кГц? И тем более 384 кбайт/с, то есть стерео? Ему и 44,1 кГц - много. 32 кГц моно - вполне достаточно. А вот FAT16 - это анахронизм, особенно для диктофона, особенно без сжатия данных. А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее, по крайней мере поштучно.


    1. aabzel Автор
      06.07.2026 11:35

      Зачем диктофону частота дискретизации 96 кГц? Ему и 44,1 кГц - много. 32 кГц - вполне достаточно.


      Я хочу сделать автономный сонар из диктофона.
      https://habr.com/ru/articles/868672/

      Если повысить частоту дискретизации до 96kHz, то это улучшит разрешение измерения расстояния.

      На частоте дискретизации 44100 Hz за один семпл (22.6 us) звук пролетает 331*(1/44100)=7.5mm. Свертка ЛЧМ дает максимум в одном семпле. Получается погрешность измерения расстояния должна быть -/+ 7.5 mm.

      На частоте 96k Hz погрешность измерения расстояния должна быть -/+ 3.4 mm.


    1. aabzel Автор
      06.07.2026 11:35

      А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее.

      Зато он прост в программировании (11 регистров всего-лишь) и его можно купить на AliExpress прямо в составе готового модуля


      https://aliexpress.ru/item/32857846271.html?shpMethod=CAINIAO\_STANDARD&sku\_id=65320258244&spm=a2g2w.productlist.search\_results.10.53306900uSNlJF


      1. Coder007
        06.07.2026 11:35

        А вот ещё варианты:

        LMD2718 + NS4168

        PCM5102 + PCM1808

        WM8960

        WM8978

        И идея сделать общение через сеть множества абонентов (один вещает всем или группе, один на один, главный общается с выбранным) с поддержкой записи на сервере всех переговоров.

        Изменять дискретизацию перед началом передачи данных, в зависимости от качества канала связи.


    1. aabzel Автор
      06.07.2026 11:35

       А вот FAT16 - это анахронизм, особенно для диктофона.

      Ну а что тут поделаешь, если модульные тесты проходят на FAT16 и проваливаются на FAT32?


    1. aabzel Автор
      06.07.2026 11:35

      А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее, по крайней мере поштучно.

      Какой тогда аудиокодек Вы предлагаете применить?


      1. Sun-ami
        06.07.2026 11:35

        Не подскажу - задача специфическая.


        1. aabzel Автор
          06.07.2026 11:35

          Да чего тут специфичного?. Заурядная звукозапись.


          1. Sun-ami
            06.07.2026 11:35

            Ну, например есть I2S-кодеки, в которых в усилителе наушников очень плохо подавлен ШИМ, и это не описано в документации. Для слушания ушами не кричитно, но вот если работать с ультразвуком - очень может вылезти.


    1. aabzel Автор
      06.07.2026 11:35

      А кодек WM8731 числится устаревшим - его уже не продают на Маузере и Дижикее, по крайней мере поштучно.

      WM8731 установлен на плате FPGA Altera-DE1. Плату FPGA Altera-DE1 тоже не продают на Маузере ?


      1. Sun-ami
        06.07.2026 11:35

        Вот такая ситуация и доступностью на Digikey - по всем вариантам корпуса - статус "Obsolet". На Mouser - вообще доступны только "IC Development Tools Eval Bd"

        Скрытый текст


        1. aabzel Автор
          06.07.2026 11:35

          А Mouser предлагает более новую альтернативу для Obsolet товаров? 


          1. Sun-ami
            06.07.2026 11:35

            Насколько я знаю, нет - это нужно искать на сайте производителя, в данном случае это Cirrus Logic.


  1. Coder007
    06.07.2026 11:35

    Все таки стоит на нормальную SD карту делать запись и как было сказано ранее, сделать готовое устройство. Просто на этих макетках как то кустарно получается. А так, сделать печатную плату, красивый корпус, все укомпоновать, добавить кнопки быстрого доступа к командам, небольшой дисплей и будет изделие, а не полуфабрикат.

    Автор, я говорил тебе уже, у тебя такой потенциал, а ты каждый раз переизобретаешь велосипед, самокат, колесо и кирпичи. И все бы ничего, дальше макетной платы ты не идёшь, почему?

    Статей много, ты делишься информацией, очень круто, а что дальше? Если ты просто хочешь научить всех, показать, как можно делать и что для этого нужно, то хорошо, пусть будет так.

    Это проект - интересный, но много НО! Контроллер на макетке, аудиоплата на макетке, какой микрофон - непонятно, как прослушать на диктофоне - непонятно. Управление - непонятно, индикации нет. Схемы устройства нет. Карта памяти только на FAT16 (объем я так понимаю был только такой в наличии) и FAT32 не работает.

    Повторить такое устройство смогут единицы, если захотят (если найдут такие компоненты и будут согласны на программно-аппаратные ограничения).

    В итоге, автор сделал классную работу, показал, выяснил, узнал, но для себя. Да я понимаю этот кайф, когда разобрался с какими-то деталями, мелочам, все заработало и на какие-то мелочи даже не обращаешь внимания, потому что сама идея была именно в этом! А про остальные важные моменты забываешь, упускаешь, предполага что это же всё просто, значит люди поймут и разберутся сами... Но это сделают единицы, поймут тоже единицы, а все кто захочет повторить - не смогут...

    Это не в упрёк, это взгляд со стороны.


    1. aabzel Автор
      06.07.2026 11:35

       А так, сделать печатную плату, красивый корпус, все укомпоновать, добавить кнопки быстрого доступа к командам, небольшой дисплей и будет изделие

      Среди российских программистов-микроконтроллеров в организациях в принципе нет пром-дизайнеров как класса. Хотя факультеты "Промышленного Дизайн" сейчас есть почти в каждом ВУЗзе. Если у нас делают какой-то электронный прибор (пусть даже с хорошей прошивкой), то он похож на кирпич, гробик или шайбу. В качестве корпуса обычно бездумно покупают готовые прямоугольные серые корпуса в ЧипИдип-е. Разъём всегда ставят DB-9 (привет из 195х). Нет уплотнений. щели получаются такие, что между разъёмом и корпусом можно аж палец засунуть. Получившееся изделие даже в руках держать противно. Торчат куски платы об которые можно поцарапаться. Даже если электроника и прошивка вдруг и внезапно получились великолепно, то механическое исполнение продукта все перечеркивает и обнуляет результат на корню.


      1. Coder007
        06.07.2026 11:35

        Даже если электроника и прошивка вдруг и внезапно получились великолепно, то механическое исполнение продукта все перечеркивает и обнуляет результат на корню.

        Разве ты такой? Или ты в себя не веришь? Или ты ментально с теми, кто делает только так?

        Почему люди часто говорят о других, но смотрят на себя, хоть таковыми и не являются? Ну вот в забре много людей, но не все так делают. Новички электроники - делают, а старички - страдают, думая что они делают только плохо, потому что все вокруг делают плохо.

        Это проблема детей СНГ, у нас слишком много самокритики, но беда в том, что мы с этим ничего не делаем, просто страдаем и сидим на попе ровно, потому что вме вокруг нас плохо, криво, некрасиво. Ну так что же мешает это изменить? Все в наших руках!

        Поверь, я тоже так считал раньше,а живу я уже долго и застал и сложные и очень сложные времена. И живу я не в России, а в Казахстане, а тут было ещё сложнее чем в России.

        Сейчас я вижу, как чувак из аула (небольшой поселок) , со своей простой идеей и небольшой реализацией банальной идеи влетает на поле битвы технологий и идёт вперед, с гробиками корпусов, макетными платами собранными в эти корпуса, но рабочим продуктом и продаёт его! Потом, со временем это превращается в изделие и серийный экземпляр. А по факту, человек просто начал изучать электронику и поверил в себя.

        А ты в себя не веришь, потому что вокруг все делают плохо и не красиво. А не нужно в них верить, нужно верить в себя. Искать тех, кто пойдёт вместе с нами и им будет плевать, что корпус выглядит на начальном этапе как квадратная коробка. Завтра, найдётся человек, который скажет - "ребята, у вас классный продукт, давайте я вам забабахаю классный корпус", и останется с нами, и станет тем, кто будет наводить красоту.

        Подумай, стоит ли разменивать свою жизнь на такое отношение к жизни. Мир не идеален, мир не совершенен, но это не значит что он останется таким навсегда, если не мы, то его сделают другие идеальным, под себя. А для нас он продолжит оставаться серым и не идеальным.

        Возможно много написал, но от чистого сердца, ты подумай, просто подумай.

        Я правда мало встречаю вот таких самородков как ты.

        P.S. Ты никому ничего не должен, и логика простая. То, что твоё образование оплатило государство, не даёт ему права владения тобой. У тебя нет бумаги или договора, согласно которому ты ДОЛЖЕН:

        возвращать результаты полученного технического образования обратно в народ.

        Нет такого! У меня старшая дочка училась на бюджете и никто с неё ничего не требует. И не сможет потребовать.

        Самое лучшее и правильное, что ты должен и по возможности, со своими знаниями, реализовывать их по максимуму. В первую очередь для себя, а потом уже отдавать государству в виде налогов.


    1. aabzel Автор
      06.07.2026 11:35

      Автор, я говорил тебе уже, у тебя такой потенциал, а ты каждый раз переизобретаешь велосипед, самокат, колесо и кирпичи.

      Спасибо. А что еще остается делать ?
      В России не разрабатывают по-настоящему крутую электронную технику.
      Негде приложить свои силы.
      Не разрабатывают вертикально приземляющиеся ракеты (реактивная посадка), не делают смартфоны, не делают электромобили, не делают радары с синтезом апертуры (SAR локаторы), не делают ЯМРТ томографы. Уровень современной embedded разработки РФ - это, условно, сделать прошивку платы для открытия и закрытия трубы - это максимум. И то с натягом.

      И все бы ничего, дальше макетной платы ты не идёшь, почему?

      Я специалист по прошивкам. Чертить 3D корпуса не умею. Топологию PCB трассировать тоже. Для того чтобы спроектировать полноценный продукт надо минимум 3 инженера: электронщик, пром-дизайнер и программист.


      1. Coder007
        06.07.2026 11:35

        В России не разрабатывают по-настоящему крутую электронную технику. Негде приложить свои силы. Не разрабатывают вертикально приземляющиеся ракеты (реактивная посадка), не делают смартфоны, не делают электромобили, не делают радары с синтезом апертуры (SAR локаторы), не делают ЯМРТ томографы. Уровень современной embedded разработки РФ - это, условно, сделать прошивку платы для открытия и закрытия трубы - это максимум. И то с натягом.

        Стань тем, кто это начнёт делать. И причём здесь Россия? Разве она тебя тормозит? Разве в ней дело?

        Ты сейчас говоришь о стране, о людях очень субъективно, но зачем? Разве они тебе мешают сделать что-то? Разве они тебя как-то ограничивают? Начни делать не ради страны, а для себя, для своего благосостояния. Начни с заботы о себе и све вокруг увидят что если ты можешь сделать для себя, то и для других сможешь.

        Не смотри и не пеняй на других, они тебе ничего не делают, максимум - комментируют твои поделки. Порой - недоделки.

        Я специалист по прошивкам. Чертить 3D корпуса не умею. Топологию PCB трассировать тоже. Для того чтобы спроектировать полноценный продукт надо минимум 3 инженера: электронщик, пром-дизайнер и программист.

        Скажу честно, это мышление того, кто в себе сомневается. Того, кто читает, что он не сможет что-либо сделать и при этом ни разу даже не попробовал это сделать. Просто сомневается и все! "Я специалист по заколачиванию гвоздей, а как их носить и куда забивать - я не знаю и никогда не узнаю, для этого есть другие люди!" - вот так я слышу это очень часто.

        Поверь, не боги разводят платы и не боги корпуса разрабатывают.

        Сейчас с нашими технологиями мы не то что корпус, мы черта в ступе можем разработать и напечатать, благо есть все для этого. И нет необходимости знать дорогостоящие и сложные продукты для моделирования.

        Касательно схем и плат: Easy EDA - как стартовый вариант - идеально! Заказ платы из программы. Хотя как у вас в России, не знаю. Из Казахстана работает прекрасно.

        Касательно моделирования корпусов (на первое время хоть кирпичом, хоть гробиком) - SketchUp. Просто и незамысловато.

        Принтер для печати - любой, хоть самый дешевый, размерами области печати 200×200×200. Для поделок хватит.

        И самое главное - желание идти вперед, стать тем самым, кто будет несмотря на сложности брать и делать.

        Я же писал тебе в личку, давай обсудим варианты, интересные, продуктивные, нужные и возможно продаваемые.


    1. aabzel Автор
      06.07.2026 11:35

      Статей много, ты делишься информацией, очень круто, а что дальше? Если ты просто хочешь научить всех, показать, как можно делать и что для этого нужно, то хорошо, пусть будет так.

      Логика проста.
      Российские налогоплательщики финансировали мое бюджетное образование в казёном Политехе. Теперь надо, по возможности, возвращать результаты полученного технического образования обратно в народ.


    1. aabzel Автор
      06.07.2026 11:35

       какой микрофон - непонятно

      Микрофон я выбрал первый попавшийся под рукой. Это оказался микрофон aceline AMIC-7.

      микрофон aceline AMIC-7
      микрофон aceline AMIC-7

      https://www.dns-shop.ru/product/5217c21ccc0a3330/mikrofon-aceline-amic-7-cernyj/


  1. 555www555
    06.07.2026 11:35

    Хороший труд. Спасибо.


  1. Mike-M
    06.07.2026 11:35

    Внутри прошивки я измерил реальную фактическую битовую скорость записи в файловую систему FAT и получил такую справку

    Такое мог написать либо голимый ИИ, либо...

    На КДПВ: вместо ActiveHight должно быть ActiveHigh, вместо Battary — Battery, вместо BlockDiagramVer:2 — Block Diagram v2. Если американская валюта обозначена через $, то и российская должна быть обозначена через ₽, а не RUR (хотя указание стоимости, температурного диапазона и корпусного исполнения на блок-схеме само по себе странно).
    Число ошибок в тексте исчисляется десятками.
    И так в каждой статье...

    За период с 2022 года я 47 раз воспользовался Ctrl-Enter, чтобы указать на необходимость корректуры перед публикацией. Просил уделять внимание правописанию, хотя бы с помощью бесплатных сервисов. Но автор с патологическим упорством продолжает писать безграмотные статьи.

    Что ж, это его выбор. Мой выбор — нажать кнопку "Скрыть публикации автора".


    1. Coder007
      06.07.2026 11:35

      Так вам не в эту студию, здесь же рассматривают самоделки, разработки, решения, обсуждают моменты улучшения, модернизации, а уроки русского языка здесь не берут и не проводят, так же как и не заказывают услуги по лингвистика и проверке синтаксис и орфографии. Спасибо за вашу инициативу и да, может вам действительно не стоит смотреть на публикации автора, если они настолько вас трогают и тревожат.

      Уверяю вас, он не пользуется ИИ, потому как таких решений, которые делает автор, там ещё нет и ИИ пока ещё не существует, а то, что вы называете ИИ - по факту является нейросетью. Это если разговаривать на Вашем языке.

      За период с 2022 года я 47 раз воспользовался Ctrl-Enter, чтобы указать на необходимость корректуры перед публикацией. Просил уделять внимание правописанию, хотя бы с помощью бесплатных сервисов. Но автор с патологическим упорством продолжает писать безграмотные статьи.

      Вы очень настойчивый человек, но кто вас об этом просит? Хоть один читатель данного автора обратился к вам за этим? Автор просил вас оценивать его статьи? С какой целью вы пытаетесь доказать несостоятельность и безграмотность данного автора в знаниях русского языка? Автор продолжает писать статьи на тему не лингвистики, а на тему разработок своих уникальных устройств, решений и делится этим с народом!

      А чем делитесь вы? Обвинениями? Оскорблениями? Претензиями? Чем?

      ОТК нужен заводам, предприятиям, выпускающим Товарную продукцию, а не НИИ, которые выпускают идеи, решения, порой безумные. Гении могут не знать правил русского языка, не видеть ошибок, но останутся гениями.

      Человеку свойственно ошибаться. Не ошибается тот, кто ничего не делает.

      Вы, по всей видимости не ошибаетесь в этой жизни...


    1. Coder007
      06.07.2026 11:35

      Что ж, это его выбор. Мой выбор — нажать кнопку "Скрыть публикации автора".

      Надеюсь меня поддержат все читатели автора aabzel. Мы уважаем Ваш выбор! Вам не стоит расстраивать себя такими статьями. Вы старались, стремились, но....


    1. aabzel Автор
      06.07.2026 11:35

      Такое мог написать либо голимый ИИ, либо...

      Вот и вправду говорят:
      "Не делай добра, не получишь и зла"


    1. aabzel Автор
      06.07.2026 11:35

       Если американская валюта обозначена через $, то и российская должна быть обозначена через ₽, а не RUR 

      Это просто смешно.
      На клавиатуре же просто нет символа P c черточкой под P, как в случае с cимволом $.
      Человек явно перфекционист.