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

Датчик СО2

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

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

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

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

Датчик СО2

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

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


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

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

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

t.every(15000, get_co2);

это в сетап секцию

Датчик СО2

Добавлено: 26.12.2017{, 20:01}
Alias
Сделал по Вашей подсказке вход En на блоке и управляю им по переднему фронту сигнала с компаратора ежеминутно. И - Бинго! - все работает!
Спасибо! Можно идти дальше.
СпойлерПоказать
Но я, все-таки, не сообразил, как внедрить таймер в сам блок, чтобы он обрел законченный вид. Если поможете, блок можно будет выложить в библиотеку. С меня тестирование и отчет.

Датчик СО2

Добавлено: 26.12.2017{, 20:47}
pan
Alias писал(а):как внедрить таймер
посмотрите. разберетесь

Датчик СО2

Добавлено: 27.12.2017{, 14:02}
Alias
Разобрался. Отлично! Спасибо огромное!
Мало того, написал несколько вариантов реально работающих конкретно у меня блоков. Но!
Полез я в код, стал кое в чем разбираться и обнаружил забавную вещь в блоке из поста выше: тип переменной LastTime объявлен как Long Integer.
Если я правильно понимаю, значение переменной начнет переполняться уже через 24 дня, при этом перестанет соблюдаться тайм-аут на опрос датчика и он будет опрашиваться уже в каждом цикле программы.
Взял на себя смелость объявить ее Unsigned long Integer, пусть она работает вплоть до обнуления самой millis.
Во вложении три блока с индексами 1, 2 и 3. Каждый из них в скетче использует 3668/3678/3718 байт памяти устройства и 324/325/328 байт динамической памяти для глобальных переменных соответственно. Если кому-то критично, могут выбирать.
В примере поставил уровень тревоги на 1200ppm, просто у меня датчик рядом с клавой лежит и я вношу нехилые возмущения в его показания.

Датчик СО2

Добавлено: 27.12.2017{, 14:32}
pan
буковку пропустил. ulong

Добавлено (27.12.2017, 14:32)
---------------------------------------------
хотя с чего вы взяли что она будет переполняться. это промежуточная переменная для отсчета нужного времени т.е
просто для вычисления разницы..
тем более она периодически через установленный интервал обнуляется.

Датчик СО2

Добавлено: 27.12.2017{, 14:44}
Alias
В смысле, в блоке вместо

unsigned long LastTime=0;

прописать

ulong LastTime=0?

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



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

Почему будет переполняться? Ну, не знаю. Просто если посмотреть код:
СпойлерПоказать
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.
Но я не настаиваю. В код в принципе я впервые стал влезать со вчерашнего дня и для меня много непонятного. Я в этой чаще и деревьев то не вижу пока что, а только под ноги смотрю.

Датчик СО2

Добавлено: 27.12.2017{, 14:49}
pan
да без разницы, unsigned long или ulong.
Alias писал(а):ее просто не впихнуть
да нам собственно и не надо. я не пробовал, но по сути там и integer хватит. если компилятор позволит.
нам все равно отслеживать  младшие разряды. при 5 секундах нам главное поймать разницу в 5000.
теоретически старшие разряды пофиг..

Датчик СО2

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

Датчик СО2

Добавлено: 27.12.2017{, 15:21}
pan
ну будемс знать что если не влазит то присваивается старшая часть значения

Датчик СО2

Добавлено: 27.12.2017{, 15:25}
Alias
Выглядит это примерно так:
СпойлерПоказать

Датчик СО2

Добавлено: 31.12.2017{, 14:48}
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 - абракадабру:
СпойлерПоказать
char.png
При этом тип переменных responseHigh, responseLow и response[2] вообще ни на что не влияют.

Прошу программистов оценить, что здесь не так и как должно быть.
Спасибо!

Датчик СО2

Добавлено: 27.09.2019{, 04:34}
ROSTISLAVKR
Здраствуйте!
У меня пришла в негодность и отклеилась пластинка заграждающая измерительную камеру в датчике MH-Z14, не могу сообразить чем ее заменить, не могу определить материал этой пластинки. Мне кажется что она воздухонепрозрачная-как тогда происходит измерение?
Материал этой заграждающей пластинки почему-то напоминает фрагмент слоя стеклотекстолита?

Датчик СО2

Добавлено: 27.09.2019{, 09:05}
Alias
Я думаю, это просто воздушный фильтр от пыли. Наблюдая на работой датчика, помещал его в плотно закрытую банку, как мне тогда казалось. Однако даже через мельчайшие щели концентрация газов менялась заметно глазу. Поэтому можно в качестве этой мембраны применять любой хоть сколько-нибудь газопроницаемый материал. В конце концов, хоть фильтр от капельницы.

Датчик СО2

Добавлено: 27.09.2019{, 11:16}
ROSTISLAVKR
Благодарен за ответ.
Воспользуюсь советом.

Датчик СО2

Добавлено: 31.10.2020{, 20:20}
Naladchik
ShishkaRoman писал(а):
31.10.2020{, 14:09}
Захотелось сравнить с показаниями по UART.
для "просто сравнить"
AN157-T6613-Arduino-uart.pdf
(1.18 МБ) 60 скачиваний
AN157-T6613-Arduino-uart.zip
(2.24 КБ) 56 скачиваний