Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

DIY Sensitive Arduino IB Metal Detector com Discriminação

Componentes e suprimentos

Arduino Nano R3
× 1
Adafruit LCD padrão - 16x2 branco em azul
× 1
IC Amplificador Operacional TL081
× 1
Alto-falante:0,25 W, 8 ohms
× 1
Transistor de uso geral NPN
× 1
Bobinas de pesquisa
× 2
Resistores, capacitores
× 1

Aplicativos e serviços online

Arduino IDE

Sobre este projeto


Desta vez, vou mostrar como fazer um detector de metal sensível também capaz de discriminar entre materiais ferrosos e não ferrosos. A sensibilidade é satisfatória, visto que se trata de um dispositivo relativamente simples.

Este projeto é patrocinado pela PCBgogo:

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

Esta é uma continuação do projeto de David Crocker apresentado no Arduino CC Forum em 2013. Decidi testar seu código porque não encontrei nenhuma evidência (foto ou vídeo) de que este detector de metal foi feito por alguém e funciona bem.

Primeiro fiz uma versão básica com o código apresentado no GitHub, para ter certeza da funcionalidade do dispositivo e depois atualizei o código para que tenha um sinal audível, e em um display LCD 16 em 2 informações visuais sobre o tipo de objeto detectado (material ferroso ou não ferroso) e gráfico de barras LCD para a proximidade dos objetos detectados.

O dispositivo é muito simples de construir e consiste em apenas alguns componentes:

- Microcontrolador Arduino Nano

- Amplificador operacional (no meu caso LT1677, mas você pode usar TL081 ou 741)

- Poucos resistores e capacitores

- Pequeno transistor e alto-falante

- Tela de LCD

- 3 interruptores

- Potenciômetro

- bateria

- E bobinas de busca

Esta é uma tecnologia de detector de equilíbrio por indução VLF (frequência muito baixa) e contém duas bobinas idênticas:bobina transmissora e bobina receptora. Como acontece com todos os detectores de equilíbrio por indução, o equilíbrio da bobina é muito crítico. O potenciômetro é usado para zerar o pequeno componente fora de fase de 90 graus do sinal. (o componente em fase é anulado ajustando a colocação relativa das bobinas no estilo típico de detector IB). Cada uma das bobinas é enrolada em um corpo de 11 cm usando 64 voltas de fio de cobre esmaltado de 0,5 mm ^ 2 em forma de D, enrolado em fita adesiva, peneirado usando folha de alumínio amarrado com fio de cobre estanhado (tomando cuidado para deixar uma pequena lacuna para que a tela não se comporta como uma curva em curto) e os embrulhei em uma placa de plástico.

Primeiro, precisamos determinar a frequência ressonante paralela do circuito do capacitor da bobina primária usando uma das muitas calculadoras online. Eu medi com um osciloscópio, mas se você seguir as dimensões fornecidas acima, será exatamente 7,64 kHz, então você pode inserir diretamente o valor fornecido no código. No caso de outro valor da frequência de ressonância, precisamos fazer uma mudança apropriada no código na fila:

#define TIMER1_TOP (249) // ajuste a frequência

Como você pode ver no vídeo, os resultados são surpreendentemente bons. Sem a presença de metal, o dispositivo é perfeitamente estável. O alcance é relativamente grande e, por exemplo, uma tampa de metal com um diâmetro de 15 cm é detectada a uma distância de mais de 30 cm. Objetos de metal maiores são detectados em distâncias maiores que 40-50 cm. Podemos detectar uma pequena moeda a uma distância de 15 cm no ar. Eu uso duas baterias de lítio para a fonte de alimentação que estão conectadas em série (7,4 volts) e esta tensão é conectada à entrada Vin do Arduino. O consumo não excede 20 mA, portanto as baterias duram muito tempo. O vídeo descreve em detalhes a construção de todo o dispositivo.

Estes são apenas resultados preliminares. Existe a possibilidade de melhorar significativamente a sensibilidade inserindo um transistor MOSFET de potência para acionar a bobina Tx, mas irei testá-lo e apresentá-lo em um dos vídeos a seguir.

Código

  • Código Arduino
  • LcdBarGraph lib.
Código Arduino Arduino
 // Detector de indução de metal de equilíbrio // Executamos a CPU a 16 MHz e o relógio ADC a 1 MHz. A resolução do ADC é reduzida para 8 bits nessa velocidade.// O temporizador 1 é usado para dividir o clock do sistema por cerca de 256 para produzir uma onda quadrada de 62,5 kHz. // Isso é usado para acionar o temporizador 0 e também para acionar as conversões ADC.// O temporizador 0 é usado para dividir a saída do temporizador 1 por 8, dando um sinal de 7,8125 kHz para acionar a bobina de transmissão.// Isso nos dá 16 ADC ciclos de clock para cada conversão de ADC (na verdade leva 13,5 ciclos), e tomamos 8 amostras por ciclo da tensão de acionamento da bobina .// O ADC implementa quatro detectores sensíveis à fase em intervalos de 45 graus. Usar 4 em vez de apenas 2 nos permite cancelar o terceiro harmônico da // frequência da bobina.// O temporizador 2 será usado para gerar um tom para o fone de ouvido ou fone de ouvido.// Outras relações de divisão para o temporizador 1 são possíveis, a partir de cerca de 235 upwards.// Fiação:// Conecte o pino digital 4 (alias T0) ao pino digital 9 // Conecte o pino digital 5 através do resistor à bobina primária e capacitor de sintonia // Conecte a saída do amplificador de recepção ao pino 0 analógico. o amplificador deve ser inclinado para cerca de metade da referência analógica.// Ao usar alimentação USB, mude a referência analógica para o pino de 3,3 V, porque há muito ruído no trilho de + 5 V para obter boa sensibilidade. # include  #include  #define max_ampAadise 200LiquidCrystal lcd (6, 7, 10, 11, 12, 13); LcdBarGraph lbg (&lcd, 16, 0, 1); #define TIMER1_TOP (259) // pode ajustar isso para ajustar a frequência para obter a bobina sintonizada (veja acima) #define USE_3V3_AREF (1) // definido como 1 de execução em um Arduino com alimentação USB, 0 para um incorporado atmega28p sem alimentação de 3,3 V disponível // Definições de pinos digitais // Pino digital 0 não usado, no entanto, se estivermos usando a porta serial para depuração, então é entrada serialconst int debugTxPin =1; // transmitir o pino reservado para debuggingconst int encoderButtonPin =2; // botão do codificador, também IN0 para acordar do modo de hibernação int earpiecePin =3; // fone de ouvido, também conhecido como OCR2B para geração de tomconst int T0InputPin =4; const int coilDrivePin =5; const int LcdRsPin =6; const int LcdEnPin =7; const int LcdPowerPin =8; // Ativação da energia e luz de fundo do LCDconst int T0OutputPin =9; const int lcdD4Pin =10; const int lcdD5Pin =11; // pinos 11-13 também usados ​​para ICSPconst int LcdD6Pin =12; const int LcdD7Pin =13; // Definições de pinos analógicosconst int receiverInputPin =0; const int encoderAPin =A1; const int encoderBpin =A2; // Pinos analógicos 3-5 não usado // Variáveis ​​usadas apenas pelos ISRint16_t bins [4]; // bins usados ​​para acumular leituras de ADC, um para cada um dos 4 phaseuint16_t numSamples =0; const uint16_t numSamplesToA band =1024; // Variáveis ​​usadas pelo ISR e fora itvolatile int16_t averages [4]; // quando acumulamos leituras suficientes nas caixas, o ISR as copia para aqui e começa novamente volátil uint32_t ticks =0; // contador de tiques do sistema para timekeepingvolatile bool sampleReady =false; // indica que a matriz de médias foi atualizada // Variáveis ​​usadas somente fora do ISRint16_t calib [4]; // valores (definidos durante a calibração) que subtraímos das médias uint8_t lastctr; volatile uint16_t misses =0; // isso conta quantas vezes o ISR foi executado tarde demais. Deve permanecer em zero se tudo estiver funcionando corretamente.const double halfRoot2 =sqrt (0,5); const double quarterPi =3,1415927 / 4,0; const double radiansToDegrees =180,0 / 3,1415927; // A amostra ADC e reter ocorre 2 relógios ADC (=32 sistema relógios) depois que o sinalizador de estouro do temporizador 1 é definido.// Isso introduz um pequeno erro de fase, que ajustamos nos cálculos.const float phaseAdjust =(45,0 * 32,0) / (float) (TIMER1_TOP + 1); limite de flutuação =5,0; // inferior =maior sensibilidade. 10 é quase utilizável com uma bobina bem balanceada. // O usuário poderá ajustar isso por meio de um potenciômetro ou encoder rotativo.void setup () {lcd.begin (16, 2); // LCD 16X2 pinMode (encoderButtonPin, INPUT_PULLUP); digitalWrite (T0OutputPin, LOW); pinMode (T0OutputPin, OUTPUT); // pino de pulso do temporizador 1 usado para alimentar o temporizador 0 digitalWrite (coilDrivePin, LOW); pinMode (coilDrivePin, OUTPUT); // saída do temporizador 0, onda quadrada para conduzir a bobina de transmissão cli (); // Pare o cronômetro 0 que foi configurado pelo núcleo do Arduino TCCR0B =0; // parar o cronômetro TIMSK0 =0; // desativa a interrupção TIFR0 =0x07; // limpa qualquer interrupção pendente // Configure o ADC para acionar e ler o canal 0 no estouro do temporizador 1 # 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; // limpa qualquer interrupção pendente TIMSK1 =(1 <
 15.000) * p =15.000; } else {* p - =val; if (* p <-15000) * p =-15000; } if (ctr ==7) {++ numSamples; if (numSamples ==numSamplesToA band) {numSamples =0; if (! sampleReady) // se a amostra anterior foi consumida {memcpy ((void *) médias, bins, sizeof (médias)); sampleReady =true; } memset (bins, 0, sizeof (bins)); }}} void loop () {while (! sampleReady) {} uint32_t oldTicks =ticks; if (digitalRead (encoderButtonPin) ==LOW) {// Botão de calibração pressionado. Salvamos as saídas do detector de fase atual e as subtraímos dos resultados futuros. // Isso nos permite usar o detector se a bobina estiver ligeiramente desequilibrada. // Seria melhor administrar várias amostras ao invés de apenas uma. para (int i =0; i <4; ++ i) {calib [i] =médias [i]; } sampleReady =false; Serial.print ("Calibrado:"); lcd.setCursor (0,0); lcd.print ("Calibrando ..."); para (int i =0; i <4; ++ i) {Serial.write (''); Serial.print (calib [i]); lcd.setCursor (0,1); lcd.print (''); lcd.print (calib [4]); lcd.print (""); } Serial.println (); } else {for (int i =0; i <4; ++ i) {médias [i] - =calib [i]; } const double f =200,0; // Massageie os resultados para eliminar a sensibilidade ao 3º harmônico e divida por 200 double bin0 =(médias [0] + halfRoot2 * (médias [1] - médias [3])) / f; double bin1 =(médias [1] + halfRoot2 * (médias [0] + médias [2])) / f; double bin2 =(médias [2] + halfRoot2 * (médias [1] + médias [3])) / f; double bin3 =(médias [3] + halfRoot2 * (médias [2] - médias [0])) / f; sampleReady =false; // terminamos de ler as médias, então o ISR está livre para sobrescrevê-las novamente double amp1 =sqrt ((bin0 * bin0) + (bin2 * bin2)); duplo amp2 =sqrt ((bin1 * bin1) + (bin3 * bin3)); ampA Average =(amp1 + amp2) /2.0; // A amostra / retenção ADC ocorre 2 relógios após o estouro do temporizador double phase1 =atan2 (bin0, bin2) * radiansToDegrees + 45.0; fase dupla2 =atan2 (bin1, bin3) * radiansToDegrees; if (fase 1> fase 2) {temperatura dupla =fase 1; fase1 =fase2; fase 2 =temp; } double phaseA Average =((phase1 + phase2) /2.0) - phaseAdjust; if (phase2 - phase1> 180.0) {if (phaseA average <0.0) {phaseAeaning + =180.0; } else {phaseA Average - =180.0; }} // Para fins de diagnóstico, imprime as contagens de bin individuais e os 2 ganhos e fases calculados independentemente 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 (fase1> =0,0) Serial.write (''); Serial.print (fase 1, 2); Serial.write (''); if (fase2> =0,0) Serial.write (''); Serial.print (fase 2, 2); Serial.print (""); // Imprime a amplitude e a fase final, que usamos para decidir o que (se houver alguma coisa) encontramos) if (ampA taking> =0.0) Serial.write (''); Serial.print (ampA Average, 1); Serial.write (''); lcd.setCursor (0,0); lcd.print (""); lcd.print (ampA Average); lcd.setCursor (0,1); lbg.drawValue (ampAadise, max_ampAffet); if (phaseA Average> =0.0) Serial.write (''); Serial.print ((int) phaseAometric); // Decida o que encontramos e diga ao usuário if (ampA Average> =threshold) {// Quando mantido em linha com o centro da bobina:// - metais não ferrosos fornecem uma mudança de fase negativa, por ex. -90deg para cobre espesso ou alumínio, uma azeitona de cobre, -30deg para alumímio fino. // Metais ferrosos fornecem mudança de fase zero ou uma pequena mudança de fase positiva. // Então, diremos que qualquer coisa com um deslocamento de fase abaixo de -20deg é não ferroso. if (phaseA average <-20.0) {Serial.print ("Non-ferrous"); lcd.setCursor (0,0); lcd.print ("NonFerous"); } else {Serial.print ("Ferroso"); lcd.setCursor (0,0); lcd.print ("Ferroso"); } float temp =ampA Average; int thisPitch =map (temp, 10, 200, 100, 1500); tom (3, thisPitch, 120); while (temp>
 threshold) {Serial.write ('!'); temp - =(limite / 2); }} Serial.println (); } while (ticks - oldTicks <8000) {}} 
LcdBarGraph lib. C / C ++
 Sem visualização (somente download). 

Esquemas


Processo de manufatura

  1. Fácil detector de choro de bebê faça você mesmo com Raspberry Pi
  2. DIY mais simples relógio IV9 Numitron com Arduino
  3. Jogo Arduino Gyroscope com MPU-6050
  4. Detector de terremotos ADXL335 sensível a DIY
  5. Voltímetro DIY com Arduino e um visor Nokia 5110
  6. MobBob:DIY Arduino Robot Controlado por Smartphone Android
  7. Roda de medição simples DIY com codificador rotativo
  8. IoT Gauge com Arduino, Yaler e IFTTT
  9. Monitor de qualidade do ar faça você mesmo com sensor Sharp GP2Y1010AU0F
  10. Contador Geiger portátil com Arduino Nano