Construire une Radio FM Style Rétro avec Module TEA5767 – Guide DIY Pas à Pas
Composants et fournitures
| Composant | Description | Quantité |
|---|---|---|
| Arduino Nano R3 | Microcontrôleur | 1 |
| Module radio FM TEA5767 | Récepteur FM stéréo I2C | 1 |
| VU-mètres analogiques (d'ancienne radio) | Indicateurs niveau signal et fréquence | 2 |
| Adafruit LCD Standard 16x2 Blanc sur Bleu | Affichage fréquence, mode, stéréo | 1 |
| Potentiomètre stéréo 10k log | Contrôle volume | 1 |
| Module amplificateur audio classe D 2×3W | Amplification puissance | 1 |
| Haut-parleur 3W, 4 Ω | Grave-médium (2 voies) | 2 |
| Haut-parleur 0.25W, 8 Ω | Aigu (2 voies) | 2 |
| Encodeur rotatif avec bouton poussoir | Réglage fréquence, mode auto/manuel | 1 |
| Bouton poussoir 12mm SparkFun | td>Touches de mémoire préréglées4 | |
| Condensateur 1 µF | Filtre passe-haut pour tweeter | 2 |
| LED générique | Indicateurs stéréo, auto/manuel | 3 |
Applications et services en ligne
- Arduino IDE
À propos du projet
Ce projet s'appuie sur le code de Rodolfo Broco Manin (RodLophus sur GitHub) qui inclut un bel affichage d'échelle analogique sur LCD 16x2. L'auteur l'a modifié en ajoutant : deux VU-mètres analogiques (niveau de signal et fréquence), une LED « stéréo », une LED « recherche auto/manuelle », et quatre touches de mémoire avec fréquences préprogrammées pour un look totalement vintage.
Les sorties audio du TEA5767 passent par le potentiomètre stéréo vers l'amplificateur classe D 2×3W, suffisant pour cette application. Deux haut-parleurs 2 voies sont connectés à l'amplificateur. Le tweeter est séparé du grave-médium par un condensateur 1µF. Les VU-mètres proviennent d'une vieille radio défectueuse ; tout type de galvanomètre convient, la déviation maximale se règle par potentiomètres d'ajustement (trimmers). L'alimentation est assurée par deux batteries lithium en série via un régulateur 7805 (5V stabilisés).
La bibliothèque TEA5767 pour Arduino est disponible ici. Le schéma et le code complet sont fournis ci-dessous.
Note : L'aiguille de fréquence se met à jour par pas de 1 MHz (limitation probable de la bibliothèque). Une solution pour un mouvement fluide serait bienvenue. La réception est excellente pour les stations locales fortes ; pour les stations faibles, un commutateur stéréo/mono serait nécessaire pour éviter les basculements intempestifs. Une future mise à jour prévoit d'ajouter les commutateurs « stéréo/mono » et « mute ».
L'ensemble est intégré dans un boîtier adapté avec antenne télescopique, offrant un récepteur FM stéréo complet au look rétro.
Code
/* Syntoniseur radio simple avec Arduino Leonardo et module Philips TEA5767 (version Arduino Uno)
Notes: - TEA5767 tension max 5V. - Niveau de signal mis à jour seulement sur changement de station.
- Pour parasites sur encodeur/bouton, ajouter réseau RC: broche Arduino >--+--/\/\/\/---> Encodeur | 100Ω | 47nF | --- GND
Connexions:
- Encodeur (avec bouton poussoir): Bouton -> D2, A -> D3, B -> D4
- LCD: D7->D8, D6->D9, D5->D10, D4->D11, RS->D13, RW->GND, E->D12, VO->2k2 vers GND
- TEA5767 (vue dessus): 1->SDA, 2->SCL, 3->GND, 5->+5V, 6->GND, 7->Audio R, 8->Audio L, 10->Antenne
*/
#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);
int i;
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(i = 0; i < 8; i++) needleChar[i] = scaleChar[i] | (0b10000 >> j);
lcd.createChar(j, needleChar);
}
lcd.begin(16, 2); lcd.clear();
for(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=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);
analogWrite(6, analogscale);
analogWrite(7, stereoled);
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);
}
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);
}
Schémas
Schéma de câblage complet : Arduino Nano, TEA5767 (I2C), LCD (parallèle), encodeur, 4 boutons mémoire, potentiomètre volume, amplificateur classe D, haut-parleurs 2 voies avec condensateur 1µF sur tweeter, VU-mètres analogiques sur sorties PWM (broches 5,6,7), LEDs indicateurs, alimentation 5V via 7805.
Processus de fabrication
- Choix de conception Bluetooth Mesh : Module vs dispositif discret
- Construire un thermostat intelligent type NEST avec Node-RED sur Raspberry Pi
- Créer une API robuste de température et capteurs sur Raspberry Pi avec le module GY‑91
- Construire un détecteur de pleurs de bébé économique avec Raspberry Pi – Guide DIY
- Construire une horloge Numitron rétro avec Arduino : simple, fiable et économe en énergie
- Importation de Modules Python — Guide Pratique avec Exemples
- Photographie Haute Vitesse : Capturez les Gouttes d'Eau avec Arduino Nano
- Construisez un skateboard VR DIY avec Arduino, Google Cardboard et Bluetooth
- Radio FM étanche pour douche : Arduino Nano, RDA5807, écran Nokia 5110 et PAM8403