Измеряем толщину ЛКП на Arduino

Публикация 17.05.2017

Измерение толщины лакокрасочного покрытия автомобиля сводится к простому измерению индуктивности катушки с полуоткрытым сердечником.

Толщиномер ЛКП Arduino

Самая сложная часть нашей установки - катушка индуктивности. Она состоит из одной обмотки внутри половинки броневого ферритового сердечника из какой-то радио аппаратуры. Если мы будем прислонять катушку открытой стороной к эелезной пластине (кузову), то чем меньше зазор между обкладками ферритового корпуса, то тем выше индуктивность. Параметры катушки серьезного значения не имеют т.к. схема будет калиброваться.
В моем случае использовалась проволока 0.08 мм для намотки порядка 100 витков. Что бы увеличить ответный сигнал с катушки цепляем параллельно металлопленочный конденсатор 100 пф. Получился колебательный контур чувствительный к толщине ЛКП.

Датчик ЛКП

Измерять частоту колебаний контура будет Arduino Nano. В зависимости от результатов измерений будут зажигаться 7 диодов-индикаторов. Они будут сигнализировать о толщине окрашенной панели. При правильной калибровке у незамкнутого сердечника магнитопровода будут гареть все диоды (металла нет - шпаклевка), при замыкании вплотную к голому металлу должен гореть один диод (металл). Чувствительность срабатывания остальных индикаторов нужно измерять экспериментально под вашу катушку.

Схема измерителя толщины ЛКП на Arduino

Перед использованием измерителя толщины краски нужно выполнить калибровку. Прикладываем датчик к голому магнитному металлу (сталь) и нажимаем кнопку "калибровка". Тем самым в энергонезависимую память Arduino будет сохранен коэффициент измерения. От него будет выполняться отсчет остальных уровней индикации.
Для выполнения измерения прикладываем датчик к кузову автомобиля и нажимаем вторую кнопку "измерение". Индикаторы покажут измеренную толщину краски на кузове.

Измеряем толщину ЛКП на Arduino

Скетч программы для Arduino:

// программа - Измеритель-толщины покрытия. 
// идея отсюда: https://github.com/sae/Arduino-LCQmeter/blob/master/LC-gen.ino
/*
simplest LC-generator on arduino
can be used as lc-meter
(C)SAE762 07.feb.2015 @home
circuit diagramm D2---R(100...1000)---D6---LC---GND; D7---GND
*/

#include <EEPROM.h> // библиотека чтения-записи eeprom 
#include "analogComp.h" // библиотека, скчана с гитхаба

/* проверка работы eeprom
 */
 //***************** ФУНКЦИИ***********
 //This function will write a 2 byte integer to the eeprom at the specified address and address + 1
 // эта функия записывает двухбайтовое целое число в РППЗУ по указанному адресу

void EEPROMWriteInt(int p_address, int p_value)
 
        {
        byte lowByte = ((p_value >> 0) & 0xFF);
        byte highByte = ((p_value >> 8) & 0xFF);

        EEPROM.write(p_address, lowByte);
        EEPROM.write(p_address + 1, highByte);
        }

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
// эта функия считывает двухбайтовое целое число в РППЗУ по указанному адресу

unsigned int EEPROMReadInt(int p_address)
        {
        byte lowByte = EEPROM.read(p_address);
        byte highByte = EEPROM.read(p_address + 1);

        return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
        }
//********конец объявления фунций************
//обявление переменных     
int ctl=2 ; // нога для накачки энергии в контур
int led=13; // нога светодиода

int rise=0; // счетчик переходов через 0
int fall=0; // такой же стетчик
int summ; //накопительный счетчик
int tchk=300; // время измерения
int zero=11625; //отладка
int delta=0; //разница между содержимым eeprom и результатом измерения

//присвоим номера пинов светодиодов
int vbat=0;  //напряжение батареи
int vbatpin=6; // аналог вход 6
int mredled=3; // красный светодиод -
int mblueled=4; //синий светодиод -
int mwhiteled=5;//белый светодиод -
int greenled=8;//зеленый светодиод
int pwhiteled=9;//белый светодиод +
int pblueled=10; //синий +
int predled=11; //красный +
// присвоим границы 
//++++++++++++++++++++++++++++++++
// тут придется внести ВАШИ значения!!!!
//===============================
int pgreen=25; // граница ОК  в плюс
int mgreen=-10;// в минус
int pwhite=55; // граница подозрительно в +
int mwhite=-30;// подозрительно в -
int pblue=100; // крашено 
int mblue=-60; // шлифовано
//int pred=130; // шпаклевка
//int mred=-60;//металл



void setup() {
  // put your setup code here, to run once:
  summ=0;// инициализация накопителя
   Serial.begin(9600); // настроим порт УБРАТЬ ПОСЛЕ ОТЛАДКИ
   pinMode(led, OUTPUT); // 
   pinMode(ctl, OUTPUT); // инициализация выхода накачки
      //настроим выхода под светодиоды
   pinMode(mredled, OUTPUT);
   digitalWrite(mredled, HIGH);
   pinMode(mblueled, OUTPUT);
   digitalWrite(mblueled, HIGH);
   pinMode(mwhiteled, OUTPUT); 
   digitalWrite(mwhiteled, HIGH);
   pinMode(greenled, OUTPUT); 
   digitalWrite(greenled, HIGH);
   pinMode(pwhiteled, OUTPUT); 
   digitalWrite(pwhiteled, HIGH);
   pinMode(pblueled, OUTPUT);
  digitalWrite(pblueled, HIGH); 
   pinMode(predled, OUTPUT); 
  digitalWrite(predled, HIGH); 
   
// тут можно дорожку сделать для индикации светодиодов, если очень хочется
// инициализация компаратора и прерываний
   digitalWrite(ctl, LOW);
  analogComparator.setOn(AIN0, AIN1);//D6+,D7- 
  analogComparator.enableInterrupt(comparatorInt,CHANGE);
  // проверка режима работа/установка 0
   vbat = analogRead(vbatpin);     // считываем значение 
  if (vbat>50) {  // если напруга больше 0 запускаем установку 0
  rise=0;
  // индикация разряженной батареи, но установка 0 продолжается
  if (vbat < 700) {digitalWrite(mredled, LOW);digitalWrite(predled, LOW);}
  //if no pulses, make a start impulse
  if (rise==0) {
    pulse();
  }
    // первый проход
  summ=0;
digitalWrite(led, LOW);   
  rise=0;
  fall=0;
  delay(tchk);              // wait for a second
  //Serial.println(rise);    // вывод на псолед порт, убрать после отладки
  summ=summ+rise;
  // второй проход
  rise=0;
  fall=0;
  delay(tchk);              // wait for a second
  summ=summ+rise;
  //третий проход
   rise=0;
  fall=0;
  delay(tchk);              // wait for a second
  summ=summ+rise-15;  // -15 странный костыль видимо недосчет во время обработки прерывания
//  Serial.print(summ);  // убрать после отладки
  //вычислим среднее
  summ=summ/3;  // вот это и есть измренное значение по результатам трех проходов
// это условная толщина покрытия в попугаях
// зная ее, можно с помомощью нехитрых арифметических действий, определить реальную толщину покрытия
//то есть померить калиброванную пленку разной толщины, записать результаты, а потом подобрать коэффициенты.

  digitalWrite(led, HIGH); 
    EEPROMWriteInt(0,summ); //занесем в eeprom 
    digitalWrite(greenled, LOW); // зажжем зелененький
    while (1); // застопорить нахрен после установки 0 !!!!!!!
                  }
}
// конец процедуры установки  
 // тут переход к процедуре измерения 
//!!!!!Главный цикл!!!
void loop() {
  // тут процедура измерения
  rise=0;
  //Serial.println(EEPROMReadInt(0));             // выводим полученное значение
  //if no pulses, make a start impulse
  if (rise==0) {
    pulse();
  }
  // первый проход
  summ=0;
digitalWrite(led, LOW);   
  rise=0;
  fall=0;
  delay(tchk);              // wait for a second
  summ=summ+rise;
  // второй проход
 rise=0;
  fall=0;
  delay(tchk);              // wait for a second
  summ=summ+rise;
  //третий проход
   rise=0;
  fall=0;
  delay(tchk);              // wait for a second
  summ=summ+rise;
//  Serial.print(rise);
  //вычислим среднее
  summ=summ/3;
  delta=summ-EEPROMReadInt(0);
Serial.print(EEPROMReadInt(0));             // из памяти  
Serial.print(";");
 Serial.print(delta);
  Serial.println(" pulses/tchk");
  digitalWrite(led, HIGH);    
 if (delta >= mgreen && delta <= pgreen ) {digitalWrite(greenled, LOW);} 
 if (delta < mblue) digitalWrite(mredled, LOW);
 if (delta >= mblue && delta < mwhite ) digitalWrite(mblueled, LOW); 
 if (delta >= mwhite && delta < mgreen) digitalWrite(mwhiteled, LOW);
 if (delta > pblue) digitalWrite (predled,LOW);
 if (delta > pwhite && delta <= pblue) digitalWrite (pblueled,LOW);
 if (delta > pgreen && delta <= pwhite) digitalWrite (pwhiteled,LOW); 
 while (1);  /// тормоза. измерение окончено
 delay(1000);              // wait for a second


}





/**
not so clear "magic" with interrupt
we need to block int's when make a power impulse
comparator is connected directly to capacitor
*/
boolean waitforRise=false;

//this function is called when comparator change status
//as set in ACSR register
void comparatorInt() {
  
  if (waitforRise) { //if we waiting for rise
    ACSR &= ~(1<<ACIS0);//set interrupt for falling
    ACSR |= (1<<ACIS1);
    waitforRise=false;
    rise++;
  } else { //if we waiting for fall
   ACSR &= ~(1<<ACIE); //disable interrupt
    //impulse to support an oscillations
   pulse();
   ACSR |= (1<<ACIE); //enable interrupt
   ACSR |= ((1<<ACIS1) | (1<<ACIS0)); //set interrupt for rising
   waitforRise=true;
  }
}

//send power impulse to LC
void pulse() {
   pinMode(ctl, OUTPUT);
   digitalWrite(ctl, HIGH);
   rise++;//make something useless )
   //digitalWrite(ctl, LOW);
   pinMode(ctl, INPUT);
}

Устройство не гарантирует точность измерений т.к. в нем не учитывается температура и уровень напряжения питания устройства. Эти переменные могут вилять на результат измерения, что в свою очередь увеличит погрешность измерения.

* комментарии публикуются после модерации
Нет комментариев