Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

techniken:messen

Filtern der Signale aus einem Sensor

Motivation

Damit Roboter mit ihrer Umgebung können, müssen sie zunächst in der Lage sein diese auch wahrzunehmen.

Ähnlich wie Menschen über Sinnesorgane verfügen, kann auch ein Roboter mit Sensoren ausgestattet werden die ihm Informationen über seine Umgebung liefern. Da sich unser Gehirn im Laufe der Jahre exakt auf die mit ihm verbundenen senorischen Organe einstellen konnte, fällt uns im Alltag kaum auf, wie verrauscht, verzerrt und unscharf die von ihnen gelieferten Signale vor ihrer Verarbeitung sind. Würden wir also unsere Ohren gegen die seines Nachbarn austauschen könnten wir zwar noch immer noch Geräusche wahrnbehmen - das Signal würde sich aufgrund der veränderten Filtereigenschaften des Aussenohres völlig verzerrt und „falsch“ anhören.

Gleiches gilt für unsere Roboter: Damit die von Sensoren über die Umgebung gelieferten Informationen richtig interpretiert werden können, muss eine dazwischengeschaltete Signalverarbeitung genau zu den Eigenschaften des vom Sensor erzeugten Signals passen. Damit das klappen kann, müssen wir zunächsteinmal eine möglichst Vorstellung davon haben, wie dieses Signal eigentlich aussieht…

Beispiel: Ein optischer Distanz-Sensor (Typ Sharp GP2Y0A60SZLF)

Anhand des besonders „hilfbedürftigen“ Distanzsensors „GP2Y0A60SZLF“ von Sharp wollen wir durchspielen, wie aus einem katastrophalen Rohsignal mit einigen kleinen Kniffen eine brauchbare Informationsquelle wird.

Das Datenblatt

Der erste Schritt führt zum Datenblatt des Sensors, alle wichtigen technischen Daten sollten dort zu finden sein: Datenblatt Sharp

Auf der Website des Herstellers Pololu Sharpy gibt es nich ein paar zusätzliche Informationen zur Platine, auf der unser Sensor verlötet ist..

So erfahren wir, dass der Sensor für jede Messung 16.5 ± 3.7 ms benötigt und die Entfernung in Form einer Spannung ausgibt, die nichtlinear mit dem Abstand abfällt. Idealerweise sollten wir also in jeder Sekunde (Frequenz = 1/Periode) 60 verschiedene Messungen bekommen.

Also.. wie sieht das Signal denn in Realität aus? Und was genau passiert zwischen zwei Messungen?

Angenommen wir haben den Sharp-Sensor am Arduino Pin A6 angeschlossen. Nun lesen wir die Spannung aus die an A6 anliegt, diese entspricht unserem Messwert, und eine weitere Messung nach 1ms. Unsere erste Annahme könnte nun sein dass die beiden Werte gleich sein müssen bzw. dass wir genau vor und nach einem Mess-Update des Sharp-Sensors gemessen haben. Um diese Annahme zu prüfen lassen wir den Arduino so schnell messen wie er kann und speichern die Daten via eines Processing-Sketch in einer Text-Datei um sie anschließend auszuwerten.

Arduino- und Processing-Sketch

Das Arduino Programm sollte so schlank sein wie möglich um sicherzustellen das der Arduino nicht mit anderen Aufgaben beschäftigt ist:

//In dieser Variable wird die momentane Systemzeit gespeichert.
unsigned long currentMicros = 0;
 
void setup() {
    //Serielle Kommunikation (schnellste Baudrate)
    Serial.begin(115200);
}
 
void loop() {
    //aktuelle Zeit
    currentMicros = micros();
    //ausgabe des Messwertes
    Serial.print(analogRead(A6));
    //"tabstop" um den Messwert vom Messzeitpunkt zu trennen
    Serial.print("\t");
    //Messzeitpunkt
    Serial.print(currentMicros);
    //"newline" um die Messungen voneinander zu trennen
    Serial.print("\n");
}

Der Processing-Sketch liest die Daten aus dem Serial-Port aus und schreibt die in eine Text-Datei:

// This program shows how to read numbers in a human readable "ASCII" format from the Serial Port 
// and saves them to a text file
// Created 2013 by Felix Bonowski
// This code is in the public Domain.
 
import processing.serial.*; //the functionality for using the Serial Port lies in a speical library. This tells Processing to use it.
Serial myPort;        // Create a "serial port" object/variable. "Serial" is the type of the object (just like "int"), "myPort" is the name of the variable
PrintWriter output; // Object that writes to .txt file
 
//this function gets called at the beginnign of the program
void setup () {
  //The file we write to. If not declared otherwise it will be saved in your sketch folder.
  output = createWriter("sharpSensor.txt"); 
  // Initialze Serial communication. There may be multiple serial ports on your computer, so we have to select one:
  String[] portNames=Serial.list();//Serial.list() returns an array of port names
  println(portNames);  //print them to the user
  // initialize the Serial port Object using the last name from the list and a Baudrate of 115200
  myPort = new Serial(this, portNames[portNames.length-1], 115200);
 
  // Set up the screen:
  size(1024, 512); // set size of the window
  background(0);// set  background color to black
  stroke(255); // set the color of things we draw to white
 
  // make the loop run as fast as it can so we dont loose any data
  frameRate(2000);
}
 
//Press mouse to end the programm
void mousePressed() {
    println("Writing to file");
    output.flush();  // Writes the remaining data to the file
    output.close();  // Finishes the file
    exit();  // Stops the program
}
 
//this function is called continously, just as "loop" in arduino
void draw () {
  // get data from the Serial Port and write to file
  readLineFromSerial(myPort);
}
 
 
//this function reads a line from the serial port and writes it to a text file
//multiple numbers can be received if they are separated by tab stops ("\t") 
void readLineFromSerial(Serial  port) {
  byte temp[] = port.readBytesUntil('\n'); //read data from buffer until a new line is finished
 
  // check if any data is available
  if (temp == null) {
     //got nothing - print nothing
  }   
  else {
    String inBuffer = new String(temp); //convert raw data to a string
    inBuffer = trim(inBuffer); //cut off whitespace
    output.print(inBuffer); //print to .txt
    output.print("\n"); //add new line as marker
    output.flush(); //sometimes not everything has been written to the file. This does the job.
  }
}

Erste Auswertung

Für die erste Messung wurde der Sharp-Sensor direkt an den Arduino angeschlossen und mit der Board-Spannung versorgt. Die Entfernung zu einem Hindernis wurde konstant gehalten.

arduinosharpmessung.jpg

Das Signal zeigt ein starkes rauschverhalten mit Spannungssprüngen von 30mV. Solch große Schwankungen sind für eine präzise Messung natürlich sehr ungünstig. Zwei Lösungen bieten sich hier:

  1. Die Messwerte über einen geeigneten Zeitraum (e.g. 20ms) aufsummieren und Mitteln in der Hoffnung dass man größtenteils ein Messplateau erwischt. Vorteil, einfach zu programmieren. Nachteil, ungenau, im Extremfall völlig falsche Ergebnisse.
  2. Ein Tiefpass-Filter der das Signal direkt glättet. Vorteil, sehr schnell und zuverlässig. Nachteil, schlecht gewählte Bauteile beeinträchtigen die Messung.

Der Tiefpassfilter

Ein Tiefpass besteht aus einer Widerstand-Kondensator-Kombination welche man auch RC-Glied nennt. Als Schaltskizze lässt sich das folgendermaßen darstellen:

Wenn sich die Eingangsspannung Ue sprunghaft ändert folgt ihr die Ausgangsspannung Ua mit einer gewissen Trägheit und im Verlauf wie eine Exponentialfunktion bis dieselbe Spannung erreich ist die am Eingang anliegt. In unserem Fall ist es wichtig das die Schaltung nicht zu träge reagiert, da unsere Messungen sonst verfälscht werden. Ein solches Negativbeispiel ist in der nachfolgenden Abbildung zu sehen. Einem Spannungssprung folgt das gefilterte Signal sehr langsam und erreicht nie das Spannungsniveau der Eingangsspannung.

tiefpassfilter4muf.jpg

Was sich jedoch schon abzeichnet ist, dass die Spannung-Spikes des Eingangssignals geglättet werden. Wählt man nun eine bessere Kombination des RC-Glieds erhält man ein geglättetes Signal das aber schnell genug auf Spannungsänderungen reagiert (siehe nachfolgende Abbildung). Weitere Informationen insbesondere zur Dimensionierung eures RC-Glieds findet ihr hier: RC-Glied Rechner

mitohnetiefpass_externv_200nf.jpg

techniken/messen.txt · Zuletzt geändert: 2018/12/17 11:55 von d.golovko