Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Internetradio mit MPC/MPD
#1
Hallo zusammen,

wenn man sich im Internet nach Lösungen für Internetradios mit dem Raspberry-Pi umsieht, stolpert man schon fast zwangsläufig über Lösungen mit dem Medienplayer MPC/MPD.

Nach dieser Anleitung:
https://feldspaten.org/2014/04/22/raspberry-als-internet-radio-station/
habe ich mir die benötigten Dateien installiert.
Dort ist auch beschrieben, welche Anpassungen noch erforderlich sind und wo die Playlisten zu liegen kommen.

Hier ist schön zu sehen, dass 'mpc' bei den Funktionsaufrufen alle evtl. benötigten Informationen zurück gibt, insbesondere auch den Umfang der Playlist.
In diesem Beispiel ist Eintrag 15 von 28 gewählt.



.png   Bildschirmfoto vom 2018-12-02 18-15-37.png (Größe: 9,82 KB / Downloads: 139)

Aus dieser Information lässt sich dann die Größe der Senderliste bestimmen und daraus der Teilerfaktor zum verteilen der Sender auf der Radioskala berechnen.

Die Anpassung meiner bisher geschriebenen Hilfsprogramme hat nur wenig Zeit in Anspruch genommen, der Befehlssatz des 'mpc' ist sehr einfach handhabbar.

Ein kleiner Nachteil sei aber nicht verschwiegen!
Im Gegensatz zum vlc kann mpc keine URL's auflösen.
Er benötigt also in der Senderliste bereits die aufgelösten URL's.

Diese bekommt man, wenn man auf einem Rechner mit installiertem VLC die gewünschte Station anspielt, dann mit einem Klick auf die rechte Maustaste das Kontextmenü aufruft und dort unter 'Werkzeuge' den Eintrag 'Medieninformation' auswählt:


.png   Bildschirmfoto vom 2018-12-02 21-31-05.png (Größe: 65,03 KB / Downloads: 139)

In der letzten Zeile bei 'Ort' sieht man dann die aufgelöste URL, diese kann dann in die Senderliste kopiert werden.
Schneller kommt man zu diesen Informationen mit CTRL-I.

Die fertige Playlist wird dann nach /var/lib/mpd/playlists kopiert.

Bei jedem Neustart des Raspberry muss die Senderliste neu geladen werden.
Dabei die Endung '.m3u' weglassen.

Also z.B. 'mlc load Sender' (wenn die Playlist Sender.m3u heißt) oder in einem Programm 'system("mlc load Sender");'.

Zuvor sollte sicherheitshalber eine ggf. noch geladene Senderliste mit 'mlc clear' gelöscht werden.

Mit 'mlc play 1' wird dann der erste Sender der Playlist aufgerufen.


Viele Grüße

Martin
Zitieren
#2
Hallo zusammen,

so, nun habe ich mein Internetempfangsmodul fertig!

Hier ein Foto vom Versuchsaufbau:

   

Zur Senderwahl dient ein lineares Poti, es können natürlich je nach Einbauverhältnissen auch Schiebepotis vorgesehen werden.

Hier der Schaltplan dazu:
   

Da ich optional noch ein Display anschließen möchte und die mir hierfür zur Verfügung stehende Hardware mit 5V-Pegeln arbeitet, habe ich einen ADuM1250 als Pegelwandler missbraucht.
Dadurch hätte ich bei Bedarf auch die Möglichkeit, eine vollständige galvanische Trennung des 5V-Teils vom Raspberry-Pi zu schaffen.

Zur gleichmäßigen Verteilung der Sender über die Skala hole ich mir aus den im vorherigen Beitrag gezeigten Informationen die Anzahl der Sender und berechne mir daraus den Teilerfaktor für die zurückgegebenen Digits des A/D-Wandlers.

Hier stelle ich mal den Code ein:

Code:
/* iradio_V3 unter Verwendung von MPC/MPD als Mediaplayer
Dient als Nachrüstlösung ohne Displayausgabe z.B. für Radios ohne UKW-Teil.
Die Senderwahl wird mittels eines Dreh- oder Linearpoti vorgenommen, zum einlesen dient ein A/D-Wandler vom Typ MCP3426.
Das zugehörige Programmteil habe ich im Internet gefunden und für meine Bedürfnisse angepasst.
Betriebart ist 12-bit, Kanal 1                                                                                            */
 
#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <bcm2835.h>
#include <stdint.h>
#include <string.h>
 
#define PIN_1 RPI_GPIO_P1_11
//#define teiler 36
 
/* Definition der Textfarben */
#define ANSI_BLACK            "\x1b[30m"
#define ANSI_RED            "\x1b[31m"
#define ANSI_GREEN            "\x1b[32m"
#define ANSI_BROWN            "\x1b[33m"
#define ANSI_BLUE            "\x1b[34m"
#define ANSI_MAGENTA        "\x1b[35m"
#define ANSI_CYAN            "\x1b[36m"
#define ANSI_LIGHTGRAY        "\x1b[37m"
#define ANSI_DARKGRAY        "\x1b[1;30m"
#define ANSI_LIGHTRED        "\x1b[1;31m"
#define ANSI_LIGHTGREEN        "\x1b[1;32m"
#define ANSI_YELLOW            "\x1b[1;33m"
#define ANSI_LIGHTBLUE        "\x1b[1;34m"
#define ANSI_LIGHTMAGENTA    "\x1b[1;35m"
#define ANSI_LIGHTCYAN        "\x1b[1;36m"
#define ANSI_WHITE            "\x1b[1;37m"
 
/* Definition der Hintergrundfarben */
#define ANSI_GRND_BLACK        "\x1b[40m"
#define ANSI_GRND_RED        "\x1b[41m"
#define ANSI_GRND_GREEN        "\x1b[42m"
#define ANSI_GRND_BROWN        "\x1b[43m"
#define ANSI_GRND_BLUE        "\x1b[44m"
#define ANSI_GRND_MAGENTA    "\x1b[45m"
#define ANSI_GRND_CYAN        "\x1b[46m"
#define ANSI_GRND_GRAY        "\x1b[47m"
 
/* Setzt Farben wieder auf den Ursprungszustand */
#define ANSI_DEFAULTCOLORS    "\x1b[0m"
 
 
/* Weitere Funktionen */
#define ANSI_CLS()            printf("\x1b[2J\x1b[1;1H")
#define ANSI_LOCATE( x, y )    printf("\x1b[%i;%iH", y, x)
#define ANSI_CLREOL()       printf("\x1b[K")
#define ANSI_COLOR( c )        printf(c) /* Hierbei ist 'c' eine der obigen Farbkonstanten */
 
 
 
int lesen()  
 
// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// MCP3426
// This code is designed to work with the MCP3426_I2CADC I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Analog-Digital-Converters?sku=MCP3426_I2CADC#tabs-0-product_tabset-2
 
{
    // Create I2C bus
    int file;
    int raw_adc;                //neu deklariert, war usprünglich weiter unten in einer else-Klausel deklariert
    char *bus = "/dev/i2c-1";
    if((file = open(bus, O_RDWR)) < 0)  
    {
        printf("Failed to open the bus. \n");
        exit(1);
    }
    // Get I2C device, MCP3426 I2C address is 0x68(104)
    ioctl(file, I2C_SLAVE, 0x68);
 
    // Select configuration command(0x10)
    // Continuous conversion mode, channel-1, 12-bit resolution
    char config[1] = {0};
    config[0] = 0x10;
    write(file, config, 1);
    //sleep(1);
    delay(100);
 
    // Read 2 bytes of data from register(0x00)
    // raw_adc msb, raw_adc lsb
    char reg[1] = {0x00};
    write(file, reg, 1);
    char data[2] = {0};
    if(read(file, data, 2) != 2)
    {
        printf("Error : Input/output Error \n");
    }
    else
    {
        // Convert the data to 12-bits
        raw_adc = ((data[0] & 0x0F) * 256 + data[1]);
        if(raw_adc > 2047)
        {
            raw_adc -= 4095;
        }
        // Ursprünglich wurden die Werte nur angezeigt  
        // Output data to screen
        // printf("Digital value of Analog Input : %d \n", raw_adc);
     }
    close(file);              //Nachtrag 28.11.18 MR, hat im Originalcode gefehlt
    return raw_adc;
}
 
 
int inhalt_lesen()
 
