Go Down

Topic: Undefinierbare Ausgabe am seriellen Monitor nach einer bestimmten Zeit (Read 79 times) previous topic - next topic

DerPeter

Hallo,

Ich habe an einem Multiplexer verschiedene Sensoren angeschlossen. Diese sollen ausgelesen werden und an einen CAN-Bus weitergeleitet werden. Nebenbei sollen die Werte am PC einsehbar sein (Monitor). Bei einem Beschleunigungssensor soll zudem ein Min und Max ausgegeben werden.

Das Auslesen klappt auch ganz gut. Binde ich nun eine Berechnungsfunktion für das Min und Max ein, so verändert sich die Ausgabe nach einer Zeit zu undefinierten Zeichen

Während am Anfang der Code noch korrekt ausgegeben wird
Code: [Select]
21:55:52.409 -> Temperature in Celsius: 30.69
21:55:52.409 -> Humidity in %: 33.56
21:55:52.409 -> Pressure in hPa: 996.54
21:55:52.409 -> Altitude in Meters: 137.98
21:55:52.409 ->
21:55:52.443 -> SHT35_Front
21:55:52.443 -> Temperature in Celsius: 25.49
21:55:52.443 -> Humidity in %: 45.90
21:55:52.443 ->
21:55:52.443 -> SHT35_Side
21:55:52.443 -> Temperature in Celsius: 24.90
21:55:52.476 -> Humidity in %: 44.61
21:55:52.476 ->
21:55:52.476 -> SHT35_Door
21:55:52.476 -> Temperature in Celsius: 26.44
21:55:52.476 -> Humidity in %: 38.89
21:55:52.476 ->
21:55:52.476 -> Acceleration X: 0.00, Y: 45.36, Z: -37.34 m/s^2
21:55:52.476 -> Rotation X: 0.03, Y: 8.99, Z: 23.43 rad/s
21:55:52.476 -> Temperature: 37.28 degC
21:55:52.476 ->
21:55:52.476 -> Max X:0.00 Min X:0.00 Max x:0.03 Min x:0.00
21:55:52.813 -> BME680
21:55:52.813 -> Temperature in Celsius: 30.43
21:55:52.813 -> Humidity in %: 39.09
21:55:52.813 -> Pressure in hPa: 996.53
21:55:52.813 -> Altitude in Meters: 138.06


treten  nach ein paar Minuten Ausgaben wie folgt auf
Code: [Select]
21:56:41.117 -> ⸮=3q5B⸮⸮⸮>⸮⸮⸮>⸮⸮⸮>\⸮>
21:56:41.117 -> ⸮<⸮⸮⸮>I2?S0⸮⸮I2?S0⸮⸮l?⸮⸮⸮>⸮⸮⸮A⸮⸮⸮>⸮⸮⸮⸮⸮@⸮!B⸮~A⸮⸮⸮⸮3q5B⸮⸮⸮A2⸮!BLl5>2Ap⸮
21:56:41.117 -> ⸮⸮⸮3q5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮< ⸮⸮< ⸮⸮<5<⸮<0.47⸮⸮>⸮⸮⸮>⸮⸮⸮>\⸮>
21:56:41.117 -> ⸮<⸮⸮⸮>I2?S0⸮⸮I2?S0⸮⸮l?⸮⸮⸮>⸮⸮⸮A⸮⸮⸮>⸮⸮⸮⸮⸮@⸮!B⸮~A⸮⸮⸮⸮3q5B⸮⸮⸮A2⸮!BLl5>2Sv⸮
21:56:41.174 -> ⸮Ɣ3q5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮< ⸮⸮< ⸮⸮<5<⸮<-120.13⸮⸮>\⸮>
21:56:41.174 -> ⸮<⸮⸮⸮>I2?S0⸮⸮I2?S0⸮⸮l?⸮⸮⸮>⸮⸮⸮A⸮⸮⸮>⸮⸮⸮⸮⸮@⸮!B⸮~A⸮⸮⸮⸮3q5B⸮⸮⸮A2⸮!BLl5>2e|⸮
21:56:41.174 -> ⸮̔3q5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮< ⸮⸮< ⸮⸮<5<⸮<45.36⸮<⸮⸮⸮>I2?S0⸮⸮I2?S0⸮⸮l?⸮⸮⸮>⸮⸮⸮A⸮⸮⸮>⸮⸮⸮⸮⸮@⸮!B⸮~A⸮⸮⸮⸮3q5B⸮⸮⸮A2⸮!BLl5>2t⸮⸮
21:56:41.174 -> ⸮є3q5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮<5<⸮< ⸮⸮< ⸮⸮<5<⸮<0.03<⸮<5<⸮< ⸮⸮< ⸮⸮<
21:56:41.174 -> ⸮>⸮⸮⸮¯⸮⸮>I2?



Konkret ist die Funktion des Beschleunigungssensors MPU6050
Code: [Select]


  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);
 

  Serial.print("Acceleration X: ");
  Serial.print(a.acceleration.x);
  Serial.print(", Y: ");
  Serial.print(a.acceleration.y);
  Serial.print(", Z: ");
  Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");
 
  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");
 
  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");
 
  Serial.println("");

Und die Berechnungsfunktion, bei deren Einbinden das Problem auftritt
Code: [Select]

acc_x_counter++;    if (acc_x_counter>10){acc_x_counter=0;}             ACC_x[acc_x_counter]=a.acceleration.x;
acc_y_counter++;    if (acc_y_counter>10){acc_y_counter=0;}             ACC_y[acc_y_counter]=a.acceleration.y;
acc_z_counter++;     if (acc_z_counter>10){acc_z_counter=0;}             ACC_z[acc_z_counter]=a.acceleration.z;
g_gyro_x_counter++; if (g_gyro_x_counter>10){g_gyro_x_counter=0;}       GYRO_x[g_gyro_x_counter]=g.gyro.x;
g_gyro_y_counter++; if (g_gyro_y_counter>10){g_gyro_y_counter=0;}       GYRO_y[g_gyro_y_counter]=g.gyro.x;
g_gyro_z_counter++; if (g_gyro_z_counter>10){g_gyro_z_counter=0;}       GYRO_z[g_gyro_z_counter]=g.gyro.x;

Serial.print("Max X:") ; Serial.print(Max(ACC_x));
Serial.print(" Min X:") ;Serial.print(Min(ACC_x));
Serial.print(" Max x:")  ;Serial.print(Max(GYRO_x));
Serial.print(" Min x:")  ;Serial.print(MinGYRO_x));
Serial.println(" ");


float Max(float array[10]){
  float max=array[0];
  for (int i=1; i<10; i++){
    if(array[i]>max)
    max=array[i];
  }
  return max;
 }

float Min(float array[10]){
  float min=array[0];
  for (int i=1; i<10; i++){
    if(array[i]<min)
    min=array[i];
  }
  return min;
 }

Hierbei wird konkret jeweils ein Array (ACC_x, ... GYRO_x,...) aus 10 Zellen beschrieben,die Arrayzellen werden sukzessiv geschrieben, ist der Zähler (counter) bei der letzten Zelle, fängt er an der ersten Position wieder an, so dass das ganze eine FIFO-Speicherung ergibt

Tommy56

Das sieht danach aus, als würde über Arraygrenzen geschrieben und damit andere Werte zerstört.
Da hilft nur der komplette Code.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

DerPeter

Code: [Select]

//MPU 6050
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
Adafruit_MPU6050 mpu;

//CAN
#include <SPI.h>
#include <mcp2515.h>
MCP2515 mcp(10);

//SHT35
#include "Seeed_SHT35.h"
SHT35 sensor(21);
u16 value=0;
u8 data[6]={0};

//Multiplexer
extern "C" {
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}
#define Multiplexer 0x70

//define LEDs
int green_LED=9;

//BME680
#include <avr/wdt.h>
#include "BlueDot_BME680.h"
BlueDot_BME680 bme680 = BlueDot_BME680();

// define Multiplexer switch function
void tcaselect(uint8_t i) {
 if (i > 7) return;

 Wire.beginTransmission(Multiplexer);
 Wire.write(1 << i);
 Wire.endTransmission(); 
}
float ACC_x[10];
float ACC_y[10];
float ACC_z[10];
float GYRO_x[10];
float GYRO_y[10];
float GYRO_z[10];

int acc_x_counter=0;
int acc_y_counter=0;
int acc_z_counter=0;
int g_gyro_x_counter=0;
int g_gyro_y_counter=0;
int g_gyro_z_counter=0;


// refresh rate in ms
int refresh_rate=500;

void setup() {
 //Serial setup
 Serial.begin(250000);
 Serial.println("Starting");
 
 //CAN SETUP
 SPI.begin();
 mcp.reset();
 mcp.setBitrate(CAN_500KBPS, MCP_8MHZ);
 mcp.setNormalMode();
 
//LED SETUP
 pinMode(green_LED, OUTPUT);

 //I2C setup
 Wire.begin();   

 //BME Setup
 bme680.parameter.I2CAddress = 0x77; //adress
 bme680.parameter.sensorMode = 0b01; //mode
 bme680.parameter.IIRfilter = 0b100; //IIR (Infinite Impulse Response)
 bme680.parameter.humidOversampling = 0b101; //oversampling factor
 bme680.parameter.tempOversampling = 0b001;   //oversampling factor
 bme680.parameter.pressOversampling = 0b101;  //oversampling factor
 bme680.parameter.pressureSeaLevel = 1013.25;   //default value of 1013.25 hPa
 bme680.parameter.tempOutsideCelsius = 15; //average temperature outside
 bme680.parameter.target_temp = 320; //target temperature of the gas sensor

 // LED Test
 digitalWrite(green_LED, HIGH);
//Checking devices
 tcaselect(0);if (bme680.init() == 0x61)       {Serial.println(F("BME680 found!"));}
 tcaselect(1);if(!sensor.init())               {Serial.println("SHT35_Front found!");}
 tcaselect(2);if(!sensor.init())               {Serial.println("SHT35_Side found!");}
 tcaselect(3);if(!sensor.init())               {Serial.println("SHT35_Door found!");}
 tcaselect(4);if(!(!mpu.begin()))              {Serial.println("MPU6050 found!");}
   
// MPU Setup
 mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
 mpu.setGyroRange(MPU6050_RANGE_500_DEG);
 mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
   
 //LED off
 digitalWrite(green_LED, LOW);
   
}
int intervall;
int millis_last=millis();
void loop() {

 //Serial.print(F("Duration in Seconds:\t\t"));
 intervall=millis()-millis_last;
 
 millis_last= millis();
 //Serial.println(intervall); 
 //Serial.println();

  //Sensors
tcaselect(0); // Multiplexer switch
 if (bme680.init() != 0x61)
 {
   Serial.println(F("BME680 could not be found!"));
 }
 else
 {
 bme680.writeCTRLMeas();
 Serial.println("BME680");
 Serial.print(F("Temperature in Celsius:\t\t"));
 Serial.println(bme680.readTempC());
 Serial.print(F("Humidity in %:\t\t\t"));
 Serial.println(bme680.readHumidity());
 Serial.print(F("Pressure in hPa:\t\t"));
 Serial.println(bme680.readPressure());
 Serial.print(F("Altitude in Meters:\t\t"));
 Serial.println(bme680.readAltitudeMeter());
 Serial.println();
 
 write_data2can((float)bme680.readTempC(),10);
 write_data2can((float)bme680.readHumidity(),11);
 write_data2can((float)bme680.readPressure(),12);
 write_data2can((float)bme680.readAltitudeMeter(),12);
 }

 tcaselect(1); //Multiplexer Switch to SHT35_Front
 
 value=0;
 data[6]={0};
 float temp_Front,hum_Front;
 if(NO_ERROR!=sensor.read_meas_data_single_shot(HIGH_REP_WITH_STRCH,&temp_Front,&hum_Front))
 {
  Serial.println("SHT35_Front could not be found!");
 }
 else
 {
  Serial.println("SHT35_Front");
  Serial.print(F("Temperature in Celsius:\t\t"));
  Serial.println(temp_Front);
  Serial.print(F("Humidity in %:\t\t\t"));
  Serial.println(hum_Front);
  Serial.println();
  write_data2can((float)temp_Front,14);
  write_data2can((float)hum_Front,15);
   }

 tcaselect(2); //Multiplexer Switch to STH35_Side

 value=0;
 data[6]={0};
 float temp_Side,hum_Side;
 if(NO_ERROR!=sensor.read_meas_data_single_shot(HIGH_REP_WITH_STRCH,&temp_Side,&hum_Side))
 {
 Serial.println("SHT35_Side could not be found!");
 }
 else
 {
   Serial.println("SHT35_Side");
   Serial.print(F("Temperature in Celsius:\t\t"));
   Serial.println(temp_Side);
   Serial.print(F("Humidity in %:\t\t\t"));
   Serial.println(hum_Side);
   Serial.println();
   write_data2can((float)temp_Side,16);
   write_data2can((float)hum_Side,17);
   }

 tcaselect(3); //Multiplexer Switch

 value=0;
 data[6]={0};
 float temp_Door,hum_Door;
 if(NO_ERROR!=sensor.read_meas_data_single_shot(HIGH_REP_WITH_STRCH,&temp_Door,&hum_Door))
 {
  Serial.println("SHT35_Door could not be found!");
 }
 else
 {
   Serial.println("SHT35_Door");
   Serial.print(F("Temperature in Celsius:\t\t"));
   Serial.println(temp_Door);
   Serial.print(F("Humidity in %:\t\t\t"));
   Serial.println(hum_Door);
   Serial.println();
   write_data2can((float)temp_Door,18);
   write_data2can((float)hum_Door,19);
   }

 tcaselect(4);

 sensors_event_t a, g, temp;
 mpu.getEvent(&a, &g, &temp);


 Serial.print("Acceleration X: ");
 Serial.print(a.acceleration.x);
 Serial.print(", Y: ");
 Serial.print(a.acceleration.y);
 Serial.print(", Z: ");
 Serial.print(a.acceleration.z);
 Serial.println(" m/s^2");

 Serial.print("Rotation X: ");
 Serial.print(g.gyro.x);
 Serial.print(", Y: ");
 Serial.print(g.gyro.y);
 Serial.print(", Z: ");
 Serial.print(g.gyro.z);
 Serial.println(" rad/s");

 Serial.print("Temperature: ");
 Serial.print(temp.temperature);
 Serial.println(" degC");

 Serial.println("");

acc_x_counter++;    if (acc_x_counter>10){acc_x_counter=0;}             ACC_x[acc_x_counter]=a.acceleration.x;
acc_y_counter++;    if (acc_y_counter>10){acc_y_counter=0;}             ACC_y[acc_y_counter]=a.acceleration.y;
acc_z_counter++;     if (acc_z_counter>10){acc_z_counter=0;}             ACC_z[acc_z_counter]=a.acceleration.z;
g_gyro_x_counter++; if (g_gyro_x_counter>10){g_gyro_x_counter=0;}       GYRO_x[g_gyro_x_counter]=g.gyro.x;
g_gyro_y_counter++; if (g_gyro_y_counter>10){g_gyro_y_counter=0;}       GYRO_y[g_gyro_y_counter]=g.gyro.x;
g_gyro_z_counter++; if (g_gyro_z_counter>10){g_gyro_z_counter=0;}       GYRO_z[g_gyro_z_counter]=g.gyro.x;
Serial.print("Max X:") ; Serial.print(Max(ACC_x));
Serial.print(" Min X:") ;Serial.print(Min(ACC_x));

Serial.print(" Max x:")  ;Serial.print(Max(GYRO_x));
Serial.print(" Min x:")  ;Serial.print(Max(GYRO_x));
Serial.println(" ");
delay(300);
 if(digitalRead(green_LED)==0)
 {
   digitalWrite(green_LED, HIGH);
 }
 else
 {
   digitalWrite(green_LED, LOW);
 } 
}


//define CAN write function
void write_data2can(float data, int can_ID){
   uint8_t can_data[sizeof(float)];
   memcpy(can_data, &data, sizeof (data));
   struct can_frame canMsg;

   canMsg.can_id = can_ID;
   canMsg.can_dlc = 4;
   canMsg.data[0] = can_data[0];
   canMsg.data[1] = can_data[1];
   canMsg.data[2] = can_data[2];
   canMsg.data[3] = can_data[3];
   mcp.sendMessage(&canMsg);   
}



float Max(float array[10]){
 float max=array[0];
 for (int i=1; i<10; i++){
   if(array[i]>max)
   max=array[i];
 }
 return max;
}

float Min(float array[10]){
 float min=array[0];
 for (int i=1; i<10; i++){
   if(array[i]<min)
   min=array[i];
 }
 return min;
}

DerPeter

Konnte im übrigen das ganze noch mehr eingrenzen.

Das ganze tritt bei Einbinden der Min/Max Funktion auf

Tommy56

Da haben wir doch schon einen möglichen Kandidaten:
Code: [Select]

u8 data[6]={0}; // definiert ein Array mit 6 Elementen (Index 0...5)
// und dann das
data[6]={0}; // Schreibt in das nicht existierende Feld mit dem Index 6 eine 0


Als erster Ansatz. Weitere Fehler habe ich jetzt nicht gesucht.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

my_xy_projekt


Tommy56

Das hätte der Kompiler schon nicht durch gelassen.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

combie

Quote
Code: [Select]
float Min(float array[10]){
  float min=array[0];
  for (int i=1; i<10; i++){
    if(array[i]<min)
    min=array[i];
  }
  return min;
 }

Ich mag hier die magischen Zahlen nicht!
Wenn es geht, verzichte auf sowas.
Ein Vertipper und es rappelt(so wie bei dir)

Tipp:
Die magische Zahl 10 darf nur an einer einzigen Stelle auftauchen.

Hier mal ein Beispiel mit nur einer 10:

Code: [Select]

using ArrayType = float[10];

ArrayType feld
{
  1.1,
  1.2,
  1.3,
  1.4,
  1.5,
  1.6,
  1.7,
  1.8,
  1.9,
  2.0,
};

float Min(const ArrayType &daten)
{
  float min = *daten;
  for(const float &d:daten) if(d<min) min = d;
  return min;
}



@Tommy56
Adlerauge!



Es ist offensichtlich, dass uns die Umstände alleine nicht glücklich oder unglücklich machen.
Es ist die Art unserer Reaktion darauf, die unsere Gefühle bestimmt.

DerPeter

Da haben wir doch schon einen möglichen Kandidaten:
Code: [Select]

u8 data[6]={0}; // definiert ein Array mit 6 Elementen (Index 0...5)
// und dann das
data[6]={0}; // Schreibt in das nicht existierende Feld mit dem Index 6 eine 0

Als erster Ansatz. Weitere Fehler habe ich jetzt nicht gesucht.

Gruß Tommy
Tatsächlich. Da hat ein Entwickler wohl geschlampt, den das hab ich nur übernommen aus dem Beispiel des Herstellers (Grove) ;-)
Hab dem ganzen noch eine Zelle hinzugefügt

Und dann habe ich noch bemerkt, dass ich bei meiner Berechnungsfunktion auch über das Ziel hinausgegangen bin
Code: [Select]
if (acc_x_counter>10){acc_x_counter=0;}

DerPeter

Ich mag hier die magischen Zahlen nicht!
Wenn es geht, verzichte auf sowas.
Ein Vertipper und es rappelt(so wie bei dir)

Tipp:
Die magische Zahl 10 darf nur an einer einzigen Stelle auftauchen.
Software Pattern ;-)

Das gleiche hatte ich gerade beim Durchlesen auch im Kopf. Und du hast natürlich Recht

my_xy_projekt

Das hätte der Kompiler schon nicht durch gelassen.

Gruß Tommy
Offensichtlich nicht, denn das erklärt sich nicht:
Code: [Select]
Serial.print("Max X:") ; Serial.print(Max(ACC_x));
Serial.print(" Min X:") ; Serial.print(Min(ACC_x));
Serial.print(" Max x:")  ; Serial.print(Max(GYRO_x));
Serial.print(" Min x:")  ; Serial.print(MinGYRO_x));
Serial.println(" ");


Da wird mindestens vorher eine Warnung irgendwo kommen, die entweder abgeschaltet wurde oder hier nicht mitgeliefert ist.

Und ja aus eigener Erfahrung unter 1.8.10 ist auch sowas hier schon - allerdings mit Warnung - durchgegangen.

Der Fehler war dann viele Zeilen vorher ;)

combie

Offensichtlich nicht, denn das erklärt sich nicht:
Code: [Select]
Serial.print("Max X:") ; Serial.print(Max(ACC_x));
Serial.print(" Min X:") ; Serial.print(Min(ACC_x));
Serial.print(" Max x:")  ; Serial.print(Max(GYRO_x));
Serial.print(" Min x:")  ; Serial.print(MinGYRO_x));
Serial.println(" ");


Da wird mindestens vorher eine Warnung irgendwo kommen, die entweder abgeschaltet wurde oder hier nicht mitgeliefert ist.

Und ja aus eigener Erfahrung unter 1.8.10 ist auch sowas hier schon - allerdings mit Warnung - durchgegangen.

Der Fehler war dann viele Zeilen vorher ;)
Unfug.
Dafür wirst du keinen Nachweis vorlegen können!
Da kannst du dich drehen und winden, wie du willst.

Das ist ein klarer und deutlicher Error.
entweder
> error: 'MinGYRO_x' was not declared in this scope
oder
> error: expected ';' before ')' token

Es ist offensichtlich, dass uns die Umstände alleine nicht glücklich oder unglücklich machen.
Es ist die Art unserer Reaktion darauf, die unsere Gefühle bestimmt.

DerPeter

Um mal das zu erklären, wie das durchkam. Hatte vor dem Kopieren an der betreffenden Stelle was geändert um was auszuprobieren und dann "manuell" rückgängig gemacht. Dabei hat sich der Fehler eingeschlichen. Also keine Angst, wäre nicht durchgegangen  :smiley-cool:

combie

Es ist offensichtlich, dass uns die Umstände alleine nicht glücklich oder unglücklich machen.
Es ist die Art unserer Reaktion darauf, die unsere Gefühle bestimmt.

Go Up