-         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 30

Thema: FM-Radio mit Arduino Pro Mini und Si4703 - Programm hängt sich auf!

  1. #11
    Erfahrener Benutzer Fleißiges Mitglied Avatar von basteluwe
    Registriert seit
    15.11.2012
    Beiträge
    100
    Anzeige

    Zitat Zitat von wkrug Beitrag anzeigen
    Die Lösung war, wenn ich richtig bin, 8 bzw. 9 Clock Impulse auf SCL zu legen, aber lies Sicherheitshalber noch mal nach.
    Danke dafür! Ich habe mal gesucht und diesen Threat gefunden. Ich glaube, ich verstehe was die Jungs sagen. Leider ist das aber programmiertechnisch nicht wirklich in meiner Liga (C geht bei mir nur sehr mäßig, ich mach eher in Arduino).
    Frage 1: sollten diese 9 Clock Impulse nur gesendet werden, wenn sich was aufhängt oder regelmäßig (wann)?
    Frage 2: wie kriege ich das im Arduino-Sketch implementiert?

    Gruß Uwe

  2. #12
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.915
    ich finde bare-metal-C-Tipps zu Arduino C++ Klassen wie Wire auch nicht so hilfreich, denn gerade die Wire Class ist bereits hoch optimiert.
    Eventuell reicht es, wenn du ab und zu einfach mal deine i2c-Devices "anpingst" , um zu sehen, ob ein Fehler zurückgegeben wird, und danach erst (wenn kein Fehler) deine Device-Lese-Schreib-Funktionen aufrufst:

    Code:
    Wire.beginTransmission(addr); // transmit to device I2C addr
    int ioerr=Wire.endTransmission();
    if(ioerr) {   // Ausgabe eines Fehlers samt i2c-addr. 
      Serial.print("Fehler bei addr 0x"); 
      if (addr<16) { Serial.print("0"); }
      Serial.print(addr,HEX); 
      Serial.print(" ioerr=");  
      Serial.println(ioerr); 
    }
    So kannst du checken, wie oft hier überhaupt wo was schief läuft.

    Aber mal eine ganz andere Frage :
    Wo in deinem Sketch (void setup() ) startest du denn überhaupt Wire mit Wire.begin() - irgendwie sehe ich es nicht....?
    Code:
    /**************************************************************************
     * This code is a modification/extract of several example-codes that come *
     * with different si4703-libraries. Libraries used are fetched from:      *
     *         http://www.mathertel.de/Arduino/RadioLibrary.aspx              *
     * Not sure if other libraries work with same code.                       *
     * 5 push-buttons control the radio (see comments in code)                *
     * OLED-display shows 3 lines:                                            *
     *  1- "frequency"                                                        *
     *  2- "station name" or "scan mode"                                      *
     *  3- "volume level" + "battery voltage" or "CHARGE BATTERY"             *
     * Code for voltage monitoring is fetched from:                           *
     * https://code.google.com/archive/p/ti...Voltmeter.wiki  *
     *                                                                        *
     * U.Galepp Jan./2018                                                     *
     **************************************************************************/
    
    #include <Arduino.h>
    #include <Wire.h>
    #include <radio.h>
    #include <si4703.h>
    #include "U8glib.h"
    
    U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);  // define type of display (OLED 0.96" 128x64 pix)
    
    #define FIX_BAND     RADIO_BAND_FM            // the band that will be tuned by this sketch is FM
    #define FIX_STATION  8760                     // station at start-up is 87.60 MHz
    #define FIX_VOLUME   1                        // volume level at start-up
    
    SI4703 radio;                                 // Create an instance of Class for Si4703 Chip
    
    int volume = FIX_VOLUME;
    int button_1 = 3;                             // button volume up at Pin 3
    int button_2 = 4;                             // button volume down at Pin 4
    int button_3 = 5;                             // button station swap at Pin 5
    int button_4 = 6;                             // button scan up at Pin 6
    int button_5 = 7;                             // button scan down at Pin 7
    int buttonState_1 = 0;
    int buttonState_2 = 0;
    int buttonState_3 = 0;
    int buttonState_4 = 0;
    int buttonState_5 = 0;
    int flag = 0;                                 // used for decission to show "Station Name" or "scan mode"
    int stationNr = 0;
    int fmFreq[10] = {8760, 8820, 9100, 9350, 9500, 10030, 10080, 10280, 10330, 10480};
    char* fmName[10] = {"   NDR 1 MV", "   NDR Kultur", "   NDR 1 MV", "   NDR 2 MV", 
                       "     N-JOY", "Deutschlandfunk", "  Antenne MV", "   NDR Info", 
                        "Radio Paradiso", "  Ostseewelle"};
    char vol[2];
    float volts;
    char akku[4];
    
    long readVcc() {
      long result;
                                                 // Read 1.1V reference against AVcc
      ADMUX = _BV(REFS0) | _BV(MUX3) 
                  | _BV(MUX2) | _BV(MUX1);
      delay(2);                                  // Wait for Vref to settle
      ADCSRA |= _BV(ADSC);                       // Convert
      while (bit_is_set(ADCSRA,ADSC));
      result = ADCL;
      result |= ADCH<<8;
      result = 1126400L / result;                // Back-calculate AVcc in mV
      return result;
    }
    
    /******************************
     *           Setup            *
     *****************************/
    void setup() {
    
      radio.init();                               // initialize radio 
      
      radio.setBandFrequency(FIX_BAND, FIX_STATION);
      radio.setVolume(volume);
      radio.setMono(false);
      radio.setMute(false);
    
      pinMode(button_1, INPUT);                   // define button Pins
      pinMode(button_2, INPUT);                   // -||-
      pinMode(button_3, INPUT);                   // -||-
      pinMode(button_4, INPUT);                   // -||-
      pinMode(button_5, INPUT);                   // -||-
      digitalWrite(button_1, HIGH);               // button-Pin Pull-up
      digitalWrite(button_2, HIGH);               // -||-
      digitalWrite(button_3, HIGH);               // -||-
      digitalWrite(button_4, HIGH);               // -||-
      digitalWrite(button_5, HIGH);               // -||-
    } 
    
    /******************************
     * Subroutine Display on OLED *
     *****************************/
    void displayData()                           
      {
      volts = (float)readVcc()/(float)1000;       // read Vcc and divide by 1000
        
      char s[12];
      radio.formatFrequency(s, sizeof(s));        // format frequency value to output like: "87,60 MHz"
    
        u8g.firstPage(); 
        do {
        u8g.drawFrame(0,0,128,64);                // display frame around screen
        u8g.setFont(u8g_font_timB14);
        u8g.drawStr(15, 22, s);
        u8g.setFont(u8g_font_unifont);
        if(flag==0)
          {
          u8g.drawStr(4, 44, fmName[stationNr]);  // if fequency from array, take name from array too
          }
        if(flag==1)
         {
          u8g.drawStr(25, 44, "scan mode");       // if frequency from scan, show "scan mode"
         }
    
        if(volts > 3.3)                           // if Vcc > 3.3V display "Volume" & "Volt"       
            {
            u8g.setFont(u8g_font_6x13);
            u8g.drawStr(6, 59,"Volume: ");                          
            sprintf (vol, "%d", volume);          // change int "volume" to char "vol"                 
            u8g.drawStr(50, 59, vol);
            u8g.drawStr(68, 59,"Bat:");
            dtostrf(volts, 2, 1, akku);           // change float "volts" to char "akku"  
            u8g.drawStr(94, 59,akku);
            u8g.drawStr(115, 59,"V");
            }
           else                                   // if VCC >= 3.3V display "CHARGE BATTERY"
           {
            u8g.drawStr(6, 59,"CHARGE BATTERY");
           }
          } 
         while( u8g.nextPage() );
      }
    
    /******************************
     *         Main Loop          *
     *****************************/
    void loop() 
      {
      buttonState_1 = digitalRead(button_1);
      buttonState_2 = digitalRead(button_2);
      buttonState_3 = digitalRead(button_3);
      buttonState_4 = digitalRead(button_4);
      buttonState_5 = digitalRead(button_5);
      
      if (buttonState_1 == LOW) 
        {
          volume ++;
          if (volume == 16) volume = 15;
          radio.setVolume(volume);
          delay(100);
         } 
         
      else if (buttonState_2 == LOW) 
        {
          volume --;
          if (volume < 0) volume = 0;
          radio.setVolume(volume);
          delay(100);
          } 
          
      else if (buttonState_3 == LOW)
        {
          stationNr ++;
          if (stationNr == 10) stationNr = 0;
          radio.setFrequency(fmFreq[stationNr]);
          flag = 0;
          delay(500);
          }
          
      else if (buttonState_4 == LOW)
        {
          radio.seekUp();
          flag = 1;
          delay(500);
          }
    
      else if (buttonState_5 == LOW)
        {
          radio.seekDown();
          flag = 1;
          delay(500);
          }   
      else displayData();
     }
    Geändert von HaWe (17.02.2018 um 12:06 Uhr) Grund: code verschönert
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  3. #13
    Erfahrener Benutzer Fleißiges Mitglied Avatar von basteluwe
    Registriert seit
    15.11.2012
    Beiträge
    100
    Zitat Zitat von HaWe Beitrag anzeigen
    Aber mal eine ganz andere Frage :
    Wo in deinem Sketch (void setup() ) startest du denn überhaupt Wire mit Wire.begin() - irgendwie sehe ich es nicht....?
    Du hast Recht, den Befehl Wire.begin() gibt es bei mir bisher nicht. Wenn das ein Fehler ist, muß ich das ggf. ändern.
    Allerdings hab ich mich beim Aufbau des Code an ein Beispiel aus der originalen "radio.h" Library angelehnt.
    Siehe hier:
    Code:
    #include <Wire.h>
    #include <radio.h>
    #include <SI4703.h>
    
    #include <RDSParser.h>
    
    SI4703   radio;    ///< Create an instance of a SI4703 chip radio.
    
    
    RDSParser rds;    /// get a RDS parser
    
    
    /// 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);
    }
    
    
    
    
    
    /// 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, 8760);
    
      // delay(100);
    
      radio.setMono(false);
      radio.setMute(false);
      // radio.debugRegisters();
      radio.setVolume(8);
    
      Serial.write('>');
    
      state = STATE_PARSECOMMAND;
    
      // setup the information chain for RDS data.
      radio.attachReceiveRDS(RDS_process);
      rds.attachServicenNameCallback(DisplayServiceName);
    
    } // 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;
      
    
    
      // 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.
    Dort gibt es den Befehl auch nicht. Da es beim Kompilieren keine Probleme gab habe ich vermutet, das die Library "radio.h" das implementiert hat. Eventuell passiert das im Befehl "radio.init()" im Setup?
    Ich meine auch andere Beispiele gesehen zu haben, wo das mit dem fehlenden Wire.begin() so ist!?

    Gruß Uwe
    Geändert von basteluwe (17.02.2018 um 13:04 Uhr)

  4. #14
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.915
    ja, du hast Recht, es kann sein dass der Befehl in einer der Libs versteckt ist, wenn du eine Klasse initialisierst.
    Kann dann aber auch passieren, dass eine andere Klasse nicht korrekt initialisiert und gestartet wird.

    Ich schreib Wire.begin() allerdings immer bei mir als allerersten Wire-Befehl in setup() rein, dann läuft nichts falsch.

    Was machen deine I2C ioerr Fehler ?
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  5. #15
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.927
    ich finde bare-metal-C-Tipps zu Arduino C++ Klassen wie Wire auch nicht so hilfreich
    Da hast Du natürlich recht.
    Aber es geht hier ja um mal einzugrenzen wo der Fehler liegt.
    Wie man das dann bei ARDUINO umsetzt ist wieder eine ganz andere Sache.

  6. #16
    Erfahrener Benutzer Fleißiges Mitglied Avatar von basteluwe
    Registriert seit
    15.11.2012
    Beiträge
    100
    Zitat Zitat von HaWe Beitrag anzeigen
    Ich schreib Wire.begin() allerdings immer bei mir als allerersten Wire-Befehl in setup() rein, dann läuft nichts falsch.
    Das scheint logisch. Kann das aber keine Konflikte geben, wenn der Befehl aus den Libraries dann auch aufgerufen wird?

    Zitat Zitat von HaWe Beitrag anzeigen
    Was machen deine I2C ioerr Fehler ?
    Gute Frage! Ich habe subjektiv den Eindruck, sie sind weniger geworden. Im Moment läuft er gerade seit ca. 15min OK. Ich gebe jetzt parallel zur OLED die Daten auch auf dem seriellen Terminal aus. Falls er sich wieder aufhängt, hoffe ich so zu sehen, ob die eigentliche Steuer und Anzeigeroutine trotzdem noch geht und "NUR" der I2C spinnt. Im schlimmsten Fall ist der Si4703 defekt. Das wäre Mist, weil schon endgültig eingebaut. Austausch wäre ein Albtraum!

    So! Gerade hat er sich wieder aufgehängt und natürlich bleibt auch die Anzeige im seriellen Monitor komplett stecken! Es geht also NICHTS mehr.
    Was ein Mist!

    Gruß Uwe

  7. #17
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.915
    Zitat Zitat von basteluwe Beitrag anzeigen
    Das scheint logisch. Kann das aber keine Konflikte geben, wenn der Befehl aus den Libraries dann auch aufgerufen wird?
    nein, das gibt keine Konflikte: Wire wird immer mit den gerade aktuellen settings gestartet, anfangs eben mit den defaults.
    Ändert dann eine andere Funktion die Wire-settings nachträglich und startet Wire.begin() erneut, gelten ab dann die neuen settings.

    Wenn du also sicher bist, was deine 1. Wire-Device lib macht, kannst du ggf. darauf verzichten, aber wenn du z.B. erst ein OLED oder einen Portmuxer initialisierst, und dann erst dein Radio, kann es schief laufen. Daher macht es Sinn, anfangs Wire.begin() zu schreiben, um sicher zu gehen, denn schaden tut es ja nicht.

    Tipp:
    füge vor alle i2c-Befehle also den ping-Befehl ein, um deinen I2C Bus zu testen.

    Passieren viele Fehler, überprüfe deine Kabel und Steckbretter.
    Sind alles Kabel ok, füge mal je ein delay(1); zwischen alle Wire-Befehle ein.
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  8. #18
    Erfahrener Benutzer Fleißiges Mitglied Avatar von basteluwe
    Registriert seit
    15.11.2012
    Beiträge
    100
    Zitat Zitat von HaWe Beitrag anzeigen
    Daher macht es Sinn, anfangs Wire.begin() zu schreiben, um sicher zu gehen, denn schaden tut es ja nicht.
    Ich bin nicht sicher, das das beim Si4703 so funktioniert, weil der I2C offensichtlich nicht schon nach Einschalten aktiv ist. Ich hatte an der Hardware einen I2C-scanner laufen lassen. Der hat nur das OLED (0x3C) gefunden, nicht aber den Si4703 (0x10). Erst als ich in den Scaner-Code auch die library und den Befehl "radio.init();" eingefügt habe, hat er beide Adressen gefunden.
    Ich denke daher, das in diesem speziellen Fall Wire.begin() am Anfang nichts bringt, weil ja der Si4703 nicht aktiv ist, oder?

    Jetzt gerade versuche ich mal eine andere Sache. Bisher rattert die main loop ständig vor sich hin und bei jedem Durchlauf wird die komplette Anzeige Subroutine aufgerufen. Ich denke, das ist Unfug. Ich werde den Aufruf mit timer steuern (millis) bzw. nur jeweils nach einer Tasten-Eingabe abrufen. Das sollte den Verkehr auf I2C massiv reduzieren, oder nicht? Vielleicht bring das ja was.

    Gruß Uwe

  9. #19
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    09.10.2014
    Beiträge
    2.915
    Zitat Zitat von basteluwe Beitrag anzeigen
    Ich bin nicht sicher, das das beim Si4703 so funktioniert, weil der I2C offensichtlich nicht schon nach Einschalten aktiv ist. Ich hatte an der Hardware einen I2C-scanner laufen lassen. Der hat nur das OLED (0x3C) gefunden, nicht aber den Si4703 (0x10). Erst als ich in den Scaner-Code auch die library und den Befehl "radio.init();" eingefügt habe, hat er beide Adressen gefunden.
    Ich denke daher, das in diesem speziellen Fall Wire.begin() am Anfang nichts bringt, weil ja der Si4703 nicht aktiv ist, oder?
    stimmt, aber schaden tut es ja auch nicht. Wäre nur möglicherweise der Fall, falls du andere I2C Geräte vorher lädst, wie ein OLED etc.
    Wenn du also nicht wirklich genau weißt, was deine Libs im Einzelnen machen, ist ein Wire.begin() am Anfang niemals falsch, insbesondere dann, wenn du irgendwelche "Hänger" bei deinem Busbetrieb beobachtest.

    Das sollte den Verkehr auf I2C massiv reduzieren, oder nicht? Vielleicht bring das ja was.
    stimmt, genau deshalb habe ich oben ja auch mindestens die delay(1) zwischen allen i2c-Bus-Zugiffen vorgeschlagen.

    Bei anspruchsvolleren Controllern (ARM) verwende ich genau deshalb auch immer Multithreading mit einem extra (langsamen) Thread nur für die Anzeige.


    PS:
    und vor blindem Herumprobieren ist es ntl immer gut, exakte Daten zu haben, daher pinge doch mal deine geräte kurz vorher an, wie ich oben beschrieben habe, bevor du sie ausliest und Daten schreibst, nur so wirst du wissen, wo und wann etwas nicht richtig funktioniert.
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  10. #20
    Erfahrener Benutzer Fleißiges Mitglied Avatar von basteluwe
    Registriert seit
    15.11.2012
    Beiträge
    100
    Zitat Zitat von HaWe Beitrag anzeigen
    daher pinge doch mal deine geräte kurz vorher an, wie ich oben beschrieben habe, bevor du sie ausliest und Daten schreibst, nur so wirst du wissen, wo und wann etwas nicht richtig funktioniert.
    Das "Anpingen" würde ich ja gern probieren, nur wie macht man das? Unwissenheit kann nerven, ich weiß!
    Gibt es einen Befehl in der Wire-Library (keinen gefunden), oder muß man das jeweils handisch coden, ähnlich wie im I2C-Scanner Code?

    Gruß Uwe

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Ähnliche Themen

  1. Unit 1.2 hängt sich auf
    Von Billy51 im Forum Open Source Software Projekte
    Antworten: 0
    Letzter Beitrag: 06.03.2011, 12:52
  2. Timer hängt sich auf?
    Von Ineedhelp im Forum C - Programmierung (GCC u.a.)
    Antworten: 15
    Letzter Beitrag: 22.08.2008, 16:49
  3. Programm hängt sich auf
    Von martin66119 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 07.10.2007, 21:06
  4. LCD hängt sich auf
    Von hotijack im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 30.05.2007, 16:47
  5. Lade Programm geht nicht (hängt sich auf)
    Von REX im Forum Robby CCRP5
    Antworten: 1
    Letzter Beitrag: 11.09.2004, 04:19

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •