Помогите с кодом
- Войдите на сайт для отправки комментариев
Чт, 09/11/2017 - 18:21
Есть код считывания - копирования ключей iButton от домофона. Сам код работает, но на экран 1602 всё выводится криво. Прошу помощи!
#include <OneWire.h>
#include <LiquidCrystal_I2C.h>
//задаем адрес LCD экрана 0x27, 16 символов, 2 строки
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int switchPin = 2; // Будем использовать аппаратное прерывание INT0, поэтому кнопка должна быть подключена к 2-му пину
const int dataPin = 10; // Data пин считывателя ключей
const int ledPin = 13; // Пин контрольного светодиода
volatile boolean writeMode = false; // Режим записи: 1 - включен; 0 - выключен (режим чтения)
boolean recoveryMode = false; // Режим восстановления нечитаемых ключей (с записанным по ошибке нулевым первым байтом)
byte oldID[8]; // Считанный ID ключа
byte newID[8]; // Записываемый ID ключа
const byte defaultID[8] = { 0x01, 0x54, 0x5E, 0x03, 0x0E, 0x00, 0x00, 0x84 }; // По умолчанию прошивается "Универсальный" ID: 01:54:5E:03:0E:00:00:84
byte crc; // Контрольная сумма CRC
OneWire ibutton (dataPin);
void setup() {
Serial.begin(115200);
loadDefaultID();
pinMode(ledPin, OUTPUT);
pinMode(switchPin, INPUT_PULLUP);
// При включении устройства, удерживая кнопку нажатой, активируется режим восстановления
if (digitalRead(switchPin) == LOW) recoveryMode = true;
attachInterrupt(0, int0, LOW); // при нажитии кнопки срабатывает 0-е прерывание, обработчик прерывания (ISR) - функция int0()
Serial.println("Device is ready. Send 'h' for help.");
lcd.init(); // Инициализируем экран
//включаем подсветку
lcd.backlight();
//Устанавливаем позицию начиная с которой выводится текст.
lcd.setCursor(2, 0);
//выводим строку 1
lcd.print ("Copy Key-2017");
lcd.setCursor (2, 1);
//Выводим строку 2
lcd.print ("Sergiev Posad11");
delay(2000); // Пауза показа заставки
lcd.clear(); // Очистка дисплея
//аналогично выводим вторую строку
}
// Загрузка дефолтного "универсального" ID
void loadDefaultID() {
for (byte x = 0; x < 8; x++) oldID[x] = defaultID[x];
}
// Переключение режима: Чтение/Запись
void changeMode () {
// Перестраховка от записи некорректного ID
if (!writeMode) {
crc = ibutton.crc8(newID, 7); // Вычисление контрольной суммы записываемого ID
if (newID[0] != 1 || newID[7] != crc) {
Serial.println(F("ID is incorrect! Writing is not permitted."));
writeModeOff();
return;
}
}
writeMode = !writeMode;
digitalWrite(ledPin, writeMode);
if (writeMode) {
Serial.print(F("Waiting for the key to WRITE the new ID: "));
for (byte x = 0; x < 8; x++) {
Serial.print(newID[x], HEX);
Serial.print(' ');
}
Serial.println(" ...");
}
else {
writeModeOff();
}
}
// Автоматическое отключение режима восстановления после записи и вывод приглашения считать новый ключ
void writeModeOff() {
if (recoveryMode) {
recoveryMode = false;
Serial.println(F("Recovery mode disabled."));
}
Serial.println(F("Waiting for the key to READ the ID..."));
}
// Обработчик прерывания по нажатию кнопки: переключает режим: Чтение/Запись (отфильтровывая дребезг контактов)
void int0() {
static unsigned long millis_prev;
if ( millis() - millis_prev > 100 ) changeMode();
millis_prev = millis();
}
// Вывод считанного ID в терминал
void printID() {
for (byte x = 0; x < 8; x++) {
Serial.print(oldID[x], HEX);
Serial.print(" ");
lcd.print(oldID[x], HEX);
}
crc = ibutton.crc8(oldID, 7); // Вычисление контрольной суммы считанного ID
Serial.print(" CRC: ");
Serial.print(crc, HEX);
lcd.print(crc, HEX);
if (oldID[0] != 0x01) Serial.print(F(" Family code is not valid!"));
if (crc != oldID[7]) Serial.print(F(" CRC is not valid!"));
Serial.println();
lcd.println();
}
void loop()
{
// Обработка команд, посылаемых через терминал COM-порта
if (Serial.available() > 0) {
byte com; // Команда, отправляемая через терминал COM-порта
com = Serial.read();
switch ( com ) {
case 'h': {
Serial.println(F("Help:"));
Serial.println(F("d - load default ID"));
Serial.println(F("w - switch read/write mode"));
Serial.println(F("m - enter ID manually"));
Serial.println(F("r - enable recovery mode (send 'r' again to disable)"));
Serial.println(F("h - show this help"));
break;
}
case 'd': {
if (writeMode) {
writeMode = false;
digitalWrite(ledPin, LOW);
}
loadDefaultID();
Serial.println(F("Default ID is loaded."));
printID();
break;
}
case 'w': {
changeMode();
break;
}
case 'r': {
writeMode = false;
recoveryMode = !recoveryMode;
Serial.println(recoveryMode ? F("Recovery mode enabled.") : F("Recovery mode disabled."));
break;
}
case 'm': {
byte inputID[8]; // Введённый вручную ID ключа
char inputChar; // Код введённого символа
char inputNum = 2; // Порядковый номер вводимого сивмола (от 0 до 15). Начинаем вводить со 2-го символа, т.к. 0-ой и 1-ый - фиксированные.
char charEncode; // 16-ричное число (от 0 до F), в которое преобразуется каждый вводимый ASCII символ
boolean even = 0; // Признак чётности порядкового номера вводимого символа
Serial.println(F("Enter the new ID, or press 'Esc' to cancel."));
inputID[0] = 1;
Serial.print(F("The new ID is: 01 "));
while (inputNum < 14) {
if (Serial.available() > 0) {
inputChar = Serial.read();
if (inputChar == 27) {
Serial.flush();
Serial.println();
Serial.print(F("Canceled..."));
break;
}
else {
if ( inputChar >= 48 && inputChar <= 57 ) charEncode = inputChar - 48;
else if ( inputChar >= 65 && inputChar <= 70 ) charEncode = inputChar - 55;
else if ( inputChar >= 97 && inputChar <= 102 ) charEncode = inputChar - 87;
else inputNum = -1;
if ( inputNum != -1 ) {
Serial.write(inputChar);
if (!even) inputID[inputNum / 2] = charEncode << 4;
else {
inputID[inputNum / 2] = inputID[inputNum / 2] + charEncode;
Serial.print(' ');
}
even = !even;
inputNum++;
}
}
}
}
if (inputNum == 14) {
inputID[7] = ibutton.crc8(inputID, 7); // Автоматическое вычисление контрольной суммы введённого ID
for (byte i = 0; i < 8; i++) oldID[i] = inputID[i];
}
Serial.println(oldID[7], HEX);
printID();
break;
}
}
}
for (byte x = 0; x < 8; x++) newID[x] = oldID[x];
// Проверяем, приложен ли ключ
if (!ibutton.search (oldID)) {
ibutton.reset_search();
delay(50);
if (!recoveryMode) return;
}
// Режим чтения
if (!writeMode) {
digitalWrite(ledPin, HIGH);
delay(50);
printID();
digitalWrite(ledPin, LOW);
}
// Режим записи
if (writeMode) {
delay(200);
digitalWrite(ledPin, LOW);
ibuttonCommand(0x33, 1, 1);
Serial.print("Old ID: ");
lcd.print("old ID:");
for (byte x = 0; x < 8; x++) {
Serial.print(ibutton.read(), HEX);
lcd.setCursor (0, 1);
lcd.print(ibutton.read(), HEX);
Serial.print(' ');
}
ibuttonCommand(0xD1, 1, 1);
// устанавливаем на линии логический 0
digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT); delayMicroseconds(60);
pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH); delay(10);
Serial.print(" New ID: ");
for (byte x = 0; x < 8; x++) {
Serial.print(newID[x], HEX);
Serial.print(' ');
}
ibuttonCommand(0xD5, 1, 1);
Serial.print("Writing... ");
for (byte x = 0; x < 8; x++) {
writeByte(newID[x]);
Serial.print('*');
}
Serial.println(F(" OK!"));
ibuttonCommand(0xD1, 0, 1);
// устанавливаем на линии логическую 1
digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT); delayMicroseconds(10);
pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH); delay(10);
changeMode();
}
}
// Отправка команды iButton
void ibuttonCommand(uint8_t command, boolean sk, boolean rs) {
if (sk) ibutton.skip();
if (rs) ibutton.reset();
ibutton.write(command);
}
// Побайтовая запись нового ID
void writeByte(byte data) {
for (int data_bit = 0; data_bit < 8; data_bit++) {
digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT);
if (data & 1) delayMicroseconds(60);
pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH);
delay(10);
data = data >> 1;
}
}
Не плодите дубли сообщений. Если в прошлый раз было мало ответов - это не потому, что ваше сообщение не заметили. Причина в том, что вы неправильно подходите к проблеме и задаете неверный вопрос.
Я вам уже писал - если у вас мало оыта, не стоит сразу писать огромные куски кода. Начните с простого - с вывода на экран что-нибудь типа @Hello World@. Когда научитесь - попробуйте вывести код ключа. Потом добавите готовый код экрана в код работы с ibutton.
А вы попробуйте сначала загрузить в ардуино код из примера библиотеки. Он работает?
Искать решение проблемя надо начиная с простого. Если данный код заработает то будем думать дальше.
Если нет, то меняйте дисплей, у меня даннй код работает отлично!
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display void setup() { lcd.init(); // initialize the lcd // Print a message to the LCD. lcd.backlight(); lcd.setCursor(3,0); lcd.print("Hello, world!"); lcd.setCursor(2,1); lcd.print("Ywrobot Arduino!"); } void loop() { }Дисплей работает, проверенно на Hello World! В сериал порт (монитор порта) всё выводится хорошо. Показывает считываемый ключ, записывыемый и тд. и все в разных строках. А на ЛСД всё в одну строку и как бы в нахлёст. следующие символы при заполнении строки ложатся на предыдущие! Вот такая беда.
Ещё один вопрос не по теме - Как удалить ошибочно созданную тему на форуме? СПС.
на ЛСД всё в одну строку и как бы в нахлёст. следующие символы при заполнении строки ложатся на предыдущие! Вот такая беда.
ну блин, при выводе строки вы же должны задавать не только начальную позицию текста, но и строку. Вы задаете?
Посмотрите примеры к библиотеке - там это должно быть. Попробуйте вывести несколько Hello World! на разных строках.
когда пшу lcd.setCursor (0,1); скетч перестаёт компилироватся
когда пшу setCursor (0,1); скетч перестаёт компилироватся
что значит "перестает компилироваться?" - виснет? ошибку выдает? - пишите текст ошибки.
И вообще - ну посмотрите же вы примеры!!! Вот выше Андрей запостил в сообщении №2 - у него в примере текст выводится в 2 строки.
Его пример рабочий, проверял. В моём коде сначала тоже в де строки вывод.
lcd.init();// Инициализируем экран031//включаем подсветку032lcd.backlight();033//Устанавливаем позицию начиная с которой выводится текст.034lcd.setCursor(2, 0);035//выводим строку 1036lcd.print ("Copy Key-2017");037lcd.setCursor (2, 1);038//Выводим строку 2039lcd.print ("Sergiev Posad11");040delay(2000);// Пауза показа заставки041lcd.clear();// Очистка дисплеяА скетч выдаёт
Ребят изначально код был без LCD, он полностью работает. Вот я и хотел к этому коду LCD прикурить, но ..... ?
#include <OneWire.h> const int switchPin = 2; // Будем использовать аппаратное прерывание INT0, поэтому кнопка должна быть подключена к 2-му пину const int dataPin = 10; // Data пин считывателя ключей const int ledPin = 13; // Пин контрольного светодиода volatile boolean writeMode = false; // Режим записи: 1 - включен; 0 - выключен (режим чтения) boolean recoveryMode = false; // Режим восстановления нечитаемых ключей (с записанным по ошибке нулевым первым байтом) byte oldID[8]; // Считанный ID ключа byte newID[8]; // Записываемый ID ключа const byte defaultID[8] = { 0x01, 0x27, 0x8F, 0x19, 0x05, 0x00, 0x00, 0x34 }; // По умолчанию прошивается "Универсальный" ID: 01:FF:FF:FF:FF:FF:FF:2F byte crc; // Контрольная сумма CRC OneWire ibutton (dataPin); void setup() { Serial.begin(115200); loadDefaultID(); pinMode(ledPin, OUTPUT); pinMode(switchPin, INPUT_PULLUP); // При включении устройства, удерживая кнопку нажатой, активируется режим восстановления if (digitalRead(switchPin) == LOW) recoveryMode = true; attachInterrupt(0, int0, LOW); // при нажитии кнопки срабатывает 0-е прерывание, обработчик прерывания (ISR) - функция int0() Serial.println("Device is ready. Send 'h' for help."); } // Загрузка дефолтного "универсального" ID void loadDefaultID() { for (byte x = 0; x < 8; x++) oldID[x] = defaultID[x]; } // Переключение режима: Чтение/Запись void changeMode () { // Перестраховка от записи некорректного ID if (!writeMode) { crc = ibutton.crc8(newID, 7); // Вычисление контрольной суммы записываемого ID if (newID[0] != 1 || newID[7] != crc) { Serial.println(F("ID is incorrect! Writing is not permitted.")); writeModeOff(); return; } } writeMode = !writeMode; digitalWrite(ledPin, writeMode); if (writeMode) { Serial.print(F("Waiting for the key to WRITE the new ID: ")); for (byte x = 0; x < 8; x++) { Serial.print(newID[x], HEX); Serial.print(' '); } Serial.println(" ..."); } else { writeModeOff(); } } // Автоматическое отключение режима восстановления после записи и вывод приглашения считать новый ключ void writeModeOff() { if (recoveryMode) { recoveryMode = false; Serial.println(F("Recovery mode disabled.")); } Serial.println(F("Waiting for the key to READ the ID...")); } // Обработчик прерывания по нажатию кнопки: переключает режим: Чтение/Запись (отфильтровывая дребезг контактов) void int0() { static unsigned long millis_prev; if ( millis() - millis_prev > 100 ) changeMode(); millis_prev = millis(); } // Вывод считанного ID в терминал void printID() { for (byte x = 0; x < 8; x++) { Serial.print(oldID[x], HEX); Serial.print(" "); } crc = ibutton.crc8(oldID, 7); // Вычисление контрольной суммы считанного ID Serial.print(" CRC: "); Serial.print(crc, HEX); if (oldID[0] != 0x01) Serial.print(F(" Family code is not valid!")); if (crc != oldID[7]) Serial.print(F(" CRC is not valid!")); Serial.println(); } void loop() { // Обработка команд, посылаемых через терминал COM-порта if (Serial.available() > 0) { byte com; // Команда, отправляемая через терминал COM-порта com = Serial.read(); switch ( com ) { case 'h': { Serial.println(F("Help:")); Serial.println(F("d - load default ID")); Serial.println(F("w - switch read/write mode")); Serial.println(F("m - enter ID manually")); Serial.println(F("r - enable recovery mode (send 'r' again to disable)")); Serial.println(F("h - show this help")); break; } case 'd': { if (writeMode) { writeMode = false; digitalWrite(ledPin, LOW); } loadDefaultID(); Serial.println(F("Default ID is loaded.")); printID(); break; } case 'w': { changeMode(); break; } case 'r': { writeMode = false; recoveryMode = !recoveryMode; Serial.println(recoveryMode ? F("Recovery mode enabled.") : F("Recovery mode disabled.")); break; } case 'm': { byte inputID[8]; // Введённый вручную ID ключа char inputChar; // Код введённого символа char inputNum = 2; // Порядковый номер вводимого сивмола (от 0 до 15). Начинаем вводить со 2-го символа, т.к. 0-ой и 1-ый - фиксированные. char charEncode; // 16-ричное число (от 0 до F), в которое преобразуется каждый вводимый ASCII символ boolean even = 0; // Признак чётности порядкового номера вводимого символа Serial.println(F("Enter the new ID, or press 'Esc' to cancel.")); inputID[0] = 1; Serial.print(F("The new ID is: 01 ")); while (inputNum < 14) { if (Serial.available() > 0) { inputChar = Serial.read(); if (inputChar == 27) { Serial.flush(); Serial.println(); Serial.print(F("Canceled...")); break; } else { if ( inputChar >= 48 && inputChar <= 57 ) charEncode = inputChar - 48; else if ( inputChar >= 65 && inputChar <= 70 ) charEncode = inputChar - 55; else if ( inputChar >= 97 && inputChar <= 102 ) charEncode = inputChar - 87; else inputNum = -1; if ( inputNum != -1 ) { Serial.write(inputChar); if (!even) inputID[inputNum/2] = charEncode << 4; else { inputID[inputNum/2] = inputID[inputNum/2] + charEncode; Serial.print(' '); } even = !even; inputNum++; } } } } if (inputNum == 14) { inputID[7] = ibutton.crc8(inputID, 7); // Автоматическое вычисление контрольной суммы введённого ID for (byte i=0; i<8; i++) oldID[i] = inputID[i]; } Serial.println(oldID[7], HEX); printID(); break; } } } for (byte x = 0; x < 8; x++) newID[x] = oldID[x]; // Проверяем, приложен ли ключ if (!ibutton.search (oldID)) { ibutton.reset_search(); delay(50); if (!recoveryMode) return; } // Режим чтения if (!writeMode) { digitalWrite(ledPin, HIGH); delay(50); printID(); digitalWrite(ledPin, LOW); } // Режим записи if (writeMode) { delay(200); digitalWrite(ledPin, LOW); ibuttonCommand(0x33, 1, 1); Serial.print("Old ID: "); for (byte x = 0; x < 8; x++) { Serial.print(ibutton.read(), HEX); Serial.print(' '); } ibuttonCommand(0xD1, 1, 1); // устанавливаем на линии логический 0 digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT); delayMicroseconds(60); pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH); delay(10); Serial.print(" New ID: "); for (byte x = 0; x < 8; x++) { Serial.print(newID[x], HEX); Serial.print(' '); } ibuttonCommand(0xD5, 1, 1); Serial.print("Writing... "); for (byte x = 0; x < 8; x++) { writeByte(newID[x]); Serial.print('*'); } Serial.println(F(" OK!")); ibuttonCommand(0xD1, 0, 1); // устанавливаем на линии логическую 1 digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT); delayMicroseconds(10); pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH); delay(10); changeMode(); } } // Отправка команды iButton void ibuttonCommand(uint8_t command, boolean sk, boolean rs) { if (sk) ibutton.skip(); if (rs) ibutton.reset(); ibutton.write(command); } // Побайтовая запись нового ID void writeByte(byte data) { for (int data_bit = 0; data_bit < 8; data_bit++) { digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT); if (data & 1) delayMicroseconds(60); pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH); delay(10); data = data >> 1; } }У меня не выдает:
-------------
-------------
Дисплей работает, проверенно на Hello World! В сериал порт (монитор порта) всё выводится хорошо. Показывает считываемый ключ, записывыемый и тд. и все в разных строках. А на ЛСД всё в одну строку и как бы в нахлёст. следующие символы при заполнении строки ложатся на предыдущие! Вот такая беда.
В монитор порта каждый раз всё выводится на новую строку, а на дисплее их всего две. Чистить кроме Вас их никто не будет. Заставка-то из строк 36 и 39 небось нормально выводится? А дальше Вы всё печатаете поверх того, что есть. Уточните, что делает функция lcd.println() (Надо в Вашей библиотеке смотреть). Скорее всего на другую строку курсор переставляет, но вряд ли какой-нибудь "скроллинг" делает или строки очищает.
То есть вот это, из вашего сетапа, у вас выводится друг на друга?
//Устанавливаем позицию начиная с которой выводится текст. lcd.setCursor(2, 0); //выводим строку 1 lcd.print ("Copy Key-2017"); lcd.setCursor (2, 1); //Выводим строку 2 lcd.print ("Sergiev Posad11"); delay(2000); // Пауза показа заставкиэто нет, а вот все остальные данные да.
А lcd.clear(); // Очистка дисплея
перед полной сменой экрана где надо делаете?
// Режим чтения if (!writeMode) { digitalWrite(ledPin, HIGH); delay(50); printID(); digitalWrite(ledPin, LOW); } // Режим записи if (writeMode) { delay(200); digitalWrite(ledPin, LOW); ibuttonCommand(0x33, 1, 1); Serial.print("Old ID: "); lcd.clear(); // НАПРИМЕР lcd.print("old ID:"); for (byte x = 0; x < 8; x++) { Serial.print(ibutton.read(), HEX); lcd.setCursor (0, 1); lcd.print(ibutton.read(), HEX); Serial.print(' '); } ibuttonCommand(0xD1, 1, 1); // устанавливаем на линии логический 0 digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT); delayMicroseconds(60); pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH); delay(10); Serial.print(" New ID: "); for (byte x = 0; x < 8; x++) { Serial.print(newID[x], HEX); Serial.print(' '); } ibuttonCommand(0xD5, 1, 1); Serial.print("Writing... "); for (byte x = 0; x < 8; x++) { writeByte(newID[x]); Serial.print('*'); } Serial.println(F(" OK!")); ibuttonCommand(0xD1, 0, 1); // устанавливаем на линии логическую 1 digitalWrite(dataPin, LOW); pinMode(dataPin, OUTPUT); delayMicroseconds(10); pinMode(dataPin, INPUT); digitalWrite(dataPin, HIGH); delay(10); changeMode(); } }