Официальный сайт компании Arduino по адресу arduino.cc
TFT 2,4 touch shield -нужна помощь в программирование кнопок на экране
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Втр, 03/11/2015 - 11:15
Здравствуйте, дорогие друзья!
Написал скетч, хочу чтобы на экране отображались изменения изображения (кнопка видоизменялась) и в последствии запускался процес. На самом деле работаю над автоматизацыей отопления.
Изменения конопок хотел сделать через переменные а и b, чтобы в последствии также сделать привязку к датчикам температуры в комнатах.
Помогите исправить скетч.
#include <TFTLCD.h> #include <TouchScreen.h> #include "DHT.h" #define DHTPIN 10 #define DHTPIN 11 #define DHTTYPE DHT11 DHT dht(DHTPIN, DHTTYPE); #define YP A1 #define XM A2 #define YM 7 #define XP 6 #define MINPRESSURE 1 #define MAXPRESSURE 1000 // Para mejor precision de la presion realizada, es necesario // medir la resistencia entre los pines X+ y X-. // En Shield TFT 2.4" LCD se mide entre los pines A2 y 6 // Instancia del panel tactil (Pin XP, YP, XM, YM, Resistencia del panel) TouchScreen ts = TouchScreen(XP, YP, XM, YM, 364); short TS_MINX = 20; // Coordenadas del panel tactil para delimitar short TS_MINY = 20; // el tamaño de la zona donde podemos presionar short TS_MAXX = 850; // y que coincida con el tamaño del LCD short TS_MAXY = 891; #define LCD_CS A3 // Definimos los pines del LCD #define LCD_CD A2 // para poder visualizar elementos graficos #define LCD_WR A1 #define LCD_RD A0 #define LCD_RESET A4 #define BLACK 0x0000 // Definimos los colores #define BLUE 0x001F // que utilizaremos para #define RED 0xF800 // el texto y los elementos graficos #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); // Instancia LCD int X; // Variables que almacenaran la coordenada int Y; // X, Y donde presionemos y la variable Z int Z; // almacenara la presion realizada int a = 0; // variable "flag" para control rebotes int b = 0; void setup(void) { tft.initDisplay(); tft.fillScreen(CYAN); pinMode(10, INPUT); pinMode(11, INPUT); pinMode(12, OUTPUT); pinMode(13, OUTPUT); tft.setRotation(45); tft.drawRect(5, 10, 145, 220, RED); tft.setCursor(30, 20); tft.setTextSize(2); tft.setTextColor(BLACK); tft.println("SENSORS:"); tft.drawRect(160, 10, 145, 110, RED); tft.setCursor(170, 20); tft.setTextSize(2); tft.setTextColor(RED); tft.println("CIRCULATION"); tft.setCursor(200, 40); tft.setTextSize(2); tft.setTextColor(RED); tft.println("PUMP"); tft.setCursor(200, 60); tft.setTextSize(2); tft.setTextColor(RED); tft.println("OFF"); tft.drawRect(160, 125, 145, 105, RED); tft.setCursor(170, 130); tft.setTextSize(2); tft.setTextColor(RED); tft.println("CONVECTION"); tft.setCursor(190, 150); tft.setTextSize(2); tft.setTextColor(RED); tft.println("CHAMBER"); tft.setCursor(190, 170); tft.setTextSize(2); tft.setTextColor(RED); tft.println("OFF"); } void loop() { buttons(); touch(); ecran(); //dhts(); } void touch() { // перша робоча кнопка if((X > 40 && X < 150) && (Y > 20 && Y < 120) && (Z > MINPRESSURE && Z < MAXPRESSURE)&& (a == 0)) { a = 1; delay(100); } else if ((X > 40 && X < 150) && (Y > 20 && Y < 120) && (Z > MINPRESSURE && Z < MAXPRESSURE)&& (a == 1)) { a = 0; delay(100); } // друга робоча кнопка if((X > 150 && X < 300) && (Y > 20 && Y < 120) && (Z > MINPRESSURE && Z < MAXPRESSURE) && (b == 0)) { b = 1; delay(100); } else if ((X > 150 && X < 300) && (Y > 20 && Y < 120) && (Z > MINPRESSURE && Z < MAXPRESSURE) && (b == 1)) { b = 0; delay(100); } } void buttons() { Point p = ts.getPoint(); // Realizamos lectura de las coordenadas pinMode(XM, OUTPUT); // La librería utiliza estos pines como entrada y salida pinMode(YP, OUTPUT); // por lo que es necesario declararlos como salida justo // despues de realizar una lectura de coordenadas. // Mapeamos los valores analogicos leidos del panel tactil (0-1023) // y los convertimos en valor correspondiente a la medida del LCD 320x240 X = map(p.x, TS_MAXX, TS_MINX, tft.width(), 0); Y = map(p.y, TS_MAXY, TS_MINY, tft.height(), 0); Z = p.z; } void ecran() { if (a == 0) { tft.drawRect(160, 10, 145, 110, RED); tft.setCursor(170, 20); tft.setTextSize(2); tft.setTextColor(RED); tft.println("CIRCULATION"); tft.setCursor(200, 40); tft.setTextSize(2); tft.setTextColor(RED); tft.println("PUMP"); tft.setCursor(200, 60); tft.setTextSize(2); tft.setTextColor(RED); tft.println("OFF"); } else if (a == 1) { tft.fillRect(160, 10, 145, 110, RED); tft.setCursor(170, 20); tft.setTextSize(2); tft.setTextColor(WHITE); tft.println("CIRCULATION"); tft.setCursor(200, 40); tft.setTextSize(2); tft.setTextColor(WHITE); tft.println("PUMP"); tft.setCursor(200, 60); tft.setTextSize(2); tft.setTextColor(WHITE); tft.println("ON"); } if (b == 0) { tft.drawRect(160, 125, 145, 105, RED); tft.setCursor(170, 130); tft.setTextSize(2); tft.setTextColor(RED); tft.println("CONVECTION"); tft.setCursor(190, 150); tft.setTextSize(2); tft.setTextColor(RED); tft.println("CHAMBER"); tft.setCursor(190, 170); tft.setTextSize(2); tft.setTextColor(RED); tft.println("OFF"); } else if (b == 1) { tft.fillRect(160, 125, 145, 105, RED); tft.setCursor(170, 130); tft.setTextSize(2); tft.setTextColor(WHITE); tft.println("CONVECTION"); tft.setCursor(190, 150); tft.setTextSize(2); tft.setTextColor(WHITE); tft.println("CHAMBER"); tft.setCursor(190, 170); tft.setTextSize(2); tft.setTextColor(WHITE); tft.println("ON"); } } void dhts(void) { dht.begin(); float t = dht.readTemperature(); float h = dht.readHumidity(); delay(1000); tft.setCursor(50, 20); tft.setTextSize(2); tft.setTextColor(BLACK); tft.println("temperature C"); tft.setCursor(70, 20); tft.setTextSize(1); tft.setTextColor(BLACK); tft.println(t); tft.setCursor(90, 20); tft.setTextSize(1); tft.setTextColor(BLACK); tft.println(h); tft.setCursor(110, 20); tft.setTextSize(1); tft.setTextColor(BLACK); tft.println("vologist %"); }
Исправить скетч чтобы что ?
Вы забыли написать, что не так со скетчем, что именно не работает.
прошу извинения:
из части void setup картинка на екран загружаеться, а дальше нет реакции на тач скрин или реакция может быть но с большим опозданием, живет своей жизнью ...
Включайте "дебаггер": допишите в void setup() строку Serial.begin(9600); , в void buttons() строки
if (Z > MINPRESSURE && Z < MAXPRESSURE)
{
Немножко видоизменил скетч:
И зделал как Вы рекомендовали. Как результат по сериал монитору вижу температуру и влажност а void buttons перестал отвечать в лупе.
Получаеться что функция dhts отключает функцию buttons.
То есть, если в loop отключить вызов dhts, начинает работать buttons ?
Вижу поменяли библиотеку на #include "stDHT.h", это к чему бы ?
Да, насчет отключения dhts вы правы, действительно кнопки начинают работать.
Библиотеку поменял из за того, что с этой просче реализовать подключение двух датчиков одновременно.
Но и с прежней проблема была та же.
Я уже начал понимать:
когда потправил задержки -начало работать, но немного не так как бы хотелось, с затормажованием.
подскажите как работают эти задержки, по мойму они налаживаються друг на друга и в последствии удленяют время исполнения функций.
спасибо
Задержки ? Я вижу только три задержки (строки 222, 225 и 284), которые выполняются при каждом проходе loop(), всего 0,22 секунды. В строке 243 всего 0,01 сек., да и то не всегда. Давайте зайдём с другой стороны: а надо ли вызывать функцию dhts() при каждом проходе loop() ? Может достаточно измерять влажности/температуры, скажем, раз в минуту ? Что-то типа
в начале скетча - unsigned long last_dhts_run = 0;
вместо строки 105 - if ( (last_dhts_run == 0) || (millis() - last_dhts_run > 60000) ) { dhts(); last_dhts_run = millis(); }
Спасибо Вам, я обязательно попробую такой вариант.
И пользуясь случаем: подскажите пожалуйста, как используя функцию millis задавать время исполнения команды. К примеру у меня в строках 226 по 243, в зависимости от значения температури идет команда LOW на 13 пин. Как задать время исполнения команди с последующим возвратом на уровень HIGH на 13 пин?
спасибо
В моём предыдущем посте как раз и расписано, как используя функцию millis задавать время исполнения команды.
В общем случае алгоритм для таймеров примерно такой:
1. В начале скетча объявляем unsigned long переменную для таймера. (Например, unsigned long event_timer = 0;)
2. После начала события (digitalWrite(13, LOW);) присваиваем переменной текущее значение millis(). (event_timer = millis();)
3. В функцию loop() помещаем проверку окончания времени события. (if (millis() - event_timer > event_duration) // event_duration - нужная нам продолжительность события в мсек.)
4. Если проверка сработала, делаем окончание события (digitalWrite(13, HIGH);)
Это, повторю, общий случай.
Отлично!
Спасибо Вам большое!
Про таймеры нормально не расскажу - не писатель я. Почитайте-ка классику:
http://alxarduino.blogspot.com/2013/08/delay.html
затем
http://alxarduino.blogspot.ru/2013/09/BlinkAndPrintWithoutDelay.html
Здравствуйте еще раз!
Спасибо Вам большое за помощь, после Ваших рекомендаций -все заработало как надо. Мне теперь, чтобы завершить проект, осталось разобраться с датчиком DallasTemperature onewire, все вроде как бы понятно, и много уже есть всего написано, но у меня датчит выдает странный результат:
результат выдает -!27
Как я понимаю это сырые данные, требующие интерпретации, или может я ошибаюсь и есть ошибка в скетче.
Буду признателен за помощь, спасибо заранее.
1. Как подключали, про резистор 4,7K не забыли ?
2. Скетч .....\Arduino\libraries\OneWire\examples\DS18x20_Temperature\DS18x20_Temperature.pde у себя найдите и попробуйте.
UPD: как-то смущает вот это
// Data wire is plugged into pin 2 on the Arduino
05
#define ONE_WIRE_BUS 1
может быть ONE_WIRE_BUS 2 правильнее.
Здравствуйте!
Спасибо за быстрый ответ: 1. -про резистор не забыл, но правда вместо 4.7кОм -поставил 10кОм.
2. Скетч о котором вы говорите пробовал, у меня выдавало что нет адресов при сканировании
3. Да я просто забыл удалить коментарий, а датчик у меня подключен к пину -1.
Да вот все вроде...
2. Скетч о котором вы говорите пробовал, у меня выдавало что нет адресов при сканировании
А вот это плохо, если все правильно подключено и сенсор исправный - должно работать.
Датчик на пин 1 не стоит подключать. Пины d0 и d1 в Ардуино обычно стараются не использовать, поскольку они задействованы под RX и TX порта Serial.
2. Скетч о котором вы говорите пробовал, у меня выдавало что нет адресов при сканировании
А вот это плохо, если все правильно подключено и сенсор исправный - должно работать.
Датчик на пин 1 не стоит подключать. Пины d0 и d1 в Ардуино обычно стараются не использовать, поскольку они задействованы под RX и TX порта Serial.
Вот блин у меня, после подключения тфт тач скрина, двух датчиков дхт и двух реле -остались свободными только д0 и д1 пины. Интересно, если я буду выводить результат не на серал, а на екран: будет ли он работать?
Разберитесь сначала с ds18b20: временно освободите какой-нибудь пин, прицепите на него ds18b20, научитесь его опрашивать и выводить результаты, тут Вам Serial.print() очень поможет. Затем верните всё на место, прицепите ds18b20 назад на первый пин, уберите из скетча Serial и, собственно, всё.
Есть еще один нюанс: при заливке скетча в ардуино он может быть неправильно залит, если на пинах d0, d1 стоит что-то. Обойти его можно, отключая датчик от первого пина перед каждой заливкой скетча. Геморно, но вполне возможно.
Благодарствую Вам Araris!
У меня все заработало, все датчики и реле. Осталась еще одна маленькая проблемка, вот робочий скетч:
Начиная с 110 строки, йде исполнения кода после включения конвекционного насоса на 1 минуту -возврат в прежнее состояние, и после этого цикл немножко нарушаеться в отношении работы только екрана -кнопка начинает постоянно мерцать и частота мерцания меняеться только посредством дилея. Но если повторно включить процес и вручную выключить, используя функцию Buttons - все становиться нормально, тольк если дать процесу отключиться по временному коду миллис -такое впечатления что процес застревает в лупе.
Подскажите пожалуйста как в лупе, в конце, стабилизировать изображение екрана?
спасибо
Все работает именно так, потому что так написано в скетче.
По окончании 60-ти секунд начинает срабатывать условие
if
(millis() - last_convection_run > 60000)
Будет оно срабатывать долго, аж до следующего присвоения last_convection_run = millis();, то есть либо до вызова dhts(), либо до нажатия второй рабочей кнопки.
И будут строки 111-124 выполняться при каждом прохождении loop(), и мерцать будет кнопка, и никакой delay() в строке 126 не спасет.
В общем, что-то Вам надо делать со строками 111-124, чтобы они бесцельной работой не занимались.
Общая рекомендация такая: перерисовывать что-то на экране имеет смысл, только если что-то должно поменяться. Иными словами, если у Вас при каждом прохождении loop() содержимое экрана не меняется, то зачем его перерисовывать ?
Согласен со всем выше сказаным, но суть вот в чем:
там про прохожении 60секун у меня останавливаеться процес посредством команды
digitalWrite(RelayConv, HIGH);
Иде остановка процеса и соответственно надо чтобы кнопка на екране перерисовалась, но только один раз, до запуска следующей команды, а не постоянно как в моем скетче.
Вопрос: куда перенести этот отрывок кода?
Ну вот, к этому вопросу я и хотел подвести (и лучше, чтобы Вы же на него ответ и нашли, на будущее пригодится). Куда перенести ? Видимо, туда, где изменение состояния (запуск/остановка) процесса.
Я ведь особо в то, что делает Ваш скетч не вникаю, я пытаюсь в общих чертах подсказывать.
Это ведь основополагающие для многих разных скетчей подходы, например, в данном случае: состояние чего-то поменялось - отобразили на экране, состояние не меняется - ничего не делаем на экране.
А логика работы конкретного скетча - дело автора.
Теперь ещё об изменении состояния чего-либо: удобнее управлять не напрямую (digitalWrite(RelayConv, HIGH); / digitalWrite(RelayConv, LOW);), а через пару переменных, определяющих текущее и предыдущее состояние.
То есть для реле заводим пару глобальных переменных, например, boolean RelayConvStatusNow, RelayConvStatusOld; Имея такую пару, мы можем разнести по разным местам скетча изменение/отображение/проверки состояния реле, и управление самим реле. В функции loop() будет что-то типа:
Такой подход много чего даёт: мы можем управлять из разных мест скетча, мы всегда знаем, в каком состоянии управляемое сейчас, и было ли изменение состояния, и.т.д.
Да, спасибо большое, суть данного совета -понимаю. В самом начале работы на данным проектом, хотел именно реализовать статус и состояние через перенменным, но в начале, в таком подходе кнопки и екран работали не коректно. Но я понял: стоит вернуться к этому подходу....
спасибо
Здравствуйте!
Еще одно хотел уточнить, пробую понять суть подхода выложенного Вами выше: я и раньше использовал переменные для фиксации статуса какого то процеса, даже в этом скетче я ввел две переменныа А и Б, которые стают 0 или 1 соответственно до состояния кнопок А и Б, но ввашем похдоде вижу нечто иное. У вас по две переменные на одну реле, то есть я так понимаю они фиксирую не состояние - а сам факт изменения, или я ошибаюсь? Могли бы Вы обяснить алгоритм описания такой роботы с переменными как у вас выложен в коментарии?
спасибо
Две переменные фиксируют два состояния - текущее и предыдущее.
Алгоритм для каждого прохода loop() :
1. Где-то, возможно, меняется само/меняем мы текущее состояние.
2. Ближе к концу loop() проверяем на изменение состояния ( if (текущее != предыдущее) ).
3. Реагируем на изменение, если оно было.
4. Готовимся к следующему проходу loop() - сохраняем текущее в предыдущее ( предыдущее = текущее ).
Здравствуйте уважаемый Araris!
Уже успешно проверил правильность выложенного Вами выше подхода -все отлично и действительно екран реагирует только после определенных действий. Спасибо большое за обьяснение подхода! Еще одна просьба к Вам, если не будет затруднительно -бросить взглядом на скетч, потому что, есть ошибки в декларировании переменных и не все процесы запускаються:
К каждой кнопке (у меня их две), я использовал пару переменних OLD и NOW - для фиксации факта изменения и плюс переменные А и Б для фиксации состояния. Кнопки включаються а выключаться не хотят, ну по температурным показателям процесы должны бы запускаться - а нет.
спасибо
В код я особо не вдавался, уж извините, но сразу вызвал подозрения кусок 113-132, может быть стоит вот так :
Возможно, проблема в том, что ифы в 113-й и 123-й не проверяют состояние переменных a и b.
Это чисто умозрительно, так что просто попробуйте.
В таком исполнении - не реагирует вообще. Такое впечатление, что код работает в реверсном режиме.
К примеру в строке 190 установлен таймер отключения реле, а он его включает в отведенное там время
и в следующем исполнении кнопки включаються но не выключаються как и раньше
Мне кажеться что я где то в коде напартачил и создал инверсию статусов!
Включайте "дебаггер" для ловли статусов )))
http://arduino.ru/forum/programmirovanie/tft-24-touch-shield-nuzhna-pomoshch-v-programmirovanie-knopok-na-ekrane#comment-145973
Я без этого вообще отладку скетчей не представляю.
Уважаемый Araris!
Благодарен Вам за помощь! Все заработало. Вот последняя рабочая версия скетча:
Последний вопрос: У меня на 13 пине дхт-сенсор, но работать он не хочет, наверное из за того что на том же пине встроеный светодиод. Можно ли как то это обойти, не меняя распиновки?
Все заработало.
Поздравляю, рад за Вас.
Последний вопрос: У меня на 13 пине дхт-сенсор, но работать он не хочет, наверное из за того что на том же пине встроеный светодиод. Можно ли как то это обойти, не меняя распиновки?
Да, это из-за него. Обойти, не меняя распиновки, вряд ли удастся. У меня был подобный случай, я просто выпаял светодиод (можно аккуратно отломать).
UPD: По-моему, в скетче много лишних tft.setTextSize() и tft.setTextColor(), их достаточно вызывать лишь в местах изменения размера/цвета шрифта, впрочем, принципиального значения это не имеет )).
016
// Para mejor precision de la presion realizada, es necesario
017
// medir la resistencia entre los pines X+ y X-.
018
// En Shield TFT 2.4" LCD se mide entre los pines A2 y 6
019
// Instancia del panel tactil (Pin XP, YP, XM, YM, Resistencia del panel)
020
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 364);
как и между какими лапами экрана вымерять сопротивление панели?
// Para mejor precision de la presion realizada, es necesario
// medir la resistencia entre los pines X+ y X-.
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 364);
как и между какими лапами экрана вымерять сопротивление панели?
#define YP A1
#define XM A2
#define YM 7
#define XP 6
Все же указано тут.