Hallo Forum,
ich betreibe einen Uno R4 mit MPU6050 und einen Oled Display an einen I2C Bus.
Nach ca. 1 Stunde hängt sich der I2C Bus auf bzw. funktioniert nicht mehr.
Ein reset des Arduino hilft nichts, nur ein Stromlos machen startet alles neu und hilft.
Warum ist das so?
Hat das Problem noch jemand bzw. eine Lösung für mich?
#include <SPI.h>
#include <SD.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <MPU6050.h>
#include <U8g2lib.h>
// Pins für die SD-Karte
#define CHIP_SELECT 10 // Ändern Sie dies, wenn Sie einen anderen Pin verwenden
// Erstellen Sie Objekte für GPS und SD
TinyGPSPlus gps;
File logFile;
File config;
SoftwareSerial ss(8, 7);
const int schalterPin = 2;
int schalterZustand = 1;
const int ledPinFehler = 3;
const int ledPinOk = 4;
int gpsSignal = 0;
float latitude = 0;
float longitude = 0;
bool headerFirma = false;
bool headerPrivat= false;
bool stop = false;
const int threshold = 25000;
int bewegung = 0;
int zaehlerStopp = 0;
int stoppVerzoegerung = 60;
int zaehlerAzBeginn = 0;
int azBeginnVerzoegerung = 60;
unsigned long azTimeMillis = 0;
unsigned long azPerviousTimeMillis = 0;
float lastLat = 0.0, lastLon = 0.0; // Vorherige Koordinaten für die Berechnung der Entfernung
float totalDistance = 0.0; // Gesamte zurückgelegte Strecke
float totalDistanceAlt = 0.0;
unsigned long myTime = 0;
unsigned long myPreviousTime = 0;
const long interval = 3000; // 3000 Millisekunden = 3 Sekunden
int currentPage = 0;
bool startAz = false;
int azAufzeichnungGestartet = 0;
int startZeitStunde = 0;
int startZeitMinute = 0;
int endZeitStunde = 0;
int endZeitMinute = 0;
int arbeitsZeit = 0;
int arbeitsZeitVorher = 0;
int currentTimeHour = 0;
int currentTimeMinute = 0;
int currentDateYear = 0;
int currentDateMonth = 0;
int currentDateDay = 0;
const unsigned long RESET_INTERVAL = 300000; // 5 Minuten in Millisekunden
unsigned long lastResetTime = 0;
MPU6050 mpu;
U8G2_SH1106_128X64_NONAME_F_HW_I2C oled(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void setup() {
pinMode(10, OUTPUT);
pinMode(schalterPin, INPUT);
pinMode (ledPinFehler, OUTPUT);
pinMode (ledPinOk, OUTPUT);
digitalWrite (ledPinFehler, LOW);
digitalWrite (ledPinOk, LOW);
Serial.begin(9600);
Wire.begin();
mpu.initialize();
if (mpu.testConnection()) {
Serial.println("MPU-521 verbunden");
} else {
Serial.println("MPU-521 Verbindung fehlgeschlagen");
}
ss.begin(9600); // GPS Serial Port
// Initialisieren der SD-Karte
while (!SD.begin(CHIP_SELECT)) {
Serial.println("SD-Karte konnte nicht initialisiert werden!");
digitalWrite (ledPinFehler, HIGH);
}
readConfig();
stoppVerzoegerung = stoppVerzoegerung / 2;
Serial.println(stoppVerzoegerung);
Serial.println(azBeginnVerzoegerung);
// Erstellen oder Öffnen der GPS-Datei
while (!logFile) {
logFile = SD.open("log.txt", FILE_WRITE);
digitalWrite (ledPinFehler, HIGH);
}
digitalWrite (ledPinFehler, LOW);
oled.setBusClock(75000);
//Wire.setClock(75000);
if (!oled.begin()) {
Serial.println(F("OLED nicht gefunden"));
}
oled.clearBuffer();
oled.setFont(u8g2_font_t0_12b_tr) ; // choose a suitable font
oled.drawStr(27,10, "Hallo, Floki!");
oled.drawStr(8,20, "Der Logger sucht ein");
oled.drawStr(45,33, "Signal!");
oled.sendBuffer();
}
void loop() {
while (ss.available() > 0) {
unsigned long I2CMillis = millis();
if (I2CMillis - lastResetTime >= RESET_INTERVAL) {
// Wenn 5 Minuten vergangen sind, setze den I2C-Bus zurück
//i2c_reset();
lastResetTime = I2CMillis; // Setze den Zeitpunkt des letzten Resets
}
schalterZustand = digitalRead(schalterPin);
int16_t ax, ay, az;
mpu.getAcceleration(&ax, &ay, &az);
long acceleration = abs(ax) + abs(ay) + abs(az);
if (acceleration > threshold) {
bewegung = 1;
azTimeMillis = millis();
azPerviousTimeMillis = azTimeMillis;
} else {
bewegung = 0;
}
if (bewegung == 0 && startAz == false){
azTimeMillis = millis();
if (azTimeMillis - azPerviousTimeMillis >= (azBeginnVerzoegerung * 1000)) {
azPerviousTimeMillis = azTimeMillis; // Speichere den aktuellen Zeitpunkt
startAz = true;
Serial.println ("AZ Beginn");
}
}
if ((zaehlerStopp + 1 > stoppVerzoegerung) && (stop == false)){
digitalWrite (ledPinFehler, HIGH);
totalDistanceAlt = totalDistance;
headerFirma = false;
headerPrivat = false;
totalDistance = 0.0;
stop = true;
}
if (bewegung == 1){
digitalWrite (ledPinFehler, LOW);
zaehlerStopp = 0;
stop = false;
if (azAufzeichnungGestartet == 1){
arbeitsZeitVorher = arbeitsZeit;
}
arbeitsZeit = 0;
startAz = false;
azAufzeichnungGestartet = 0;
}
gps.encode(ss.read());
if(gps.location.isUpdated()){
gpsSignal = 1;
}
else{
gpsSignal = 0;
}
if(gpsSignal == 1){
currentTimeHour = gps.time.hour() ;
currentTimeMinute = gps.time.minute();
currentDateYear = gps.date.year();
currentDateMonth = gps.date.month();
currentDateDay = gps.date.day();
endZeitStunde = gps.time.hour();
endZeitMinute = gps.time.minute();
// GPS-Daten abrufen
latitude = gps.location.lat();
longitude = gps.location.lng();
if (startAz == true && azAufzeichnungGestartet == 0){
startZeitStunde = gps.time.hour();
startZeitMinute = gps.time.minute();
Serial.print(startZeitStunde);
Serial.print(startZeitMinute);
azAufzeichnungGestartet = 1;
}
printDisplay();
}
if (gpsSignal == 1 && (zaehlerStopp < stoppVerzoegerung) ) {
if (lastLat == 0){
lastLat = latitude;
lastLon = longitude;
}
// Berechnung der Strecke mit Haversine
float distance = haversine(lastLat, lastLon, latitude, longitude);
totalDistance += distance; // Gesamte zurückgelegte Strecke
// Aktualisiere lastLat und lastLon mit den aktuellen GPS-Werten
lastLat = latitude;
lastLon = longitude;
digitalWrite (ledPinOk, HIGH);
if (gps.date.day() < 1){
delay (2000);
}
else {
if(schalterZustand == 1){
if (!headerFirma){
logFile.println();
logFile.println();
logFile.print("Firma ");
logFile.print(gps.date.year());
logFile.print(".");
logFile.print(gps.date.month());
logFile.print(".");
logFile.print(gps.date.day());
logFile.print(", ");
logFile.print(" ");
logFile.print((gps.time.hour() + 1));
logFile.print(":");
logFile.print(gps.time.minute());
logFile.print(" ");
headerFirma = true;
headerPrivat = false;
}
}
else{
if (!headerPrivat){
logFile.println();
logFile.println();
logFile.print("Privat ");
logFile.print(gps.date.year());
logFile.print(".");
logFile.print(gps.date.month());
logFile.print(".");
logFile.print(gps.date.day());
logFile.print(", ");
logFile.print(" ");
logFile.print((gps.time.hour() + 1));
logFile.print(":");
logFile.print(gps.time.minute());
logFile.print(" ");
headerPrivat = true;
headerFirma = false;
}
}
// GPS-Tracelog schreiben
logFile.print(latitude, 6); // 6 Dezimalstellen
logFile.print(" ");
logFile.print(longitude, 6); // 6 Dezimalstellen
if ((logFile.print(", ")) < 1){
digitalWrite (ledPinFehler, HIGH);
}
// Daten im Serial Monitor ausgeben
Serial.print("Lat: ");
Serial.print(latitude, 6);
Serial.print(" Lon: ");
Serial.println(longitude, 6);
// Daten auf SD Karte schreiben
logFile.flush();
if (bewegung == 0){
zaehlerStopp = zaehlerStopp + 1;
}
Serial.println(zaehlerStopp);
delay(2000);
}
}
else{
digitalWrite (ledPinOk, LOW);
}
if(startAz == true){
arbeitsZeit = timeDifference (startZeitStunde, startZeitMinute, endZeitStunde, endZeitMinute);
}
}
}
float haversine(float lat1, float lon1, float lat2, float lon2) {
const float R = 6371.0; // Erdradius in km
float phi1 = toRadians(lat1);
float phi2 = toRadians(lat2);
float deltaPhi = toRadians(lat2 - lat1);
float deltaLambda = toRadians(lon2 - lon1);
float a = sin(deltaPhi / 2) * sin(deltaPhi / 2) +
cos(phi1) * cos(phi2) *
sin(deltaLambda / 2) * sin(deltaLambda / 2);
float c = 2 * atan2(sqrt(a), sqrt(1 - a));
return R * c; // Entfernung in km
}
// Hilfsfunktion, um Grad in Radiant zu konvertieren
float toRadians(float degrees) {
return degrees * 3.141592653589793 / 180.0;
}
void printDisplay (){
myTime = millis();
if (myTime - myPreviousTime >= interval) {
myPreviousTime = myTime; // Speichere den aktuellen Zeitpunkt
// Nächste Seite anzeigen
currentPage = (currentPage + 1) % 2; // Wechselt zwischen 0, 1 und 2
}
oled.clearBuffer();
switch (currentPage){
case 0:
oled.setFont(u8g2_font_t0_12b_tr) ;
oled.drawStr(27,10, "Hallo, Floki!");
oled.drawStr(12,23, "Signal gefunden");
oled.setCursor(0,36);
oled.print(currentTimeHour + 1);
oled.setCursor(12,36);
oled.print(":");
oled.setCursor(18,36);
oled.print(currentTimeMinute);
oled.setCursor(35,36);
oled.print(currentDateDay);
oled.setCursor(47,36);
oled.print(".");
oled.setCursor(53,36);
oled.print(currentDateMonth);
oled.setCursor(65,36);
oled.print(".");
oled.setCursor(71,36);
oled.print(currentDateYear);
oled.setCursor(0, 49);
oled.print("Strecke: ");
oled.print(totalDistance, 3);
oled.setCursor(0, 62);
oled.print("Strecke vorher: ");
oled.print(totalDistanceAlt, 3);
break;
case 1:
oled.setFont(u8g2_font_t0_16b_tr) ;
int differenzStunden = arbeitsZeit / 60;
int differenzRestMinuten = arbeitsZeit % 60;
int differenzStundenVorher = arbeitsZeitVorher / 60;
int differenzRestMinutenVorher = arbeitsZeitVorher % 60;
char azStunden[3];
sprintf(azStunden, "%02d", differenzStunden);
char azMinuten[3];
sprintf(azMinuten, "%02d", differenzRestMinuten);
char azStundenVorher[3];
sprintf(azStundenVorher, "%02d", differenzStundenVorher);
char azMinutenVorher[3];
sprintf(azMinutenVorher, "%02d", differenzRestMinutenVorher);
oled.setCursor(0, 18);
oled.print("AZ lfd: ");
oled.print(azStunden);
oled.print(":");
oled.print(azMinuten);
oled.setCursor(0, 36);
oled.print("AZ letzte: ");
oled.print(azStundenVorher);
oled.print(":");
oled.print(azMinutenVorher);
break;
}
oled.sendBuffer();
}
int timeDifference (int startHour, int startMinute, int endHour, int endMinute) {
int startInMinuten = startHour * 60 + startMinute;
int endInMinuten = endHour * 60 + endMinute;
int differenzInMinuten = 0;
// Berechnung der Differenz in Minuten
differenzInMinuten = endInMinuten - startInMinuten;
// Wenn die Differenz negativ ist (Endzeit liegt vor Startzeit), einen neuen Tag annehmen
if (differenzInMinuten < 0) {
differenzInMinuten += 24 * 60; // 24 Stunden in Minuten
}
return differenzInMinuten;
}
void readConfig (){
config = SD.open("config.txt");
if (!config) {
Serial.println("Fehler beim Öffnen der Config Datei.");
return;
}
String line = "";
while (config.available()) {
char c = config.read(); // Zeichenweise lesen
if (c == '\n' || c == '\r') {
// Wenn eine Zeile endet, prüfen, ob sie "Stoppzeit: " enthält
if (line.startsWith("Stoppzeit in Sekunden: ")) {
// Entferne "Zeit: " und konvertiere den restlichen Text in eine Zahl
String zahlString = line.substring(23); // Ab der 23. Position (nach "Zeit: ")
stoppVerzoegerung = zahlString.toInt(); // String in Integer umwandeln
// Verlasse die Schleife, nachdem die Zahl gefunden wurde
}
if (line.startsWith("Arbeitszeit Verzoegerung in Sekunden: ")) {
// Entferne "Zeit: " und konvertiere den restlichen Text in eine Zahl
String zahlStringAz = line.substring(38); // Ab der 38. Position (nach "Zeit: ")
azBeginnVerzoegerung = zahlStringAz.toInt(); // String in Integer umwandeln
break; // Verlasse die Schleife, nachdem die Zahl gefunden wurde
}
line = ""; // Leere die Zeile für die nächste Zeile
} else {
line += c; // Zeileninhalt aufbauen
}
}
config.close();
}
void i2c_reset() {
Wire.beginTransmission(0x68); // MPU 6050 Adresse
Wire.write(0x6B); // Power Management Register
Wire.write(0x40); // Versetzt den Sensor in den Schlafmodus
Wire.endTransmission();
Wire.end(); // Schließt die aktuelle I2C-Verbindung
delay(500); // Kurze Pause, um den Bus freizugeben
Wire.begin(); // Startet den I2C-Bus neu
Serial.println("I2C reset");
Wire.beginTransmission(0x68); // MPU 6050 Adresse
Wire.write(0x6B); // Power Management Register
Wire.write(0x00); // Aktiviert den Sensor
Wire.endTransmission();
}