Arduino hängt sich auf ? Try-catch ?

Hallo,

Ich bastel grad einen Quadcopter den ich mit einem Arduino uno steure. Ich lese nun Werte vom Magnetometer (10DOF modul) ein: MPU_mag.getMagData(magbuffer);

(die Library ist MPULib von Bluecopter bzw. Basel Al-Rudainy)

Wenn ich ein Kabel am Sensormodul lockere, hängt sich der Arduino auf, ich kann nichts mehr steuern, und die Motoren laufen weiter. Kabel wieder anstecken bringt dann auch nichts mehr.

Wie kann ich das verhindern ? Try-Catch gibt es ja in C nicht. Ist das vielleicht ein Fehler in der verlinkten Bibliothek ? Gibt es eine kompatible, die sich nicht aufhängt ?

[edit]

Falsch gelesen. Ist ein elektrisches Problem...

Nein, warum soll das ein Fehler der Libary sein, wenn du Sachen machst, die im Betrieb nicht gemacht werden.

Das gleiche tritt auch auf, wenn du zB ein LCD Display vom Steckbrett ziehst und dann wieder aufsetzt. Dann steht dort natürlich nichts mehr.

Ähnlich es es mit dem 10DOF. Wenn du ihn abziehst, an Kabeln wackelst, oder ähnliches, dann ist er danach nicht mehr initialisiert. Es kommen keine plausiblen Werte oder garkeine Werte an.

Das muss du selber abfangen in deiner Software.

Wüsste jetzt nicht wie ich die abfangen soll, wenn der Arduino keine einzige Codezeile mehr abarbeitet. Wie kann ich das debuggen ?

Der Watchdog Timer ist die Brachial-Option für sowas Der löst einen Reset aus wenn er nicht innerhalb eines bestimmten Zeitraums zurückgesetzt wird

Wenn es ein Arduino Mega ist sollte man da aber vorher sicherheitshalber einen aktuellen Bootloader aufspielen

Auf einem Quad-Copter ist das aber wohl auch nicht so gut, da der Bootloader eine Zeit lang braucht bis er durchläuft. Oder man macht in platt und programmiert den Arduino über SPI.

Besser: gar kein Bootloader. Dann ist eine Komponente weniger im System die Ärger machen kann. ISP kaufen und fertig.

ISP klingt interessant, aber ich möchte es gern mit dem Arduino machen.

Folgendes:

Serial.println("before");
  MPU_mag.getMagData(magbuffer);
  Serial.println("after getting data from mag");

füllt fleißig den Serial Monitor. Lockert sich das Kabel, ist die letzte Ausgabe immer "before". Es bleibt also bei dem getMagData hängen. Da kann ich auch keine Werte auf Korrektheit testen. Jemand ne Idee ?

Tja, dann ist die Funktion blockierend. Vielleicht gibts ja eine zweite, welche nicht blockiert. Oder du bastelst dir eine dran.

(bin gerade zu faul um die Lib zu untersuchen)

Könnte also doch an der Lib liegen.

Auszug:

void MPULib::getMagData(int buff[]){
   byte buffer[6];
   readCmd(HMC_addr,HMC_X_MSB,6,buffer);
   buff[0]=(buffer[0]<<8) | buffer[1];
   buff[2]=(buffer[2]<<8) | buffer[3];
   buff[1]=(buffer[4]<<8) | buffer[5];
}

Bin nicht so fit in Bitshifting… Blockiert der Code, wenn buffer nicht gefüllt wurde ? Oder könnte es schon bei readCmd hängen ?

Dieses blockiert!

while(Wire.available()<num);

Wenn du den Stecker ziehst werden kein Daten mehr kommen.

Ach! Na klar, "readCmd" ist auch ne Methode der Bibliothek !

Danke, ich werd da mal einen Timeout einbauen. :)

Habe mit “micros()” die Zeit gemessen. Im Schnitt immer um die 950 Microsekunden.
Daher jetzt einen Timeout auf 2000 (2 Millisekunden) gesetzt. 2ms stören nicht, da dann noch genug Rechenzeit für die übrigen Berechnungen zur Verfügung steht (pro Loop ca 15ms bei 60 Loops/Sekunde)

Es wird 0 zurückgegeben, wenn der Timeout überschritten wird. Steckt man das Kabel wieder an (Timeout wird plötzlich wieder eingehalten) läuft es ganz normal weiter und es kommen wieder Daten.

Falls es mal jemandem hilft, hier die modifizierte MPULip.cpp:

/*
	MODIFIED by Kai F., 04.02.2015. "while(Wire.available()<num);" blocks if cable not attatched (anymore). Fixed with timeout.
*/

/*
  Created by Basel Al-Rudainy, 6 april 2013.
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*/

#include "MPULib.h"
#include "Arduino.h"
#include "Wire.h"

unsigned long start, end, delta; //Kai

MPULib::MPULib()
{
	start = 0; //Kai
	end = 0; //Kai
	delta = 0; //Kai
}

void MPULib::init(){
Wire.begin(); 
//init - ADXL345
writeCmd(ADXL_addr,REG_DATA_FORMAT,0x0B); //+-16g
writeCmd(ADXL_addr,REG_PWR_CTL,0x08);  //measurement mode
writeCmd(ADXL_addr,REG_BW_RATE,0x09);  //REG_BW_RATE rate=50hz, bw=20hz
//1G = 265
//-----end init ADXL345

//init - L3G4200D
writeCmd(L3G4_addr,CTRL_REG1,L3G4_BW_ENAX);
writeCmd(L3G4_addr,CTRL_REG2,L3G4_LPF);
writeCmd(L3G4_addr,CTRL_REG4,MODE_2000);
writeCmd(L3G4_addr,CTRL_REG5,L3G4_HPF);
//-----end init L3G4200D

//init - HMC5883
writeCmd(HMC_addr,HMC_mode_reg,HMC_contm_val);
//-----end init HMC5883
}

void MPULib::getAxlData(int buff[]){
byte buffer[6];
readCmd(ADXL_addr,DATAX0,6,buffer);
buff[0]=(buffer[1]<<8) | buffer[0];
buff[1]=(buffer[3]<<8) | buffer[2];
buff[2]=(buffer[5]<<8) | buffer[4];

}

void MPULib::getGyroData(float buff[]){
byte buffer[6];
readCmd(L3G4_addr,READALLSIX,6,buffer);
buff[0]=(float)((int)(buffer[1]<<8) | buffer[0])*SCALE_2000;
buff[1]=(float)((int)(buffer[3]<<8) | buffer[2])*SCALE_2000;
buff[2]=(float)((int)(buffer[5]<<8) | buffer[4])*SCALE_2000;
}

void MPULib::getMagData(int buff[]){
byte buffer[6];
readCmd(HMC_addr,HMC_X_MSB,6,buffer);
buff[0]=(buffer[0]<<8) | buffer[1];
buff[2]=(buffer[2]<<8) | buffer[3];
buff[1]=(buffer[4]<<8) | buffer[5];
}

void MPULib::readCmd(byte addr,byte reg,byte num,byte buff[]){
start = micros();//Kai

  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(addr, num);
  while(Wire.available()<num && delta<2000){ // timeout nach 2000 micros - also //Kai
	end = micros();//Kai
	delta = end-start; //Kai
  };
  if(delta < 2000){ //Kai - alles normal
	for(byte i = 0;i<num;i++){
		buff[i] = Wire.read();
	}
  }else{ // kabel Locker? 0 senden.
	delta = 0;
	for(byte i = 0;i<num;i++){
		buff[i] = 0;
	}
  }
}

void MPULib::writeCmd(byte addr, byte reg, byte val){
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.write(val);
  Wire.endTransmission();
}

Glückwunsch!

Danke für die Hilfe :)