Датчик СО2
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
Попробовал разобраться, как создаются блоки CODE. Взял за основу блок от Anydy и немного переделал секции.
До этого нашел скетч якобы работающего устройства: во вложении.
Решил попробовать покопипастить из него. Там, кстати, есть опечатка ближе к
концу, возможно, непредумышленная. Модифицированный блок во вложении, но он точно так же работает. То есть вывод на экран возможен только в момент опроса СО2, то есть, в данном случае каждые 5 секунд.
Я так понимаю, что это все из-за delay(5000). Если ее удалить вовсе, на
глаз ничего уже и не тормозит, но com-порт при этом заваливает потоком данных с датчика.
В скетче выше задержка реализована через таймер:
Timer t;
t.every(15000, get_co2);
Прошу гуру подсказать, куда и как можно воткнуть его в блоке пользователя,
чтобы он не мешал работе всей программы. Или можно как-то активировать
работу самого блока через вход En по внешнему таймеру? Не знаю, как его,
вход, корректно создать.
С восторгом предаюсь в руки родной милиции, надеюсь на нее и уповаю (с)
До этого нашел скетч якобы работающего устройства: во вложении.
Решил попробовать покопипастить из него. Там, кстати, есть опечатка ближе к
концу, возможно, непредумышленная. Модифицированный блок во вложении, но он точно так же работает. То есть вывод на экран возможен только в момент опроса СО2, то есть, в данном случае каждые 5 секунд.
Я так понимаю, что это все из-за delay(5000). Если ее удалить вовсе, на
глаз ничего уже и не тормозит, но com-порт при этом заваливает потоком данных с датчика.
В скетче выше задержка реализована через таймер:
Timer t;
t.every(15000, get_co2);
Прошу гуру подсказать, куда и как можно воткнуть его в блоке пользователя,
чтобы он не мешал работе всей программы. Или можно как-то активировать
работу самого блока через вход En по внешнему таймеру? Не знаю, как его,
вход, корректно создать.
С восторгом предаюсь в руки родной милиции, надеюсь на нее и уповаю (с)
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Датчик СО2
всякие дилэи конечно убирать надо.
и весь код блока запихиваете в эти скобки.
это в декларе секцию.
это в сетап секцию
вкладка "входы". добавляете вход, на пример enAlias писал(а):через вход En
СпойлерSPOILER_SHOW
![Изображение](http://i7.5cm.ru/i/RnpH.png)
всё так же как в скетче.Alias писал(а):куда и как можно воткнуть его в блоке пользователя
Код: Выделить всё
Timer t;
Код: Выделить всё
t.every(15000, get_co2);
это в сетап секцию
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
Сделал по Вашей подсказке вход En на блоке и управляю им по переднему фронту сигнала с компаратора ежеминутно. И - Бинго! - все работает!
Спасибо! Можно идти дальше.
Но я, все-таки, не сообразил, как внедрить таймер в сам блок, чтобы он обрел законченный вид. Если поможете, блок можно будет выложить в библиотеку. С меня тестирование и отчет.
Спасибо! Можно идти дальше.
СпойлерSPOILER_SHOW
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Датчик СО2
посмотрите. разберетесьAlias писал(а):как внедрить таймер
У вас нет необходимых прав для просмотра вложений в этом сообщении.
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
Разобрался. Отлично! Спасибо огромное!
Мало того, написал несколько вариантов реально работающих конкретно у меня блоков. Но!
Полез я в код, стал кое в чем разбираться и обнаружил забавную вещь в блоке из поста выше: тип переменной LastTime объявлен как Long Integer.
Если я правильно понимаю, значение переменной начнет переполняться уже через 24 дня, при этом перестанет соблюдаться тайм-аут на опрос датчика и он будет опрашиваться уже в каждом цикле программы.
Взял на себя смелость объявить ее Unsigned long Integer, пусть она работает вплоть до обнуления самой millis.
Во вложении три блока с индексами 1, 2 и 3. Каждый из них в скетче использует 3668/3678/3718 байт памяти устройства и 324/325/328 байт динамической памяти для глобальных переменных соответственно. Если кому-то критично, могут выбирать.
В примере поставил уровень тревоги на 1200ppm, просто у меня датчик рядом с клавой лежит и я вношу нехилые возмущения в его показания.
Мало того, написал несколько вариантов реально работающих конкретно у меня блоков. Но!
Полез я в код, стал кое в чем разбираться и обнаружил забавную вещь в блоке из поста выше: тип переменной LastTime объявлен как Long Integer.
Если я правильно понимаю, значение переменной начнет переполняться уже через 24 дня, при этом перестанет соблюдаться тайм-аут на опрос датчика и он будет опрашиваться уже в каждом цикле программы.
Взял на себя смелость объявить ее Unsigned long Integer, пусть она работает вплоть до обнуления самой millis.
Во вложении три блока с индексами 1, 2 и 3. Каждый из них в скетче использует 3668/3678/3718 байт памяти устройства и 324/325/328 байт динамической памяти для глобальных переменных соответственно. Если кому-то критично, могут выбирать.
В примере поставил уровень тревоги на 1200ppm, просто у меня датчик рядом с клавой лежит и я вношу нехилые возмущения в его показания.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Alias 27 дек 2017, 14:04, всего редактировалось 1 раз.
Датчик СО2
буковку пропустил. ulong
Добавлено (27.12.2017, 14:32)
---------------------------------------------
хотя с чего вы взяли что она будет переполняться. это промежуточная переменная для отсчета нужного времени т.е
просто для вычисления разницы..
тем более она периодически через установленный интервал обнуляется.
Добавлено (27.12.2017, 14:32)
---------------------------------------------
хотя с чего вы взяли что она будет переполняться. это промежуточная переменная для отсчета нужного времени т.е
просто для вычисления разницы..
тем более она периодически через установленный интервал обнуляется.
Последний раз редактировалось pan 27 дек 2017, 14:34, всего редактировалось 1 раз.
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
В смысле, в блоке вместо
unsigned long LastTime=0;
прописать
ulong LastTime=0?
В скетче при компиляции ошиок не выдает и выглядит вот так:
Не знал, исправлю. Спасибо за подсказки!
Почему будет переполняться? Ну, не знаю. Просто если посмотреть код:
LastTime = millis(); // запоминаем текущее значение таймера. И, если мы берем тип Long Integer с предельным значением переменной 2147483647, то в нее просто не впихнуть значение millis при превышении лимита, тк сама millis, как я понимаю, Unsigned long Integer с пределом до 4294967295.
Но я не настаиваю. В код в принципе я впервые стал влезать со вчерашнего дня и для меня много непонятного. Я в этой чаще и деревьев то не вижу пока что, а только под ноги смотрю.
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 =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);
}
Но я не настаиваю. В код в принципе я впервые стал влезать со вчерашнего дня и для меня много непонятного. Я в этой чаще и деревьев то не вижу пока что, а только под ноги смотрю.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Датчик СО2
да без разницы, unsigned long или ulong.
нам все равно отслеживать младшие разряды. при 5 секундах нам главное поймать разницу в 5000.
теоретически старшие разряды пофиг..
да нам собственно и не надо. я не пробовал, но по сути там и integer хватит. если компилятор позволит.Alias писал(а):ее просто не впихнуть
нам все равно отслеживать младшие разряды. при 5 секундах нам главное поймать разницу в 5000.
теоретически старшие разряды пофиг..
Последний раз редактировалось pan 27 дек 2017, 14:50, всего редактировалось 1 раз.
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
Я, когда решил прикинуть, сколько места можно сэкономить в блоке на замене типов переменных, первым делом заменил тип этой переменной на int. И, мониторя com-порт, увидел, какая лавина обрушивается с датчика. Дополнил блок еще одной строкой по примеру предыдущей:
Serial.println(ppm);
Serial.println(LastTime);
и понял, в чем суть. И именно через 32 секунды.
Типу Integer соответствуют целые числа от -32768 до 32767. По программе, мы сравниваем показания таймера системы с нашей переменной. Если разница больше установленного значения, мы присваиваем ей нулевое значение как флаг события и тут же по этому флагу присваиваем переменной текущее значение таймера контроллера.
Сразу после рестарта, значения таймера невелики. Но после 32 секунд, как только его значения переваливают за 32767, мы входим в бесконечный цикл, тк на каждом цикле мы видим, что значения таймера куда больше значения нашей переменной, значит, пора ее обнулять, присваивать ей текущее значение таймера, опрашивать датчик, отправлять в порт.
Присвоить то присвоили. Но не все влезло и далеко не лишнее было отсечено. и на следующем цикле опять мы видим, что разница между текущим значением таймера и переменной куда больше лимита, значит, пора ее обнулять...
Я так думаю (с)
Serial.println(ppm);
Serial.println(LastTime);
и понял, в чем суть. И именно через 32 секунды.
Типу Integer соответствуют целые числа от -32768 до 32767. По программе, мы сравниваем показания таймера системы с нашей переменной. Если разница больше установленного значения, мы присваиваем ей нулевое значение как флаг события и тут же по этому флагу присваиваем переменной текущее значение таймера контроллера.
Сразу после рестарта, значения таймера невелики. Но после 32 секунд, как только его значения переваливают за 32767, мы входим в бесконечный цикл, тк на каждом цикле мы видим, что значения таймера куда больше значения нашей переменной, значит, пора ее обнулять, присваивать ей текущее значение таймера, опрашивать датчик, отправлять в порт.
Присвоить то присвоили. Но не все влезло и далеко не лишнее было отсечено. и на следующем цикле опять мы видим, что разница между текущим значением таймера и переменной куда больше лимита, значит, пора ее обнулять...
Я так думаю (с)
Датчик СО2
ну будемс знать что если не влазит то присваивается старшая часть значения
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
Выглядит это примерно так:
СпойлерSPOILER_SHOW
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Последний раз редактировалось Alias 27 дек 2017, 15:34, всего редактировалось 1 раз.
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
Не дает покоя мне код, вернее, типы переменных в нем.
Штудируя скудную относительно 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 - абракадабру:
При этом тип переменных responseHigh, responseLow и response[2] вообще ни на что не влияют.
Прошу программистов оценить, что здесь не так и как должно быть.
Спасибо!
Штудируя скудную относительно 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
Прошу программистов оценить, что здесь не так и как должно быть.
Спасибо!
У вас нет необходимых прав для просмотра вложений в этом сообщении.
- Alias
- Лейтенант
- Сообщения: 481
- Зарегистрирован: 27 ноя 2017, 13:15
- Откуда: Rus44
- Имя: Michael
- Контактная информация:
Датчик СО2
Я думаю, это просто воздушный фильтр от пыли. Наблюдая на работой датчика, помещал его в плотно закрытую банку, как мне тогда казалось. Однако даже через мельчайшие щели концентрация газов менялась заметно глазу. Поэтому можно в качестве этой мембраны применять любой хоть сколько-нибудь газопроницаемый материал. В конце концов, хоть фильтр от капельницы.
Датчик СО2
для "просто сравнить"
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 0 гостей