Официальный сайт компании Arduino по адресу arduino.cc
i2c display и прерывания.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пт, 11/09/2015 - 20:06
Здравствуйте, уважаемые специалисты. Помогите разобраться с проблемой. Есть желание измерять мгновенное значение проходящей в трубе жидкости. Для этого приобретен прибор http://ru.aliexpress.com/item/1-x-1-30L-min-1-75MPa-Water-Flow-Sensor-Flowmeter-Hall-Flow-Water-Sensor-New/2045383642.html?spm=2114.03020208.3.29.9p7lIN&ws_ab_test=201407_2,201444_5,201409_3 К нем есть стандартный скетч с выводом данных через Serial порт.
[code]
// reading liquid flow rate using Arduino and Water Flow sensor.
volatile int Fan;//measuring the rising edges of the signal
int Calc;
int hallsensor = 2;//The pin location of the sensor
void rpm()//this is the function of that the interupt calls
{
Fan++;
}
void setup() {
pinMode(hallsensor, INPUT);
Serial.begin(9600);
attachInterrupt(0, rpm, RISING);
}
void loop() {
Fan=0;
sei();
delay(1000);
cli();
Calc = (Fan*60/5.5);//(puls frequency x 60)/5.5Q = flow rate in L/hour
Serial.print (Calc, DEC);
Serial.print (" L/hour\r\n"); //Prints "L/hour" and returnes a new line
}
[/code]
Все работает. Но хотелось бы вывести результат на lcd дисплей. Есть под рукой lcd 20 на 4 с интерфейсом i2c. Берем скетч из примеров, делаем микс из двух получаем:
[code]
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,20,4);
// reading liquid flow rate using Arduino and Water Flow sensor.
volatile int Fan;//measuring the rising edges of the signal
int Calc;
int hallsensor = 2;//The pin location of the sensor
void rpm()//this is the function of that the interupt calls
{
Fan++;
}
void setup() {
pinMode(hallsensor, INPUT);
attachInterrupt(0, rpm, RISING);
lcd.init();
lcd.backlight();
}
void loop() {
Fan=0;
sei();
delay(1000);
cli();
Calc = (Fan*60/5.5);
//lcd.clear;
lcd.print (Calc, DEC);
}
[/code]
Но данный код не работает. Если исключить из кода строки
sei();
delay(1000);
cli();
а переменной Fan присвоить значение (например 10) то на экране появляется значение, полученное при вычислении (при Fan=10 получим 109, что есть правильно).
Подскажите, в чем проблема.
Заранее благодарю.
BorisU, этот ваш скетч для замера просто как пример работы, никто в здравом уме такие программы не использует. Наиболее просто можно обойти delay по аналогии со светодиодом http://arduino.ru/tutorials/BlinkWithoutDelay
PS: вообще-то уберите cli() наверное и так заработает.
dimax, не заработало. Индикации как не было так и нет.
По поводу cli(). Если убрать это убрать, то не понятно, как программа будет работать. Логика простая. Есть датчик Холла. Нам нужно знать сколько импульсов пройдет в единицу времени. Для этого мы ставим sei() - enable interrupt, delay(1000) - считаем количество импульсов за секунду, cli() - disable interrupt. Переменная Fan больше не меняется и можно проводить вычисления. Если убрать cli(), то ничего посчитать будет нельзя, так как не будет не ясно за какое время прошло n импульсов. Как-то так.
BorisU, нет, разрешение и запрещение прерываний тут фактически не на что не влияют. Если ставить cli(), то с этого момента и до sei() переменная Fan не инкременируется. Если не стоит, то переменная конечно инкременируется, но перед паузой всё равно обнуляется. Проверьте. С LCD без cli работать должно, попробуйте после Lcd.print небольшую паузу поставить. А лучше конечно переделать всё, что б небыло секундной паузы.
PS: Вот, начертил, пробуйте:
Здесь время считает таймер, каждую секунду выходит в прерывание, делает подсчёт, обнуляет Fan, и начинает сначала. В лупе выводит данные только если есть изменения. Никаких delay :-)
В первую мировую летчики научили обезьяну взлетать и садиться. Однажды она разбилась, потому, что в полете вспомнила, что забыла винт подергать....
Конкатенация не помогает, включайте понимание.
Dimax Вы издеваетесь? К Вам с букварём, а Вы с алгеброй :)
dimax, большое Вам спасибо за время, которое Вы уделили. Все, кто изучил матан, когда-то держал в руках букварь. В этом нет ничего особенного. Все зависит насколько дальше человек готов идти и кто ему в этом поможет. Спасибо Вам за помощь. Для меня это лишний повод заняться более глубоким изучением программирования.
По сути проблемы. Она, проблема, заключается в том, что изначально значение переменной Cacl выводится на монитор последовательного порта, но не выводится на lcd. Кусок кода с sei and cli я убирал, что бы убедиться, что проблем с lcd как таковым нет. Код выше, я уверен, более правильный с точки зрения науки, но он тоже не работает. Информация не выводиться ни на lcd, ни на монитор порта. К сожалению.
BorisU, а какая у вас плата? Скетч, который я дал -это готовая рабочая "шапка" для atmega328, я в него просто ваши исходные данные вставил. Не работать он не может)
Я тестил на меге 2560 r3. Вся проблема в выводе данных на дисплей. Дисплей девственно чист. Я, как уже ясно, еще собаку не съел на этом деле, и поэтому могу задавать глупые вопросы. Я подумал, нет ли связи между интерфейсом I2C и прерываниями?
BorisU, в обработчике I2C есть прерывание, но оно не используется в режиме мастер по-моему. Так что взаимосвязи нет, разбирайтесь, что делаете не так. Попробуйте в lcd.print вывести просто текст lcd.print("test"); например. Кстати посмотрел, мой скетч по идее совместим с мегой2560, так что должен работать. Разкомментируйте строчки, выведите в serial для проверки.
dimax, что бы все было ясно и понятно. Я взял "неправильный" скетч. Закомментил sei() и cli(). Присвоил переменной Calc=10. Загрузил в Мегу. Дисплей показал 109, что является правильным ответом. Удалил почти все, кроме библиотек. Вставил Ваш код. Загрузил в Мегу. Дисплей не показывает ничего. Закомментил все что касается lcd и раскомментил Serial. Загрузил в Мегу. Монитор порта не показывает ничего.
BorisU, когда пробывали в сериал выводить - то 3 и 23 строку закомментировали? Если lcd зависнет, то он заблокирует loop
dimax, да закомментировал все, что относиться к lcd включая библиотеки. Результат - показаний нет.
BorisU, не знаю что вам посоветовать. Попробуйте на уно. Я вчера проверил скетч, подключил вместо счётчика энкодер. Покрутил - как и следовало ожидать всё работает. Меги2560 у меня нет, но разницы по идее быть не должно.
PS: заметил ещё любопытную вещь: вы используете прерывание 0 attachInterrupt(0, rpm, RISING); а пин у вас указан 2. Но этот пин для Уно, у меги2560 INT0 на 21-ой ардуиновской ноге. Но тогда непонятно как у вас работал первый вариант без LCD.
dimax, большое спасибо за помощь. Я тестил на нано, но результат тоже отрицательный. Думаю нужно задать вопрос в аппаратной ветке. А за скетч спасибо еще раз. Я его разобрал уже процентов на 80. Там все не так сложно, но нужно еще некоторые вопросы синтаксиса разобрать.
Впервые вижу такое объявление экрана ( LiquidCrystal_I2C lcd(0x27,20,4); ).
Где lcd.begin?
dimax, есть новость. Я установил на другой компьютер среду версию 1.6.3 (на родном версия 1.5.7) и протестил. На мониторе порта все работает, на lcd нет. Результат - lcd не хочет работать ни при каких условиях. Значит нужно спрашивать о совместимости железа.
Это объявление работает. Все зависит от библиотеки, как я понимаю. Кстати, с этой библиотекой нужно lcd.init вместо lcd.begin. Экран работает с этой библиотекой.
А если экран цеплять не по i2c, то работает?
На мониторе порта все работает, на lcd нет. Результат - lcd не хочет работать ни при каких условиях. Значит нужно спрашивать о совместимости железа.
Попробуйте другую библиотеку LCD, возможно эта просто кривая или со свежими версиями IDE не совместима. У меня кстати помимо новой есть дежурная ардуино IDE 1.0.5 , и всегда проверяю на ней, если есть подозрения на несовместимость.
Да, я согласен, нужно другую библиотеку потестить. А экрана без I2C у меня нет, а выпаять - не так просто. Ног много можно перегреть, отслоиться плата. Напишу как найду подходящую библиотеку.
У меня все китайские так запускались. Либа
Доброго аремени суток уважаемый ALL!
Есть проблема с работой дисплея 1602 подключенного к atmege 328 по i2c при обработке прерывания.
при попытке вывести сообщение на экран при обработке прерывания работа устройства замерзает.
вот текст проги
подскажите как победить этот трабл.
сильно не пинайте ламера.
P.S. при коментировании строк обращения к экрану в обработчике прерывания все работает нормально.
Ну, значит какой вывод? Нефиг в ISR пихать все подряд. Выставили там флаг и в главном цикле написали на LCD, если флаг выставлен.
Так и должно быть. Эта библиотека слишком медленно работает с экраном. Тут есть относительно скоростной драйвер, но и он шустрее 95-125мксек на символ не работает. Примерно 1.58-2.0 миллисекунды на строку в 16 символов - это "самое шустрое" что можно предложить. Чтобы работать неблокирующе с экраном надо преобразовать ваш код и библиотеку (или "шустрый" драйвер) так, чтобы пока экран занят отрисовкой можно было бы что-нибудь делать полезное.
В общем, сейчас немного занят, но в планы себе поставил.
дело в том, что прога должна стоять в этом режиме пока не отпустится кнопка аварийной остановки.
вабрабоччике прерывания прерывания запрещены, а нутренний i2c работает на прерываниях. Дальше прадолжать?
и нафига вам здесь прерывания нужны....
Дело в том, что есть необходимость остановить выполнение, программы по нажатию аварийной кнопки, при этом должны сработать клапана аварийного сброса давления
Ujine, похоже программировать через цифровой автомат запретили на территории РФ для новичков и остальных.
Дело в том, что есть необходимость остановить выполнение, программы по нажатию аварийной кнопки, при этом должны сработать клапана аварийного сброса давления
и для этого без прерываний никак?
Ешшо и прерывание по кнопке. Мрак безпросветный. Исходник сжечь. Новый писать после изучения фундаментальных трудов классиков.
вабрабоччике прерывания прерывания запрещены, а нутренний i2c работает на прерываниях. Дальше прадолжать?
Уважаемые форумчане, подскажите, пожалуйста.
Работаю с несколькими устройствами по шине I2C (в частности lcd, eeprom, ds3231, mcp23017), плюс использую код для отправки сообщений в стороннее железо по протоколу wiegand26 :
Появилась необходимость использовать светодиод для индикации работы программы, смена состояния которого будет происходить в обработчике прерывания. Могут ли появиться проблемы при таком подходе?
Появилась необходимость использовать светодиод для индикации работы программы, смена состояния которого будет происходить в обработчике прерывания. Могут ли появиться проблемы при таком подходе?
Что-то не понятно где обработчик прерывания в вышеприведенном коде и как там светодиод управляется.
В общем случае в прерывании вполне себе допустимо дергать пинами. Главное не вставлять туда всякие delay() и вообще не деалать дополнительных задержек.
Что-то не понятно где обработчик прерывания в вышеприведенном коде и как там светодиод управляется.
обработчик прерывания планирую такой:
обработчик прерывания планирую такой:
Так точно работать не будет. Безпроблемно в прерывании можно дергать только пины самой Ардуины.
В данном случае, скорее всего, достаточно будет разрешить глобальные прерывание в начачале timerIsr(). Но этро при условии что Timer1 нигде больше не используется.
Безпроблемно в прерывании можно дергать только пины самой Ардуины.