{
    char titel[90];
    char delimiter[] = "/ ";
    char *ptr;
    int faktor;
    int teiler;
    int zaehler = 1;
 
    FILE *text1 = popen("mpc play 1 | grep playing", "r");
    fgets(titel,90,text1);
    pclose(text1);
    // initialisieren von strtok und ersten Abschnitt erstellen
    ptr = strtok(titel, delimiter);
    while(ptr != NULL)
      {
        if (zaehler == 3) faktor = atoi(ptr);  //Die Länge der Senderliste ist der dritte Eintrag
    // nächsten Abschnitt erstellen
     ptr = strtok(NULL, delimiter);
    zaehler++;
      }
    teiler = 2047 / faktor;
    teiler = teiler/2;
    return teiler;    
}
 
 
void info_lesen(int sender)
 
{
    char titel[150];
    char titel_neu[150] = "tralala";
    char delimiter[] = ":";
    char *ptr;
    int testwert;
    int zaehler = 0;
 
    FILE *text1 = popen("mpc current", "r");
    fgets(titel,150,text1);
    pclose(text1);
    ANSI_COLOR(ANSI_LIGHTGRAY);
    //Hat sich die Senderinfo verändert?
    testwert = strcmp(titel,titel_neu);
    if (testwert != 0);
    {
    // initialisieren von strtok und ersten Abschnitt erstellen
    ptr = strtok(titel, delimiter);
    while(ptr != NULL)  
      {
        if (zaehler < 2)
        {
            ANSI_LOCATE(10-zaehler,10+zaehler);
            ANSI_CLREOL();
            printf("%s", ptr);
        }
    // nächsten Abschnitt erstellen
     ptr = strtok(NULL, delimiter);
    zaehler++;
      }
    strcpy(titel_neu,titel);
    }
}
 
 
int main()
    {
    char kommando[20];
    int wert;
    int sender;
    int station;
    int rest;
    int sender_alt = 999;
    int zaehler = 1;
    int teiler;
 
    if (!bcm2835_init())
    return 1;
    bcm2835_gpio_fsel(PIN_1, BCM2835_GPIO_FSEL_OUTP);
    ANSI_CLS();
    //mpc initialisieren:
      system("mpc clear");
      system("mpc load Sender");
      system("mpc volume 80");
    teiler = inhalt_lesen();
    //Falls einlesen fehlschlägt, wird ein Defaultwert gesetzt
    if (teiler < 1) teiler = 36;
    //Endlosschleife für daemon-Betrieb    
    while (1)
           {
           wert = lesen();
        zaehler = zaehler+1;
           if (wert == 0) wert = 1;
           sender = wert / teiler;
                if (sender != sender_alt)  
                   {
                    station = sender/2;
                    rest = sender % 2;
                    if (rest == 0)
                        {
                            sprintf(kommando, "mpc play %d",station+1);
                            system(kommando);
                            sender_alt = sender;
                            bcm2835_gpio_write(PIN_1, LOW);
                            ANSI_COLOR(ANSI_GRND_BLUE);
                            ANSI_CLS();
                            ANSI_COLOR(ANSI_LIGHTGREEN);
                            ANSI_LOCATE(10,5);
                            printf("Info für Sender %d",station+1);
                        }
                        else bcm2835_gpio_write(PIN_1, HIGH);
                       }
            info_lesen(station+1);
           }
    ANSI_COLOR(ANSI_DEFAULTCOLORS);
     ANSI_CLS();
    system("mpc stop");
     return 0;
    }

Als 'Opfergerät' habe ich mir diesen Siemens RG71 ausgesucht:

.jpg   DSCF1414.jpg (Größe: 110,84 KB / Downloads: 19)

Da ich jedoch im Moment sowohl durch mein Ehrenamt als auch durch begonnene Restaurierungen stark beansprucht bin, wird es eine Weile dauern, bis es hier weitergeht.


Viele Grüße

Martin
Zitieren


Möglicherweise verwandte Themen...
Thema Verfasser Antworten Ansichten Letzter Beitrag
  Ein Internetradio Bausatz von PIMORONI Bernhard45 175 4.996 Vor 10 Stunden
Letzter Beitrag: Bernhard45
  Autophon-Internetradio saarfranzose 5 69 Vor 10 Stunden
Letzter Beitrag: Bernhard45
  VE 301 Internetradio saarfranzose 43 977 Gestern, 09:55
Letzter Beitrag: saarfranzose
  Ein minimales Internetradio für alte und neue Raspberrys Bernhard45 85 2.317 08.12.2018, 17:11
Letzter Beitrag: Bernhard45
  Briconti-Internetradio mit Raspberry saarfranzose 3 179 07.12.2018, 14:00
Letzter Beitrag: saarfranzose

Gehe zu: