Ввод текста в переменную "char" с матричной клавиатуры.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

Добрый вечер. Прошу помощи у опытных ардуинщиков. Никак немогу сообразить как в переменную "char" ввести текст с матричной клавиатуры. Вот пример программы, но таким способом сохраняется последний введённый символ. Понимаю что нужно работать с массивами, но туплю конкретно, никак не соображу чё и как. Помогите пожлуйста, а то мозг уже начинает закипать.


void loop()
{
 for (int i = 1; i <= 4; i++) // цикл, передающий 1 по всем столбцам
  {
    digitalWrite(ryad[i - 1], HIGH); // если i меньше 4 , то отправляем 1 на ножку
    for (int j = 1; j <= 4; j++) // цикл, принимающих 1 по строкам
    {
      if (digitalRead(stroka[j - 1]) == HIGH) // если один из указанных портов входа равен 1, то...
      {
      time = millis();
      }
      if (digitalRead(stroka[j - 1]) == HIGH && a == 0) // если один из указанных портов входа равен 1 и переменная "а" равна 0, то...
      {
        lcd.clear(); //очищаем экран lcd
        chislo = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры
        lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        a = 1;  //переменной "а" присваиваем 1
      }
      if (digitalRead(stroka[j - 1]) == LOW && a == 1 && millis() - time >= 10) //если кнопка отпущена, переменная "а" равна 1 и прошло 100 мсек, то...
      {
       a = 0;  //переменной "а" возвращаем 0
      }
    }
    digitalWrite(ryad[i - 1], LOW); // подаём обратно низкий уровень
  }
}

Таким способом тоже ничего не получилось

char chislo[16];

if (digitalRead(stroka[j - 1]) == HIGH && a == 0) // если один из указанных портов входа равен 1 и переменная "а" равна 0, то...
      {
        lcd.clear(); //очищаем экран lcd
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры
        lcd.print(chislo[b]); // выводим на экран lcd данные переменной "chislo"
        b++;
        a = 1;  //переменной "а" присваиваем 1
      }

 

rigl
Offline
Зарегистрирован: 15.10.2014

Во втором примере, исправьте 

lcd.print(chislo[b]);

на 

if(b < 15)
{
chislo[b+1] = 0x00;
lcd.print(chislo);
}

 

toc
Offline
Зарегистрирован: 09.02.2013

Сергей, есть же библиотека
http://playground.arduino.cc/Code/Keypad

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

rigl пишет:

Во втором примере, исправьте 

lcd.print(chislo[b]);

на 

if(b < 15)
{
chislo[b+1] = 0x00;
lcd.print(chislo);
}

 

lcd не реагирует, экран чистый.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

Сергей С.В. пишет:

rigl пишет:

Во втором примере, исправьте 

lcd.print(chislo[b]);

на 

if(b < 15)
{
chislo[b+1] = 0x00;
lcd.print(chislo);
}

 

lcd не реагирует, экран чистый.

Разобрался. У меня было int b = 1, поменнял на int b = 0, lcd ожил но всё равно показывает только последний введённый знак, значит в переменную "char chislo[16]" записуется только один знак, а мне нужно записать строку минимум из 18-ти знаков.

rigl
Offline
Зарегистрирован: 15.10.2014

Покажите весь код, в char chislo[16] можно записать строку длинной 15 символов+ символ окончания строки 0x00. В вашем коде не вижу объявления b и непонятно где инициализируется массив.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

rigl пишет:

Покажите весь код, в char chislo[16] можно записать строку длинной 15 символов+ символ окончания строки 0x00. В вашем коде не вижу объявления b и непонятно где инициализируется массив.

#include <LiquidCrystal.h>   // Лобавляем необходимую библиотеку
const int ryad[4] {6, 7, 8, 9};
const int stroka[4] {10, 11, 12, 13};
const char value[4][4] 
{
  {'1', '4', '7', '*'},
  {'2', '5', '8', '0' },
  {'3', '6', '9', '#'},
  {'A', 'B', 'C', 'D'}
};
int time = 0;
int a = 0;
int b = 0;
char chislo[16];
LiquidCrystal lcd(0, 1, 2, 3, 4, 5); // (RS, E, DB4, DB5, DB6, DB7)
void setup()
{
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
  lcd.begin(16, 2);                  // Задаем размерность экрана
  lcd.setCursor(0, 0);            // Устанавливаем курсор в начало 1 строки
}
void loop()
{
 for (int i = 1; i <= 4; i++) // цикл, передающий 1 по всем столбцам
  {
    digitalWrite(ryad[i - 1], HIGH); // если i меньше 4 , то отправляем 1 на ножку
    for (int j = 1; j <= 4; j++) // цикл, принимающих 1 по строкам
    {
      if (digitalRead(stroka[j - 1]) == HIGH) // если один из указанных портов входа равен 1, то...
      {
      time = millis();
      }
      if (digitalRead(stroka[j - 1]) == HIGH && a == 0) // если один из указанных портов входа равен 1 и переменная "а" равна 0, то...
      {
        lcd.clear(); //очищаем экран lcd
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры        
        if(b < 15)
        {
          chislo[b+1] = 0x00;
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        }
        a = 1;  //переменной "а" присваиваем 1
      }
      if (digitalRead(stroka[j - 1]) == LOW && a == 1 && millis() - time >= 10) //если кнопка отпущена, переменная "а" равна 1 и прошло 100 мсек, то...
      {
       a = 0;  //переменной "а" возвращаем 0
      }
    }
    digitalWrite(ryad[i - 1], LOW); // подаём обратно низкий уровень
  }
}

 

rigl
Offline
Зарегистрирован: 15.10.2014

После lcd.print(chislo); 

Добавте b++;

это если после заполнения строки ее не надо очищать, если надо.

То тут 2 пути, сделать карусельку, последний символ вытесняет первый или чистить и писать сначала.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

rigl пишет:

После lcd.print(chislo); 

Добавте b++;

это если после заполнения строки ее не надо очищать, если надо.

То тут 2 пути, сделать карусельку, последний символ вытесняет первый или чистить и писать сначала.

Вот спасибо, всё получилось. У меня к вам ещё просьба будет, покажите как вытеснять первый символ.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

И ещё одна посьба. обьясните мне строку chislo[b+1] = 0x00; а то я боюсь опять залезть в дебри и ненайду толкового обьяснения из-за кучи информации в гугле.

rigl
Offline
Зарегистрирован: 15.10.2014

данный код:

        lcd.clear(); //очищаем экран lcd
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры        
        if(b < 15)
        {
          chislo[b+1] = 0x00;
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        }

Замените на:

        lcd.clear(); //очищаем экран lcd
    
        if(b < 15) // тут бы надо заменить 15 на размер массива-1 (можно объявить #define SIZE)
        {
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры  
          chislo[b++] = 0x00; // тогда не нfдо дополнительного b++
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        }
       else
{
for(b=1; b<14;b++) // а тут 14 на размер массива-2
chislo[b-1] = chislo[b];
chislo[b-1] = value[i - 1][j - 1]; 
}

chislo[b+1] = 0x00;

0x00 или '\0' - это специальный знак, который говорит, что показать символы до него, а его и после не надо. b у нас указывет последний символ который надо выводить, вот после него (b+1) и ставим.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

rigl пишет:

данный код:

        lcd.clear(); //очищаем экран lcd
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры        
        if(b < 15)
        {
          chislo[b+1] = 0x00;
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        }

Замените на:

        lcd.clear(); //очищаем экран lcd
    
        if(b < 15) // тут бы надо заменить 15 на размер массива-1 (можно объявить #define SIZE)
        {
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры  
          chislo[b++] = 0x00; // тогда не нfдо дополнительного b++
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        }
       else
{
for(b=1; b<14;b++) // а тут 14 на размер массива-2
chislo[b-1] = chislo[b];
chislo[b-1] = value[i - 1][j - 1]; 
}

chislo[b+1] = 0x00;

0x00 или '\0' - это специальный знак, который говорит, что показать символы до него, а его и после не надо. b у нас указывет последний символ который надо выводить, вот после него (b+1) и ставим.

Я сделал вот так

void loop()
{
 for (int i = 1; i <= 4; i++) // цикл, передающий 1 по всем столбцам
  {
    digitalWrite(ryad[i - 1], HIGH); // если i меньше 4 , то отправляем 1 на ножку
    for (int j = 1; j <= 4; j++) // цикл, принимающих 1 по строкам
    {
      if (digitalRead(stroka[j - 1]) == HIGH) // если один из указанных портов входа равен 1, то...
      {
      time = millis();
      }
      if (digitalRead(stroka[j - 1]) == HIGH && a == 0) // если один из указанных портов входа равен 1 и переменная "а" равна 0, то...
      {
        lcd.clear(); //очищаем экран lcd
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры 
        chislo[b+1] = 0x00;
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
          b++;
        if(b > 16)
        {
          c = b - 16;
          for(c; c > 0; c--)
          {
          lcd.scrollDisplayLeft();
          }
        }
        a = 1;  //переменной "а" присваиваем 1
      }
      if (digitalRead(stroka[j - 1]) == LOW && a == 1 && millis() - time >= 10) //если кнопка отпущена, переменная "а" равна 1 и прошло 100 мсек, то...
      {
       a = 0;  //переменной "а" возвращаем 0
      }
    }
    digitalWrite(ryad[i - 1], LOW); // подаём обратно низкий уровень
  }
}

Сейчас попробую сделать как вы посоветовали.

rigl
Offline
Зарегистрирован: 15.10.2014

Я кажись, забыл b++; добавить в предпоследнюю строку, а то он еще раз по првому условию зайдет.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

rigl пишет:

Я кажись, забыл b++; добавить в предпоследнюю строку, а то он еще раз по првому условию зайдет.

В предпоследнюю, это в каком месте?

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

А то что вы в цикле использовали переменную "b" на работе программы никак не отразится?

rigl
Offline
Зарегистрирован: 15.10.2014
if(b > 16)
b не может равняться 16, b должно быть < 16, т.е. у вас вылет за границы уже при b > 15


char chislo[16];
chislo[0] - первый элемент
chislo[1] - второй элемент
..
chislo[15] - 16-й элемент

chislo[16] вылет за пределы выделения памяти, поведение не предсказуемо.

 

rigl
Offline
Зарегистрирован: 15.10.2014

Сергей С.В. пишет:

rigl пишет:

Я кажись, забыл b++; добавить в предпоследнюю строку, а то он еще раз по првому условию зайдет.

В предпоследнюю, это в каком месте?

        lcd.clear(); //очищаем экран lcd
    
        if(b < 15) // тут бы надо заменить 15 на размер массива-1 (можно объявить #define SIZE)
        {
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры  
          chislo[b++] = 0x00; // тогда не нfдо дополнительного b++
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        }
       else
{
for(b=1; b<14;b++) // а тут 14 на размер массива-2
chislo[b-1] = chislo[b];
chislo[b-1] = value[i - 1][j - 1]; 
b++; // чтоб она снова равнялась 15
}

 

rigl
Offline
Зарегистрирован: 15.10.2014

Сергей С.В. пишет:

А то что вы в цикле использовали переменную "b" на работе программы никак не отразится?

Она используется только для того, чтоб перемещаться по вашему массиву. Не должна :-). Если все правильно.

Для нагллядности конечно это может плохо , но бывают случаи когда нету пары лишних байт.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

Молчит мониторчик.

rigl
Offline
Зарегистрирован: 15.10.2014

Точно, вывода до нет :-))

        lcd.clear(); //очищаем экран lcd
    
        if(b < 15) // тут бы надо заменить 15 на размер массива-1 (можно объявить #define SIZE)
        {
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры  
          chislo[b++] = 0x00; // тогда не нfдо дополнительного b++
        }
       else
{
for(b=1; b<14;b++) // а тут 14 на размер массива-2
chislo[b-1] = chislo[b];
chislo[b-1] = value[i - 1][j - 1]; 
b++; // чтоб она снова равнялась 15
}
 lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"

 

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

Вернул назад кусок скетча

chislo[b+1] = 0x00; // тогда не нfдо дополнительного b++
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
         b++;

лсд ожил но, на 16-ом знаке экран очищается и больше не реагирует.

Я Вас ещё не задолбал?

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

rigl пишет:

Точно, вывода до нет :-))

        lcd.clear(); //очищаем экран lcd
    
        if(b < 15) // тут бы надо заменить 15 на размер массива-1 (можно объявить #define SIZE)
        {
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры  
          chislo[b++] = 0x00; // тогда не нfдо дополнительного b++
        }
       else
{
for(b=1; b<14;b++) // а тут 14 на размер массива-2
chislo[b-1] = chislo[b];
chislo[b-1] = value[i - 1][j - 1]; 
b++; // чтоб она снова равнялась 15
}
 lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"

 

И так молчит.

rigl
Offline
Зарегистрирован: 15.10.2014

Сергей С.В. пишет:

Вернул назад кусок скетча

chislo[b+1] = 0x00; // тогда не нfдо дополнительного b++
          lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
         b++;

лсд ожил но, на 16-ом знаке экран очищается и больше не реагирует.

Я Вас ещё не задолбал?

Вставте последний код, (в препоследнем вывод был только по условию, если символов было меньше 15) 

rigl
Offline
Зарегистрирован: 15.10.2014

Сергей С.В. пишет:

rigl пишет:

Точно, вывода до нет :-))

        lcd.clear(); //очищаем экран lcd
    
        if(b < 15) // тут бы надо заменить 15 на размер массива-1 (можно объявить #define SIZE)
        {
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры  
        chislo[b+1] = 0x00;
              b++;

        }
       else
{
for(b=1; b<14;b++) // а тут 14 на размер массива-2
chislo[b-1] = chislo[b];
chislo[b-1] = value[i - 1][j - 1]; 
b++; // чтоб она снова равнялась 15
}
 lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"

 

И так молчит.

 lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"

Точно в конце идет ?

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

Сделал вот так

#include <LiquidCrystal.h>   // Лобавляем необходимую библиотеку
const int ryad[4] {6, 7, 8, 9};
const int stroka[4] {10, 11, 12, 13};
const char value[4][4] 
{
  {'1', '4', '7', '*'},
  {'2', '5', '8', '0' },
  {'3', '6', '9', '#'},
  {'A', 'B', 'C', 'D'}
};
int time = 0;
int a = 0;
int b = 0;
int c = 0;
char chislo[255];
LiquidCrystal lcd(0, 1, 2, 3, 4, 5); // (RS, E, DB4, DB5, DB6, DB7)
void setup()
{
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
  lcd.begin(16, 2);                  // Задаем размерность экрана
  lcd.setCursor(0, 0);            // Устанавливаем курсор в начало 1 строки
}
void loop()
{
 for (int i = 1; i <= 4; i++) // цикл, передающий 1 по всем столбцам
  {
    digitalWrite(ryad[i - 1], HIGH); // если i меньше 4 , то отправляем 1 на ножку
    for (int j = 1; j <= 4; j++) // цикл, принимающих 1 по строкам
    {
      if (digitalRead(stroka[j - 1]) == HIGH) // если один из указанных портов входа равен 1, то...
      {
      time = millis();
      }
      if (digitalRead(stroka[j - 1]) == HIGH && a == 0) // если один из указанных портов входа равен 1 и переменная "а" равна 0, то...
      {
        lcd.clear(); //очищаем экран lcd
       if(b < 16) // тут бы надо заменить 15 на размер массива-1 (можно объявить #define SIZE)
        {
        chislo[b] = value[i - 1][j - 1]; // вводим в переменную "chislo" символы с клавиатуры  
          chislo[b+1] = 0x00; // тогда не нfдо дополнительного b++
         b++;
        }
       else
{
for(b=1; b<16;b++) // а тут 14 на размер массива-2
chislo[b-1] = chislo[b];
chislo[b-1] = value[i - 1][j - 1]; 
b++; // чтоб она снова равнялась 15
}
 lcd.print(chislo); // выводим на экран lcd данные переменной "chislo"
        a = 1;  //переменной "а" присваиваем 1
      }
      if (digitalRead(stroka[j - 1]) == LOW && a == 1 && millis() - time >= 10) //если кнопка отпущена, переменная "а" равна 1 и прошло 100 мсек, то...
      {
       a = 0;  //переменной "а" возвращаем 0
      }
    }
    digitalWrite(ryad[i - 1], LOW); // подаём обратно низкий уровень
  }
}

всё работает, проблема была в этой команде

chislo[b++]

когда поменял на 

chislo[b+1]

всё пошло хорошо.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

Только что провёл эксперемент с командой chislo[b++] нажимал на кнопки когда в впрграмме использовалась эта комонда. На 24-е нажатие на ЛСД высветилиси все элементы на которые я нажимал и дальше программа работала нормально.

Сергей С.В.
Offline
Зарегистрирован: 02.01.2016

rigl большое спасибо что уделии мне внимание.

rigl
Offline
Зарегистрирован: 15.10.2014

всё работает, проблема была в этой команде

1 chislo[b++]

когда поменял на 

1 chislo[b+1]

всё пошло хорошо.

Так и оставте, я ошибся.