Radio TEA5767 Sketch gesucht

Ich hab das mal auf einen Controller spielen lassen.

Auf einem UNO oder einem MEGA muss das funktionieren.
Zudem muss eine LED auf dem Controller blinken.

#include <Wire.h>
#include <TEA5767.h>
#include <LiquidCrystal.h>

#define DEBUG              // Wenn aktiviert, werden Zwischenwerte ausgegeben

#ifdef DEBUG
  #define DBG_PRINTLN(...) Serial.println(__VA_ARGS__)
  #define DBG_PRINT(...) Serial.print(__VA_ARGS__)
#else
  #define DBG_PRINTLN(...
  #define DBG_PRINT(...)

#endif

LiquidCrystal lcd( 8, 9, 4, 5, 6, 7);
TEA5767 radio = TEA5767();                                           // Der kann hier auch Parameter übergeben werden....

// Display
constexpr uint8_t spalten {16};
constexpr uint8_t zeilen {2};

// Keypad
constexpr uint8_t btnPin {A0};
enum class BTNSTATE : uint8_t {NO, UP, DOWN, LEFT, RIGHT, SELECT};

// Suchrichtung
constexpr bool forward {true};
constexpr bool backward {!forward};
bool direction = forward;

// Radio
constexpr float minFreq {87.5};
constexpr float maxFreq {108.0};
float frequency = minFreq;
constexpr float stepFreq {0.2};
// - Signalstärke für Wiedergabe
constexpr uint8_t minLevel {6};
// - Mute während des Suchlaufs
constexpr bool seekMute {true};

// Spielzeit
constexpr uint32_t minWait {100};
constexpr uint32_t maxWait {1000};
constexpr uint32_t waitStep {100};
uint32_t wait = minWait;
uint32_t lastScanTime;

bool stopped = true;

uint8_t count = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  delay(1000);
  pinMode(btnPin, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  Wire.begin();
  lcd.begin(spalten, zeilen);
  splashScreen();
  delay(1500);
}

void loop()
{
  if (getButton() == BTNSTATE::SELECT)
  { stopped = !stopped; }

  if (stopped == true)
  { deviceSetup(); }
  else
  { searchNext(); }

  heartBeat(500);
}

void deviceSetup()
{
  // clang-format off
  //*INDENT-OFF*
  BTNSTATE btn = getButton();                              // holt Tastenzusatand
  switch (btn)
  {
    case BTNSTATE::RIGHT: radio.setMuted(!radio.isMuted()); break;   
    case BTNSTATE::LEFT:  direction = !direction;           break;
    case BTNSTATE::UP:    setWait(maxWait);                 break;
    case BTNSTATE::DOWN:  setWait(minWait);                 break;
    default:                                                break;
  }
  if (btn != BTNSTATE::NO)                                 // eine Taste wurde gedrückt
  {
  displaySetup();                                          // aktuallisiere Display
  }
  //*INDENT-ON*
  // clang-format on
}

void displaySetup()
{
  char buf[spalten + 1] = {'\0'};
  lcd.clear();
  snprintf(buf, spalten, "Mute: %s # Dir: %s", radio.isMuted() == true ? "Y" : "N", direction == forward ? ">" : "<");
  lcd.print(buf);
  Serial.println(buf);
  snprintf(buf, spalten, "Wait: %li ms", wait);
  lcd.setCursor(0, 1);
  lcd.print(buf);
  Serial.println(buf);
}

void setWait(const uint32_t end)
{
  if (end == minWait)
  {
    if ((wait - waitStep) >= minWait)
    { wait -= waitStep; }
  }
  else
  {
    if ((wait + waitStep) <= maxWait)
    { wait += waitStep; }
  }
}

BTNSTATE getButton()
{
  uint16_t btnValue = analogRead(btnPin);
  static BTNSTATE lastState = BTNSTATE::NO;
  static bool isRelease = false;
  BTNSTATE newState = BTNSTATE::NO;
  static uint32_t releaseTime = 0;
  const uint32_t debounceTime = 100;

  // clang-format off
  //*INDENT-OFF*
  switch (btnValue)
  {
    case   0 ...  59: newState = BTNSTATE::RIGHT;   break;
    case  60 ... 199: newState = BTNSTATE::UP;      break;
    case 200 ... 399: newState = BTNSTATE::DOWN;    break;
    case 400 ... 599: newState = BTNSTATE::LEFT;    break;
    case 600 ... 799: newState = BTNSTATE::SELECT;  break;
    default:          newState = BTNSTATE::NO;      break;
  }
  //*INDENT-ON*
  // clang-format on

  if (lastState != newState)                          // geänderte Auswahl?
  {
    DBG_PRINT(F("Neuer BTN-Value: "));
    DBG_PRINTLN(btnValue);

    if (lastState == BTNSTATE::NO)                    // Vorher: keine Taste aktiv
    {
      DBG_PRINTLN(F("neue Taste!"));
      lastState = newState;                           // Neue ausgewählte Taste merken
      return newState;                                // Taste zurückgeben
    }
    else                                              // Vorher: Taste aktiv
    {
      if (newState == BTNSTATE::NO)                   // Jetzt: Taste inaktiv
      {
        DBG_PRINTLN(F("keine Taste"));

        if (isRelease == false)                       // vorher nicht losgelassen
        {
          DBG_PRINTLN(F("erstes release"));
          releaseTime = millis();                     // Zeit merken
          isRelease = true;                           // losgelassen merken
        }
        else                                          // war vorher losgelassen
        {
          if (millis() - releaseTime > debounceTime)  // Zeit abgelaufen
          {
            DBG_PRINTLN(F("Button gelöscht"));
            isRelease = false;                        // Merker löschen
            lastState = newState;                     // Status merken
          }
        }
      }
    }
  }

  return BTNSTATE::NO;                                // - Keine Wiederholung! - ungedrückte Taste!
}

void splashScreen()
{
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(F("Spiritmaster"));
  lcd.setCursor(0, 1);
  lcd.print(F("by Masterdetektor"));
}

void checkFreq()
{
  if (direction == forward)
  {
    if (frequency > maxFreq)
    {
      frequency = minFreq;
      count = 0;
    }
  }
  else
  {
    if (frequency < minFreq)
    {
      frequency = maxFreq;
      count = 0;
    }
  }
}

float nextFreq()
{
  if (direction == forward)
  { frequency += stepFreq; }
  else
  { frequency -= stepFreq; }

  checkFreq();
  return frequency;
}

void searchNext()
{
  if (millis() - lastScanTime > wait)
  {
    char buf[spalten + 1] = {'\0'};                                    // Buffer für eine Zeile LCD anlegen
    lcd.clear();
    snprintf(buf, spalten, "Scanning... %s", direction == forward ? "->->" : "<-<-"); // baut 1.te Zeile für LCD
    lcd.print(buf);                                                    // Ausgabe :-)
    Serial.println(buf);

    if (seekMute)                                                      // wenn Mute während Sendersuchlauf
    { radio.setMuted(true); }

    uint8_t oldCount = count;                                          // Merker für Vergleich

    while (count == oldCount)                                          // Wiederhole, bis Sender gefunden
    {
      radio.setFrequency(nextFreq());
      delay(50);                                                       // Hier kann versucht werden, mit dem Wert noch weiter runter zu gehen

      if (minLevel < radio.getSignalLevel())                           // Wenn Sender gefunden
      { count++; }

      char fbuf[7] = {'\0'};
      dtostrf(radio.getFrequency(), 4, 1, fbuf);                       // float zu *char
      snprintf(buf, spalten, "F: %s # c: %i", fbuf, count);            // baut 2.te Zeile für LCD
      lcd.setCursor(0, 1);
      lcd.print(buf);
    }

    radio.setMuted(false);                                             // garantiert, dass nach Senderfund Ton an ist
    Serial.println(buf);                                               // gibt den letzten Inhalt nach dem neuen Senderfund aus
    Serial.println(F("*************\r\n"));
    lastScanTime = millis();                                           // Merker, wann der Sender gefunden wurde
  }
}

