Страница 1 из 1

Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Пн сен 07, 2015 11:46:51
Draghkon
Здравствуйте!
Соображаю банальную поливалку для цветов на Ардуино. Чтобы не спалить насос, нужно понимать что вода в баке достигла некоего минимума.
Морочится было лень, так что я решил схалтурить: сунуть витую пару в пластиковую трубочку, один провод зачистилна самом конце трубки, другой на нужном уровне срабатывания. Т.е. идея банальна: получать на цифровом входе 1 - когда уровень воды достаточный и 0 - когда уровень ниже минимума и контакты разомкнутны.
Когда весь код уже был написан, при тестировании столкнулся с проблемой именно в этом узле: сопротивление водопроводной воды оказалось слишком высоким, чтобы давать логическую 1, когда между контактами более нескольких мм, а нужно срабатывание на расстоянии в 5-7см.
Конечно стоило бы сделать простой поплавок на герконах, но теперь уже поздно.

Я так понимаю, что нужно сделать усилитель. к сожалению в радиоэлектронике полный нуб, поэтому прошу вашей помощи.

Недавно делал релейный модуль для этого же проекта (моя первая печатная плата) - так что попробовал накидать схему по аналогии:

Изображение

Но чую что не будет работать... А если и будет, то чую что нужно как-то ограничить ток и напряжение которое будет приходить на пин контроллера, т.к. сопротивление раствора может быть не постоянным (удобрение вместо воды), да и вообще контакты может случайно замкнуть, так что "максимальный" сигнал не должен сжечь плату.
Прошу советов. Спасибо.

Re: Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Пн сен 07, 2015 13:47:12
Morroc
Подключите к АЦП и настройте порог срабатывания :dont_know: Слишком высокое сопротивление - это сколько в цифрах ? Как вариант не подтягивайте внутренним резистором ножку, а поставьте свой с бОльшим сопротивлением (1-2 МОм или даже больше).

Вы бы выложили код и схему (можно на бумажке и сфоткать), а то кто вас знает что за девайс соорудили :))

Re: Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Пн сен 07, 2015 21:25:12
Draghkon
Благодарю.. к аналоговому входу цеплять не хотелось бы, чтобы не электролизировать воду.
Заменил подтягивающий к земле резистор (10К) на 1Мом - действительно появились показания.. Значит делитель напряжения работает так, что чем больше подтягивающий резистор, тем чувствительнее?
но показания какие-то хаотичные - показывает 0, в следующий раз 1, потом несколько раз подряд 0 может быть, несколько раз 1 и т.д. причем если соединить провода накоротко - то показания стабильные, хотя и появляются на 2-3й интерации опроса.
т.е. контакт разомкнут в сериале пишет:

Код: Выделить всё

alarmLvl=1;
//замыкаю контакт
alarmLvl=1;
alarmLvl=1;
//WTF???
alarmLvl=0;
/снова размыкаю контакт
alarmLvl=0;
alarmLvl=0;
alarmLvl=1;
возможно это связано с тем что digitalRead использует какой-нибудь средневзвешенный способ чтобы перевести сигнал в 0-1, поэтому такие лаги, иначе просто мистика..


на всякий случай вот схема подключения:
Изображение

А вот кусок кода относящийся к делу:

Код: Выделить всё

#include <SimpleTimer.h>

#define aLvlPin 8 //уровень жидкости сигнальный
#define critLvlPin 7 //critical level of water
#define lvlTime 10000 //10сек

boolean critLvl = true;
boolean alarmLvl = true;
byte lvlCheckId=255;

SimpleTimer timer; //timer object

void setup()
{
	Serial.begin(19200);
	//pinMode(relePin, OUTPUT);
	//pinMode(ledPin, OUTPUT);
	pinMode((aLvlPin, critLvlPin, perPin, durPin, sunPin), INPUT);
	//LedSwitch(); //вкл. диод
	//digitalWrite(relePin, LOW); //убедится что реле выключено.
	//askTimeId=timer.setInterval(askTime, controlCheck); // периодическая проверка ручек управления каждые..
	lvlCheckId=timer.setInterval(lvlTime, lvlCheck); //checking water level every..
	//sunCheckId=timer.setInterval(sunTime, sunCheck); //checking luminosity every..
	//controlCheck(); //опрос регуляторов
	lvlCheck(); //опрос уровня жидкости
	//sunCheck(); //опрос уровня освещенности
	//timer.setTimeout(1000, LedSwitch); //выключить диод через 1с
	//timer.setInterval(2000, numprint); //печатать число активных таймеров для отладки

}

void lvlCheck(){
	//читаем данные критического и сигнального значения уровня жидкости
	critLvl = 1-digitalRead(critLvlPin);
	alarmLvl = 1-digitalRead(aLvlPin);
	Serial.print("alarmLvl:");
	Serial.println(alarmLvl);
	Serial.print("critLvl:");
	Serial.println(critLvl);
	//static int preLvl; //last fixed levev
	if (critLvl){ //если уровень критический, то поргаем чаще и вырубаем воду
		if (timer.isEnabled(alarmT)){
			timer.deleteTimer(alarmT);
			Serial.println("Level crit Timer deleted and set");
		};
		Serial.println("Alarm critical!");
		alarmT=timer.setInterval(2000, AlarmBlink);
		WaterStop();
		Serial.println("Stop watering!");
		if (timer.isEnabled(durTimer)){ //если шел полив - отключить таймер
			timer.deleteTimer(durTimer);
			Serial.println("watering timer deleted");
		}
		//не использовать 2 таймера одновременно.
	}
	else if (alarmLvl){ //если сигнальный уровень пройден моргаем раз в 5сек
		if (timer.isEnabled(alarmT)){
			timer.deleteTimer(alarmT);
			Serial.println("Level alarm Timer deleted and set");
		};
		 alarmT=timer.setInterval(5000, AlarmBlink);
		 Serial.println("Alarm lvl!");
	}
	else {
		if (timer.isEnabled(alarmT)){
			timer.deleteTimer(alarmT);  //если сигнала низкого уровня нет, то удалить таймер мигания.
			Serial.println("Level Timer deleted");
		};
	};
	
}

void loop(){
timer.run();
}
Как видно большая часть задач построена на таймерах используя библиотеку SimpeTimer (все по ней:http://playground.arduino.cc/Code/SimpleTimer).

Довольно удобная вещь, хотя то, что timerID выдается последовательно и не уникально(т.е. выданный и освобожденный ID может быть выдан повторно SIC! :o ), а еще то, что проверить можно только Enabled (включен), но не "Существует", создает кучу гемороя: если в коде удаляются и создаются таймеры (как у меня), то растет риск, что они начнут путаться между собой(что таки происходит :facepalm: )... Переписывать неохота, но чую придется.
Впрочем, на показания датчика уровня это влиять никак не должно.

Re: Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Пн сен 07, 2015 22:25:43
uk8amk
При мегаомной подтяжке кусок проволочки запросто может ловить радио или наводку от двигателя насоса.
Чтобы полностью исключить разложение электродов и насыщение воды солями металла нужно электроды герметизировать и перейти к измерению емкости(диэлектрической приницаемости).
Но сначала просто повесьте конденсатор микрофарад 100 чтобы задушить наводку.

Re: Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Вт сен 08, 2015 13:37:00
Аlex
Draghkon писал(а):
Спойлер

Код: Выделить всё

#include <SimpleTimer.h>

#define aLvlPin 8 //уровень жидкости сигнальный
#define critLvlPin 7 //critical level of water
#define lvlTime 10000 //10сек

boolean critLvl = true;
boolean alarmLvl = true;
byte lvlCheckId=255;

SimpleTimer timer; //timer object

void setup()
{
	Serial.begin(19200);
	//pinMode(relePin, OUTPUT);
	//pinMode(ledPin, OUTPUT);
	pinMode((aLvlPin, critLvlPin, perPin, durPin, sunPin), INPUT);
	//LedSwitch(); //вкл. диод
	//digitalWrite(relePin, LOW); //убедится что реле выключено.
	//askTimeId=timer.setInterval(askTime, controlCheck); // периодическая проверка ручек управления каждые..
	lvlCheckId=timer.setInterval(lvlTime, lvlCheck); //checking water level every..
	//sunCheckId=timer.setInterval(sunTime, sunCheck); //checking luminosity every..
	//controlCheck(); //опрос регуляторов
	lvlCheck(); //опрос уровня жидкости
	//sunCheck(); //опрос уровня освещенности
	//timer.setTimeout(1000, LedSwitch); //выключить диод через 1с
	//timer.setInterval(2000, numprint); //печатать число активных таймеров для отладки

}

void lvlCheck(){
	//читаем данные критического и сигнального значения уровня жидкости
	critLvl = 1-digitalRead(critLvlPin);
	alarmLvl = 1-digitalRead(aLvlPin);
	Serial.print("alarmLvl:");
	Serial.println(alarmLvl);
	Serial.print("critLvl:");
	Serial.println(critLvl);
	//static int preLvl; //last fixed levev
	if (critLvl){ //если уровень критический, то поргаем чаще и вырубаем воду
		if (timer.isEnabled(alarmT)){
			timer.deleteTimer(alarmT);
			Serial.println("Level crit Timer deleted and set");
		};
		Serial.println("Alarm critical!");
		alarmT=timer.setInterval(2000, AlarmBlink);
		WaterStop();
		Serial.println("Stop watering!");
		if (timer.isEnabled(durTimer)){ //если шел полив - отключить таймер
			timer.deleteTimer(durTimer);
			Serial.println("watering timer deleted");
		}
		//не использовать 2 таймера одновременно.
	}
	else if (alarmLvl){ //если сигнальный уровень пройден моргаем раз в 5сек
		if (timer.isEnabled(alarmT)){
			timer.deleteTimer(alarmT);
			Serial.println("Level alarm Timer deleted and set");
		};
		 alarmT=timer.setInterval(5000, AlarmBlink);
		 Serial.println("Alarm lvl!");
	}
	else {
		if (timer.isEnabled(alarmT)){
			timer.deleteTimer(alarmT);  //если сигнала низкого уровня нет, то удалить таймер мигания.
			Serial.println("Level Timer deleted");
		};
	};
	
}

void loop(){
timer.run();
}
Как видно большая часть задач построена на таймерах используя библиотеку SimpeTimer (все по ней:http://playground.arduino.cc/Code/SimpleTimer).

Довольно удобная вещь, хотя то, что timerID выдается последовательно и не уникально(т.е. выданный и освобожденный ID может быть выдан повторно SIC! :o ), а еще то, что проверить можно только Enabled (включен), но не "Существует", создает кучу гемороя: если в коде удаляются и создаются таймеры (как у меня), то растет риск, что они начнут путаться между собой(что таки происходит :facepalm: )... Переписывать неохота, но чую придется.
Впрочем, на показания датчика уровня это влиять никак не должно.
И вот это всё - чтобы опросить один вывод МК ? :facepalm:

Re: Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Вт сен 08, 2015 19:00:14
Draghkon
И вот это всё - чтобы опросить один вывод МК ? :facepalm:
вообще 2 вывода, но технически, чтобы опрашивать каждые N секунд, достаточно вот этого:

Код: Выделить всё

#include <SimpleTimer.h>

#define aLvlPin 8 //уровень жидкости сигнальный
#define critLvlPin 7 //critical level of water
#define lvlTime 10000 //10сек

boolean critLvl = true;
boolean alarmLvl = true;

SimpeTimer timer;

void setup()
{
   Serial.begin(19200);
   
   pinMode((aLvlPin, critLvlPin, perPin, durPin, sunPin), INPUT);
   lvlCheckId=timer.setInterval(lvlTime, lvlCheck); //checking water level every..
   lvlCheck(); //опрос уровня жидкости
}

void lvlCheck(){
   //читаем данные критического и сигнального значения уровня жидкости
   critLvl = 1-digitalRead(critLvlPin);
   alarmLvl = 1-digitalRead(aLvlPin);
   Serial.print("alarmLvl:");
   Serial.println(alarmLvl);
   Serial.print("critLvl:");
   Serial.println(critLvl);
 
   
}

void loop(){
timer.run();
}

а остальное - это обработка и т.п.

Re: Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Чт сен 10, 2015 16:54:24
Draghkon
в процессе выяснилось что дело в пвх трубке (d5мм) в которой располагались повода датчика... когда провода просто опущены в воду - все работает, когда они опущены внутри трубки - не работает. Возможно по какой-то причине уровень воды в трубке не выравнивается с уровнем в емкости, хотя конец соединен с атмосферой и вокруг проводов есть еще место до стенок. Даже сверление дополнительных дырок в трубке ничего не дало... Загадка. В итоге плюнул и вывел концы проводов наружу (через те самые дырки) - все заработало.

Re: Усилитель сигнала датчика уровня жидкости для Ардуино

Добавлено: Пт сен 11, 2015 00:57:11
Morroc
Конденсатор действительно прицепите чтобы показания не прыгали, а лучше пару - керамический 0.1-1 uF и электролит. Наверное если пальцем ткнуть - тоже 0 / 1 прыгают ?