Датчик СО2

Использование прочих датчиков и энкодеров и пользовательских блоков к ним
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

Попробовал разобраться, как создаются блоки CODE. Взял за основу блок от Anydy и немного переделал секции.
До этого нашел скетч якобы работающего устройства: во вложении.

Решил попробовать покопипастить из него. Там, кстати, есть опечатка ближе к
концу, возможно, непредумышленная. Модифицированный блок во вложении, но он точно так же работает. То есть вывод на экран возможен только в момент опроса СО2, то есть, в данном случае каждые 5 секунд.
Я так понимаю, что это все из-за delay(5000). Если ее удалить вовсе, на
глаз ничего уже и не тормозит, но com-порт при этом заваливает потоком данных с датчика.
В скетче выше задержка реализована через таймер:

Timer t;
t.every(15000, get_co2);

Прошу гуру подсказать, куда и как можно воткнуть его в блоке пользователя,
чтобы он не мешал работе всей программы. Или можно как-то активировать
работу самого блока через вход En по внешнему таймеру? Не знаю, как его,
вход, корректно создать.
С восторгом предаюсь в руки родной милиции, надеюсь на нее и уповаю (с)
У вас нет необходимых прав для просмотра вложений в этом сообщении.
pan
Полковник
Сообщения: 2860
Зарегистрирован: 13 апр 2017, 11:57
Имя: noname

Датчик СО2

Сообщение pan »

всякие дилэи конечно убирать надо.
Alias писал(а):через вход En
вкладка "входы". добавляете вход, на пример en

СпойлерSPOILER_SHOW
Изображение
 и весь код блока запихиваете в эти скобки.
Alias писал(а):куда и как можно воткнуть его в блоке пользователя
 всё так же как в скетче.


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

Timer t;
это в декларе секцию.

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

t.every(15000, get_co2);

это в сетап секцию
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

Сделал по Вашей подсказке вход En на блоке и управляю им по переднему фронту сигнала с компаратора ежеминутно. И - Бинго! - все работает!
Спасибо! Можно идти дальше.
СпойлерSPOILER_SHOW
Но я, все-таки, не сообразил, как внедрить таймер в сам блок, чтобы он обрел законченный вид. Если поможете, блок можно будет выложить в библиотеку. С меня тестирование и отчет.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
pan
Полковник
Сообщения: 2860
Зарегистрирован: 13 апр 2017, 11:57
Имя: noname

Датчик СО2

Сообщение pan »

Alias писал(а):как внедрить таймер
посмотрите. разберетесь
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

Разобрался. Отлично! Спасибо огромное!
Мало того, написал несколько вариантов реально работающих конкретно у меня блоков. Но!
Полез я в код, стал кое в чем разбираться и обнаружил забавную вещь в блоке из поста выше: тип переменной LastTime объявлен как Long Integer.
Если я правильно понимаю, значение переменной начнет переполняться уже через 24 дня, при этом перестанет соблюдаться тайм-аут на опрос датчика и он будет опрашиваться уже в каждом цикле программы.
Взял на себя смелость объявить ее Unsigned long Integer, пусть она работает вплоть до обнуления самой millis.
Во вложении три блока с индексами 1, 2 и 3. Каждый из них в скетче использует 3668/3678/3718 байт памяти устройства и 324/325/328 байт динамической памяти для глобальных переменных соответственно. Если кому-то критично, могут выбирать.
В примере поставил уровень тревоги на 1200ppm, просто у меня датчик рядом с клавой лежит и я вношу нехилые возмущения в его показания.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Alias 27 дек 2017, 14:04, всего редактировалось 1 раз.
pan
Полковник
Сообщения: 2860
Зарегистрирован: 13 апр 2017, 11:57
Имя: noname

Датчик СО2

Сообщение pan »

буковку пропустил. ulong

Добавлено (27.12.2017, 14:32)
---------------------------------------------
хотя с чего вы взяли что она будет переполняться. это промежуточная переменная для отсчета нужного времени т.е
просто для вычисления разницы..
тем более она периодически через установленный интервал обнуляется.
Последний раз редактировалось pan 27 дек 2017, 14:34, всего редактировалось 1 раз.
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

В смысле, в блоке вместо

unsigned long LastTime=0;

прописать

ulong LastTime=0?

В скетче при компиляции ошиок не выдает и выглядит вот так:



Не знал, исправлю. Спасибо за подсказки!

Почему будет переполняться? Ну, не знаю. Просто если посмотреть код:
СпойлерSPOILER_SHOW
if (millis() - LastTime > interval) // если установленное время прошло
                    {
                        LastTime =0; //сбрасывам запомненное значение
                    }

if( LastTime ==0) {
LastTime = millis(); // запоминаем текущее значение таймера
mySerial.write(cmd, 9);
mySerial.readBytes(response, 9);
unsigned int responseHigh = (unsigned int) response[2];
unsigned int responseLow = (unsigned int) response[3];
ppm = (256*responseHigh) + responseLow;
Serial.println(ppm);
}
LastTime = millis(); // запоминаем текущее значение таймера. И, если мы берем тип Long Integer с предельным значением переменной 2147483647, то в нее просто не впихнуть значение millis при превышении лимита, тк сама millis, как я понимаю, Unsigned long Integer  с пределом до 4294967295.
Но я не настаиваю. В код в принципе я впервые стал влезать со вчерашнего дня и для меня много непонятного. Я в этой чаще и деревьев то не вижу пока что, а только под ноги смотрю.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
pan
Полковник
Сообщения: 2860
Зарегистрирован: 13 апр 2017, 11:57
Имя: noname

Датчик СО2

Сообщение pan »

да без разницы, unsigned long или ulong.
Alias писал(а):ее просто не впихнуть
да нам собственно и не надо. я не пробовал, но по сути там и integer хватит. если компилятор позволит.
нам все равно отслеживать  младшие разряды. при 5 секундах нам главное поймать разницу в 5000.
теоретически старшие разряды пофиг..
Последний раз редактировалось pan 27 дек 2017, 14:50, всего редактировалось 1 раз.
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

Я, когда решил прикинуть, сколько места можно сэкономить в блоке на замене типов переменных, первым делом заменил тип этой переменной на int. И, мониторя com-порт, увидел, какая лавина обрушивается с датчика. Дополнил блок еще одной строкой по примеру предыдущей:
Serial.println(ppm);
Serial.println(LastTime);
и понял, в чем суть. И именно через 32 секунды.
Типу Integer соответствуют целые числа от -32768 до 32767. По программе, мы сравниваем показания таймера системы с нашей переменной. Если разница больше установленного значения, мы присваиваем ей нулевое значение как флаг события и тут же по этому флагу присваиваем переменной текущее значение таймера контроллера.
Сразу после рестарта, значения таймера невелики. Но после 32 секунд, как только его значения переваливают за 32767, мы входим в бесконечный цикл, тк на каждом цикле мы видим, что значения таймера куда больше значения нашей переменной, значит, пора ее обнулять, присваивать ей текущее значение таймера, опрашивать датчик, отправлять в порт.
Присвоить то присвоили. Но не все влезло и далеко не лишнее было отсечено. и на следующем цикле опять мы видим, что разница между текущим значением таймера и переменной куда больше лимита, значит, пора ее обнулять...
Я так думаю (с)
pan
Полковник
Сообщения: 2860
Зарегистрирован: 13 апр 2017, 11:57
Имя: noname

Датчик СО2

Сообщение pan »

ну будемс знать что если не влазит то присваивается старшая часть значения
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

Выглядит это примерно так:
СпойлерSPOILER_SHOW
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Alias 27 дек 2017, 15:34, всего редактировалось 1 раз.
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

Не дает покоя мне код, вернее, типы переменных в нем.
Штудируя скудную относительно z-19 информацию в сети, вижу, что в русскоязычном секторе все крутится по сути вокруг одной и той же статьи, которую растаскивают на цитаты и принимают за эталон. Однако, встречал несколько раз комментарии, дескать, тип переменных не тот!
Вот кусок "оригинала":
int responseHigh = (int) response[2];
int responseLow = (int) response[3];
Встречается еще одна вариация, тоже активно кочующая по сети:
unsigned int responseHigh = (unsigned int) response[2];
unsigned int responseLow = (unsigned int) response[3];
Бывалые ухмыльнутся: "И что?.."
А мне вот не понятно, зачем байт, получаемый в ответе от датчика, помещать в переменную типа int или unsigned int? Не достаточно ли типа byte?
И еще. Какой же тип необходим и достаточен для переменных responseHigh и responseLow?
Интерес не праздный - хочу сам разобраться, да и блок довести до состояния, достойного помещения в раздел пользовательских блоков.
Понимаю, что и так сойдет, но хочу понять правильный подход.

И, что самое главное, два, казалось бы одинаковых блока выдают разные результаты.
Я поместил датчик в герметичную банку. Мои блоки, что сейчас допиливаю
MH-Z19_UART3_(CODE)
MH-Z19_UART3_2.0_(CODE)
выдают 995ppm, а ранее выкладывавшийся здесь
CO2UART_(CODE)
показывает 740ppm.
При этом датчик физически от питания не отрывался и, соответственно, не калибровался, только обновлялся скетч.
Куда копать? Кому верить?
Может это (unsigned char) / (char) response[9]? Меняю в своем блоке один тип на другой и получаю разные значения, отличающиеся почти в полтора раза.
Решил посмотреть, что присылает в ответе датчик в зависимости от типа переменной response, и оказалось, что типы unsigned char и byte возвращают вполне адекватные значения, а char - абракадабру:
SPOILERSPOILER_SHOW
char.png
При этом тип переменных responseHigh, responseLow и response[2] вообще ни на что не влияют.

Прошу программистов оценить, что здесь не так и как должно быть.
Спасибо!
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
Alias
Лейтенант
Сообщения: 481
Зарегистрирован: 27 ноя 2017, 13:15
Откуда: Rus44
Имя: Michael
Контактная информация:

Датчик СО2

Сообщение Alias »

Я думаю, это просто воздушный фильтр от пыли. Наблюдая на работой датчика, помещал его в плотно закрытую банку, как мне тогда казалось. Однако даже через мельчайшие щели концентрация газов менялась заметно глазу. Поэтому можно в качестве этой мембраны применять любой хоть сколько-нибудь газопроницаемый материал. В конце концов, хоть фильтр от капельницы.
Naladchik
Капитан
Сообщения: 832
Зарегистрирован: 04 окт 2015, 19:10
Откуда: Новосибирск
Имя: Павел

Датчик СО2

Сообщение Naladchik »

ShishkaRoman писал(а): 31 окт 2020, 14:09 Захотелось сравнить с показаниями по UART.
для "просто сравнить"
AN157-T6613-Arduino-uart.pdf
AN157-T6613-Arduino-uart.zip
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Win10-64. FLProg Portable.
Изображение
Ответить

Вернуться в «Прочие датчики и энкодеры»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 0 гостей