Absender: Harald Härtl
Datum: Sa, 18.03.2006 18:41:49
In-reply-to:
<200603171353.38977.tevers@xxxxxxxxxxxxx>
References:
<9612803660.20060317112342@xxxxxxxxxxxxxxxxx> <8614128726.20060317114547@xxxxxxxxxxxxxxxxx> <441A94E3.6060709@xxxxxxxxxxxx> <200603171353.38977.tevers@xxxxxxxxxxxxx>
Hallo Torsten Evers,
Die Messwerte schwanken zwar immer noch über die letzten zwei Stellen
gleicher Effekt bei mir. Ich habe einen Patch geschrieben (-> Anhang), der für alle analogen Sensoren einen gleitenden Mittelwert berechnet, wobei der Glättungsfaktor für jeden Sensor einzeln einstellbar ist. Jetzt ist bei mir einigermaßen Ruhe auf der Anzeige.
Grüße, Harald
Index: include/sensor_correction.h =================================================================== RCS file: /ctbot/ct-Bot/include/sensor_correction.h,v retrieving revision 1.1 diff -u -r1.1 sensor_correction.h --- include/sensor_correction.h 4 Mar 2006 14:54:23 -0000 1.1 +++ include/sensor_correction.h 18 Mar 2006 18:29:56 -0000 @@ -25,8 +25,8 @@ #ifndef SENSOR_CORRECTION_H_ #define SENSOR_CORRECTION_H_ -#define SENSDISTSLOPE 65330 /*!< Steigung der Sensorkennlinie */ -#define SENSDISTOFFSET -3 /*!< Offset der Sensorkennlinie */ +#define SENSDISTSLOPE 5084 /*!< Steigung der Sensorkennlinie */ +#define SENSDISTOFFSET 43 /*!< Offset der Sensorkennlinie */ #endif /*SENSOR_CORRECTION_H_*/ Index: mcu/sensor-low.c =================================================================== RCS file: /ctbot/ct-Bot/mcu/sensor-low.c,v retrieving revision 1.4 diff -u -r1.4 sensor-low.c --- mcu/sensor-low.c 4 Mar 2006 14:54:23 -0000 1.4 +++ mcu/sensor-low.c 18 Mar 2006 18:29:57 -0000 @@ -105,6 +105,32 @@ timer_2_init(); } +/*! + * Berechnung eines fliessenden Mittelwerts + * @param actValue Aktuell vom Sensor erfasster Wert + * @param sensor Nummer des Sensors (#defines aus ADC-Pins) + * @return Geglaetteter Messwert des Sensors + */ + int16 smooth (int16 actValue, uint8 sensor) { + + static long oldValue[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + static int8 strength[8] = {3, 3, 2, 2, 3, 3, 1, 1}; + // DIST LINE LDR BORDER + + /* Bitshiften statt multiplizieren/dividieren sollte Rechenzeit sparen. */ + /* Formel: wert = (alt * (2^strength - 1) + neu) / 2^strength */ + /* stength = 0: Keine Glaettung */ + /* stength = 1: Mittelwert: (alt + neu)/2 */ + /* stength = 2: Neuer Wert geht zu einem Viertel ein */ + /* stength = 3: Neuer Wert geht zu einem Achtel ein */ + + oldValue[sensor] = ((oldValue[sensor] << strength[sensor]) - oldValue[sensor] + actValue) >> strength[sensor]; + + return (int16)oldValue[sensor]; + } + + + /*! * Konvertiert einen Sensorwert vom analogen Abstandssensor in mm * Da die Sensoren eine nichtlineare Kennlinie haben, @@ -114,8 +140,15 @@ * @return Distanz in mm */ int16 sensor_abstand(int16 sensor_data){ - // TODO reale Kennlinie beachten!!!! - return SENSDISTSLOPE / (sensor_data - SENSDISTOFFSET); + // SENSDISTSLOPE sprengt bei Millimeterauflösung den Wertebereich + // eines int16. Also Zentimeter und in der Berechnung mal 10. + // Eine Messgenauigkeit im Millimeterbereich ist sowieso nicht gegeben. + static const int16 max = (SENSDISTSLOPE + 99 * SENSDISTOFFSET) / 99; + + if (sensor_data > max) + return 10 * (SENSDISTSLOPE / (sensor_data - SENSDISTOFFSET)); + else + return 999; // Ein Meter und mehr kann sowieso nicht mehr vernuenftig gemessen werden // return 1023-sensor_data; } @@ -142,23 +175,23 @@ sensMouseX += sensMouseDX; // ---------- analoge Sensoren ------------------- - sensLDRL = adc_read(SENS_LDR_L); - sensLDRR = adc_read(SENS_LDR_R); + sensLDRL = smooth (adc_read(SENS_LDR_L), SENS_LDR_L); + sensLDRR = smooth (adc_read(SENS_LDR_R), SENS_LDR_R); - sensBorderL = adc_read(SENS_KANTE_L); - sensBorderR = adc_read(SENS_KANTE_R); + sensBorderL = smooth (adc_read(SENS_KANTE_L), SENS_KANTE_L); + sensBorderR = smooth (adc_read(SENS_KANTE_R), SENS_KANTE_R); ENA_off(ENA_KANTLED); - sensLineL = adc_read(SENS_M_L); - sensLineR = adc_read(SENS_M_R); + sensLineL = smooth (adc_read(SENS_M_L), SENS_M_L); + sensLineR = smooth (adc_read(SENS_M_R), SENS_M_R); ENA_off(ENA_MAUS); //Aktualisiere Distanz-Sensoren // Die Distanzsensoren sind im Normalfall an, da sie 50 ms zum booten brauchen // sensDistL= adc_read(SENS_ABST_L); // sensDistR= adc_read(SENS_ABST_R); - sensDistL= sensor_abstand(adc_read(SENS_ABST_L)); - sensDistR= sensor_abstand(adc_read(SENS_ABST_R)); + sensDistL= smooth (sensor_abstand(adc_read(SENS_ABST_L)), SENS_ABST_L); + sensDistR= smooth (sensor_abstand(adc_read(SENS_ABST_R)), SENS_ABST_R); // ------- digitale Sensoren ------------------ sensDoor = (SENS_DOOR_PINR >> SENS_DOOR) & 0x01;