Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Ретро FM-радио на модуле TEA5767 и Arduino Nano: пошаговое руководство

Компоненты и материалы

Компонент Описание Кол-во
Arduino Nano R3 Управление 1
TEA5767 FM-модуль Приемник FM 1
Аналоговые стрелочные индикаторы (из старого радио) Уровень сигнала и частота 2
Adafruit LCD 16x2 (белый на синем) Цифровая шкала и инфо 1
Стереопотенциометр 10к лог Регулятор громкости/баланса 1
D-класс аудио усилитель 2×3Вт Усилитель звука 1
Динамик 3Вт, 4 Ом Низко-середние частоты 2
Динамик 0.25Вт, 8 Ом Высокие частоты 2
Ротационный энкодер с кнопкой Настройка частоты 1
Тактильные кнопки 12 мм 4 кнопки памяти станций 4
Конденсатор 1 мкФ Разделение полос динамиков 2
Светодиоды Индикация Stereo, Auto/Manual 3

Приложения и сервисы

О проекте

База — код Rodolfo Broco Manin (RodLophus на GitHub) с красивой аналоговой шкалой на LCD 16x2. Добавлено:

Аудиовыходы TEA5767 → стереопотенциометр → D-класс усилитель 2×3Вт → двухполосные динамики (ВЧ отделен 1мкФ конденсатором). Стрелки от старого радио, полное отклонение настраивается подстроечными резисторами. Питание: 2 литий-ионных элемента в последовательно через стабилизатор 7805 (стабильные 5В).

Ретро FM-радио на модуле TEA5767 и Arduino Nano: пошаговое руководство

Библиотека TEA5767: GitHub. Схема и код ниже.

Известные нюансы: стрелка частоты обновляется дискретно (каждые 1 МГц) — особенность библиотеки. При слабых станциях частая переключение стерео/моно — в следующем обновлении добавлю переключатель Stereo/Mono и Mute.

Всё собрано в корпусе с телескопической антенной — готовый FM-стереоприемник в ретро-стиле.

Код

FM Radio (Arduino)

/* Simple radio tuner using Arduino Leonardo and the Philips TEA5767 module (Arduino Uno version)
Notes: - TEA5767 max 5V. - Signal level updates only on station change.
Encoder debouncing: pin >---+---/\/\/\/----> Encoder pin | 100Ohms | ----- 47nF cap | --- GND
Connections:
Encoder (with push): SW->D2, A->D3, B->D4
LCD: D7->D8, D6->D9, D5->D10, D4->D11, RS->D13, RW->GND, E->D12, VO->2k2 to GND
TEA5767: 1->SDA, 2->SCL, 3->GND, 5->5V, 6->GND, 7->Audio R, 8->Audio L, 10->Antenna
*/
#include <LiquidCrystal.h>
#include <Wire.h>
#include <TEA5767.h>

#define ENCODER_SW 2
#define ENCODER_A 3
#define ENCODER_B 4
#define button_freq1 A0
#define button_freq2 A1
#define button_freq3 A2
#define button_freq4 A3

#define SCALE_CLEAR 5
#define STEREO_CHAR_S 6
#define STEREO_CHAR_T 7

#define ST_AUTO 0
#define ST_STEREO 1
#define ST_GO_UP 2
#define ST_GO_DOWN 3
#define ST_SEARCH 4

const int LED = 0;
int analogsignal=0, analogscale=0, stereoled=0;
TEA5767 Radio;
float frequency = 88;
byte status = 0;
LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

void updateScale() {
  int lcdBase = (frequency - 88) * 4;
  if(lcdBase > 79) lcdBase = 79;
  int lcdMajor = lcdBase / 5;
  int lcdMinor = lcdBase % 5;
  if(lcdMajor > 0) { lcd.setCursor(lcdMajor - 1, 0); lcd.write(SCALE_CLEAR); }
  else lcd.setCursor(lcdMajor, 0);
  lcd.write(lcdMinor);
  if(lcdMajor < 15) lcd.write(SCALE_CLEAR);
}

void isrEncoder() {
  delay(50);
  if(digitalRead(ENCODER_B) == HIGH) bitWrite(status, ST_GO_UP, 1);
  else bitWrite(status, ST_GO_DOWN, 1);
}

void isrSwitch() {
  delay(50);
  if(bitRead(status, ST_AUTO)) bitWrite(status, ST_AUTO, 0);
  else bitWrite(status, ST_AUTO, 1);
}

void setup() {
  Serial.end();
  pinMode(button_freq1, INPUT); digitalWrite(button_freq1,LOW);
  pinMode(button_freq2, INPUT); digitalWrite(button_freq2,LOW);
  pinMode(button_freq3, INPUT); digitalWrite(button_freq3,LOW);
  pinMode(button_freq4, INPUT); digitalWrite(button_freq4,LOW);
  pinMode(LED, OUTPUT); pinMode(6,OUTPUT); pinMode(7,OUTPUT); pinMode(5,OUTPUT);
  byte needleChar[8];
  byte stereoChar1[8] = { 0b01111, 0b11000, 0b11011, 0b11101, 0b11110, 0b11000, 0b01111, 0b00000 };
  lcd.createChar(STEREO_CHAR_S, stereoChar1);
  byte stereoChar2[8] = { 0b11110, 0b00011, 0b10111, 0b10111, 0b10111, 0b10111, 0b11110, 0b00000 };
  lcd.createChar(STEREO_CHAR_T, stereoChar2);
  byte scaleChar[8] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00100, 0b10101, 0b10101 };
  lcd.createChar(SCALE_CLEAR, scaleChar);
  for(int j = 0; j < 5; j++) {
    for(int i = 0; i < 8; i++) needleChar[i] = scaleChar[i] | (0b10000 >> j);
    lcd.createChar(j, needleChar);
  }
  lcd.begin(16, 2); lcd.clear();
  for(int i = 0; i < 16; i++) lcd.write(SCALE_CLEAR);
  pinMode(ENCODER_SW, INPUT); digitalWrite(ENCODER_SW, HIGH);
  pinMode(ENCODER_A, INPUT); digitalWrite(ENCODER_A, HIGH);
  pinMode(ENCODER_B, INPUT); digitalWrite(ENCODER_B, HIGH);
  attachInterrupt(0, isrSwitch, RISING);
  attachInterrupt(1, isrEncoder, RISING);
  Wire.begin(); Radio.init(); Radio.set_frequency(frequency);
}

void loop() {
  unsigned char buf[5];
  int stereo, signalLevel, searchDirection, i;
  i=0;
  lcd.setCursor(12, 1); lcd.write(bitRead(status, ST_AUTO) ? 'A' : 'M');
  if(bitRead(status, ST_AUTO)) digitalWrite(LED, LOW); else digitalWrite(LED, HIGH);
  if (Radio.read_status(buf) == 1) {
    frequency = floor(Radio.frequency_available(buf) / 100000 + .5) / 10;
    stereo = Radio.stereo(buf);
    signalLevel = (Radio.signal_level(buf) * 100) / 15;
    analogsignal = map(signalLevel, 0, 100, 0, 255);
    analogscale = map(frequency, 88, 114, 0, 255);
    stereoled = map(stereo, 0.7, 1, 0, 255);
    analogWrite(5, analogsignal); // Signal meter
    analogWrite(6, analogscale);  // Frequency meter
    analogWrite(7, stereoled);    // Stereo LED
    updateScale();
    lcd.setCursor(0, 1); lcd.write(183);
    if(signalLevel < 100) lcd.write(' ');
    lcd.print(signalLevel); lcd.write('%');
    lcd.setCursor(6, 1);
    if(frequency < 100) lcd.write(' ');
    lcd.print(frequency, 1);
    lcd.setCursor(14, 1);
    if(stereo){ lcd.write(STEREO_CHAR_S); lcd.write(STEREO_CHAR_T); }
    else lcd.print(" ");
  }
  if(bitRead(status, ST_SEARCH)) {
    if(Radio.process_search(buf, searchDirection) == 1) bitWrite(status, ST_SEARCH, 0);
  }
  // Кнопки памяти (4 преднастроенные частоты)
  if(digitalRead(button_freq2)==HIGH){ if(frequency > 94.8) { frequency=94.8; Radio.set_frequency(frequency); bitWrite(status, ST_GO_DOWN, 0); } else { frequency=94.8; Radio.set_frequency(frequency); bitWrite(status, ST_GO_UP, 0); } precrtajScale(); }
  if(digitalRead(button_freq1)==HIGH){ if(frequency > 92) { frequency=92; Radio.set_frequency(frequency); bitWrite(status, ST_GO_DOWN, 0); } else { frequency=92; Radio.set_frequency(frequency); bitWrite(status, ST_GO_UP, 0); } precrtajScale(); }
  if(digitalRead(button_freq3)==HIGH){ if(frequency > 97) { frequency=97; Radio.set_frequency(frequency); bitWrite(status, ST_GO_DOWN, 0); } else { frequency=97; Radio.set_frequency(frequency); bitWrite(status, ST_GO_UP, 0); } precrtajScale(); }
  if(digitalRead(button_freq4)==HIGH){ if(frequency > 101.2) { frequency=101.2; Radio.set_frequency(frequency); bitWrite(status, ST_GO_DOWN, 0); } else { frequency=101.2; Radio.set_frequency(frequency); bitWrite(status, ST_GO_UP, 0); } precrtajScale(); }
  // Энкодер: ручное/авто поиск
  if(bitRead(status, ST_GO_UP)) {
    if(bitRead(status, ST_AUTO) && !bitRead(status, ST_SEARCH)) {
      bitWrite(status, ST_SEARCH, 1);
      searchDirection = TEA5767_SEARCH_DIR_UP;
      Radio.search_up(buf); delay(50);
    } else {
      if(frequency < 108) { frequency += 0.1; Radio.set_frequency(frequency); }
    }
    bitWrite(status, ST_GO_UP, 0);
  }
  if(bitRead(status, ST_GO_DOWN)) {
    if(bitRead(status, ST_AUTO) && !bitRead(status, ST_SEARCH)) {
      bitWrite(status, ST_SEARCH, 1);
      searchDirection = TEA5767_SEARCH_DIR_DOWN;
      Radio.search_down(buf); delay(50);
    } else {
      if(frequency > 88) { frequency -= 0.1; Radio.set_frequency(frequency); }
    }
    bitWrite(status, ST_GO_DOWN, 0);
  }
}

void precrtajScale() {
  int i; lcd.clear();
  for(i = 0; i < 16; i++) lcd.write(SCALE_CLEAR);
}

Схемы

Ретро FM-радио на модуле TEA5767 и Arduino Nano: пошаговое руководство

Производственный процесс

  1. Bluetooth Mesh: выбор между модулем и дискретным чипом
  2. Сборка DIY умного термостата типа NEST на Node-RED и Raspberry Pi
  3. Построение надёжного Temperature & Sensor API на Raspberry Pi с модулем GY‑91
  4. Создание бюджетного детектора плача ребенка на Raspberry Pi — DIY-руководство
  5. Ретро-часы на индикаторах Numitron с Arduino: просто, надёжно, экономно
  6. Импорт модулей в Python: практическое руководство с примерами
  7. Высокоскоростная фотография капель воды на Arduino Nano — DIY-триггер для вспышки
  8. Сборка DIY VR-скейтборда на Arduino, Google Cardboard и Bluetooth
  9. Водонепроницаемая FM-радио для душа на Arduino Nano, RDA5807, Nokia LCD и PAM8403
  10. Подключение Arduino Mega к GPS-модулю NEO‑6M: пошаговое руководство