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: 462)

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: 460)

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: 333)

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
#3
Hallo zusammen,

gemäß den Anregungen von Bernhard habe ich mir nun auch einen Display-Daemon 'gezimmert'.

Dazu habe ich ein Codebeispiel aus dem Internet verwendet, welches für mich leichter zu durchschauen ist als das von Bernhard verwendete.
Dieses Codebeispiel ist sehr einfach an alle möglichen Punktmatrixdisplays anpassbar.

Herausgekommen ist dabei das da:
   

Angesteuert wird das Display von einem Adapterbausatz, welcher bei Pollin erhältlich ist.
Dieser Adapterbausatz arbeitet mit dem bekannten Portexpander PCF8574.
Ein Vorteil dieses Bausatzes ist, dass er an fast alle gängigen Displays anschließbar ist, da hier sowohl Displays mit einreihigem 16-poligen Stecker verwendet werden können als auch solche mit einem 2x8-poligen Steckverbinder.

Hier noch der Quellcode dazu:

Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <wiringPi.h>
    #include <pcf8574.h>
    #include <time.h>
    #include <stdint.h>
    #include <unistd.h>

    //Definition der Displayfunktionen
    #define        RS_CMD              0
    #define        RS_DATA             1
    #define        BACKLIGHT_ON        0
    #define        BACKLIGHT_OFF       1
    #define        LC_SIG_RESET        0x03
    #define        LC_SIG_4BINP        0x02
    #define        LC_SIG_4BMODE       0x28
    #define        LC_SIG_DON          0x0C
    #define        LC_SIG_SHOWCURSOR   0x02
    #define        LC_SIG_CURSORBLINK  0x01
    #define        LC_SIG_NORMALMODE   0x06
    #define        LC_CMD_CLEAR        0x01
    //Liniendefinitionen für 4x20-Zeichendisplay
    #define        LC_LINE1            0x80
    #define        LC_LINE2            0xC0
    #define        LC_LINE3            0x94
    #define        LC_LINE4            0xD4
    #define        PINBASE             100
    //Moduladresse ggf. anpassen!
    #define        MOD_ADRESS          0x27
    #define        PIN_RS
    #define        PIN_RW
    #define        PIN_E
    
    void send4BitCmd(int RS, char Command) {
        int i;
        digitalWrite(104, RS);
        digitalWrite(106, 1);
        
        
        for (i = 4; i < 8; ++i) {
            digitalWrite((107 - i),(Command >> 11 - i) & 1);
            //printf("%d", (Command >> 11 - i) & 1);
        }
        digitalWrite(106, 0);
        digitalWrite(106, 1);
        
        for (i = 0; i < 4; ++i) {
            digitalWrite((103 - i),(Command >> 3 - i) & 1);
            //printf("%d", (Command >> 3 - i) & 1);
        }
        digitalWrite(106, 0);
    }

    void sendNibble(int RS,char Command) {
    int i;
        digitalWrite(104, RS);
        digitalWrite(106, 1);
        
        for (i = 0; i < 4; ++i) {
            digitalWrite((100 + i),(Command >> i) & 1);
        }
        
        digitalWrite(106, 0);
    }

    void initLCDisplay() {
         //Soft Reset Signal
         digitalWrite(105, 0); //Display auf Ausgabe stellen
         
         sendNibble(RS_CMD,LC_SIG_RESET);
         sendNibble(RS_CMD,LC_SIG_RESET);
         sendNibble(RS_CMD,LC_SIG_RESET);
         
         sendNibble(RS_CMD,LC_SIG_4BINP);  //Set 4 Bit Input
         
         send4BitCmd(RS_CMD,LC_SIG_4BMODE); //Set 4 Bit Mode
         send4BitCmd(RS_CMD,LC_SIG_DON); //Display on hide cursor no blinking
         send4BitCmd(RS_CMD,LC_CMD_CLEAR); //Clear
         send4BitCmd(RS_CMD,LC_SIG_NORMALMODE); //Entry Mode, Increment cursor position, No display shift
    }

    void sendBacklight(int Switch) {
        digitalWrite(107, Switch);
    }

    void sendPosition(int Line, int Col) {
        send4BitCmd(RS_CMD, Line + Col);
    }

    void sendText(char *source) {    
        int i = 0;
        
        for (i;i < (int)strlen(source); i++)
        {
            send4BitCmd(RS_DATA, source[i]); //[i] dazu, hat im Original gefehlt
            
        }
    }

    void LCD_clreol()
    {
        sendText("                    \0");
    }

int main (void)
{
    char buffer[21], buffer_1[21], buffer_2[21], buffer_3[21], buffer_4[21];
    char Sender[100];
    char Stueck[100];
    char Hilfstext[100];
    char titel[150];
    char titel_neu[150] = "tralala";
    char delimiter[] = ":";
    char *ptr;
    int testwert;
    int zaehler = 0;
    int i;
    time_t curtime;
    struct tm *loctime;

    //Initialisierung von wiringPi und Display        
     //printf ("RasPi LCD\n");
     if (wiringPiSetup () == -1)
      return 1;
     
     if (pcf8574Setup (100, MOD_ADRESS) == -1)
      return 1;
 
     initLCDisplay();
     
     sendBacklight(BACKLIGHT_ON);
     send4BitCmd(RS_CMD,LC_CMD_CLEAR);

    //Endlosschleife für Daemon-Betrieb      
     for (;;)
    {
        // Hier gewinnen wir die Senderinformationen
        FILE *text1 = popen("mpc current", "r");
        fgets(titel,150,text1);
        pclose(text1);

        //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)
            {
                if (zaehler == 0) strcpy(Sender,ptr);
                if (zaehler == 1) strcpy(Stueck,ptr);
            } //von if (zaehler)
        // nächsten Abschnitt erstellen
         ptr = strtok(NULL, delimiter);
        zaehler++;
            } //von while
        strcpy(titel_neu,titel);

        //Zuerst das führende Leerzeichen des Titels entfernen
        for (i = 1; i < strlen(Stueck); ++i)
            {
                Hilfstext[i-1] = Stueck[i];
            }
        Hilfstext[strlen(Stueck)] = '\0';
        //printf("1: %s\n",Sender);
        //printf("2: %s\n",Stueck);
        //printf("3: %s\n",Hilfstext);

        //Sender- und Titelinformationen 'zurechtstutzen'
        strncpy(buffer_3,Sender,20);
        strncpy(buffer_4,Hilfstext,20);
        if (strlen(buffer_3) > 19) buffer_3[20] = '\0';
        if (strlen(buffer_4) > 19) buffer_4[20] = '\0';
        
        //und jetzt ins Display schreiben
        sendPosition(LC_LINE2, 0);
        LCD_clreol();
        sendPosition(LC_LINE2, 0);
        sendText(buffer_3);
        sendPosition(LC_LINE3, 0);
        LCD_clreol();
        sendPosition(LC_LINE3, 0);
        sendText(buffer_4);
        //printf("%s\n",buffer_3);
        //printf("%s\n",buffer_4);
        } //von if (testwert)

        //Titelzeile schreiben
        sendPosition(LC_LINE1, 0);
        sendText(" Internetradio V0.1 ");

        //Einlesen von Zeit und Datum
        curtime = time (NULL);
        loctime = localtime (&curtime);
        strftime (buffer_1, 21, "%H:%M", loctime);
        strftime (buffer_2, 21, "%d.%m.%Y", loctime);
        sprintf(buffer, "%*s %s",7,buffer_1,buffer_2); //7 = Länge des ersten Teilstrings zzgl. zwei führenden Leerzeichen
        sendPosition(LC_LINE4, 0);
        sendText(buffer);
        sleep(5);
        zaehler = 0;
     } //von for(;;);
    return 0;
    }

Nächste geplante Schritte:

- Übergeben der I²C-Adresse als Übergabeparameter
- Anpassen an Displays mit 2x 40 Zeichen, davon habe ich noch zwei in der Bastelkiste liegen
- scrollen von Titelinformationen welche länger als 20 bzw. 40 Zeichen sind


Viele Grüße

Martin
Zitieren
#4
Hallo Martin,

das hast Du gut gelöst!

Ich kann Dein Programm leider nicht testen, aber ist das Semikolon an der markierten Stelle gewollt?
  
Code:
       //Hat sich die Senderinfo verändert?
       testwert = strcmp(titel,titel_neu);
       if (testwert != 0);  <- Hat sich hier ein Semikolon eingeschlichen???
       {
       // initialisieren von strtok und ersten Abschnitt erstellen
       ptr = strtok(titel, delimiter);
Grüße aus Wassenberg,
Norbert.
Zitieren
#5
bei meinen ersten attiny-Experimenten hatte ich auch ein Poti in Bereiche geteilt (manuell).

Preset-Tuner mit ATtiny und TEA5767

Später fiel mir auf wie ungenau und schwankend Potiwerte digital ausgelesen werden. Eine gute Referenzspannung schafft auch nur begrenzt Abhilfe. Bei der Preset-Geschichte fällt es nicht so auf, nur wenn das Poti ungünstig im Grenzbereich zwischen zwei Abstufungen steht. Wohl aber wenn man die abgegriffene Spannung direkt z.B. in eine Frequenz umrechnet. Ohne weitere (Software-)Massnahmen hat man keine stabile Ausgangsgröße. Deshalb bin ich dann hauptsächlich auf Drehencoder umgestiegen. Klar, die muss man auch entprellen, und um einen Skalenbereich abzufahren braucht man eine Kalibrierung und muss die Impulse zählen, damit der Prozessor die Position des Skalenzeigers ermitteln kann.
Nur mal meine Gedanken dazu..
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#6
Hallo zusammen,

@Norbert:
Das Semikolon hat sich da in der Tat eingeschlichen und war nicht beabsichtigt.
Jedenfalls tut das Programm was es soll.
Die Displayanzeige wird alle 5 Sekunden aktualisiert.

@Jupp:
Wie gut oder nicht gut die Reproduzierbarkeit der Winkeleinstellung ist, habe ich noch nicht getestet.
Jedenfalls habe ich nach aus- und wieder einschalten immer die ursprünglich gewählte Station.
Ich habe es in meinem Algorithmus auch so gelöst, dass ich nur die geradzahligen Stufen zur Senderumschaltung benutze, ich habe also immer einen Drehwinkel x Lücke.
In der Lücke leuchtet dann die angeschlossene LED, so dass ich erkennen kann, ob ich auf einer Senderposition bin oder nicht.
Die mögliche Präzision wird auch von der Auflösung des A/D-Wandlers, dessen Fehler sowie von der Anzahl der in der Playlist gespeicherten Stationen abhängen.
In meinem Falle habe ich 28 Stationen in der Playlist und einen A/D-Wandler mit nutzbaren 11bit (2048 digits) Auflösung, da dieser +- 2,048V verarbeiten kann und somit das zwölfte Bit als Vorzeichen benutzt.

Ich will auch zu einem späteren Zeitpunkt mal ausprobieren, ob ich den oben genannten LED-Anschluss auch zum Ansteuern der Stereoanzeige meines 'Opfergerätes' nutzen kann, um darüber eine Anzeige zu haben, ob ich auf einen Sender 'abgestimmt' habe oder nicht.
Das ganze wird dann natürlich schön mittels Optokoppler vom Raspberry getrennt.


Viele Grüße

Martin
Zitieren
#7
versuche mal das Poti so einzustellen daß die LED grade so keine Lücke signalisiert, also möglichst hart an die Grenze. Nach meinen Experimenten müsste die LED dann flackern. Wenn das der Fall ist weist du was ich meine.
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#8
Hallo Jupp,

habe ich eben versucht, zum flackern bekomme ich die LED nicht, so sehr ich mich auch anstrenge!

Mag sein, dass es daran liegt, dass ich noch einen Kondensator 10n vom Potischleifer gegen Masse habe.
Des weiteren verwende ich ja einen externen A/D-Wandler.

Lt. Datenblatt führt dieser bei jeder Abfrage eine Selbstkalibrierung (Offset und Verstärkung) aus.


Viele Grüße

Martin
Zitieren
#9
prima, dann hast du nicht das Problem welches ich mit den einfachen attiny und Arduino Nano hatte.
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#10
Hallo Jupp,

mag sein, dass bei den ATtiny die interne Referenz nicht so stabil ist.

Mir ist noch dunkel in Erinnerung, in einem meiner Bücher zum Arduino gelesen zu haben, dass es da beim abfragen von Potis zu Problemen kommen kann, diese aber mit irgendwelchen Softwaretricks zu beheben sind.
Ich muss mal sehen, ob ich diese Passage gelegentlich finde.

Bernhard hat in einem seiner Artikel im Zusammenhang mit einem Poti auch einen Microcontroller verwendet und sinngemäß geschrieben, dass er im Microcontroller noch ein Filter programmiert hat.

Der Vorteil der Potilösung, wenn sie denn funktioniert, ist halt der, dass keine Referenzpunkte benötigt werden und auch keine Impulse gezählt werden müssen.


Viele Grüße

Martin
Zitieren
#11
Radiobastler schrieb:...Der Vorteil der Potilösung, wenn sie denn funktioniert, ist halt der, dass keine Referenzpunkte benötigt werden und auch keine Impulse gezählt werden müssen..

das ist korrekt, dafür musst du den Drehwinkel brücksichtigen, und der ist bei Poti (270°) und Drehko (180°) unterschiedlich (falls diese gekoppelt werden sollen)
Gruß,
Jupp
-----------------------------

was du baust ist immer mit dir verbunden
(Lego)

Einsamkeit ist nur ein Mangel an Technologie
(@beetlebum)
Zitieren
#12
Hallo Jupp,

ja, das mit den unterschiedlichen Drehwinkeln ist mir bewusst!

Aber auch dafür gibt es Lösungen, entweder mechanisch über ein 2:3-Getriebe, oder elektrisch.
Ich muss ohnehin den Spannungshub des Poti einschränken, da die Referenzspannung meines A/D-Wandlers 2,048V beträgt, meine Versorgungsspannung hingegen 5V.
Dafür habe ich in meiner Schaltung ein Trimmpoti vorgesehen.

Dann kann ich das Trimmpoti vor dem eigentlichen 'Drehgeber' so einstellen, dass dieser bereits bei 180° Drehwinkel die 2,048V (oder eine Kleinigkeit weniger) erreicht.


Grüße

Martin
Zitieren


Möglicherweise verwandte Themen…
Thema Verfasser Antworten Ansichten Letzter Beitrag
  Huth E72 Internetradio mit ESP32 saarfranzose 10 1.785 12.05.2023, 14:49
Letzter Beitrag: saarfranzose
  Ein Internetradio Bausatz von PIMORONI Bernhard45 200 81.557 06.06.2022, 19:17
Letzter Beitrag: Reparateur
  Ein minimales Internetradio für alte und neue Raspberrys Bernhard45 189 105.625 12.04.2022, 16:00
Letzter Beitrag: navi
  Dementia III ESP32 Internetradio mit Simulation saarfranzose 9 2.805 21.01.2022, 23:14
Letzter Beitrag: saarfranzose
  Ein minimales Internetradio für alte und neue (Android) Smartphones Bernhard45 15 10.413 24.05.2021, 19:58
Letzter Beitrag: reinersbg

Gehe zu: