millis() ZERSTÖRT das Ergebnis!

Naja, was heißt ZERSTÖRT?

Ich habe EINEN Aufbau und diesen mit millis() und mit delay() getestet.

Dazu nutze ich einen Arduino Pro Mini (8MHz) und ein Si470x Radio-Modul. Genauer gesagt ist es ein Si4703.

Ich möchte die einzelnen Radiofrequenzen “durchscannen”. Also es wird nach einer bestimmten Zeit die Frequenz gewechselt.
Da ich gerne noch nebenbei Tasten betätigen will, bietet sich millis() an. Ginge auch mit delay() aber da habe ich, je nach Delayzeit einen unschönen verlauf und man muss zur richtigen Zeit drücken etc.

Nutze ich also millis(), bekomme ich beim scannen Störgeräusche auf den Kopfhörer. Dieses habe ich beim nutzen von delay() nicht. Daher jetzt meine Frage - WORAN KANN DAS LIEGEN?

MIT millis()

#include <Arduino.h>
#include <Wire.h>
#include <radio.h>
#include <si4703.h>


const int resetPin = 2;
const int SDIO = A4;
const int SCLK = A5;


uint16_t Frequenz = 7600;
int Geschwindigkeit_Scan = 100;

SI4703 radio;

#define FIX_BAND     RADIO_BAND_FM 

#define FIX_VOLUME   15  


unsigned long lastMillis_scan;


void setup()
{
  radio.init();
  
  radio.setBandFrequency(FIX_BAND, Frequenz);
  radio.setVolume(FIX_VOLUME);
  radio.setMono(false);
  radio.setMute(false);

  lastMillis_scan = millis();
  
}

void loop() {
 

          if ((millis() - lastMillis_scan > Geschwindigkeit_Scan)) {
            
      
            radio.setBandFrequency(FIX_BAND, Frequenz);
            lastMillis_scan = millis();
            
            Frequenz = Frequenz + 10;
            if (Frequenz > 10800)  {
              Frequenz = 7600;
            }

            }

        }

MIT delay()

#include <Arduino.h>
#include <Wire.h>
#include <radio.h>
#include <si4703.h>

//Pins festlegen und benennen
const int resetPin = 2;
const int SDIO = A4;
const int SCLK = A5;


uint16_t Frequenz = 7600;
int Geschwindigkeit_Scan = 100;

SI4703 radio;

#define FIX_BAND     RADIO_BAND_FM 

#define FIX_VOLUME   15  


void setup()
{ 
  radio.init();
    
  radio.setBandFrequency(FIX_BAND, Frequenz);
  radio.setVolume(FIX_VOLUME);
  radio.setMono(false);
  radio.setMute(false);
   
}

void loop()
{


            Frequenz = Frequenz + 10;
            if (Frequenz > 10800)  {
              Frequenz = 7600;
            }
            
      radio.setBandFrequency(FIX_BAND, Frequenz);
      delay(100);
    
}

Alternativ habe ich das ganze mal mit einem eigenen Zähler (Variable die hochzählt) getestet also z.B. >> scantimer ++; <<
und dann wenn scantimer = die benötigte Zeit (Wert) ist geht der in ein IF rein jedoch läuft das total unrund und das Programm zählt nicht gleichmäßig. Mal geht es schneller und mal langsamer aber immerhin ohne Störgeräusche.

Hat jemand vielleicht eine Idee, warum millis() da so ein “quatsch” macht?
VIELEN DANK

Hallo,

ich hätte da erstmal nur eine Vermutung. millis arbeitet mit Timer und Interrupt. Immer wenn millis ausgelesen wird werden immer kurzzeitig die Interrupts gesperrt. Das wirkt sich auf andere Interrupts aus, die dann paar Takte verzögert abgearbeitet werden. Wenn die radio Lib mittels anderen Timer einen Ton erzeugt könnte sich das gegenseitig stören. Vielleicht hilft schon statt ständig millis erneut abzufragen dieses nur einmal pro loop Umlauf in einer unsigned long Variablen zu speichern und diese dann für die restliche loop Verarbeitung zu nutzen. Dann werden die Interruptsperren reduziert. Und/oder du schaltest während der Frequenzänderung kurz "mute" ein.

Was macht das define?
define FIX_BAND RADIO_BAND_FM
Ich sehe keine Wertzuweisung?
Man sollte zusammen mit define FIX_VOLUME 15 passende Datentypen verwenden.
Das am Rande.

Kann es sein, dass

radio.setBandFrequency()

merkliche Zeit dauert?
Dann würde sich empfehlen, die Reihenfolge zu tauschen:

            lastMillis_scan = millis();
            radio.setBandFrequency(FIX_BAND, Frequenz);

Aber genauer betrachtet, ist Doc's Vorschlag erheblich besser.

Ich würde auch testen, was bei selteneren (oder ohne) Frequenz-Änderungen passiert.
Wenn ein simpler millis() - Aufruf dein Radio stört, sehe ich den Fehler übrigens eher in der radio Library. :wink:

Hi und vielen Dank für die schnelle Hilfe.

define FIX_BAND RADIO_BAND_FM

das nutzt eine Bibliothek um das Frequenzband zu bestimmen. Das taucht in der radio.h und
si4703.h auf.

void setBand(RADIO_BAND newBand);

////////////

enum RADIO_BAND {
RADIO_BAND_NONE = 0, ///< No band selected.

RADIO_BAND_FM = 1, ///< FM band 87.5 – 108 MHz (USA, Europe) selected.
RADIO_BAND_FMWORLD = 2, ///< FM band 76 – 108 MHz (Japan, Worldwide) selected.
RADIO_BAND_AM = 3, ///< AM band selected.
RADIO_BAND_KW = 4, ///< KW band selected.

RADIO_BAND_MAX = 4 ///< Maximal band enumeration value.
};

Original nutze ich auch eigentlich nicht define FIX_VOLUME 15 sondern ein uint8_t. Der Wert kann maximal 15 sein und sollte auch eigentlich dauerhaft so bleiben.
Im Programm mit Tastern kann ich starten und anhalten und schalte da dann noch immer die Lautstärke auf 0.

@Doc_Arduino.

Das hört sich sehr logisch an was du schreibst.
Wie genau würde ich das mit dem millis() nur einmal abfragen und speichern genau oder am besten machen?

Soll ich dann auch am besten noch wie michael_x schrieb, die Reihenfolge tauschen?
Vielleicht kannst du mir das mit dem loop und millis() etwas genauer schreiben? Das wäre super.

Zusätzlich schalte ich vor dem radio.setBandFrequency(FIX_BAND, Frequenz); auf MUTE und danach auf UNMUTE?

Wie genau würde ich das mit dem millis() nur einmal abfragen und speichern genau oder am besten machen?

void loop () {
   unsigned long zeit = millis();
       if (zeit - lastMillis_scan > Geschwindigkeit_Scan)) {
          lastMillis_scan=zeit;
           ...
       }
}

Aber, lass mal dein Radio einfach auf einer festen Frequenz laufen und höre, ob der dauernde millis() Aufruf an sich überhaupt das Problem ist.

Hey michael_x.

Danke für die schnelle Antwort. Das werde ich mal testen.

Werde auch noch mal gucken, dass ich eine andere Radio Library finde. Hattest du ja auch erwähnt (sollte es durch millis() in Kombination passieren).

Also denkst du, dass man über MUTE am meisten erfolg haben kann?

Ich teste auch deinen Vorschlag mit der getauschten Reihenfolge.

ICH DANKE EUCH und werde über das Ergebnis berichten

SO!
Ich habe jetzt mehrere Varianten (9) ausprobiert und eine Aufnahme gemacht um es besser zu vergleichen.

Fakt ist: Die Variante mit delay() ist die Beste.

Aufgefallen ist, dass man über das setzten von MUTE viel an lauten Störgeräuschen verhindern kann. Ich habe MUTE an 3 verschiedenen Stellen getestet und überall wirkt es anders. INTERESSANT!

Ich habe aber auch das Gefühl, als wenn das Radio-Modul bei jedem Start anders reagiert. Wenn ein Programm mehrfach aufgenommen wird, sieht die Audioaufnahme trotzdem anders aus. Das ist komisch.

Das wechseln von lastMillis_scan = millis(); und radio.setBandFrequency(FIX_BAND, Frequenz); hatte keine hörbare Veränderung bewirkt

Am besten war die Aufnahme in der MUTE gesetzt wurde und millis() nur einmal abgefragt wurde. Jetzt werde ich weiter testen wo der MUTE am besten wirkt.

ICH DANKE EUCH und falls ihr noch weitere gute Ideen habt - immer her damit.

lass mal dein Radio einfach auf einer festen Frequenz laufen und höre, ob der dauernde millis() Aufruf an sich überhaupt das Problem ist

War das eine deiner Varianten?
Dann kannst du auch mal während des Radioempfangs einfach regelmäßig Serial.print("Irgendwas"); machen und beobachten, ob man das auch hört.

Nach diesem Beispiel scheint zumindest das zu funktionieren, jedenfalls mit der Sparkfun - Library.

Beim SI4703 findet die gesamte Audio-Verarbeitung im SI4703 statt. Auch die Kopfhörer sind direkt an diesem Chip angeschlossen. Der Arduino dient nur zur Einstellung des Chips ( Initiierung, Frequenzauswahl, Lautstärke ... ). Stellt man am SI4703 etwas um ( z.B. die Frequenz ), sollte man das Audio-Signal stummschalten ( soweit er das nicht alleine macht - sollte im DaBla stehen, ist schon 'ne Weile her, dass ich da was gemacht habe ).
Störungen vom Arduino können da allerdings schon 'reinspucken' - eine saubere Entkopplung der Versorgung ist Pflicht. Das wirkt sich aber eher nicht so aus wie beschrieben. Ist eher ein leises Summen und Zwitschern, dass dem Audiosignal überlagert ist.

Dann wäre noch die Frage, wie er verbunden ist. Der SI4703 hat ja 2 verschiedene Schnittstellen. Die I2C Schnittstelle ist m.M.n. suboptimal, da man da die Register nicht einzeln ansprechen kann ( wenn ich mich recht erinnere ... ). Ich hatte damals jedenfalls bewusst nicht die I2C-Schnittstelle sondern den 3-wire Mode genutzt um die REgister einzel ansprechen zu können.
Und Störungen bei der Verwendung von millis() gab's definitiv nicht.

Hallo MicroBahner.

Danke für deine Infos. Du scheinst da schon gut Erfahrung mit gemacht zu haben.

Also angeschlossen ist es über per Wire.h und SDIO / SCLK. Also das wird dann I²C sein.
So wie es auch beim Link von michael_x ist:

Das mit dem MUTE bringt viel Verbesserung.

Wie würde es denn per 3 Wire gehen? Das sagt mir so nix, kenne nur 2 Wire.

@michael_x - habe eine feste Frequenz getestet. Im Hintergrund wurde dauerhaft die millis() zeit geprüft. Hat man nichts gehört also das Signal wurde nicht beeinträchtigt.

WAMBO:
Wie würde es denn per 3 Wire gehen? Das sagt mir so nix, kenne nur 2 Wire.

Das ist eine proprietäre Schnittstelle des Chips. Ahnlich wie SPI, aber nicht ganz kompatibel. Ich habe das damals ( vor etwa 2 Jahren ) komplett selbst geschrieben, ohne eine Lib. Oder, besser gesagt, ich habe mir eine lib selbst geschrieben :wink: (Edit: Die Übertragung im 3-wire Mode ist auch wesentlich schneller als bei 2-wire)

Ich denke nicht, dass deine Probleme direkt mit den millis() zu tun haben, was ja auch dein letzter Test zeigt. Ich vermute, dass es das Timing ist, mit dem Du den chip beim Scannen ansprichst. Das ist sicher mit der delay-Version anders als mit millis. Und stören kannst Du ihn eigentlich nur, wenn Du ihn über die Schnittstelle ansprichst.

Also tut es dem Chip eigentlich nicht so gut, wenn man ihn regelmäßig anspricht?

Wie kann man denn das Timing verbessern wenn ich ihn, je Durchlauf, 1x auffordere die Frequenz zu ändern?

Was würdest du mir denn empfehlen bzw. gibt es eine Möglichkeit, dein Skript und deine Lib zu bekommen? Natürlich nicht gratis.

Danke und beste Grüße

Hallo,
jetzt habe ich mir das mal genauer angeschaut. Der Sinn des ganzen erschließt sich mir noch nicht.
Was willst Du damit bezwecken, im 100ms Takt den Empfangskanal zu wechseln, ohne zu prüfen, ob da überhaupt was empfangen wird?
Ausserdem startet RADIO_BAND_FM bei 8750 und nicht bei 7600. Es wäre auch besser, im Setup nur 1x das Empfangsband ( setBand(RADIO_BAND_FM) ) einzustellen, und dann nur die Frequenz mit setFrequency zu verändern. Schließlich bleibt das Band ja gleich, das musst Du nicht ständig mitschicken.

Meine Lib könnte ich dir natürlich zur Verfügung stellen. Aber ich habe die damals nicht mit dem Hintergedanken einer allgemein verwendbaren lib geschrieben. Deshalb gibt es auch keine Dokumentation ausser den Kommentaren im Code. Der Sketch selber wird dir vermutlich wenig helfen, da da eine sehr spezielle eigene HW zur Bedienung und Anzeige angesteuert wird.

Hallo,

mich wundert immer noch warum der Sketch mit delay keine Probleme macht.
Wenn das alles sowieso im Chip passiert wäre das noch seltsamer.
Die Änderungsgeschwindigkeit und Schnittstellenaktionen/Schnittstellenzugriff bleiben davon unberührt.
Alles aller x ms. Oder übersehe ich irgendwas?

Gefunden habe ich diese Lib. Ob das dein Problem behebt weiß ich allerdings nicht.
Github: Arduino Radio Library - The Library

Vielleicht ist ja die Lib von Microbahner noch besser ... ? :slight_smile:

Wenn eine von beiden Abhilfe schafft wäre schön, aber das mit delay vs. millis wundert mich dennoch.

WAMBO:
also das Signal wurde nicht [durch die millis() - Aufrufe] beeinträchtigt

Dann sind wir uns ja einig :slight_smile:
Könntest ja daraufhin den Titel deines ersten Beitrags aktualisieren.

Dass millis() vs. delay() über anderen Strombedarfsverlauf das Radio stört, wäre mir allerdings auch seltsam.

WAMBO:
Nutze ich also millis(), bekomme ich beim scannen Störgeräusche auf den Kopfhörer.

Kannst Du beschreiben was das für Störgeräusche sind? Offensichtlich hörst Du ja nicht wirklich einen Sender, denn Du bleibst ja bei keiner Frequenz stehen. D.h. Du hörst eigentlich nur Hintergrundgeräusche oder?


Edit: Ich hab' jetzt mal meine alte HW vorgekramt, und das Ganze nochmal ausprobiert. Bei mir war das für einen Nano vorgesehen. Also einen Nano draufgesteckt, Sketch aufgespielt - und läuft. Da sind auch keine Störungen zu hören, wenn man ein Radioprogramm anhört. Obwohl da einiges mit millis gemacht wird, und auch immer wieder der Chip angesprochen wird, um das RDS auszulesen ( allerdings nicht im 100ms-Takt ). Bei reinen Sprachbeiträgen und voll aufgedrehter Lautstärke hört man in den Sprechpausen ein gaaanz leises Summen. Man muss aber schon drauf achten, sonst fällt es nicht auf. Da dürfte nochwas vom Arduino reinstreuen. Der erzeugt ja auch einiges an Störungen/Frequenzen. Ist allerdings auch eine Frage, wie groß der Störabstand beim SI4703 überhaupt ist.

Was für ein Breakout-Board hast Du eigentlich ( bitte einen Link ) ?