void heartBeat(const uint32_t beat)
{
  static uint32_t lastBeat = 0;

  if (millis() - lastBeat > beat)
  {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    lastBeat = millis();
  }
}

Der Kölner sagt: Wor isch nit :wink:
Natürlich hab ich den Seriellen Monitor offen gelassen, natürlich hab ich die Resettaste gedrückt, natürlich ist der Arduino am PC angeschlossen, andernfalls könnte ich ja keinen Bottloader oder Sketches hochladen.
Ich denke das hängt mit der IDE Version für Ubuntu zusammen...die IDE Software ist keineswegs fehlerfrei.

Die Voreinstellung ist genau so...
Ich lade den Sketch nochmal und dann kopiere ich die Fensterausgabe...mom

Hardware kann ich :wink:
DA ist alles prima

Ich muß es per Bildschirmfoto machen...die Meldung bekomme ich nicht herauskopiert.

Und, wie man sieht...keine Reaktion beim Seriellen Monitor...
Ich denke das ist ein Problem mit der IDE für Linux...kostet momentan nur Zeit und führt zu nix, oder ?

Blinkt die LED auf dem Controller? (halbsekundentakt)
Du benutzt die 1.8.12 - die letzte ist .19 und auch die einzige, die nicht von der log4J-Schwachstelle betroffen ist.

Ich habe das mit einem Controller testen könne, zwar ohne shield, aber mit einer Simulation der Tasten.
Da funktioniert das.

Nimm mal bitte das Shield und alle Anschlüsse ab.
Nur das USB-Kabel dran und Sketch hochladen.
Seriellen Monitor aufmachen und?

Jawohl, die blinkt

1 Like

Klick mal mit der Maus unten in das schwarze Fenster, dann STRG-A dann STRG-C Dann hier in Codetags einfügen.

Was machst Du da?
Programmierst Du den via ISP?

Ohne Shield ist es das gleiche... Ja, ich benutze einen STK500 clon, anders bekomme ich keinen Zugriff auf das Board

Dann kann das mit dem SerMon nicht gehen! Du schreibst via ISP!
Zieh mal das USB-Kabel vom STK-Klone ab und steck es an den UNO!

Dann in der IDE den Port auswählen (evtl. ist es der gleiche) Dann den SerMon aufmachen.

Ok, so bekomme ich nun diese endlos Ausgabe.... hilft die?
Ohne den ISP bekomme ich aber nichts hochgeladen :man_shrugging:

Doch.
Also USB Wieder den zurück an den STK.

Dann WERKZEUGE - BOOTLOADER BRENNEN

Dann Wieder zurück mit dem Kabel an den UNO.
Dort den Port einstellen.
Das Board einstellen.
Dann STRG-U und den Sketch hochladen.

Die Ausgabe sollte dann etwas anders aussehen.

Ja.
Da ist ständig eine Taste gedrückt :thinking:

LOL...ohne Keypad? :grin:

Ne, dann ist es der offene Anschluß :-)
ach menno :rofl:

Aber ja, das zeigt, das es funktionert :+1:

:sweat_smile: immerhin

So los, brenn den Bootloader, damit wir hier zu was kommen...
Ich bin nachher wieder mehrfach offline und würde das gerne fertig bekommen.

Gemacht, Anzeige sieht genau geich aus....Endlosschleife

Jetzt wieder alles zusammenbauen....
Und dann schaun wa mal, was passiert, wenn Du den dann startest und die select-Taste drückst.

Der Scan startet, aber danach keine Tastenreaktion mehr...kann drücken so oft ich will...

Monitor gibt die Ausgabe: