Был сделан прибор для общения и обучения слепо-глухонимых. Состоит из обычной клавиатуры PS/2, LCD 1602, самодельной клавиатуры на 7 кнопок(подключенных через i2c), тактильного дисплея(представляет собой устройство из 6 пар катушек, 6 ВЧ диодами, соединённых параллельно каждой паре катушек и 6 поднимаемыми ими штырей) и платы с ардуиной во главе. Фото ниже. В последствии экран и клавиатура ps/2 были подключены через PS/2 разъемы, а не через обычные штырьевые, но сути это не меняет. Питание системы осуществляется через DC-DC преобразователь. Первая линия питания с неизмененными 9 вольтами с DC-DC идут на каскад транзисторов, включенных в режиме ключа, и питают тактильный дисплей. Вторая линия идет на Arduino где стабилизируется до 5 вольт и питает оставшиеся компанеты. Код писался и адаптировался соответственно из разных частей непроффесионалами, пожелания по улучшению принимаются. Есть 2 версии, с массивами и без. Тут привожу с массивами. Без в ссылке ниже. Работает все так. Человек пишет на клавиатуре ps/2, текст выводится побуквено на тактильный дисплей и полностью на ЛСД экран. Тоже самое в обратном направлении. Слепо-глухонемой человек набирает на своей клавиатуре текст и он выводится на тактильный дисплей(Для проверки написанного) и на ЛСД экран. И вот какая проблема. Без тактильного дисплея все работает стабильно и быстро. Набираешь текст на одной из клавиатур и он тут же выводится на экран. Но. Как только подключаешь тактильный дисплей начинаются проблемы с клавиатурой PS/2. Вместо нужных букв выводятся другие, клавиатура не реагирует на нажатия, происходят зависания. При этом с самоделкой на 7 кнопок все хорошо, все буквы четко и правильно выводятся. Сначала грешили на питание, но просадок и проблем не нашли. Возможно код? Без массивов работа чуть лучше, но проблема не исчезает, да и почему тогда без тактильного дисплея все работает отлично? В общем мы пока в тупике. То ли клавиатура отказывается в паре робить, то ли катушки поле создают и все ломают и необходимо все экранировать дополнительно. Уповаем на мудрые советы форумчан. Надеюсь проблема понятна. Видео с примером проблемной работы https://vk.com/im?sel=152090993&z=video152090993_456239092/137ce12a044bec08bb Видео с нормальной работой без тактильного дисплея https://vk.com/im?sel=152090993&z=video152090993_456239093/c6eca5f6ddd84a1202 Ссылка на вторую версию кода без массивов. https://yadi.sk/d/15MImTH5sCboKw Код (C++): #include <LCD_1602_RUS.h> #include <PS2Keyboard.h> #include <Wire.h> #include <LCD_1602_RUS.h> #define ADDR_KBRD 0x27 LCD_1602_RUS lcd(0x3F,16,2); const int DataPin = 2; const int IRQpin = 3; int i; int j; int pins[6] = {4, 5, 6, 7, 8, 9}; String str; byte dio_in; bool b; bool key[7]; PS2Keyboard keyboard; int bCount = 0; String LCD_array[33] = {"А", "Б", "В", "Г", "Д", "Е", "Ё", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ы", "Ь", "Э", "Ю", "Я"}; String S7_keyboard[33] = {"115", "113", "5", "65", "67", "83", "51", "69", "18", "101", "32", "114", "112", "98", "66", "82", "96", "80", "100", "68", "50", "97", "81", "99", "64", "19", "34", "16", "36", "4", "37", "17", "33"}; int PS_keyboard[33] = {102, 44, 100, 117, 108, 116, 96, 59, 112, 98, 113, 114, 107, 118, 121, 106, 103, 104, 99, 110, 101, 97, 91, 119, 120, 105, 111, 93, 115, 109, 39, 46, 122}; byte Taktor_array[33] = {B00000001, B00000011, B00111010, B00011011, B00011001, B00010001, B00100001, B00011010, B00110101, B00001010, B00101111, B00000101, B00000111, B00001101, B00011101, B00010101, B00001111, B00010111, B00001110, B00011110, B00100101, B00001011, B00010011, B00001001, B00011111, B00110001, B00101101, B00110111, B00101110, B00111110, B00101010, B00110011, B00101011}; void setup() { lcd.init(); // Инициализация экрана lcd.backlight(); // Включаем подсветку Wire.begin(); Wire.beginTransmission(ADDR_KBRD); Wire.endTransmission(); delay(1000); keyboard.begin(DataPin, IRQpin); Serial.begin(9600); Serial.println("Keyboard Test:"); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); } void loop() { if (keyboard.available()) { char c = keyboard.read(); if (c == PS2_ENTER) { Serial.println(); lcd.setCursor( 15, 0); lcd.print("-"); lcd.setCursor( 0, 1); } else if (c == PS2_TAB) { digitalWrite(pins[0], LOW); digitalWrite(pins[1], LOW); digitalWrite(pins[2], HIGH); digitalWrite(pins[3], HIGH); digitalWrite(pins[4], HIGH); digitalWrite(pins[5], HIGH); lcd.print("="); } else if (c == PS2_ESC) { Serial.print("[ESC]"); } else if (c == PS2_PAGEDOWN) { Serial.print("[PgDn]"); } else if (c == PS2_PAGEUP) { Serial.print("[PgUp]"); } else if (c == PS2_LEFTARROW) { Serial.print("[Left]"); } else if (c == PS2_RIGHTARROW) { Serial.print("[Right]"); } else if (c == PS2_UPARROW) { Serial.print("[Up]"); } else if (c == PS2_DOWNARROW) { Serial.print("[Down]"); } else if (c == PS2_DELETE) { lcd.clear(); lcd.setCursor( 0, 0); } else if (c == 32) { digitalWrite(pins[0], LOW); digitalWrite(pins[1], LOW); digitalWrite(pins[2], LOW); digitalWrite(pins[3], LOW); digitalWrite(pins[4], LOW); digitalWrite(pins[5], LOW); lcd.print(" ");} for (int i=0; i<33; i++) { if (c == PS_keyboard[i]) { lcd.print(LCD_array[i]); for (int j=0; j<6; j++) { Serial.print(bitRead(Taktor_array[i], j)); digitalWrite(pins[j], bitRead(Taktor_array[i], j)); } } } } Wire.requestFrom(ADDR_KBRD,1); while (!Wire.available()); byte dio_in = Wire.read(); //читаем состояние портов PCF8574P str=String(dio_in, DEC); //Serial.println(str); for (int i=0; i<33; i++) { if (str == S7_keyboard[i]) { lcd.print(LCD_array[i]); delay(500); for (int j=0; j<6; j++) { // Serial.print(bitRead(Taktor_array[i], j)); digitalWrite(pins[j], bitRead(Taktor_array[i], j)); } } } }
kirilikyzzz - да как же этому коду работать, если у вас при считывании данных с I2C клавиатуры после каждого считанного символа задержка полсекунды? конечно оно будет постоянно тормозить и зависать Я не вполне понимаю, как у вас эта тактильная клавиатура устроена и зачем там задержка. Попробуйте ее либо убрать совсем, либо уменьшить, скажем. до 20-50 мс (речь о строке delay(500) примерно десятая строка от конца кода
Да, когда объединяете много устройств delay опасен в неумелых руках - в setup еще простительно, эта процедура выполняется 1 раз при включении, а вот в loop появляются проблемы. А while (!Wire.available()); тоже может повесить программу - отвиснет только при нажатии. Нужно понять логику, чего вы тут хотите сделать. Видео в вк, судя по всему, ограничено в доступе - не посмотреть.
Видео загрузил на Диск, теперь должно работать Неправильная работа: https://yadi.sk/i/NCtnoAsrP11WGw Нормальная работа без тактора: https://yadi.sk/i/e9pLnAeGAGZIUA while (!Wire.available()); Используеться только потому, что это единственный способ(который нашли), чтобы подключить самодельную 7ми символьную клавиатуру. Других не знаем к сожалению. Логика проста. Обычный человек набирает текст на PS/2, команды передается в ардуину и от туда на ЛСД экран и тактильный дисплей и тоже самое наоборот. Тактильный дисплей односимвольный, поэтому выглядит так. Человек нажал кнопку на клавиатуре, этаже буква вывелась на тактильный дисплей и на экран, нажал следующую, на тактильном дисплее поднялась другая буква, а лсд записалась в следующую позицию, пока не заполняться обе строки. Надеюсь на видео будет понятно. С делеем мы пробовали разные варианты, и убирали и добавляли. Не сказал бы что есть какие то ощутимые изменения.
Эта задержка введена специально. Из за особенности работы клавиатуры для слепого. Ардуина постоянно считывает её состояние, то есть в порт постоянно приходит её состояние, наверно раз 5-10 в секунду. Дело в том, что слепо-глухонемой, набирает на 6 верхних кнопках определенную комбинацию и нижней клавишей подтвержлает её отправку. Если делей слишком маленький, ниже 200 точно, то при удержании кнопки отправки чуть дольше, вместо 1 буквы, вылетает сразу 2-6 на лсд, в зависимости от долготы нажатия. т.к. ардуина все время считывает состояние и очень быстро. Как вариант замедлить это считывание, но как я не знаю. Надеюсь понятно объяснил.
Я вижу 2 варианта: 1. Если не хочется думать над кодом, то взять 2ую ардуинку, обмениваться буквами с 1ой по uart. 2ая будет работать "глупо" с задержками только с тактором. 2. Подумать над кодом. Заходить в обработку трактора не по while (в данном случае этот вайл вам стопорит выполнения кода), а через if. Если что-то есть, то обработать. + delay тут вводит тупую задержку, она не помогает ничем. Т.к. пользователь нажал кнопку, while сработал и всё. Больше данные не считываются/проверяются/обрабатываются.