PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : FM-Radio mit Arduino Pro Mini und Si4703 - Programm hängt sich auf!



basteluwe
13.02.2018, 09:29
Hallo Leute,
ich betreibe ein SI4703 breakout an einem Pro-Mini. Gesteuert wird mit 5 Tastern.
2x Volume +/-
1x Wechsel zu nächster Station (10 Stationen voreingestellt)
2x +/- Scan zu nächster auffindbarer Station
KEINE RDS-Auswertung.
Die Anzeige der Daten erfolgt auf OLED 128x64.

/************************************************** ************************
* 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/tinkerit/wikis/SecretVoltmeter.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();
}
Prinzipiell funktioniert alles prima, nur leider friert das Ding immer mal wieder ein!
Das kann schon Sekunden nach dem Start passieren, manchmal aber auch erst nach längerer Zeit.
Ich bin nicht sicher, ob der Sketch auf dem Arduino einfriert oder ob es der SI4703 ist. Eigentlich glaube ich eher an ein Problem mit dem Sketch, weil dann auch die Anzeigewerte nicht mehr richtig reagieren, wenn ich auf Taster drücke. Andererseits habe ich manchmal den Eindruck, das das Einfrieren durch Bewegung in der Nähe der Antenne getriggert wird. Das würde für mich eher auf ein Problem mit dem SI4703 deuten. Ich habe versuchsweise die Anzeigeroutine auskommentiert. Das hat nichts gebracht.
Hier noch die Schaltung, falls das wichtig ist:
33275
Irgendwelche Ideen warum das Ding einfriert?

Gruß Uwe

wkrug
14.02.2018, 07:35
Ob es am Controller oder der Peripherie liegt lässt sich relativ einfach feststellen.
Aktiviere den Watchdog Timer des Controllers und mach im Main Loop den WDR ( Watchdog Reset ) befehl rein.
Bleibt die Peripherie hängen, wird der Controller nicht resettet und der Fehler wird wie beschrieben auftreten.

Liegt der Fehler im Controller wird der Watchdog zuschlagen und den Controller resetten.

Ein möglicher Fehler wäre z.B. das der Controller in einer Subroutine auf irgendwas wartet, das dann nicht kommt ( Quittung vom I²C z.B. ).
Oder ein IC blockiert den I²C Bus.
Das könnte man so lösen, das man da, wo eine Quittung erwartet wird einen Timer aktiviert.
Wenn das Ganze zu lange dauert die Subroutine abgebrochen wird und an die aufrufende Routine eine negative Quittung zurück gegeben wird.
Dort kann man dann eine Fehlerbehandlung durchführen.

basteluwe
14.02.2018, 08:19
Vielen Dank für die Antwort


Liegt der Fehler im Controller wird der Watchdog zuschlagen und den Controller resetten.

Das bedeutet sicher, falls der Watchdog zuschlägt, beginnt das Programm wieder bei 0, also mit den voreingestellten Variablen aus dem Setup?

Gruß Uwe

sast
14.02.2018, 11:13
I2C hat PullUps?

sast

wkrug
14.02.2018, 12:01
Das bedeutet sicher, falls der Watchdog zuschlägt, beginnt das Programm wieder bei 0, also mit den voreingestellten Variablen aus dem Setup?
So ist es.
Allerdings sollte im Programm die Peripherie dann Resettet werden.
Über ein Register ( MCUSR ) kann man feststellen, durch was der Reset ausgelöst wurde und dementsprechend die Initialisierungen anpassen.
Die Pullups für I²C gehören natürlich auch mit rein.

basteluwe
14.02.2018, 15:52
Die Pullups für I²C gehören natürlich auch mit rein.

Wenn mit den Pullups externe Widerstände an A4 und A5 (SDA & SCL) des Arduino gemeint sind, dann gibt es die bisher bei mir nicht! Die Schaltung im ersten Post zeigt die aktuelle Situation.
Ich lese, daß bei 5V Vcc 4,7k als Pullup OK sind. Ich habe ja aber nur die 3,3V Version. Dann sollte wohl 3,3kOhm besser sein, oder?


Gruß Uwe

oberallgeier
14.02.2018, 16:48
.. externe Widerstände an A4 und A5 (SDA & SCL) .. gibt es die bisher bei mir nicht .. bei 5V Vcc 4,7k .. die 3,3V Version .. 3,3kOhm besser sein, oder ..Wie fast immer hilft ein passendes Datenblatt. Beispielsweise dies hier (http://www.csd.uoc.gr/~hy428/reading/i2c_spec.pdf), auf Seite 42. Anmerkung: ich habe bei 1,5 m (ein + einhalb Meter) Leitungslänge zu vier Slaves sogar 1,1 kΩ. Ausserdem hilft auch ein Oszilloskop und die kritische Betrachtung der Peaks - oder Nicht-Peaks *gg* bei der jeweils eingestellten Übertragungsrate (kann man die I²C-Frequenz bei arduion denn überhaupt festlegen?).

HaWe
14.02.2018, 18:53
Wie fast immer hilft ein passendes Datenblatt. Beispielsweise dies hier (http://www.csd.uoc.gr/~hy428/reading/i2c_spec.pdf), auf Seite 42. Anmerkung: ich habe bei 1,5 m (ein + einhalb Meter) Leitungslänge zu vier Slaves sogar 1,1 kΩ. Ausserdem hilft auch ein Oszilloskop und die kritische Betrachtung der Peaks - oder Nicht-Peaks *gg* bei der jeweils eingestellten Übertragungsrate (kann man die I²C-Frequenz bei arduion denn überhaupt festlegen?).

Die Arduinos funktionieren im Allgemeinen perfekt mit Pullups zwischen 1,4k bis 10kOhm.
Der ArduinoMega (5V) hat z.B. 10k Pullups fest eingebaut, der Arduino Due (3.3V) 1,47 k; beide funktionieren für i2c clock von 100kHz bis 1MHz
Zum Vergleich:
Der Raspberry Pi (3.3V) hat fest eingebaute Pullups von 1.8k, ebenfalls für i2c clock von 100kHz bis 1MHz (ggf. sogar noch schneller, nicht getestet)

2.2k bis 4.7k sind also sicher immer ein guter Mittelwert.

basteluwe
15.02.2018, 16:26
Danke für eure Antworten soweit.
Ich habe jetzt nacheinander zwei Dinge getan:
zuerst habe ich den Watchdog aktiviert (hoffentlich richtig?):

#include <avr/wdt.h> (ganz oben im Code)
wdt_enable(WDTO_1S); (im Setup)
wdt_reset(); (als letztes in der Hauptschleife)

Trotzdem ist der Fehler wieder aufgetreten, ohne das der Watchdog reagiert hätte. Es hat also keinen Reset vom Watchdog gegeben. Das Ding friert einfach ein und gut ist.

Danach hab ich 1,8k Pullups am I2C eingelötet. Leider hat auch das den Fehler nicht beseitigt! Auch danach ist er schon wieder 1x hängen geblieben!
Ich bin also wieder am Anfang!

Wat nu???

wkrug
16.02.2018, 17:52
Dann würd ich mal sagen, blockiert einer der Chips den I²C bus.
Oder ein Chip selber hängt sich auf.
Da war mal hier ein Threat drin, bei dem das gleiche passiert ist.
Schau mal im aufgehangenen Zustand, welche Pegel am I²C Bus anliegen.
Die Lösung war, wenn ich richtig bin, 8 bzw. 9 Clock Impulse auf SCL zu legen, aber lies Sicherheitshalber noch mal nach.

basteluwe
17.02.2018, 11:22
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 (https://www.roboternetz.de/community/threads/71551-Sensoren-blockieren-I2C-Bus?highlight=i2c+blockiert) 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

HaWe
17.02.2018, 11:48
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:


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....?



/************************************************** ************************
* 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/tinkerit/wikis/SecretVoltmeter.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();
}

basteluwe
17.02.2018, 12:49
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:

#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

HaWe
17.02.2018, 13:02
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 ?

wkrug
17.02.2018, 17:19
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.

basteluwe
17.02.2018, 17:48
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?



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

HaWe
17.02.2018, 19:05
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.

basteluwe
18.02.2018, 08:40
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

HaWe
18.02.2018, 09:14
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.

basteluwe
18.02.2018, 10:18
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

HaWe
18.02.2018, 10:33
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

habe ich doch oben geschrieben!

vor jedem einzelnen Geräte-Zugriff (Radio, OLED, was auch immer) IMMER zwischendurch diesen Code einfügen:

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);
}

am besten sogar noch mit Debug-Zusätzen wie
Serial.println("vor Lautstärke:");
...
Serial.println("vor Sender:");
...
Serial.println("vor RDS:");
...
Serial.println("vor OLED print:");
...
usw usf

Für addr musst du ntl dort jeweils die exakte i2c-Geräteadresse einsetzen (z.B. wenn OLED die Adresse 0x3c hat, dann jeweils vor OLED-Zugriff):


int addr=0x3c; // für OLED
Wire.beginTransmission(addr); // transmit to device I2C addr
int ioerr=Wire.endTransmission();
if(ioerr) { // Ausgabe eines Fehlers samt i2c-addr.
Serial.println("vor OLED print:");
Serial.print("Fehler bei addr 0x");
if (addr<16) { Serial.print("0"); }
Serial.print(addr,HEX);
Serial.print(" ioerr=");
Serial.println(ioerr);
}


PS:
für diesen Code-Block kannst du ntl auch eine eigene Debug-Funktion spendieren


void i2c_debug(int addr, char * message) {
Wire.beginTransmission(addr); // transmit to device I2C addr
int ioerr=Wire.endTransmission();
if(ioerr) { // Ausgabe eines Fehlers samt i2c-addr.
Serial.println(message);
Serial.print("Fehler bei addr 0x");
if (addr<16) { Serial.print("0"); }
Serial.print(addr,HEX);
Serial.print(" ioerr=");
Serial.println(ioerr);
}
}

Aufruf dieser Funktion ist dann ja wohl trivial ;)

basteluwe
18.02.2018, 12:39
habe ich doch oben geschrieben!

Mist! Wer lesen kann hat tatsächlich Vorteile!
Tut mir leid, das hab ich im ganzen Frust irgendwie ausgeblendet, werde ich aber natürlich nun versuchen.

Seit ich die Anzeigeroutine aus der main-loop nur noch alle 5 Sekunden aufrufe oder auch nach Änderungen durch Tastendruck, hat das Script sich bisher noch nicht wieder aufgehängt!
Ist aber sicher noch zu früh, sich zu freuen.

Gruß und einen schönen Restsonntag,
Uwe

basteluwe
18.02.2018, 15:57
Ist aber sicher noch zu früh, sich zu freuen.

Wenn man es beschreit!!! :mad:
Na klar blockiert er immer noch! Subjektiv ist es zwar seltener geworden aber er spinnt nach wie vor von Zeit zu Zeit.
Den I2C-check hab ich jetzt wie vorgeschlagen eingebaut aber auch der hat nichts angezeigt. Der Hänger passiert ja immer aus heiterem Himmel OHNE irgendwelche Interaktion. Am I2C zum Si4703 bringt der wahrscheinlich in der Form sowieso nichts, der Bus wird dort aktuell nur zum Schreiben benutzt. Das heisst, beim Tastendruck wird zwar Volume oder Frequenz geändert. Ich lese aber vom Radio-Chip nichts aus! Also passiert dort I2C-mäßig nichts, wenn keine Taste gedrückt wird, richtig? Deshalb zeigt der Checker dort auch keinen Fehler.
Auch am Beginn der OLED-Printfunktion habe ich den I2C-Checker drin, ohne Erfolg! Keine Fehlermeldung trotz Hänger!

Langsam fange ich an, an einen Hardware-Bug des Si4703 zu glauben. Komisch ist nämlich, das der Hänger mehrfach aufgetreten ist, wenn ich mich in der unmittelbaren Nähe des Geräts bewegt habe. Andererseits lässt sich auch DAS nicht reproduzieren. Vielleicht bestelle ich mir doch noch einen Ersatz und tausche noch mal.

Gruß Uwe

HaWe
18.02.2018, 16:12
am i2c-check siehst du genau, welcher Zugriff als letzter noch korrekt funktioniert hat und wann ggf. danach ein fehlerhafter Zugriff passiert ist.
Der serielle Monitor muss ntl dabei auch immer ständig mitlaufen, aber das wird ja wohl klar sein ;)

basteluwe
20.02.2018, 08:29
am i2c-check siehst du genau, welcher Zugriff als letzter noch korrekt funktioniert hat und wann ggf. danach ein fehlerhafter Zugriff passiert ist.

Genau DAS funktioniert so nicht!
Ich erklärs nochmal am Beispiel des Si4703 (den OLED lass ich jetzt mal aussen vor):
Der I2C zugriff erfolgt NUR wenn ich eine Taste drücke. Und auch nur dann wird der I2C gecheckt. Das Aufhängen tritt aber nie beim Tastendruck auf, sondern IMMER wenn das Ding eigentlich nur einfach so vor sich hin spielt. Genau dann läuft aber ja der Checker NICHT!
Also wird auch nichts angezeigt.
Der Serielle Monitor läuft natürlich immer mit!

Gruß Uwe

HaWe
20.02.2018, 08:48
ach so, OK.
Läuft denn auch kein OLED und nichts anderes auf dem i2c Bus?
wie könnte ansonsten der i2c Bus blockieren, wenn niemand drauf ist?
Aber was wäre dann im Zweifelsfall, wenn du immer einmal pro loop alle i2c Geräte nacheinander durchpingst, egal ob eine Taste gedrückt wurde?
Oder ist es gar nicht der Bus, der blockiert?

basteluwe
20.02.2018, 17:24
ach so, OK.
Aber was wäre dann im Zweifelsfall, wenn du immer einmal pro loop alle i2c Geräte nacheinander durchpingst...
Ach Mensch! Nun hab ich aber richtig in die Ka..e gegriffen! Was ähnliches als das, was du hier oben vorschlägst, hatte ich nämlich gerade schon selbst versucht und es ist gründlich schief gegangen!
Nun hab ich wohl den Arduino zerschossen!
Ich hatte versucht, in die Loop den normalen I2C-Scanner zu integrieren (nicht den Checker von Dir!).
Dabei hab ich wohl im Code gründlich Mist gebaut. Es wurde aber kein Compilerfehler angezeigt. Nach dem Upload lief jedenfalls gar nichts mehr! Egal dachte ich, dann kommt eben erst mal der normale Code wieder drauf = DENKSTE! Geht nicht mehr!!
Ich kann nun gar keinen Sketch mehr hochladen! Bekomme nur noch die berüchtigte Meldung:

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xb8
Wobei bei jedem Hochladeversuch die Hex-Adresse am Ende der Meldung eine andere ist. Und nein, ich habe nichts an den Einstellungen verändert. Scheint, als wenn der Arduino irgendwie das Hochladen blockiert.
Also hab ich jetzt erst mal ein noch größeres, hausgemachtes Problem zu lösen.

Gruß Uwe

basteluwe
12.03.2018, 10:22
Kurzes Update:
Den Arduino hatte ich wirklich getötet, er lässt sich nicht mehr programmieren. Gestern hab ich einen neuen eingebaut und der Hänger ist immer noch da! Inzwischen kann ich das "Aufhängen" auch provozieren: Beim Druck auf die Tasten "Scan-Up" oder "Scan-Down" hängt er sich nun sicher auf. Manchmal nicht beim ersten Druck aber beim 2. oder 3. passiert das sicher. Darüber hinaus hängt er auch immer wieder völlig ohne dass irgendwelche Aktionen von aussen passieren.
Ich habe in den Code am Anfang der Loop den I2C-Check für beide (OLED und Radio) eingebaut. Der läuft ohne Beanstandungen bis zum Aufhängen durch, dann stoppt die Schleife einfach OHNE irgendeinen I2C-Fehler zu zeigen. Nur zum Test habe ich falsche I2C-Adressen eingegeben, die er sofort als Fehler anzeigt. Der Checker funktioniert also.
Was ich auch nicht verstehe ist, warum der Watchdog nicht reagiert!? Ich hänge mal den kompletten Code in der letzten Variante hier ran. Im Moment warte ich auf zwei neue SI4703-Module aus China.
Was anderes, als auch das Radio-Modul zu wechseln, fällt mir nicht mehr ein, oder gibt es von euch noch Ideen?

P.S.
Eben habe ich mal ALLES was zum OLED gehört aus dem Code auskommentiert. Ich dachte, das vielleicht einfach Radio und OLED sich nicht mögen. Hat aber auch nichts gebracht. Auch wenn das Display praktisch nicht existiert und keine Anzeigeroutinen laufen, hängt sich der Code auf!


#include <Arduino.h>
#include <Wire.h>
#include <radio.h>
#include <si4703.h>
#include "U8glib.h"
#include <avr/wdt.h> // only needed for Watchdog

#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

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // define type of display (OLED 0.96" 128x64 pix)

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"};

unsigned long startMillis; // for timing display interval
unsigned long currentMillis; // -||-
const unsigned long period = 1000; // display interval = 1 second

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() {

wdt_enable(WDTO_1S); // enable Watchdog, set time to 1 second

radio.init(); // initialize radio

Wire.begin();
Serial.begin(9600);

startMillis = millis(); // start timer for display interval

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"

// begin debugging I2C failure
int addr=0x3c; // für OLED
Wire.beginTransmission(addr); // transmit to device I2C addr
int ioerr=Wire.endTransmission();
if(ioerr) { // Ausgabe eines Fehlers samt i2c-addr.
Serial.println("vor OLED print:");
Serial.print("Fehler bei addr 0x");
if (addr<16) { Serial.print("0"); }
Serial.print(addr,HEX);
Serial.print(" ioerr=");
Serial.println(ioerr);
}
// end debugging I2C failure

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()
{

// begin debugging I2C failure
Serial.println("Test läuft: ");
int addr=0x10; // für SI4703
Wire.beginTransmission(addr); // transmit to device I2C addr
int ioerr=Wire.endTransmission();
if(ioerr) { // Ausgabe eines Fehlers samt i2c-addr.
Serial.println("für SI4703 print:");
Serial.print("Fehler bei addr 0x");
if (addr<16) { Serial.print("0"); }
Serial.print(addr,HEX);
Serial.print(" ioerr=");
Serial.println(ioerr);
}

addr=0x3c; // für OLED
Wire.beginTransmission(addr); // transmit to device I2C addr
ioerr=Wire.endTransmission();
if(ioerr) { // Ausgabe eines Fehlers samt i2c-addr.
Serial.println("für OLED print:");
Serial.print("Fehler bei addr 0x");
if (addr<16) { Serial.print("0"); }
Serial.print(addr,HEX);
Serial.print(" ioerr=");
Serial.println(ioerr);
}
// end debugging I2C failure

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);
displayData();
}
else if (buttonState_2 == LOW)
{
volume --;
if (volume < 0) volume = 0;
radio.setVolume(volume);
delay(100);
displayData();
}
else if (buttonState_3 == LOW)
{
stationNr ++;
if (stationNr == 10) stationNr = 0;
radio.setFrequency(fmFreq[stationNr]);
flag = 0;
delay(500);
displayData();
}
else if (buttonState_4 == LOW)
{
radio.seekUp();
flag = 1;
delay(500);
displayData();
}
else if (buttonState_5 == LOW)
{
radio.seekDown();
flag = 1;
delay(500);
displayData();
}
else
{
currentMillis = millis(); // get the current "time" (number of milliseconds since the circle started)
if (currentMillis - startMillis >= period) // test whether the period has elapsed
{
displayData(); // call display routine
startMillis = currentMillis; // save new start time for next display circle
}
}
wdt_reset(); // reset Watchdog
}

HaWe
12.03.2018, 11:11
ich sehe keinen richtigen offensichtlichen Fehler, allerdings kommt mir deine Button-press-Abfrage etwas kritisch vor, was sich u.U. ungünstig während der Laufzeit auswirken könnte:
Denn du liest einen Buttondruck, ohne auf Loslassen zu warten:


if (buttonState_1 == LOW)
{
volume ++;
if (volume == 16) volume = 15;
radio.setVolume(volume);
delay(100);
displayData();
}
else if (buttonState_2 == LOW)
{
volume --;
if (volume < 0) volume = 0;
radio.setVolume(volume);
delay(100);
displayData();
}

ich mache das bei mir in solchen Fällen so:


// digitalRead(buttonPin_1); // button_pressed == LOW?
if(!digitalRead(buttonPin_1) ) {
while(!digitalRead(buttonPin_1) ) // wait for button_up == HIGH
{delay(10);}
// volume ++;
//...usw...
}

// digitalRead(buttonPin_2); // button_pressed == LOW?
if(!digitalRead(buttonPin_2) ) {
while(!digitalRead(buttonPin_2) ) // wait for button_up == HIGH
{delay(10);}
// volume --;
//...usw...
}


vlt wäre das ja mal einen Versuch wert....

basteluwe
12.03.2018, 12:32
Denn du liest einen Buttondruck, ohne auf Loslassen zu warten

Das ist richtig. Danke für den Hinweis. Das kannte ich so noch nicht, probiere es gleich aus.

Gruß Uwe

basteluwe
02.07.2018, 18:21
Nach längerer Zeit (andere Projekte) mal ein kurzes Update:
Ich habe einen Neuaufbau vorgenommen und auch neue Module zur Verfügung. Inzwischen vermute ich die Fehlerursache direkt in den Si4703 Modulen. Die Software als Ursache sehe ich im Moment nicht. Beide verfügbaren Module zeigen das gleiche Verhalten. Ich habe die Stromaufnahme der Schaltung und der einzelnen Module gemessen. Bei normaler Funktion ist der Gesamtstrom 32 mA. Wenn der Hänger passiert, geht der Strom auf 16 mA zurück. Der Hänger betrifft offensichtlich zuerst (oder nur) das Radiomodul, erst danach friert u.U. auch der Arduino ein (nicht immer). Das vermute ich, weil dann die Stromaufnahme des Si4703 von normal 17 mA auf 2 mA runter geht.

Zum Auslöser des Problems:
Ich kann inzwischen den Stop selber auslösen und zwar durch Berühren verschiedener Kontaktpunkte (besonders VCC oder auch GND) mit metallischen Gegenständen (Pinzette, Schraubendreher). Antippen der metallischen USB-Buche löst das schon aus. Spätestens beim zweiten oder dritten Antasten hängt er! Durch Druck auf Reset am Arduino lässt er sich meist wieder starten. Eine Watchdog-Routine im Program springt NICHT an! Die Programmschleife hängt also wohl nicht!
Eher selten stoppt er auch ohne direkte Berührung aber bei heftigen Bewegungen unmittelbar über der Schaltung. Das sieht für mich irgendwie nach statischen Problemen (Erdung o.ä.) aus.
Zusätzliche Kapazitäten (100nF + 100uF) direkt an VSS & GND des Si4703 haben nichts gebracht.

Irgendwelche Ideen? Bitte!!!

Gruß Uwe

wkrug
03.07.2018, 14:58
Eventuell bringen Dioden mit geringer Kapazität am Antenneneingang etwas?!
Scheint ja irgendwie ein Problem mit Statischer Aufladung zu sein.

basteluwe
04.07.2018, 08:34
Scheint ja irgendwie ein Problem mit Statischer Aufladung zu sein.

Ja irgend sowas vermute ich auch. Das Ding (Breadboard-Aufbau) hat eben 30 Minuten ohne Probleme neben mir auf dem Schreibtisch gestanden und gespielt. Dann bin ich vom Stuhl aufgestanden ohne es irgendwie zu berühren und prompt hat es blockiert!

Ich hänge mal einen Ausschnitt aus der Schaltung des Moduls hier dran.
33528
Da sieht man die Eingangsschaltung der Antenne. Mit Drossel gegen Masse und Kondensator zum RF-Eingang sieht das normal aus, denke ich. Ob Dioden da was bringen? Wenn ja, welche Typen wären geeignet? Vielleicht sollte ich das Modul metallisch abschirmen?

Gruß Uwe