c't

c't-Projekte - Mailinglisten


[Voriger (Datum)] [Nächster (Datum)] [Voriger (Thread)] [Nächster (Thread)]
[Nach Datum][Nach Thread]

Re: [ct-bot] Informationen zu den Abstandssensoren

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;