Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

empfindlicher DIY Arduino IB Metalldetektor mit Diskriminierung

Komponenten und Verbrauchsmaterialien

Arduino Nano R3
× 1
Adafruit Standard LCD - 16x2 Weiß auf Blau
× 1
TL081 Operationsverstärker-IC
× 1
Lautsprecher:0,25 W, 8 Ohm
× 1
Allzwecktransistor NPN
× 1
Suchspulen
× 2
Widerstände, Kondensatoren
× 1

Apps und Onlinedienste

Arduino-IDE

Über dieses Projekt

Dieses Mal zeige ich Ihnen, wie Sie einen empfindlichen Metalldetektor herstellen, der auch in der Lage ist, zwischen Eisen- und Nichteisenmaterialien zu unterscheiden. Die Empfindlichkeit ist zufriedenstellend, da es sich um ein relativ einfaches Gerät handelt.

Dieses Projekt wird von PCBgogo gesponsert:

https://www.pcbgogo.com/promo/from_MirkoPavleskiMK

Dies ist eine Fortsetzung von David Crockers Projekt, das 2013 auf dem Arduino CC Forum vorgestellt wurde. Ich habe mich entschieden, seinen Code zu testen, weil ich keine Beweise (Bild oder Video) dafür gefunden habe, dass dieser Metalldetektor von irgendjemandem hergestellt wurde und gut funktioniert.

Zuerst habe ich eine Basisversion mit dem auf GitHub präsentierten Code erstellt, um die Funktionalität des Geräts sicherzustellen, und dann habe ich den Code so aktualisiert, dass er ein akustisches Signal hat und auf einem 16 auf 2 LCD-Display visuelle Informationen über den Typ von erkanntes Objekt (Eisen- oder Nichteisenmaterial) und LCD-Balkenanzeige für die Nähe erkannter Objekte.

Das Gerät ist sehr einfach aufzubauen und besteht aus nur wenigen Komponenten:

- Arduino Nano-Mikrocontroller

- Operationsverstärker (in meinem Fall LT1677, aber Sie können TL081 oder 741 verwenden)

- Wenige Widerstände und Kondensatoren

- Kleiner Transistor und Lautsprecher

- LCD-Anzeige

- 3 Schalter

- Potentiometer

- Batterie

- Und Suchspulen

Dies ist eine VLF (Very Low Frequency) Induction Balance Detektortechnologie und enthält zwei identische Spulen:Sender- und Empfängerspule. Wie bei allen Induktionsbalance-Detektoren ist die Spulenbalance sehr kritisch. Das Potentiometer wird verwendet, um die kleine 90 Grad phasenverschobene Komponente des Signals auf Null zu setzen. (Die phasengleiche Komponente wird durch Einstellen der relativen Anordnung der Spulen im typischen IB-Detektor-Stil auf Null gesetzt). Jede der Spulen ist auf einen 11 cm langen Körper mit 64 Windungen aus 0,5 mm ^ 2 emailliertem Kupferdraht in D-Form gewickelt, mit Klebeband umwickelt und mit Aluminiumfolie abgeschirmt, die mit verzinntem Kupferdraht verbunden ist (achten Sie darauf, einen kleinen Spalt zu lassen, damit der Bildschirm verhält sich nicht wie eine kurzgeschlossene Kurve) und wickelte sie auf eine Plastikplatte.

Zuerst müssen wir die Parallelresonanzfrequenz der Primärspule-Kondensator-Schaltung mit einem der vielen Online-Rechner bestimmen. Ich habe es mit einem Oszilloskop gemessen, aber wenn Sie sich an die oben angegebenen Abmessungen halten, werden es genau 7,64 kHz sein, sodass Sie den im Code angegebenen Wert direkt eingeben können. Bei einem anderen Wert der Resonanzfrequenz müssen wir den Code in der Warteschlange entsprechend ändern:

#define TIMER1_TOP (249) // Feinabstimmung der Frequenz

Wie Sie im Video sehen können, sind die Ergebnisse überraschend gut. Ohne das Vorhandensein von Metall ist das Gerät absolut stabil. Die Reichweite ist relativ groß und beispielsweise wird eine Metallabdeckung mit einem Durchmesser von 15 cm in einer Entfernung von mehr als 30 cm erkannt. Größere Metallobjekte werden in Entfernungen von mehr als 40-50 cm erkannt. Wir können eine kleine Münze in einer Entfernung von 15 cm in der Luft erkennen. Für die Stromversorgung verwende ich zwei in Reihe geschaltete Lithiumbatterien (7,4 Volt) und diese Spannung wird an den Vin-Eingang des Arduino angeschlossen. Der Verbrauch überschreitet nicht 20 mA, sodass die Batterien sehr lange halten. Das Video beschreibt ausführlich den Aufbau des gesamten Gerätes.

Dies sind nur vorläufige Ergebnisse. Es besteht die Möglichkeit, die Empfindlichkeit durch Einfügen eines Leistungs-MOSFET-Transistors zum Ansteuern der Tx-Spule deutlich zu verbessern, aber ich werde dies in einem der folgenden Videos testen und präsentieren.

Code

  • Arduino-Code
  • LcdBarGraph-Bibliothek
Arduino-CodeArduino
// Metalldetektor mit Induktionswaage// Wir betreiben die CPU mit 16 MHz und den ADC-Takt mit 1 MHz. Die ADC-Auflösung wird bei dieser Geschwindigkeit auf 8 Bit reduziert. // Timer 1 wird verwendet, um den Systemtakt durch etwa 256 zu teilen, um eine 62,5-kHz-Rechteckwelle zu erzeugen. // Dies wird verwendet, um Timer 0 anzusteuern und auch ADC-Wandlungen auszulösen. // Timer 0 wird verwendet, um die Ausgabe von Timer 1 durch 8 zu teilen, was ein 7,8125-kHz-Signal zum Ansteuern der Sendespule ergibt. // Dies ergibt 16 ADC Taktzyklen für jede ADC-Wandlung (es dauert tatsächlich 13,5 Zyklen), und wir nehmen 8 Abtastungen pro Zyklus der Spulenantriebsspannung. // Der ADC implementiert vier phasenempfindliche Detektoren in 45-Grad-Intervallen. Die Verwendung von 4 anstelle von nur 2 ermöglicht es uns, die dritte Harmonische der // Spulenfrequenz zu unterdrücken.// Timer 2 wird verwendet, um einen Ton für die Hörmuschel oder das Headset zu erzeugen.// Andere Teilungsverhältnisse für Timer 1 sind möglich, ab etwa 235 aufwärts.// Verdrahtung:// Digital Pin 4 (alias T0) mit Digital Pin 9 verbinden // Digital Pin 5 über Widerstand mit Primärspule und Abstimmkondensator verbinden // Ausgang vom Empfangsverstärker mit Analog Pin 0 verbinden. Ausgang von Receive Verstärker sollte auf etwa die Hälfte der analogen Referenz vorgespannt werden. // Wenn Sie USB-Strom verwenden, ändern Sie die analoge Referenz auf den 3,3-V-Pin, da zu viel Rauschen auf der +5-V-Schiene vorhanden ist, um eine gute Empfindlichkeit zu erzielen.#include  #include #define max_ampAverage 200LiquidCrystal lcd(6, 7, 10, 11, 12, 13);LcdBarGraph lbg(&lcd, 16, 0, 1); #define TIMER1_TOP (259) // kann dies einstellen, um die Frequenz fein abzustimmen, um die Spule abzustimmen (siehe oben) atmega28p ohne 3,3-V-Versorgung verfügbar // Digitale Pin-Definitionen // Digitaler Pin 0 nicht verwendet, aber wenn wir den seriellen Port zum Debuggen verwenden, dann ist es serieller Inputconst int debugTxPin =1; // Sende-Pin reserviert für Debuggingconst Int EncoderButtonPin =2; // Encoder-Taste, auch IN0 zum Aufwachen aus dem Schlafmodusconst int earpiecePin =3; // Hörmuschel, auch bekannt als OCR2B zur Tonerzeugungconst int T0InputPin =4;const int coilDrivePin =5;const int LcdRsPin =6;const int LcdEnPin =7;const int LcdPowerPin =8; // LCD-Stromversorgung und Hintergrundbeleuchtung aktivierenconst int T0OutputPin =9; const int lcdD4Pin =10; const int lcdD5Pin =11; // Pins 11-13 werden auch für ICSP verwendet const int LcdD6Pin =12;const int LcdD7Pin =13;// Analoge Pindefinitionenconst int receiverInputPin =0;const int encoderAPin =A1;const int encoderBpin =A2;// Analogpins 3-5 nicht verwendet // Variablen, die nur von den ISRint16_t-Bins verwendet werden[4]; // Bins, die verwendet werden, um ADC-Messwerte zu akkumulieren, eine für jede der 4 phaseuint16_t numSamples =0;const uint16_t numSamplesToAverage =1024; // Variablen, die vom ISR und außerhalb von itvolatile int16_t Averages verwendet werden[4]; // Wenn wir genügend Messwerte in den Bins gesammelt haben, kopiert der ISR sie hierher und startet erneutvolatile uint32_t ticks =0; // System-Tick-Zähler für timekeepingvolatile bool sampleReady =false; // zeigt an, dass das Array der Mittelwerte aktualisiert wurde // Variablen, die nur außerhalb von ISRint16_t calib[4] verwendet werden; // Werte (während der Kalibrierung eingestellt), die wir vom Durchschnitt subtrahierenvolatile uint8_t lastctr;volatile uint16_t misses =0; // dies zählt, wie oft der ISR zu spät ausgeführt wurde. Sollte auf Null bleiben, wenn alles richtig funktioniert.const double halfRoot2 =sqrt(0.5);const double quarterPi =3.1415927/4.0;const double radiansToDegrees =180.0/3.1415927;// Das ADC-Sampling und Halten erfolgt 2 ADC-Takte (=32 System Clocks), nachdem das Überlauf-Flag von Timer 1 gesetzt wurde. // Dies führt zu einem leichten Phasenfehler, den wir in den Berechnungen ausgleichen. const float phaseAdjust =(45,0 * 32,0)/(float)(TIMER1_TOP + 1); 5,0; // niedriger =höhere Empfindlichkeit. 10 ist mit einer gut ausbalancierten Spule gerade noch brauchbar. // Der Benutzer kann dies über einen Pot oder einen Drehregler einstellen.void setup () { lcd.begin (16, 2); // LCD 16X2 pinMode (encoderButtonPin, INPUT_PULLUP); digitalWrite (T0OutputPin, LOW); pinMode (T0OutputPin, AUSGANG); // Impulsstift von Timer 1 verwendet, um Timer 0 zu speisen DigitalWrite (coilDrivePin, LOW); pinMode (coilDrivePin, AUSGANG); // Timer 0-Ausgang, Rechteckwelle zum Ansteuern der Sendespule cli (); // Stoppen Sie den Timer 0, der vom Arduino-Kern eingerichtet wurde TCCR0B =0; // Stoppen Sie den Timer TIMSK0 =0; // Interrupt deaktivieren TIFR0 =0x07; // alle anstehenden Unterbrechungen löschen // ADC zum Triggern und Lesen von Kanal 0 bei Timer 1-Überlauf einrichten #if USE_3V3_AREF ADMUX =(1 <> 8); OCR1AL =(TIMER1_TOP/2 &0xFF); ICR1H =(TIMER1_TOP>> 8); ICR1L =(TIMER1_TOP &0xFF); TCNT1H =0; TCNT1L =0; TIFR1 =0x07; // alle anstehenden Unterbrechungen löschen TIMSK1 =(1 <
 15000) *p =15000; } sonst { *p -=val; wenn (*p <-15000) *p =-15000; } if (ctr ==7) { ++numSamples; if (numSamples ==numSamplesToAverage) { numSamples =0; if (!sampleReady) // wenn das vorherige Sample verbraucht wurde { memcpy((void*)averages, bins, sizeof(averages)); sampleReady =wahr; } memset(bins, 0, sizeof(bins)); } }}void loop(){ while (!sampleReady) {} uint32_t oldTicks =ticks; if (digitalRead(encoderButtonPin) ==LOW) {// Taste kalibrieren gedrückt. Wir speichern die aktuellen Phasendetektorausgaben und subtrahieren sie von zukünftigen Ergebnissen. // Dadurch können wir den Detektor verwenden, wenn die Spule leicht aus dem Gleichgewicht geraten ist. // Es wäre besser, mehrere Proben zu nehmen, anstatt nur eine zu nehmen. for (int i =0; i <4; ++i) { calib[i] =Durchschnitte[i]; } sampleReady =false; Serial.print ("Kalibriert:"); lcd.setCursor(0,0); lcd.print("Kalibrieren..."); for (int i =0; i <4; ++i) { Serial.write (' '); Serial.print (kalib[i]); lcd.setCursor(0,1); lcd.print(' '); lcd.print (kalibrieren[4]); lcd.print(" "); } Serial.println(); } Else { for (int i =0; i <4; ++i) { Averages[i] -=calib[i]; } const double f =200,0; // Massiere die Ergebnisse, um die Empfindlichkeit gegenüber der 3. Harmonischen zu beseitigen, und dividiere durch 200 double bin0 =(averages[0] + halfRoot2 * (averages[1] - means[3]))/f; double bin1 =(Mittelwerte[1] + halfRoot2 * (Mittelwerte[0] + Mittelwerte[2]))/f; double bin2 =(Mittelwerte[2] + halfRoot2 * (Mittelwerte[1] + Mittelwerte[3]))/f; double bin3 =(Mittelwerte[3] + halfRoot2 * (Mittelwerte[2] - Mittelwerte[0]))/f; sampleReady =false; // wir haben die Durchschnittswerte gelesen, sodass der ISR sie wieder überschreiben kann double amp1 =sqrt((bin0 * bin0) + (bin2 * bin2)); double amp2 =sqrt((bin1 * bin1) + (bin3 * bin3)); doppelter ampAverage =(amp1 + amp2)/2.0; // Der ADC-Sample/Hold erfolgt 2 Takte nach dem Timer-Überlauf double phase1 =atan2(bin0, bin2) * radiansToDegrees + 45.0; Doppelphase2 =atan2(bin1, bin3) * radiansToDegrees; if (phase1> phase2) { double temp =phase1; Phase1 =Phase2; Phase2 =Temperatur; } double phaseAverage =((phase1 + phase2)/2.0) - phaseAdjust; if (phase2 - phase1> 180,0) { if (phaseAverage <0,0) { phaseAverage +=180,0; aufrechtzuerhalten. Sonst { phaseAverage -=180.0; } } // Drucken Sie zu Diagnosezwecken die einzelnen Bin-Zählungen und die 2 unabhängig berechneten Verstärkungen und Phasen Serial.print (misses); Serial.write(' '); if (bin0>=0.0) Serial.write(' '); Serial.print (bin0, 2); Serial.write(' '); if (bin1>=0.0) Serial.write(' '); Serial.print (bin1, 2); Serial.write(' '); if (bin2>=0.0) Serial.write(' '); Serial.print (bin2, 2); Serial.write(' '); if (bin3>=0.0) Serial.write(' '); Serial.print (bin3, 2); Serial.print ( " "); Serial.print (amp1, 2); Serial.write(' '); Serial.print (amp2, 2); Serial.write(' '); if (phase1>=0.0) Serial.write(' '); Serial.print (Phase1, 2); Serial.write(' '); if (phase2>=0.0) Serial.write(' '); Serial.print (Phase2, 2); Serial.print ( " "); // Ausgabe der endgültigen Amplitude und Phase, die wir verwenden, um zu entscheiden, was (wenn überhaupt) wir gefunden haben) if (ampAverage>=0.0) Serial.write (' '); Serial.print (ampAverage, 1); Serial.write(' '); lcd.setCursor(0,0); lcd.print(" "); lcd.print (ampAverage); lcd.setCursor(0,1); lbg.drawValue(ampAverage, max_ampAverage); if (phaseAverage>=0.0) Serial.write(' '); Serial.print ((int)phaseAverage); // Entscheiden Sie, was wir gefunden haben und teilen Sie dem Benutzer mit, ob (ampAverage>=threshold) { // In einer Linie mit der Spulenmitte gehalten:// - Nichteisenmetalle ergeben eine negative Phasenverschiebung, z. -90deg für dickes Kupfer oder Aluminium, eine Kupferolive, -30deg für dünnes Aluminium. // Eisenmetalle ergeben eine Phasenverschiebung von null oder eine kleine positive Phasenverschiebung. // Also sagen wir, dass alles mit einer Phasenverschiebung unter -20deg nicht eisenhaltig ist. if (phaseAverage <-20,0) {Serial.print ("Nichteisen"); lcd.setCursor(0,0); lcd.print("Nichteisenhaltig"); } sonst {Serial.print ( "Eisen"); lcd.setCursor(0,0); lcd.print("Eisen"); } Float Temp =Ampere Durchschnitt; int thisPitch =map (temp, 10, 200, 100, 1500); Ton (3, diese Tonhöhe, 120); while (temp>
 Schwellenwert) { Serial.write ('!'); temp -=(Schwelle/2); } } Serial.println(); } while (ticks - oldTicks <8000) { } }
LcdBarGraph lib.C/C++
Keine Vorschau (nur Download).

Schaltpläne


Herstellungsprozess

  1. Einfacher DIY-Baby-Weindetektor mit Raspberry Pi
  2. DIY einfachste IV9 Numitron-Uhr mit Arduino
  3. Arduino-Gyroskop-Spiel mit MPU-6050
  4. empfindlicher DIY-Erdbebendetektor ADXL335
  5. DIY Voltmeter mit Arduino und einem Nokia 5110 Display
  6. MobBob:DIY-Arduino-Roboter, der von einem Android-Smartphone gesteuert wird
  7. DIY Einfaches Messrad mit Drehgeber
  8. IoT-Messgerät mit Arduino, Yaler und IFTTT
  9. DIY-Luftqualitätsmonitor mit Sharp GP2Y1010AU0F-Sensor
  10. Handheld-Geigerzähler mit Arduino Nano