Experimente mit Hall Sensor und Multi Function Shield

Das Multi Function Shield, das ich ja bereits vorgestellt habe und das mittlerweile ja auch um einen Drehgeber erweitert wurde, bietet mit der Möglichkeit zur einfachen Anzeige von Daten auf seinem 4-fach-7-Segment-Display und den freien Anschlusspins eine gute Grundlage, Sensoren ausprobieren.

Das Letzte mal ging es um Reed Kontakte / Sensoren. Heute geht es um die artverwandten Hall-Sensoren. Auch sie reagieren auf magnetische Felder. Von der Sensoren fand ich gleich drei Bauteile in meiner 37-in-one-Sensoren-Bulk-Sammlung.

Hardware: Hall-Sensoren


Hall Sensoren nutzen den nach Edwin Hall benannten Hall-Effekt, bei dem eine sogenannte Hall-Spannung entsteht, wenn ein magnetisches Feld einen Stromfluss schneidet.

Damit ist auch gleich klar, dass ein Hall-Sensor im Gegensatz zu einem Reed Kontakt eine Versorgungsspannung benötigt, um diesen Strom fließen lassen zu können. Ein weitere Nachteil ist, dass Hall-Sensoren gegen elektrostatische Entladungen zerstört werden können, was bei Reed-Kontakten nicht der Fall ist.

Dafür kann man Hall-Sensoren kleiner produzieren und sie vermögen, auch die Flußdichte in gewissen Grenzen zu messen, während Reedschalter nur die Zuständen an und aus kennen.

Auf dem Foto ist ganz links das Modul KY-035 mit einem 49E-Hall-Sensor.

In der Mitte des Foto findet sich das Modul KY-003 mit einem Sensor vom Typ 3144.

Diese beiden Module verfügen über 3 Anschlüsse (von oben nach unten, Vorderseite oben, Pins rechts): Sie geben ein analoges Signal aus, dass im Rahmen von 400 bis 600 schwankt. Die Minimal und Maximalwerte von 0 (extrem hohe Flussdichte) und 1023 (keine Flussdichte) kamen bei meinen Experimenten niemals vor. Es ist davon auszugehen, dass jeder Sensor geringfügig andere Werte ausspuckt, so dass man sie vorher kalibrieren sollte, also die Minimal- und Maximalwerte speichern sollte.

Zu beachten ist auch, dass die Sensoren jeweils zu der Fläche, auf dem die Typenbezeichnung aufgedruckt ist, empfindlich sind und auf der anderen Seite nicht.

Technische Daten: 49E 3144 Vers.-Spannung 2.3 ... 10 V 4.5 ... 24 V Ouput Spannung 2.3 ... 2.7 V Leistungsaufnahme 6.5 mA typ. 4.4 mA (max 9 mA) max. Temperatur 120 °C -40 ... 150 °C Empfindlichkeit 1.7 ... 3.2 mV/Gauß 70 ... 350 Gauß Rauschen 90 mV Einschaltzeit typ. 0.04 µs (max 2) Ausschaltzeit typ. 0.18 µs (max 2) Ergebnisse sind temperaturabhängig Gegenüber dem KY-035 verfügt das KY-003 noch über eine LED samt Vorwiderstand, die leuchtet, wenn ein fest eingestellter Schwellenwert (8mm-Neodym-Magnet auf ca. 1 cm Entfernung) erreicht ist.

Ganz rechts auf dem Foto ein KY-024-Modul, ebenfalls mit einem 49E-Sensor und mit einem zusätzlichen LM393 Vergleichs-Chip und einem Potentiometer, um einzustellen, ab welchem analogen Wert der digitale Ausgang auf HIGH gehen soll.

Die Anschlussbelegung ist hier (von oben nach unten, Vorderseite oben, Pins rechts): Zu beachten ist bei dem 3. Modul, dass hier der Hall-Sensor mit der empfindlichen Seite nach unten verlötet ist, was in einigen Fälle evtl. ungünstig ist; auch weil das Poti doch ein wenig Höhe einnimmt.

