Arduino и PROGMEM
- Войдите на сайт для отправки комментариев
Втр, 25/09/2018 - 00:10
Добрый вечер!
Прощу помощи у опытных юзеров!
Уже обращался с этим вопросом, получил пинок нужном направлении, однако усвоил не до конца.
Суть: Нужен проверщик ответов. Т.е. заранее прописываем правильные ответы, задаем вопросы, проверяем, и выводим на дисплей результат. Если ответ правильный - переходим к следующему. В арсенале ардуинка, LCD, мембранная клава.
Вот код:
#include <Keypad.h> #include <LCD_1602_RUS.h> #include <Password.h> #include <Servo.h> #include <avr/pgmspace.h> #define Q_COUNT 4 Servo servo; LCD_1602_RUS lcd(0x27, 16, 2); const char asnwer_good[] PROGMEM = "Правильно"; const char answer_bad[] PROGMEM = "Неправильно!"; const char answers[] PROGMEM = { 'A', 'C', 'D', 'A' };// тут сидят правильные ответы const char question01[] PROGMEM = "Первый вопрос?"; const char question02[] PROGMEM = "Второй вопрос?"; const char question03[] PROGMEM = "Третий вопрос?"; const char question04[] PROGMEM = "Четвертый вопрос?"; const char* const questions[] PROGMEM = { question01, question02, question03, question04 }; char buffer[90]; char key_answer; const byte ROWS = 4; // 4 строки const byte COLS = 4; // 4 столбца char keys[ROWS][COLS] = { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; byte rowPins[ROWS] = {12, 11, 10, 9}; // тут пишем диджитал пины к которым клава коннектится к ардуинке. byte colPins[COLS] = {8, 7, 6, 5}; // Просто тупо слева направо первые 4 это ROWS последние 4 COLS. Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); void setup() { servo.attach(2); lcd.begin(); } void loop() { // Проходим по списку вопросов for (int i = 0; i < Q_COUNT; i++) { strcpy_P(buffer, (char*)pgm_read_word(&(questions[i]))); lcd.clear(); lcd.setCursor(0, 0); lcd.print(buffer); if (pgm_read_word_near(answers + i) == keypad.getKey()) { strcpy_P(buffer, (char*)pgm_read_word(&(asnwer_good))); lcd.clear(); lcd.setCursor(0, 0); lcd.print(buffer); } else { strcpy_P(buffer, (char*)pgm_read_word(&(answer_bad))); lcd.clear(); lcd.setCursor(0, 0); lcd.print(buffer); // Выходим из цикла / начинаем сначала. break; } } }
Суть проблеммы: не вижу свою ошибку. Вроде-бы умные люди мне показали как надо, я подправил под свои нужны, а все-равно не работает.
Как сделать "Проверщик ответов"?
Для начала запишите желаемый алгоритм работы по-русски.
Пишу: после подачи питания на ардуино на lcd (1602, подключен по i2c) пользователя встречает надпись: «Первый вопрос» в первой строке и «A B C D» во второй. Пользователь на мембранной клавиатуре (та что с цифрами 0-9, *#, и буквами A-D) выбирает, по его мнению, правильный ответ. Ответ пользотателя сверяется с записанным ранее в код ответом для первого вопроса, выводит на дисплей «ПРАВИЛЬНО» (если ответ пользователя совпадает с записанным в код ответом для первого вопроса) в первой строке и «ПРАВИЛЬНЫХ ОТВЕТОВ: 1 из 4» во второй. И переходит ко второму вопросу, какой тоже имеет варианты ответа A B C D, но только один правильный. Если пользователь даст неправильный ответ, на экран выводится «НЕ ПРАВИЛЬНО» в первой строке и «КОЛИЧЕСТВО ЖИЗНЕЙ: 4». Заранее в коде прописывается счетчик жизней. Например 5. Если дан неправильный ответ, количество жизней уменьшается на 1. Если пользователь правильно ответил на большинство вопросов и количество жизней больше нуля, после последнего вопроса па экран выводится: «ПОБЕДА» и програма завершается. Если после какого-то из ответов количество жизней становится равным 0, на экран выводится: «ПОЖАЖЕНИЕ» и програма завершается. Так-же пытаюсь все это упаковать в PROGMEM, так как вопросов планирую делать много.
Помогите, пожалуйста... Понимаю, что не вижу ошибку у себя под носом...
Пользователь на мембранной клавиатуре (та что с цифрами 0-9, *#, и буквами A-D) выбирает, по его мнению, правильный ответ.
Вообще-то подразумевался алгоритм действий программы, а не пользователя.
Не следует путать одно с другим.
Ответ пользотателя сверяется с записанным ранее в код ответом для первого вопроса, выводит на дисплей «ПРАВИЛЬНО» (если ответ пользователя совпадает с записанным в код ответом для первого вопроса) в первой строке и «ПРАВИЛЬНЫХ ОТВЕТОВ: 1 из 4» во второй. И переходит ко второму вопросу, какой тоже имеет варианты ответа A B C D, но только один правильный. Если пользователь даст неправильный ответ, на экран выводится «НЕ ПРАВИЛЬНО» в первой строке и «КОЛИЧЕСТВО ЖИЗНЕЙ: 4». Заранее в коде прописывается счетчик жизней. Например 5. Если дан неправильный ответ, количество жизней уменьшается на 1.
Из этого описания более или менее понятно, что делать при правильном ответе - переходить к следующему вопросу и повторять то же самое для него. Но совершенно непоенятно, что при неправильном. Ладно, уменьшили количество жижней и что дальше?
Если пользователь правильно ответил на большинство вопросов и количество жизней больше нуля,
А разве это независимые условия?
после последнего вопроса па экран выводится: «ПОБЕДА» и програма завершается. Если после какого-то из ответов количество жизней становится равным 0, на экран выводится: «ПОЖАЖЕНИЕ» и програма завершается.
"Программа завершается" - это для ПК, в случае микроконтроллеров программа не завершается никогда.
Для ПК полным высказыванием будет "программа завершается и передает управление ОС", а в случае МК никакой ОС нет и передавать управление некому.
Помогите, пожалуйста... Понимаю, что не вижу ошибку у себя под носом...
Программу можно написать следующим образом:
1. Записать алгоритм работы программы по-русски.
2. Перевести с русского на нужный язык программировангия.
Ваша ошибка заключается в том, что Вы слишком рано взялись за написание текста на Си - еще до того, как сумели внятно и однозначно сформулировать алгоритм по-русски (читай: раньше, чем поняли, как должен работать алгоритм).
добавлю к предыдущему оратору
Den - вы так и не написали, что именно в программе не работает. Все ограничилось рассуждениями о том, что вам дали пинок, но этого недостаточно и что вы "не видите ошибку у себя под носом".
Предлагаете, чтоб каждый, кто зайдет в тему - собирал вашу схему и пробовал программу "вживую". пытаясь разобраться. что же там не работает?
Вы потерялись в входящих и исходящих данных. Советую сначала сделать программу с вводом и выводом на терминал, обкатать ее, а затем добавлять клавиатуры, дисплеи и т.д. Обкатайте основной алгоритм программы, а затем занимайтесь украшательствами.
При неправильном ответе отнимаем одну жизнь и переходим к следующему вопросу.
По поводу количества жизней больще нуля соласен, зависимые.
Программа завершается, имею ввиду что гаснет дисплей и программа больше не принимает и не отдает ничего.
У меня не получается из Progmem достать нужную мне инфу в нужном месте программы. Вот я записываю, что загоняю во флеш память (буфер) фразу «Первый вопрос»:
А вот этим куском кода, найденным на просторах интернета, хочу из буфера достать его и вывести его на дисплей (поправьте меня, если я вкорне неправ)
а то, что вопрос хранится в массиве question01. а извлекать вы его пытаетесь из массива questions - вас не смущает?
Тут вроде все верно. Я pgm давно не трогал, но танцы с массивом pgm-нутых строк похоже на правильные. В массив questions помещаются указатели на массивы строк.
я бы так написал
Вижу первый косяк, b707, спасибо, исправлю!)
qwone, я человек. В моем первом сообщении указано, что я подключаю библиотеку для работы с lcd 1602 по i2c и использовать кириллицу. Я понимаю, что мои попытки научится и мои ошибки вызывают у Вас ухмылку. Будьте внимательнее. Буду признателен за комментарий по сути.
что я подключаю библиотеку для работы с lcd 1602 по i2c и использовать кириллицу.
Ключевое тут в том, что по умолчанию скетч сохраняется в кодировке UTF-8, в том числе все строки, написанные на русском. Кодировка UTF-8 - до 6 байт на ОДИН символ, чтобы вывести её на дисплей - надо делать дополнительные телодвижения, как правило.
Попробуйте просто: пока написать латиницей тексты - что будет? Латиница в UTF-8 влезает в 1 байт на символ.
DIYMan, qwone, благодарю за подсказки, обязательно попробую. Если-бы не знал, что работает, не пришел бы сюда. В начале я проверил всю переферию отдельно. Дисплей работал как с русским так и с английским текстом, клава выводила нажатые кнопки на этот самый дисплей. Потом я полез в PROGMEM, так как нужно на экран вывести много текста (1602 не лучший инструмент, но его преимущество в том, что он есть). Копаясь в PROGMEM наткнулся на работу одного хорошего человека на соседнем форуме. Он так-же пихал кириллицу в PROGMEM, и на выходе получал кириллицу. Без проблем. Код стащил себе у него. Вот его работа:
http://ns1.arduino.ru/forum/programmirovanie/850-strok-dve-kolonki-tekstovye-znacheniya?page=1#comment-323382
P.S. Не знаю, можно ли тут приводить ссылки на другие форумы, ну раз qvone можно, значит, думаю не накажут.
P.P.S. Я так понимаю, что qvone тут отвечает за развлекательную часть народа. Это похвально, такие люди нужны - без них скучно. В древности даже професия такая была при царском дворе. Никак не припомню, как называлась...
P.S. Не знаю, можно ли тут приводить ссылки на другие форумы
ЛОЛ
это же тот же форум...
Господа, оффтоп: почему у моих предыдущих сообщений такой гиганский шрифт? Как это поправить? И где вообще выбирается размер шрифта?
b707, ничего не знаю, ns1 зачем приставка тогда?))
Вариант. Вопросы и вариант ответы сохранять в sd card flash memory. Взамен, нажимать кнопк для ответа, приложить rfid card. Для дети маленькие – это много интересно. Также от id rfid card вы имеете возможность знать, кто верно ответил. Каждый имеет персональные 4 rfid cards ответы. Возможно отказаться от LCD и применить аndroid tablet.
Отчитываюсь, господа:
Что умеет этот код: Брать фразу: ПЕРВЫЙ ВОПРОС из PROGMEM и держать её на экране в первой строке.
Что еще я хочу от этого кода: Чтоб выводилось во второй строчке A B C D вместе с ПЕРВЫЙ ВОПРОС в первой. Как я указал в начале кода, const char answers - тут находятся правильные ответы.
Вопрос господа: Как организовать сравнение данных, введеных с мембранной клавиатуры пользователем, с const char answers и последующего вывода на дисплей сообщения ПРАВИЛЬНО (сonst char asnwer_correct) при правильном ответе и, сообветственно НЕПРАВИЛЬНО при неправильном?
strarbit, идея шикарная, но поймите, я уже месяц пытаюсь разобраться как простенький проверщик ответов сделать. Меня тут или прикидываются, что не понимают, или реально не понимают. Что если на экран выведено ПЕРВЫЙ ВОПРОС и варианты A B C D. Пользователь выбирает правильный, по его мнению и на экран выводится ПРАВИЛЬНО или НЕПРАВИЛЬНО в зависимости от ответа. Ну я описывал выше. Если на таком простом я не могу ничего толкового сделать, то что уж говорить про RFID?
Отчитываюсь, господа:
Что умеет этот код: Брать фразу: ПЕРВЫЙ ВОПРОС из PROGMEM и держать её на экране в первой строке.
Что еще я хочу от этого кода: Чтоб выводилось во второй строчке A B C D вместе с ПЕРВЫЙ ВОПРОС в первой. Как я указал в начале кода, const char answers - тут находятся правильные ответы.
погодите хотеть что-то еще - давайте разберемся с первым вопросом темы. Я же вам дал пример, как читать из массива PROGMEM, зачем вы его перекорежили? Как вы думаете, что будет читать в буфер приведенная выше строчка кода? - всегда строку "Первый вопрос" и никогда "Второй.." и "Третий..." Если вы спрашиваете - то хотя бы внимательно относитесь к тем ответам, которые вам дают. Тогда, может, и не придется сетовать, что на этом форуме вас не понимают.
Во-вторых, продолжим разбор кода. Для начала про строки в ПРОГМЕМ. Обьясните, зачем вам четыре одинаковых строки "A B C D" - разве нельзя обойтись одной? И в случае вопросов - они все похожи, меняется только первое слово, а второе всегда одинаково. Эффективнее будет хранить отдельно "Первый", "Второй", "Третий"... и отдельно строчку " вопрос", а при выводе просто склеивать числительное и существительное
Меня тут или прикидываются, что не понимают, или реально не понимают. Что если на экран выведено ПЕРВЫЙ ВОПРОС и варианты A B C D. Пользователь выбирает правильный, по его мнению и на экран выводится ПРАВИЛЬНО или НЕПРАВИЛЬНО в зависимости от ответа.
По-моему, это вы что-то не понимаете в отношении форума. Вашу идею с выводом вопросов и ответов форум понял еше в прошлый раз. Непонятно, чего вы ждете от форума в ответ? - что кто-то бросится писать готовый код под это описание? - тут это не принято
ТС решил "удивить" нас своими вопросами. А мы "удивим" его своми ответами.
qwone, спасибо, буду разбираться. Это займет некоторе время...
Что означает аббревиатура ТС?
https://seopult.ru/library/%D0%A2%D0%BE%D0%BF%D0%B8%D0%BA%D1%81%D1%82%D0...
b707, может я что-то делал не так, но по Вашему примеру у меня не получилось... Поковырял немного и получилось.
Так и есть, всегда берет только первый и никогда остальные. Будьте добры, объясните, почему? Я же вверху прописал:
const
char
*
const
questions[] PROGMEM = { question01, question02, question03, question04 };
теперь этой строкой пытаюсь извлечь из флеш-памяти первый, второй и т.д вопросы:
strcpy_P(buffer, (
char
*)pgm_read_word(&(questions)));
Поправьте меня, если я ошибаюсь...
По Вашему примеру
strcpy_P(buffer, pgm_read_word_near((
int
)(questions+ i)));
Все... увидел. (int)(questions+ i) стоит читать как "увеличить questions на 1". Но проясните, пожалуйста, для чего там int и i?
ТОЧНО! Абсолютно согласен, я неправ. Вполне возможно обойтис одной строкой A B C D.
"при выводе просто склеивать числительное и существительное" - объясните, пожалуйста, как это осуществить? А то уже становится интересно)
Вовсе нет, готовый код, это медвежья услуга (qwone, простите)))
Прошлый раз у нас не завязался диалог. В этот раз с каждым разом становится всё понятнее.
P.S. Как правильно цитировать? Имею ввиду куски сообщения, не всё.
qwone, спасибо, понял
strarbit, идея шикарная, но поймите, я уже месяц пытаюсь разобраться как простенький проверщик ответов сделать. Меня тут или прикидываются, что не понимают, или реально не понимают. Что если на экран выведено ПЕРВЫЙ ВОПРОС и варианты A B C D. Пользователь выбирает правильный, по его мнению и на экран выводится ПРАВИЛЬНО или НЕПРАВИЛЬНО в зависимости от ответа. Ну я описывал выше. Если на таком простом я не могу ничего толкового сделать, то что уж говорить про RFID?
В форум помогают вам советы.
Ваш выбор удобно применить rfid или кнопка. В ваш скетч можно стереть много раз одникаковые слова, больше flash для скетч.
По Вашему примеру
strcpy_P(buffer, pgm_read_word_near((
int
)(questions+ i)));
Все... увидел. (int)(questions+ i) стоит читать как "увеличить questions на 1". Но проясните, пожалуйста, для чего там int и i?
Это стоит читать не как "увеличить questions на 1", а как "увеличить на i". questions - это указатель на нулевой элемент массива, а
(questions+ i) - это указатель на элемент массива номер i.
Вы в своем коде берете указатель
questions, без индекса - поэтому всегда получаете только "Первый вопрос"
Я у себя так делал
Вызывал функцию в которую передовал имя массива в PROGMEM и его длину
Прощу помощи у опытных юзеров!Робота с PROGMEM приятна и в тоже время сложна.Суть проблемы в следующем есть матрица 16 на 16 для опроса 256 контактов(шлейфов).256 названий этих шлейфов лежат в PROGMEM, но нормально выходят на Serial 128 шлейфов,что я делаю не так.
У меня нет библиотеки для кнопок, но подозреваю, что там тип char используется, а он максимум 127.
И зачем вы используете 255 раз слово Гараж? Можно же его просто добавлять к строке. А там у вас цифры в основном, их вообще можно не пихать. Букву А добавлять по условию.
Спасибо за ответ.Вместо слов гараж будут дополнительные символы.
Добрый День .Подскажите уважаемые какое количество строк можна записать в PROGMEM.
Code:
Output:
Добрый День .Подскажите уважаемые какое количество строк можна записать в PROGMEM.
Зачем?? Чтобы вывести 256 раз надпись "№" ?
Более дебильного кода и придумать трудно. И не лень было набивать?
Вместо этого:
напишите вот так
простейшая функция, печатает "№хх", где xx - введенное число. Это же программирование, учитесь автоматизировать однообразные действия. а не копировать одну и ту же строку 256 раз подряд.
И ВСЕ!!!! И даже прогмем не нужен
Спасибо .Та же проблема от 1 до 128 шлейфа вывод нормальный ,а с 129 по 256 входит мусор.
Уважаемый b707 под символом № зарезервированное место под 50 символов.Каждая строка это разные сообщения. Вопрос в другом почему 128 строк я вывожу ,другие 128 (с 129по256) не могу вывести.
Вопрос в другом почему 128 строк я вывожу ,другие 128 (с 129по256) не могу вывести.
Опять обсуждаем совсем не тот код? Выложите ИМЕННО ТОТ КОД, который вы используете, без всякого упрощения и замены строк.
Я догадываюсь, откуда у вас проблема. Слишком подозрительно круглые числа (в двоичном смысле) у вас - 128 строк показываются. 128 нет. Похоже, что в каком-то месте у вас индекс имеет диапазон 0-127 вместо 0-255. Но этого невозможно понять по выложенному коду - он явно имеет мало общего с действительностью.
Для начала пройдитесь по программе и замените ВЕЗДЕ тип индекса с char. на byte
Спасибо .Самое интересное ,что код кнопки int от 0 до 255 выводится ,а char символы нет.
Спасибо .Самое интересное ,что код кнопки int от 0 до 255 выводится ,а char символы нет.
ничего удивительного, у вас же в программе не один индекс. Хотите помощи - выкладывайте полный код. а не кастрированный
Это какой то паноптикум....
psv1962 - вам заняться нечем? зачем вы снова выложили тот же код? Где у вас строки нормальные?
И научитесь уже правильно вставлять код в сообщение!
кстати. что за ардуина у вас?
Мега 2560
Я же вам ответил в 34 посте. Если не поняли, то уточню - kchar имеет тип char, и физически не сможет быть больше 127.
psv1962 - вам заняться нечем? зачем вы снова выложили тот же код? Где у вас строки нормальные?
И научитесь уже правильно вставлять код в сообщение!
кстати. что за ардуина у вас?
Я снова хочу напомнить, что мы неоднократно договаривались ВООБЩЕ не отвечать на сообщения с неправильно вставленным кодом.