Themabewertung:
  • 1 Bewertung(en) - 5 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Preset-Tuner mit ATtiny und TEA5767
#1
ich tüftele schon einige Zeit an diesem Konzept. Die Platine soll für unterschiedliche Anforderungen benutzt werden. Bei Bedarf soll ein Display zusteckbar sein, ebenso ein Servo für eine motorische Frequenzanzeige. Die Abstimmung kann auf unterschiedliche Arten erfolgen. Entweder mit Poti, oder mit Tasten, oder mit Rotary-Encoder. Aber auch mit kapazitiven Touch Key Modulen. Ich stelle mir beispielsweise vor daß mit einem solchen Tuner ein AM-Röhrenradio nachgerüstet wird und man berührt das Emblem auf der Schallwand um auf den nächsten Sender umzuschalten, der entweder als Festfrequenz vorliegt oder per scan gefunden wird.

Warum Preset-Tuner? Ich teile hier ein Poti in 6 Bereiche. Jedem Bereich ist eine Festfrequenz zugeordnet. Diese Bedienung ist praktisch barrierefrei.

Der Testaufbau brachte einige Schwächen zutage, die ich teilweise ausräumen konnte. Ein Problem ist daß in den ATtiny nicht alle Bibliotheken geladen werden können, weil der Programmspeicher einfach zu klein ist. Ich muss also unterschiedliche Sketche bereithalten. Dann hat sich herausgestellt daß der I2C-Bus sich kritisch verhält. Je nach Kombination der Peripherie wurde der Tuner nicht mehr angesprochen. Hier erhoffe ich mir Abhilfe durch Pegel-Converter. Der ATtiny arbeitet mit 5V, was für den TEA5767 die oberste Grenze darstellt. Mit den Convertern kann ich den Tuner dann auf 3,3V laufen lassen. Bernhard gab mir dann noch den Tipp daß man den Tuner abfragen kann ob er mit seiner Konversation fertig ist, und dann erst andere Aufgaben über den I2C Bus erledigt. Am Programm-Code gibt es noch weiteren Handlungsbedarf. Die IF-ELSE Verschachtelungen lassen sich noch stark vereinfachen. Aber ich hab so schon mal was funktionierendes und vorzeigbares. Bestimmt fließen noch weitere Ideen ein, das wird sich dann ergeben.

Entsprechende Geräte für einen Einbau sind schon auf der Werkbank und in absehbarer Zeit kann ich Komplettgeräte zeigen. Im Moment gibt es nur die Platine als Prototyp:

   

Den TEA5657-Baustein hatte ich zwecks Fehlersuche von der Platine ausgelagert. Praktischer ist es wenn man dafür auch ein fertiges Breakout-Board nimmt. Die engen Kontakte der Platine sind sehr schwierig zu verdrahten.

   

Das breakout-board mit dem ATtiny kann zum Programmieren abgezogen werden. Unter dem Board befindet sich die 3,3V-Versorgung und die Pullup's für den I2C-Bus. Das Digispark-Board liefert über einen eingebauten Spannungsregler 5V und wird selbst mit 7 - 12V (oder mehr) versorgt.

   

   

und weil ein Filmchen mehr aussagt als Bildchen:



Der aktuelle Code:

Code:
#include <TinyWireM.h>
#include <LiquidCrystal_I2C.h>
//#include <SoftRcPulseOut.h>
#include <TEA5767Tiny.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);
TEA5767Tiny Radio;
//SoftRcPulseOut servo;

#define REFRESH_PERIOD_MS 20

int analogInPin = A2; // PB4
int poti = 0;
int poti_pwm = 0;
int poti_preset = 0;
int poti_preset_out = 0;

double frequenz;

char Sendername[17] = "Platzhalter";

void setup() {

pinMode(analogInPin, INPUT);

//servo.attach(1);
//servo.setMaximumPulse(2200);
//SoftRcPulseOut::refresh();
 
lcd.init();
lcd.backlight();
lcd.clear();
lcd.print (poti_preset_out);
delay (30);

Radio.init();
delay (30);

}

void loop() {
 
poti = analogRead(analogInPin);
poti_preset = map(poti, 0, 1000, 1, 6);
poti_pwm = map(poti, 0, 1000, 0, 180);

if (poti_preset == 1) {
      frequenz = 88.0;
      strcpy (Sendername, "SR 1 Europawelle");
      }
     
else if (poti_preset == 2) {
      frequenz = 91.3;
      strcpy (Sendername, "SR 2 Kultur     ");
      }
     
else if (poti_preset == 3) {
      frequenz = 95.5;
      strcpy (Sendername, "SR3Saarlandwelle");
      }
     
else if (poti_preset == 4) {
      frequenz = 100.9;
      strcpy (Sendername, "ClassicRockRadio");
      }

else if (poti_preset == 5) {
      frequenz = 101.7;
      strcpy (Sendername, "Radio Salue     ");      
      }
     
     
 else if (poti_preset == 6) {
      frequenz = 103.7;
      strcpy (Sendername, "SR Unser Ding   ");
      }

if ((poti_preset_out) != (poti_preset)) {
 poti_preset_out = poti_preset;
 Radio.set_frequency(frequenz);
 delay (30);      
 lcd.setCursor ( 0, 0 );
 lcd.print (poti_preset);
 lcd.print (" - ");
 lcd.print (frequenz);
 lcd.print ("MHz ");
 lcd.setCursor(0, 1);
 lcd.print (Sendername);  
 //servo.write(poti_pwm);
}

delay (30);
}
Zitieren
#2
Hallo Jupp,
ich möchte Dir gerne bei dem Projekt helfen, wenn Du Dein ok gibst.

Auf 'die Schnelle' einige Anmerkungen zu dem Projekt:
- die Double Variable Frequenz - sie benötigt die Standard Float Lib des Compilers.
  Diese Library alleine belegt 264 Byte SRAM des ATtiny85 (das ist mehr als die Hälfte!).
- Mir schwebt vor, die Sendeliste / Frequenz in eine Struktur zu packen.
  Dann kann über die poti_preset Variable direkt auf die entsprechenden Variablen zugegriffen werden
  (d.h. if-then-else entfällt!)
- Warum möchtest Du Poti   u n d  Drehgeber verwenden? Gibt es dafür einen wichtigen Hintergrund?
  Persönlich würde ich nur Drehgeber verwenden.

Wie liegt Dein Zeitrahmen für das Projekt? Meine Freizeit ist äusserst knapp bemessen.

Ach ja - ich habe keine Arduino-Umgebung auf meinem Laptop. Aber ob das ein Nachteil ist weiss ich nicht.

So in etwa sieht die radio.h aus.

Code:
struct Radio {
    char Station[17];
    double Frequenz;
};
    
struct Radio Sender[6] ={
    {"SR 1 Europawelle", 88.8,},
    {"SR 2 Kultur     ", 91.3,},
    {"SR3Saarlandwelle", 95.5,},
    {"ClassicRockRadio", 100.9,},
    {"Radio Salue     ", 101.7,},
    {"SR Unser Ding   ", 103.7,},
    };

Du müsstest sie im Programm einbinden
#include radio.h
und testen, ob sie Fehler produziert (hoffentlich nicht!).

Wenn ok, dann kann z.B. mit

Radio.set_frequency(Sender[poti_preset].Frequenz);
anstelle von
Radio.set_frequency(frequenz);

lcd.print (Sender[poti_preset].Frequenz);
anstelle von
lcd.print (frequenz);

lcd.print (Sender[poti_preset].Station);
anstelle von
lcd.print (Sendername);  

gearbeitet werden.
Grüße aus Wassenberg,
Norbert.
Zitieren
#3
danke Norbert für dein Hilfeangebot! Zeitdruck hab ich keinen, ich wußte vorher gar nicht daß ich überhaupt so weit komme.
Mit der Abstimmung will ich mich nicht binden, sondern das benutzen was sich grade anhand der Gegebenheiten ergibt. Deshalb sehe ich Poti, Encoder, Tasten und Touchsensoren vor.
Zitieren
#4
Jupp, ich helfe gerne!

Ich könnte das Programm im Laufe des Tages abändern und Dir zur Verfügung stellen.
Testen musst Du aber selbst, da ich keinerlei Hardware hier habe.

Noch eine Anmerkung zu Poti oder Dreh-Encoder:
- das Poti hat den Vorteil, dass nur ein Pin belegt wird. Dafür muss aber Analogwert-Verarbeitung erfolgen.
- der Dreh-Encoder belegt 3 Pins (2xImpuls, 1Taster). Damit kann aber eine Menü-Steuerung realisiert werden.
Grüße aus Wassenberg,
Norbert.
Zitieren
#5
Hier einmal die Klassendeklaration der TEA5767 Bibliothek für den Tiny die du benutzt.

Code:
class TEA5767Tiny {
    private:
        tea5767_ctrl ctrl_data;
        int HILO;
    protected:
        int hilo_optimal (unsigned long freq);
        void set_frequency (int hilo, double freq);
        int ready (unsigned char *buf);
        int bl_reached (unsigned char *buf);
    public:
        TEA5767Tiny();
        TEA5767Tiny(double initial_freq);
        void set_frequency (double freq);
        int read_status (unsigned char *buf);
        int signal_level (unsigned char *buf);
        int stereo (unsigned char *buf);
        double frequency_available (unsigned char *buf);
        void search_up (unsigned char *buf);
        void search_down (unsigned char *buf);
        int process_search (unsigned char *buf, int search_dir);
        void init();
};
Das Datenblatt des Radio-ICs liegt hier https://www.sparkfun.com/datasheets/Wire...EA5767.pdf

Eine Signal- und auch Stereo-Anzeige könnte man noch zusätzlich mit aufs Display nehmen, Platz ist ja genug da.  Vielleicht als selbstgezeichnetes Symbol über einen eigenen Font? Solche LCD-Module sind ja auch begrenzt grafiktauglich.
Das Umschalten würde ich nicht so hart machen wenn es geht und den TEA5767 vielleicht vorher "muten", also per Software stummschalten, dann die Frequenz ändern und den Ton wieder anschalten. Das verhindert das Krachen bei der Umschaltung mit dem Poti. 

Viele Bastlergrüße 
Bernhard.
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#6
anbei das geänderte Hauptprogramm, hoffe das Alles passt….

Code:
#include <TinyWireM.h>
#include <LiquidCrystal_I2C.h>
//#include <SoftRcPulseOut.h>
#include <TEA5767Tiny.h>
#include <radio.h>           //NEU
LiquidCrystal_I2C lcd(0x3F, 16, 2);
TEA5767Tiny Radio;
//SoftRcPulseOut servo;

#define REFRESH_PERIOD_MS 20

int analogInPin = A2; // PB4
int poti = 0;
int poti_pwm = 0;
int poti_preset = 0;
int poti_preset_out = 0;

// double frequenz;   NEU

// char Sendername[17] = "Platzhalter";  NEU

void setup() {

pinMode(analogInPin, INPUT);

//servo.attach(1);
//servo.setMaximumPulse(2200);
//SoftRcPulseOut::refresh();

lcd.init();
lcd.backlight();
lcd.clear();
lcd.print (poti_preset_out);
delay (30);

Radio.init();
delay (30);

}

void loop() {

poti = analogRead(analogInPin);
poti_preset = map(poti, 0, 1000, 1, 6);
poti_pwm = map(poti, 0, 1000, 0, 180);

/*     NEU
if (poti_preset == 1) {
     frequenz = 88.0;
     strcpy (Sendername, "SR 1 Europawelle");
     }
     
else if (poti_preset == 2) {
     frequenz = 91.3;
     strcpy (Sendername, "SR 2 Kultur     ");
     }
     
else if (poti_preset == 3) {
     frequenz = 95.5;
     strcpy (Sendername, "SR3Saarlandwelle");
     }
     
else if (poti_preset == 4) {
     frequenz = 100.9;
     strcpy (Sendername, "ClassicRockRadio");
     }

else if (poti_preset == 5) {
     frequenz = 101.7;
     strcpy (Sendername, "Radio Salue     ");      
     }
     
     
else if (poti_preset == 6) {
     frequenz = 103.7;
     strcpy (Sendername, "SR Unser Ding   ");
     }
*/       //NEU

if ((poti_preset_out) != (poti_preset)) {
poti_preset_out = poti_preset;
Radio.set_frequency(Sender[poti_preset].Frequenz);  //NEU
// Radio.set_frequency(frequenz);
delay (30);      
lcd.setCursor ( 0, 0 );
lcd.print (poti_preset);
lcd.print (" - ");
lcd.print (Sender[poti_preset].Frequenz);    //NEU
// lcd.print (frequenz);
lcd.print ("MHz ");
lcd.setCursor(0, 1);
lcd.print (Sender[poti_preset].Station);      //NEU
//lcd.print (Sendername);
//servo.write(poti_pwm);
}

delay (30);
}

Ich finde Bernhard's Idee sehr gut. Vielleicht kann er bei der Umsetzung unterstützen??
Ich habe sowieso eine Frage an Dich, Bernhard, wie wird z.B. die Radio.h in das Arduino
Projekt eingebunden? 
Und könntest Du bitte über das Hauptprogramm schauen, ob es korrekt ist??

Ich habe den nicht benutzten Code nur ausdokumentiert aber absichtlich stehen lassen,
so dass der ursprüngliche Code noch sichtbar ist.
Wenn alles ok ist, dann können die Zeilen natürlich entfernt werden.
Grüße aus Wassenberg,
Norbert.
Zitieren
#7
Moin,

ein schönes Projekt und sehr interessant! Ich werde das auf jeden Fall weiter beobachten, das Potenzial ist wirklich sehr bemerkenswert. Bei mir erledigt der Arduino immer noch recht banale Dinge, da sollte ich mich wohl mal mehr mit auseinandersetzen.

Beste Grüße und einen schönen Sonntag
Peter

98
Zitieren
#8
Zitat:Ich habe sowieso eine Frage an Dich, Bernhard, wie wird z.B. die Radio.h in das Arduino
Projekt eingebunden? 
Und könntest Du bitte über das Hauptprogramm schauen, ob es korrekt ist??

Hallo Norbert, 

das geht genau wie bei der Headerdatei TEA5767Tiny.h, auch bezüglich der Instanziierung des Datentyps, dann aber im Hauptprogramm und nicht in der Header selbst.
Letztendlich müsste aber beides funktionieren und kompilierbar sein. Direkt in der Arduino IDE reicht es ein neues Radio.ino (im selben Ordner wie das Hauptprogramm) zu erstellen und dann Definition und Deklaration dort reinzuschreiben. Ein explizites Einbinden über include wäre nicht mehr nötig!

Nebenbei als Klasse in C++ geschrieben sähe das zum Beispiel so aus. Ich würde auch gleich einen String anstelle eines Char-Arrays nehmen, ist finde ich einfacher und eleganter darauf zuzugreifen wenn man sich mal die Memberfunktionen der String-Klasse anschaut.
Ich würde also gleich durchgängig mit Klassen arbeiten, so wird es in der TEA5767Tiny- und LCD-Bibliothek ja schon gemacht. Also wenn schon C++ im Programm genutzt wird, dann gleich alles auf C++.


Code:
class Radio {
    private:
        String Station;
        double Frequenz;
    public:
        Radio(String Station, double Frequenz); // Konstruktor

        String  getStation();
        double getFrequenz();

        void setStation(String str);
        void setFrequenz(double freq);
}

Man könnte dann auch ganz einfach die Klasse Radio so ausbauen, das diese über eine weitere Memberfunktion den Sender per I2C-Bus einstellt und das Display aktualisiert.
Möchte man später ein DAB-Modul ansteuern, könnte man eine Klasse DABRadio schreiben die von der Klasse Radio abstammt und viele Eigenschaften der Klasse Radio erbt. Das sind dann in der Objektorientierten Programmierung die Themen Vererbung und Polymorphismus und wie man dadurch Softwareteile wiederverwenden kann.
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#9
Hallo Bernhard,
Zitat:
Nebenbei als Klasse in C++ geschrieben sähe das zum Beispiel so aus. Ich würde auch gleich einen String anstelle eines Char-Arrays nehmen, ist finde ich einfacher und eleganter darauf zuzugreifen wenn man sich mal die Member der Klasse anschaut.
Ich würde also gleich durchgängig mit Klassen arbeiten, so wird es in der TEA5767Tiny- und LCD-Bibliothek ja schon gemacht. Also wenn schon C++ im Programm genutzt wird, dann gleich alles auf C++.

Genau aus diesem Grund habe ich um Deine Mithilfe gefragt. Mit C++ sieht es bei mir eher dunkel aus.
Testen kann ich eigentlich Nichts, da weder Hardware noch Arduino-Software vorhanden.
Und einen besseren Fachmann als Dich hier im Forum kenne ich aktuell nicht.
Könntest Du denn bitte hier ein wenig Licht ins Dunkle bringen?
Grüße aus Wassenberg,
Norbert.
Zitieren
#10
Hallo Norbert,

ich habe jetzt auch keinen ATTiny und den TEA5767 zur Hand um das Programm komplett zu testen, aber die Version von Jupp tut ja was sie soll, deshalb meine Hochachtung vor dieser Leistung! Bitte so weitermachen Jupp! Ich will auch gar nicht Jupps-Programm zerpflücken oder großartig abändern, es funktioniert ja. Muting und Signal-/Stereo-Anzeige braucht ein UKW-Modul ja auch nicht in einem Oldtimer-Radio. Dort wird Jupp sicher seinen Prozessor ohne Display betreiben wollen. Ich wollte nur erwähnen was noch möglich wäre mit der Klassenbibliothek des Chips.

Meine Radioklasse (radio.h oben) war nur ein Beispiel wie man es in C++ umsetzten könnte. Von den Sprachelementen unterscheiden sich C und C++ ja nur durch wenige Extrakonstrukte. Vielmehr ist C++ eine andere Denkweise um das Problem zu lösen. Während C das Problem Top-to-Down der Reihe nach löst, sind in C++ alle Dinge der Welt ersteinmal in Klassen beschrieben. Jedes Ding hat Eigenschaften und kann bestimmte Sachen machen, wie man ja auch an den Headerdateien für den TEA5767Tiny und das LCD-Display erkennen kann. Das macht große Probleme übersichtlicher, die Programme dadurch durchsichtiger. Viele Softwareteile lassen sich durch Klassenvererbung und Polymorphismus wiederverwenden. Bei so einem kleinen übersichtlichen Projekt hier ist es wahrscheinlich egal ob es in C oder C++ geschrieben ist.

Und natürlich bin ich jederzeit bereit meine Hilfe einzubringen wenn es Fragen oder Probleme gibt. Die Sache mit dem Fachmann lassen wir mal, ich bin ein Bastler der sich mit Microcontrollern schon ein paar Monate beschäftigt, mehr nicht!

Viele Bastlergrüße
Bernhard
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#11
danke Bernhard! Die letzten postings hatten meinen Horizont überschritten, jetzt seh ich wieder Licht.
Das Display hab ich hauptsächlich angeklemmt weil ich die Möglichkeit sowieso vorsehen wollte und weil am ATtiny der serielle Monitor nicht zur Verfügung steht. So konnte ich die Berechnung der Variablen nicht kontrollieren und wusste auch nicht wo das Programm stockte. Ich hab mir dann die Infos die ich brauchte auf dem Display ausgegeben.
Richtig, ich werde den Baustein hauptsächlich im Mono-Betrieb einsetzen.
Zitieren


Möglicherweise verwandte Themen…
Thema Verfasser Antworten Ansichten Letzter Beitrag
  UKW Baustein TEA5767 mit Arduino saarfranzose 34 12.336 21.07.2017, 22:28
Letzter Beitrag: klammi †
  UKW-Baustein TEA5767 mit ATtiny85 saarfranzose 1 1.645 12.07.2017, 21:22
Letzter Beitrag: saarfranzose

Gehe zu: