MyTetra Share
Делитесь знаниями!
интернет-радио на базе ESP8266 (NodeMCU) с расширенными возможностями
Время создания: 24.05.2025 13:48
Автор: alensav
Текстовые метки: интернет-радио на базе ESP8266 (NodeMCU)
Раздел: FRAM
Запись: alensav/MyTetra2/main/base/1748083702kz4a8ex6or/text.html на raw.githubusercontent.com

Хочу реализовать : Добавить вывод названия трека и станции на экран. Реализовать логирование событий в FRAM . Настроить работу с несколькими станциями и сохранение выбора пользователя. Оптимизировать использование памяти и пинов. Применить: Модуль поворотного энкодера KY-040. 1.2 RIXITE XH-A232 Цифровой аудиоусилитель 30Вт+30Вт; 1.3 Estardyn PCM5102 DAC декодер для Raspberry Pi; 1.4 Цветной TFT дисплей 1.8′ SPI 128×160 px на базе ST7735; 1.5Контроллер NodeMCU ESP8266 (учесть номерацию пинов в формате D и GPI0.

Qwen3-235B-A22B1:44 PM

Отлично! Мы будем создавать интернет-радио на базе ESP8266 (NodeMCU) с расширенными возможностями:



🎯 Цель проекта:

Создание интернет-радио с:

  • Воспроизведением потокового аудио.
  • Отображением информации о станции и треке на TFT ST7735.
  • Работой с несколькими радиостанциями.
  • Сохранением текущей станции в FRAM.
  • Логированием событий в FRAM.
  • Управлением через энкодер KY-040.
  • Использованием внешнего PCM5102 DAC через I²S для высококачественного звука.



📦 Компоненты


КОМПОНЕНТ

НАЗНАЧЕНИЕ

ИНТЕРФЕЙС

NodeMCU ESP8266

Контроллер

KY-040 Encoder

Управление станциями, громкость

GPIO (D5, D6, D7)

PCM5102 DAC

Высококачественный аудиовыход

I²S

RIXITE XH-A232 усилитель

Усиление звука

Аналоговый вход

FM24CL64B x2

Хранение данных (станция, логи)

I²C

SD-карта

Хранение изображений/обложек

SPI

ST7735 1.8" TFT

Отображение UI

SPI



📝 Основные функции


ФУНКЦИЯ

РЕАЛИЗАЦИЯ

Переключение станций

Энкодером KY-040

Сохранение текущей станции

FRAM (FM24CL64B)

Логирование событий

FRAM (вторая микросхема или второй адрес той же)

Вывод информации

TFT ST7735

Аудио вывод

PCM5102 DAC через I²S

Чтение метаданных (ID3)

Поддерживается вESP8266Audio



🔧 Пины ESP8266 (NodeMCU)


ПИН (GPIO / D)

НАЗНАЧЕНИЕ

D0 (GPIO16)

CS TFT

D1 (GPIO5)

SCL (I²C)

D2 (GPIO4)

SDA (I²C)

D3 (GPIO0)

DC TFT

D4 (GPIO2)

RST TFT

D5 (GPIO14)

CLK энкодера

D6 (GPIO12)

DT энкодера

D7 (GPIO13)

SW энкодера / MOSI

D8 (GPIO15)

CS SD

RX (GPIO3)

Serial (отладка)

TX (GPIO1)

Serial (отладка)

GPIO17 (не на NodeMCU)

MISO (если нужен)

GPIO0

BOOT (подтянуть к GND при загрузке)

⚠️ Убедитесь, что пины не конфликтуют между SPI/I²C модулями.


📄 Структура проекта

cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

#include <ESP8266WiFi.h>

#include <Wire.h>

#include <SPI.h>


// === Audio ===

#include <AudioGeneratorMP3.h>

#include <AudioFileSourceICYStream.h>

#include <AudioFileSourceBuffer.h>

#include <AudioOutputI2SNoDAC.h>


// === Display ===

#include <Adafruit_ST7735.h>


// === SD Card ===

#include <SdFat.h>


// === Encoder ===

#include <Encoder.h>



💡 Пример кода (частично реализованный функционал)

📋 1. Инициализация Wi-Fi и подключение к станции

cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

const char* ssid = "your_wifi";

const char* password = "wifi_password";


const char* stations[] = {

"http://stream.station1.com/stream",

"http://stream.station2.com/stream",

"http://stream.station3.com/stream"

};


int currentStation = 0;

bool stationChanged = true;


void connectToRadio() {

if (mp3 && mp3->isRunning()) mp3->stop();


file = new AudioFileSourceICYStream(stations[currentStation]);

buff = new AudioFileSourceBuffer(file, 2048);

mp3 = new AudioGeneratorMP3();

outp = new AudioOutputI2SNoDAC();

mp3->begin(buff, outp);

}



📋 2. Энкодер KY-040 — переключение станций

cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

#define ENCODER_CLK D5 // GPIO14

#define ENCODER_DT D6 // GPIO12

#define ENCODER_SW D7 // GPIO13


Encoder myEncoder(ENCODER_CLK, ENCODER_DT);


long lastPosition = -999;


void IRAM_ATTR isr_encoder() {

long newPosition = myEncoder.read();

if (newPosition != lastPosition) {

if (newPosition > lastPosition) {

currentStation = (currentStation + 1) % (sizeof(stations)/sizeof(char*));

} else {

currentStation = (currentStation - 1 + sizeof(stations)/sizeof(char*)) % (sizeof(stations)/sizeof(char*));

}

stationChanged = true;

lastPosition = newPosition;

}

}


void setup() {

pinMode(ENCODER_SW, INPUT_PULLUP);

attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), isr_encoder, CHANGE);

}



📋 3. FRAM — сохранение текущей станции и логирование

cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

#define FRAM_ADDR_1 0x50 // для станции

#define FRAM_ADDR_2 0x51 // для логов


void saveCurrentStation(int stationIndex) {

Wire.beginTransmission(FRAM_ADDR_1);

Wire.write(0x00); // адрес

Wire.write(stationIndex);

Wire.endTransmission();

}


int loadCurrentStation() {

Wire.beginTransmission(FRAM_ADDR_1);

Wire.write(0x00);

Wire.endTransmission();

Wire.requestFrom(FRAM_ADDR_1, 1);

return Wire.read();

}


void logEvent(const char* event) {

static uint16_t logPos = 0;

for (int i = 0; event[i]; i++) {

writeByte(FRAM_ADDR_2, logPos++, event[i]);

}

writeByte(FRAM_ADDR_2, logPos++, '\n');

}



📋 4. TFT ST7735 — отображение информации

cpp

1

2

3

4

5

6

7

8

9

10

11

12

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);


void updateDisplay(const char* stationName, const char* trackTitle) {

tft.fillScreen(ST77XX_BLACK);

tft.setTextSize(1);

tft.setTextColor(ST77XX_YELLOW);

tft.setCursor(0, 0);

tft.println("Станция:");

tft.println(stationName);

tft.println("\nТрек:");

tft.println(trackTitle);

}



✅ Дополнительно: работа с ID3-тегами

cpp

1

2

3

4

5

6

7

if (file->getMetadataLength()) {

char metadata[512];

int len = file->readMetadata(metadata, sizeof(metadata));

metadata[len] = 0;

Serial.println("Метаданные:");

Serial.println(metadata);

}



🧰 Что еще можно оптимизировать?


ЗАДАЧА

РЕШЕНИЕ

Память

Используйте буферы только по необходимости, освобождайте память после использования

Пины

Используйте мультиплексор I²C/SPI при конфликтах

Производительность

Используйтеyield()иdelay(1)в циклах

Питание

Используйте LDO стабилизатор 3.3В для питания всех модулей



📌 Далее можем добавить:

  • Чтение обложки с SD и вывод на экран
  • Сохранение истории прослушивания
  • Изменение громкости через энкодер
  • Визуализация звука на экране (VU-метр)
  • OTA-обновления прошивки
  • Web-конфигуратор станций



🛠 Тебе понадобится:

  • NodeMCU ESP8266
  • Модуль поворотного энкодера KY-040
  • PCM5102 DAC
  • Усилитель RIXITE XH-A232
  • ST7735 1.8" дисплей
  • microSD карта
  • FM24CL64B x2
  • Конденсаторы, провода, источник питания 3.3 В



✅ Готов к следующему шагу?

Напиши: 👉 «Хочу реализовать вывод обложки» ,
👉
«Хочу добавить громкость через энкодер» ,
👉
«Хочу реализовать визуализацию звука» ,
👉
«Хочу пример сборки схемы»

И я подготовлю соответствующую часть проекта.



🚀 Когда закончим, у тебя будет полноценное интернет-радио с цветным интерфейсом, управлением и надёжным хранением данных.


 
MyTetra Share v.0.67
Яндекс индекс цитирования