Radio łazienkowe cz.1

Posted on Sun 06 March 2022 in Automatyczny dom • 5 min read

W kontekście tego szaleństwa, które nas otacza od dni 10-ciu, szaleństwem nie mniejszym wydaje się robienie łazienkowego radia. Ale muszę coś robić, żeby nie zwariować od wiadomości pokazujących w jak czarnej dziurze jesteśmy. Mogę tylko dodać: wspierajcie Fundację Ad Arma - to są dobrzy i rozsądni ludzie.

Projekt ten zaczął się już 4 lata temu ale jakoś się nie rozwinął. Były to próby z zupełnie innym, niż obecny, modułem. Radio działało, miało wyświetlacz (od Nokii) potencjometry i wzmacniacz ale sam moduł miał jakąś wadę. Kopałem się z tym koniem tak długo, że skończyła mi się cierpliwość.
Resztki wyglądają tak:
image1

Nowy moduł to TEA5767 z gniazdami typu jack dla anteny i słuchawek. Wyjście słuchawkowe wykorzystam jako sygnał do dodatkowego wzmacniacza bo głośnika, wbudowany nie uciągnie.

Zalążek wygląda tak:

image2

W Arduino IDE doinstalowałem bibliotekę o nazwie "Radio", strona biblioteki jest pod tym adresem: http://www.mathertel.de/Arduino/RadioLibrary.aspx.

Używam Arduino UNO ale im bliżej końca tym bardziej będę chciał użyć jakiegoś klona Nano, mam ATmega328 CH340, z tym że boję się czy wystarczy pamięci do sprawnego działania. Ostatnim razem miałem, jak pisałem już wyżej, kłopoty i coś mi się zaczyna przypominać, że jechał już na oparach jeśli chodzi o pamięć.

Głośnik mam sufitowy, marki Blow, o nast. specyfikacji:

Średnica 4 cale
Moc maksymalna 15 W
Impedancja 8 Ohm
Cewka 0,75" ASV
Magnes 60x24x8
Zakres częstotliwości 104Hz - 15kHz
Czułość 87dB +/- 2dB

Myślę nad wzmacniaczem... moje typy, totalnie na czuja i chyba przesadzone:

https://mageek.com.pl/audio-wzmacniacze/458-modul-wzmacniacz-audio-tda2030-18w-koncowka-mocy-18w.html

https://mageek.com.pl/audio-wzmacniacze/244-modul-wzmacniacz-audio-pam88610.html

Do sterowania mam zamiar użyć panelu dotykowego:

Wydrukować pod spód wkładkę z narysowanymi przyciskami bo nie znalazłem wodoodpornego panelu.

A'propos wody to myślę jak zabezpieczyć całość. Ludzie proponują takie specyfiki:

https://www.mgchemicals.com/products/conformal-coating/silicone-conformal-coatings/silicone-modified-conformal-coating/

ewentualnie pudełko:

https://www.adafruit.com/product/341

Aha, a kod? Zalążek wzięty z przykładu załączonego do blblioteki "Radio":

///
/// \file SerialRadio.ino
/// \brief Radio implementation using the Serial communication.
///
/// \author Matthias Hertel, http://www.mathertel.de
/// \copyright Copyright (c) 2014 by Matthias Hertel.\n
/// This work is licensed under a BSD style license.\n
/// See http://www.mathertel.de/Arduino/RadioLibrary.aspx
///
/// \details
/// This is a full function radio implementation that uses a LCD display to show the current station information.\n
/// It can be used with various chips after adjusting the radio object definition.\n
/// Open the Serial console with 57600 baud to see current radio information and change various settings.
///
/// Wiring
/// ------
/// The necessary wiring of the various chips are described in the Testxxx example sketches.
/// The boards have to be connected by using the following connections:
///
/// Arduino port | TEA5767 z portami dla anteny i sluchawek
/// :----------: | :-----------:
/// GND (black)  | GND
/// 3.3V (red)   | -
/// 5V (red)     | VCC
/// A5 (yellow)  | SLC (SLCK)
/// A4 (blue)    | SDA (SDIO)
/// D2           | -
///
/// UWAGA RDS NIE DZIALA!
///
/// More documentation and source code is available
/// at http://www.mathertel.de/Arduino
///
/// History:
/// --------
/// * 05.08.2014 created.
/// * 04.10.2014 working.

#include <Wire.h>
#include <radio.h>
#include <TEA5767.h>
#include <RDSParser.h>


// Define some stations available at your locations here:
// 89.40 MHz as 8940

RADIO_FREQ preset[] = {
  8780, // Wnet
  8840, // Pogoda
  8900, // Maryja
  8980, // Supernova
  9060, // RMF FM
  9200, // Polskie Radio 24
  9240, // Jedynka
  9330, // Eska
  9710, // Kampus
  9770, // Tok FM
  9880, // Trojka
  10110, // Zlote Przeboje
  10150, // ChilliZet
  10370, // Rock Radio
  10680 // Antyradio
};

int    i_sidx = 0;        ///< Start at Station with index=0

/// The radio object has to be defined by using the class corresponding to the used chip.
/// by uncommenting the right radio object definition.

TEA5767  radio;    ///< Create an instance of a TEA5767 chip radio.


/// get a RDS parser
RDSParser rds;


/// State definition for this radio implementation.
enum RADIO_STATE {
  STATE_PARSECOMMAND, ///< waiting for a new command character.

  STATE_PARSEINT,     ///< waiting for digits for the parameter.
  STATE_EXEC          ///< executing the command.
};

RADIO_STATE state; ///< The state variable is used for parsing input characters.

// - - - - - - - - - - - - - - - - - - - - - - - - - -



/// Update the Frequency on the LCD display.
void DisplayFrequency(RADIO_FREQ f)
{
  char s[12];
  radio.formatFrequency(s, sizeof(s));
  Serial.print("FREQ:"); Serial.println(s);
} // DisplayFrequency()


/// Update the ServiceName text on the LCD display.
void DisplayServiceName(char *name)
{
  Serial.print("RDS:");
  Serial.println(name);
} // DisplayServiceName()


// - - - - - - - - - - - - - - - - - - - - - - - - - -


void RDS_process(uint16_t block1, uint16_t block2, uint16_t block3, uint16_t block4) {
  rds.processData(block1, block2, block3, block4);
}


/// Execute a command identified by a character and an optional number.
/// See the "?" command for available commands.
/// \param cmd The command character.
/// \param value An optional parameter for the command.
void runSerialCommand(char cmd, int16_t value)
{
  if (cmd == '?') {
    Serial.println();
    Serial.println("? Help");
    Serial.println("+ increase volume DON'T WORK");
    Serial.println("- decrease volume DON'T WORK");
    Serial.println("> next preset");
    Serial.println("< previous preset");
    Serial.println(". scan up DON'T WORK");
    Serial.println(", scan down  DON'T WORK");
    Serial.println("fnnnnn: direct frequency input");
    Serial.println("i station status");
    Serial.println("s mono/stereo mode");
    Serial.println("b bass boost  DON'T WORK");
    Serial.println("u mute/unmute");
  }

  // ----- control the volume and audio output -----

  else if (cmd == '+') {
    // increase volume
    int v = radio.getVolume();
    if (v < 15) radio.setVolume(++v);
    Serial.println();
    Serial.print("Increasing volume:"); Serial.println(v);
  }
  else if (cmd == '-') {
    // decrease volume
    int v = radio.getVolume();
    if (v > 0) radio.setVolume(--v);
    Serial.println();
    Serial.print("Decreasing volume:"); Serial.println(v);
  }

  else if (cmd == 'u') {
    // toggle mute mode
    radio.setMute(!radio.getMute());
  }

  // toggle stereo mode
  else if (cmd == 's') {
    radio.setMono(!radio.getMono());
  }

  // toggle bass boost
  else if (cmd == 'b') {
    radio.setBassBoost(!radio.getBassBoost());
  }

  // ----- control the frequency -----

  else if (cmd == '>') {
    // next preset
    if (i_sidx < (sizeof(preset) / sizeof(RADIO_FREQ)) - 1) {
      i_sidx++; radio.setFrequency(preset[i_sidx]);
    } // if
  } else if (cmd == '<') {
    // previous preset
    if (i_sidx > 0) {
      i_sidx--;
      radio.setFrequency(preset[i_sidx]);
    } // if

  } else if (cmd == 'f') {
    radio.setFrequency(value);
  }

  else if (cmd == '.') {
    radio.seekUp(false);
  } else if (cmd == ':') {
    radio.seekUp(true);
  } else if (cmd == ',') {
    radio.seekDown(false);
  } else if (cmd == ';') {
    radio.seekDown(true);
  }


  // not in help:
  else if (cmd == '!') {
    if (value == 0) radio.term();
    if (value == 1) radio.init();

  } else if (cmd == 'i') {
    char s[12];
    radio.formatFrequency(s, sizeof(s));
    Serial.print("Station:"); Serial.println(s);
    Serial.print("Radio:"); radio.debugRadioInfo();
    Serial.print("Audio:"); radio.debugAudioInfo();

  } // info

  else if (cmd == 'x') {
    radio.debugStatus(); // print chip specific data.
  }
} // runSerialCommand()


/// Setup a FM only radio configuration with I/O for commands and debugging on the Serial port.
void setup() {
  // open the Serial port
  Serial.begin(57600);
  Serial.print("Radio...");
  delay(500);

  // Initialize the Radio
  radio.init();

  // Enable information to the Serial port
  radio.debugEnable();

  radio.setBandFrequency(RADIO_BAND_FM, preset[i_sidx]); // 5. preset.

  // delay(100);

  radio.setMono(false);
  radio.setMute(false);
  // radio._wireDebug();
  radio.setVolume(8);

  Serial.write('>');

  state = STATE_PARSECOMMAND;

  // setup the information chain for RDS data.
  radio.attachReceiveRDS(RDS_process);
  rds.attachServicenNameCallback(DisplayServiceName);

  runSerialCommand('?', 0);
} // Setup


/// Constantly check for serial input commands and trigger command execution.
void loop() {
  int newPos;
  unsigned long now = millis();
  static unsigned long nextFreqTime = 0;
  static unsigned long nextRadioInfoTime = 0;

  // some internal static values for parsing the input
  static char command;
  static int16_t value;
  static RADIO_FREQ lastf = 0;
  RADIO_FREQ f = 0;

  char c;
  if (Serial.available() > 0) {
    // read the next char from input.
    c = Serial.peek();

    if ((state == STATE_PARSECOMMAND) && (c < 0x20)) {
      // ignore unprintable chars
      Serial.read();

    } else if (state == STATE_PARSECOMMAND) {
      // read a command.
      command = Serial.read();
      state = STATE_PARSEINT;

    } else if (state == STATE_PARSEINT) {
      if ((c >= '0') && (c <= '9')) {
        // build up the value.
        c = Serial.read();
        value = (value * 10) + (c - '0');
      } else {
        // not a value -> execute
        runSerialCommand(command, value);
        command = ' ';
        state = STATE_PARSECOMMAND;
        value = 0;
      } // if
    } // if
  } // if


  // check for RDS data
  radio.checkRDS();

  // update the display from time to time
  if (now > nextFreqTime) {
    f = radio.getFrequency();
    if (f != lastf) {
      // print current tuned frequency
      DisplayFrequency(f);
      lastf = f;
    } // if
    nextFreqTime = now + 400;
  } // if

} // loop

// End.