Fidget Spinner ohne Rauschunterdrückung

Hier benutze ich den selben Versuchsaufbau mit der gleichen Software, die ich auch schon als Drehzahlmesser beim Reed-Sensor eingesetzt hatte.



Dabei fällt auf, dass es einen Unterschied im Verhalten gibt. Beim Reed-Sensor hab es je nach Position des Magneten / Reedschalters eine oder zwei eindeutige Punkte, an denen der Reedschalter durchschaltete. Beim Hallsensor gibt es einen Eintritts- und einen Austrittspunkt (vor und nach einem eindeutigen Bereich), bei dem das Signal fluktuiert / rauscht, d. h. das Signal wechselt schnell zwischen an und aus. Logischerweise bringt dies unseren Drehzahlmesser durcheinander, der ja die Zeitspannen zwischen einem an und aus misst.

Fidget Spinner mit Rauschunterdrückung

Die Software muss also nachgearbeitet werden, so dass das Rauschen ignoriert wird. Dazu nehme ich nun das analoge Signal her und schaue, ob dessen Wert im Kernbereich liegt, und auch (wichtig, wenn der Wert genau an der Kern-Grenze fluktuiert), ob das davor gemessene Signal darin lag.

Der angepasste Code sieht dann so aus:

Source-Code

Hier der Source-Code für den Umdrehungsmesser:

Umdrehungsmesser.ino (klicken, um diesen Abschnitt aufzuklappen)
//////////////////////////////////////////////////////// // (C) 2018 by Oliver Kuhlemann // // Bei Verwendung freue ich mich über Namensnennung, // // Quellenangabe und Verlinkung // // Quelle: http://cool-web.de/arduino/ // //////////////////////////////////////////////////////// #include <TimerOne.h> // für Timings und Interrupts #include <MultiFuncShield.h> // API für das Multi Function Shield #define PinData 5 // wo ist Digital Out angeschlossen? #define PinAnalog A5 // wo ist Analog Out angeschlossen? void setup() { Timer1.initialize(); MFS.initialize(&Timer1); // initialize multi-function shield library pinMode (PinData, INPUT_PULLUP); Serial.begin (115200); } void loop() { MFS.beep(1, 5, 2); // bereit long mic=0; long micBef=micros(); long micDelta=0; byte stateBef=HIGH; byte state=HIGH; float upm=0; int normal=analogRead(PinAnalog); // Wert ohne magnetischen Einfluß, kleiner ist höhere Flußdichte int ana=normal; int anaBefore=normal; while (1) { anaBefore=ana; ana=analogRead(PinAnalog); Serial.println(ana); //state=digitalRead(PinData); // nein, stattdessen Methode mit Flimmerkompensation benutzen state=0; if (ana <= normal-70 or anaBefore <= normal-70) state=1; // ggf. muss die 70 angepasst werden // piepen mit State, Beeper ist Pin 3 digitalWrite(3, !state); MFS.writeLeds(LED_1, state); // wenn Statusänderung if (state != stateBef) { // Zählbeginn, wenn Flanke auf HIGH (=geschlossen) wechselt if (state == HIGH) { mic=micros(); micDelta=mic-micBef; micBef=mic; upm=1./(micDelta/1000000.)*60.; MFS.write( (int) upm); } } stateBef=state; delayMicroseconds(1000); } }



Mit der angepassten Software funktioniert der Drehzahlmesser wieder, wobei ich allerdings das Gefühl habe, dass die Version mit Reed-Kontakt noch genauer war.

Festplatte mit Rauschunterdrückung

Als weiteren Test wollen wir die Umdrehungsgeschwindigkeit noch verdreifachen und führen das Experiment mit der Festplatte und 3322 UPM noch einmal durch:



Seltsamerweise zeigt der Arduino nur 1660 UPM, also recht genau die Hälfte an. Wie das kommt, ist mir schleierhaft. Eigentlich sollte er mit einem Delay von 1 ms UPMs bis 60'000 (1000 pro Sekunde) anzeigen können. Sollte da der Reed-Kontakt schon nicht mehr mitkommen und jedes zweite Ereignis überspringen? Zwischendrin geht er ja auch mal über 2000 UPM.

Erkenntnis für mich aus diesem Experiment: nimm für einen Drehzahlmesser lieber einen Reed-Kontakt, das ist einfacher und zuverlässiger.

Messung der Magnetfeldstärke

Was ein Reed-Kontakt allerdings nicht kann, ist die magnetische Flußdichte stufenweise messen. Ein Hall-Sensor kann das und bei ihm macht der analoge Ausgang auch Sinn, denn er gibt nich tnur die Werte 0 und 1023 aus, sondern mehr Werte im Bereich von 400 und 600.

Diese Werte schwanken aber je nach Sensortyp und Temperatur und darum sollte man vor jeder Messung kalibrieren, sprich den Minimalwert und den Maximalwert speichern und diese Grenzpunkte in Relation zu 100% und 0% setzen. Was ich mit dem nachfolgenden Programm gemacht habe.

Source-Code 2

Hier der Source-Code für den Flussdichtemesser:

Flussdichte.ino (klicken, um diesen Abschnitt aufzuklappen)
//////////////////////////////////////////////////////// // (C) 2018 by Oliver Kuhlemann // // Bei Verwendung freue ich mich über Namensnennung, // // Quellenangabe und Verlinkung // // Quelle: http://cool-web.de/arduino/ // //////////////////////////////////////////////////////// #include <TimerOne.h> // für Timings und Interrupts #include <MultiFuncShield.h> // API für das Multi Function Shield //#define PinData 5 // wo ist Digital Out angeschlossen? #define PinAnalog A5 // wo ist Analog Out angeschlossen? void setup() { Timer1.initialize(); MFS.initialize(&Timer1); // initialize multi-function shield library //pinMode (PinData, INPUT_PULLUP); Serial.begin (115200); } void loop() { boolean silence=false; MFS.beep(1, 5, 2); // bereit int anaMin=1023; int anaMax=0; int ana=0; int prozent=0; while (1) { ana=analogRead(PinAnalog); if (ana < anaMin) anaMin=ana; if (ana > anaMax) anaMax=ana; Serial.print(ana); Serial.print(", min: "); Serial.print(anaMin); Serial.print(", max: "); Serial.println(anaMax); prozent=map(ana, anaMax, anaMin, 0, 100); if (anaMax - anaMin < 70) { MFS.write("CAL."); } else { MFS.writeLeds(LED_4, (prozent >= 20)); MFS.writeLeds(LED_3, (prozent >= 40)); MFS.writeLeds(LED_2, (prozent >= 60)); MFS.writeLeds(LED_1, (prozent >= 80)); MFS.write(prozent); } delay(100); } }

Erreicht der Messbereich eine Größe von 70 oder mehr, gelten die Messwerte als genau genug, um Prozentzahlen auszugeben. Im Hintergrund werden die Min/Maxwerte aber trotzdem laufend aktualisiert, so dass zum Beispiel das Umdrehen des Magneten immer noch einen Einfluß hat, auch wenn nicht mehr "CAL." angezeigt wird.

So sieht das Programm in Aktion aus:



Der LM393 ist übrigens nicht - wie falsch im Video erwähnt - ein Verstärker, sondern ein Komparator, sprich er vergleicht Werte miteinander und schaltet einen Ausgang auf High, wenn ein bestimmter Wert überschritten wird. Dieser wird widerum mit dem Poti auf dem Modul eingestellt.

Reed oder Hall?

Ich werde dem Reed-Kontakt immer den Vorzug geben, es sei denn: