Помощь с кодом (ввод 2х символов, конвертация в 16ричную систему)

EnTeen
Offline
Зарегистрирован: 30.10.2017

Добрый день,

Прошу подсобить с кодом, ломал голову не получается решить задачу, пока сложновата для моих знаний.

Устройство пульт. ИК передачик. Клавиатура 3х4.

Задача: При вводе с клавиатуры значения от 1 до 100 передать это число в 16 виде в функцию которая формирует посылку на отправку.

А именно включили пульт, он ждет команду, набираем 35, число конвертируется в 16 систему исчисления и подставляется в эту команду вместо этого значения: fire (0x80, 0x01, 0xE8);

 

#include <Keypad.h>                             // Библиотека матричной клавиатуры
#include "Adafruit_NeoPixel.h"                  // Подключаем библиотеку Adafruit NeoPixel. Светодиод


#define IR_PIN                  2               // ПИН ИК Диода
#define BTN_PIN                 3               // ПИН TSOP
#define LED_PIN                 4               // ПИН LED

#define LED_COUNT               1               // Указываем, какое количество светодиодов у нашей ленты.

int LevelMenu = 1;                              // Уровень меню

const byte ROWS = 4;                            //четыре строки на клавиатуре
const byte COLS = 3;                            //три столбца на клавиатуре
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {10, 9, 8, 7};              //подключить к выводам строк клавиатуры
byte colPins[COLS] = {13, 12, 11};               //подключить к выводам столбцов клавиатуры

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {

  pinMode(IR_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT);

  digitalWrite(BTN_PIN, HIGH);

  Serial.begin(9600);
  Serial.println("Ready...");

  strip.begin();
  strip.show();

}


void loop() {

  char key = keypad.getKey();

  MenuLED(LevelMenu, 1);

  if (LevelMenu == 1) {
    switch (key) {
      case '1':
        Serial.println("+1 Live");
        fire (0x80, 0x01, 0xE8);
        MenuLED2();
        break;

      case '#':
        LevelMenu++;
        break;
      case '*':
        LevelMenu = 3;
        break;
    }
  }

  else if (LevelMenu == 2) {

    switch (key) {

          case '#':
        LevelMenu++;
        break;
      case '*':
        LevelMenu--;
        break;

    }
  }

  else if (LevelMenu == 3) {
    switch (key) {
   
      case '#':
        LevelMenu = 1;
        break;
      case '*':
        LevelMenu--;
        break;

    }
  }
}



//-------------------------------------------------
// Отработка светодиодом какое меню запущено
//-------------------------------------------------
void MenuLED (int Var, unsigned int ShowDelay)
{

  if (Var == 1) {
    strip.setPixelColor(0, strip.Color(10, 0, 0));
    strip.show();
    delay(ShowDelay);

  }
  else if (Var == 2) {
    strip.setPixelColor(0, strip.Color(0, 10, 0));
    strip.show();
    delay(ShowDelay);

  }
  else if (Var == 3) {
    strip.setPixelColor(0, strip.Color(0, 0, 10));
    strip.show();
    delay(ShowDelay);

  }
}

//-------------------------------------------------
// Отработка светодиодом прерывание
//-------------------------------------------------
void MenuLED2 ()
{

  strip.setPixelColor(0, strip.Color(0, 0, 0));
  strip.show();
  delay(200);

}


//-------------------------------------------------
// Отработка выстрела
//-------------------------------------------------
void fire (int sendByte1, int sendByte2, int sendByte3) {
  sendHeader();
  sendByte(sendByte1);
  sendByte(sendByte2);
  sendByte(sendByte3);
}

прошу прощения если нимешал кашу :)

PS: Не очень понятно, как отрабатывать число 100. С первой десяткой в принципе понятно можно просто ввести 01, 02 ... а со 100 не очень понятно, хотелось бы что бы отрабатывал число без дополнительных нажатий в виде * или #, так как эти клавиши задействованы на переход между меню ...

sadman41
Offline
Зарегистрирован: 19.10.2016

Сделайте Serial.println(0x80) и вы сильно удивитесь...

EnTeen
Offline
Зарегистрирован: 30.10.2017

Прошу прощения, отвлекли, забыл добавить вместо какого значения :)

Значение 0x01 заменить на то что введено с клавиатуры, конвертированное в 16ричную систему исчисления: fire (0x80, 0x01, 0xE8);

EnTeen
Offline
Зарегистрирован: 30.10.2017

sadman41 пишет:

Сделайте Serial.println(0x80) и вы сильно удивитесь...

Спасибо

Могу предположить что он сразу конвертирует в нужную систему :), нет под рукой ардуинки ... тогда остается вторая часть вопроса, организовать сбор 2х значных чисел и передача в функцию корректно...

b707
Offline
Зарегистрирован: 26.05.2017

EnTeen пишет:

А именно включили пульт, он ждет команду, набираем 35, число конвертируется в 16 систему исчисления и подставляется в эту команду вместо этого значения: fire (0x80, 0x01, 0xE8);

не очень понятно, зачем для этого конвертировать число в 16-ричный вид.  Компьютеру все равно, в каком виде число.

EnTeen
Offline
Зарегистрирован: 30.10.2017

Функция которая отрабатывает и отправляет ИК посылку работает только с числами в этом формате :(

 

sadman41
Offline
Зарегистрирован: 19.10.2016

EnTeen пишет:

Функция которая отрабатывает и отправляет посылку работает только с числами в этом формате :(

Поверьте дидам - вашей функции всё равно, дадите вы ей на вход 0x20 или 32.

b707
Offline
Зарегистрирован: 26.05.2017

EnTeen пишет:

Функция которая отрабатывает и отправляет ИК посылку работает только с числами в этом формате :(

 

БРЕД - код этой таинственной функции приведен в вашем же скетче, там ясно видно, что она принимает целые числа: void fire (int sendByte1, int sendByte2, int sendByte3)

Поймите - шестнадцитиричные числа - это просто вид записи числа, число от этого другим не становится. Это как текст, набран он фонтом Вердана или Сансерифом - все тот же текст.

EnTeen
Offline
Зарегистрирован: 30.10.2017

Что бы не мудрить, весь код ниже ...

#include <Keypad.h>                             // Библиотека матричной клавиатуры
#include "Adafruit_NeoPixel.h"                  // Подключаем библиотеку Adafruit NeoPixel. Светодиод


#define IR_PIN                  2               // ПИН ИК Диода
#define BTN_PIN                 3               // ПИН TSOP
#define LED_PIN                 4               // ПИН LED

#define LED_COUNT               1               // Указываем, какое количество светодиодов у нашей ленты.

#define CARRIER_INTERVAL        4               // Относится к генерации ИК посылки
#define MLT_SPACE_INTERVAL      600             // Относится к генерации ИК посылки
#define MLT_HEADER_CYCLES       162             // Относится к генерации ИК посылки
#define MLT_BIT0_CYCLES         36              // Относится к генерации ИК посылки
#define MLT_BIT1_CYCLES         78              // Относится к генерации ИК посылки

int LevelMenu = 1;                              // Уровень меню

const byte ROWS = 4;                            //четыре строки на клавиатуре
const byte COLS = 3;                            //три столбца на клавиатуре
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {10, 9, 8, 7};              //подключить к выводам строк клавиатуры
byte colPins[COLS] = {13, 12, 11};               //подключить к выводам столбцов клавиатуры

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {

  pinMode(IR_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT);

  digitalWrite(BTN_PIN, HIGH);

  Serial.begin(9600);
  Serial.println("Ready...");

  strip.begin();
  strip.show();

}


void loop() {

  char key = keypad.getKey();

  MenuLED(LevelMenu, 1);

  if (LevelMenu == 1) {
    switch (key) {
      case '1':
        Serial.println("+1 Live");
        fire (0x80, 0x01, 0xE8);
        MenuLED2();
        break;

        case '#':
        LevelMenu++;
        break;
      case '*':
        LevelMenu = 3;
        break;
    }
  }

  else if (LevelMenu == 2) {

    switch (key) {

      case '1':
        Serial.println("10%");
        fire (0xA5, 0x0A, 0xE8);
        MenuLED2();
        break;

        case '#':
        LevelMenu++;
        break;
      case '*':
        LevelMenu--;
        break;

    }
  }

  else if (LevelMenu == 3) {
    switch (key) {
      case '1':
        Serial.println("StormTrooper");
        fire (0xA8, 0x01, 0xE8);
        MenuLED2();
        break;

         case '#':
        LevelMenu = 1;
        break;
      case '*':
        LevelMenu--;
        break;

    }
  }
}



//-------------------------------------------------
// Отработка светодиодом какое меню запущено
//-------------------------------------------------
void MenuLED (int Var, unsigned int ShowDelay)
{

  if (Var == 1) {
    strip.setPixelColor(0, strip.Color(10, 0, 0));
    strip.show();
    delay(ShowDelay);

  }
  else if (Var == 2) {
    strip.setPixelColor(0, strip.Color(0, 10, 0));
    strip.show();
    delay(ShowDelay);

  }
  else if (Var == 3) {
    strip.setPixelColor(0, strip.Color(0, 0, 10));
    strip.show();
    delay(ShowDelay);

  }
}

//-------------------------------------------------
// Отработка светодиодом прерывание
//-------------------------------------------------
void MenuLED2 ()
{

  strip.setPixelColor(0, strip.Color(0, 0, 0));
  strip.show();
  delay(200);

}


//-------------------------------------------------
// Отработка выстрела
//-------------------------------------------------
void fire (int sendByte1, int sendByte2, int sendByte3) {
  sendHeader();
  sendByte(sendByte1);
  sendByte(sendByte2);
  sendByte(sendByte3);
}

void sendHeader() {
  sendPulse(MLT_HEADER_CYCLES);
  delayMicroseconds(MLT_SPACE_INTERVAL);
}

void sendByte(byte x) {
  for (int i = 0; i < 8; i++) {
    if (x & 0x80) {
      sendPulse(MLT_BIT1_CYCLES);
    } else {
      sendPulse(MLT_BIT0_CYCLES);
    }
    x = x << 1;
    delayMicroseconds(MLT_SPACE_INTERVAL);
  }
}

void sendPulse(int cycles) {
  for (int i = 0; i < cycles; i++ ) {
    digitalWrite(IR_PIN, HIGH);
    delayMicroseconds(CARRIER_INTERVAL);
    digitalWrite(IR_PIN, LOW);
    delayMicroseconds(CARRIER_INTERVAL);
  }
}

 

b707
Offline
Зарегистрирован: 26.05.2017

EnTeen пишет:

Что бы не мудрить, весь код ниже ...

И что? посмотрите заголовок функции в строке 155. Или для вас это тарабарская грамота?

 

EnTeen
Offline
Зарегистрирован: 30.10.2017

Все команды которые которые отправляются мне известны только в таком формате

fire (0x80, 0x01, 0xE8), т.е. 8001E8

b707
Offline
Зарегистрирован: 26.05.2017

EnTeen пишет:

Все команды которые которые отправляются мне известны только в таком формате

fire (0x80, 0x01, 0xE8), т.е. 8001E8

продолжаете УПОРНО тупить? - вам видно это нравится... ну как хотите... Можете цифры еще в римскую нотацию перевести...

EnTeen
Offline
Зарегистрирован: 30.10.2017

Согласен, передаем в целых числах. Буду подтягивать мат.часть ) в части типов данных.

EnTeen
Offline
Зарегистрирован: 30.10.2017

Но давайте отвлечемся от типов данных, и поможем мне во второй части вопроса ...

b707
Offline
Зарегистрирован: 26.05.2017

EnTeen пишет:

Но давайте отвлечемся от типов данных, и поможем мне во второй части вопроса ...

Ввод чисел по принципу как в тв-пульте. Ввводите 2 и делаете паузу - получаете вторую программу , вводите 2 и потом быстро 3 - получаете 23-ю. "100". если это единственное трехзначное число - я бы выкинул, слишком много мороки из-за одного числа. Вместо 100 вариантов. всегда можно обойтись 99-ю :)

EnTeen
Offline
Зарегистрирован: 30.10.2017

b707, хорошо "100" можно пренебречь.

Тогда прошу помочь с рабочим кодом по вводу 2х чисел ... Спасибо

b707
Offline
Зарегистрирован: 26.05.2017

EnTeen пишет:

b707, хорошо "100" можно пренебречь.

Тогда прошу помочь с рабочим кодом по вводу 2х чисел ... Спасибо

"100" можно заменить на "00". кстати.  Насчет кода - сами пробовали что-нибудь писать?

"Игра в одни ворота" тут не принята.

EnTeen
Offline
Зарегистрирован: 30.10.2017

Пробовал, не заработало, стер :) ... могу что то попробовать написать, если не заработает прислать код, но это будет позже :)

... с 00 отличная идея!

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

У вас в коде куча delay с таким кодом толком клавиатуру не считать. Если нажать во время delayнажатие проигнорируется.

b707
Offline
Зарегистрирован: 26.05.2017

Penni пишет:

У вас в коде куча delay с таким кодом толком клавиатуру не считать. Если нажать во время delayнажатие проигнорируется.

EnTeen,  Penni прав, чтобы нормально опрашивать клавиатуру, полный "оборот" loop() не должен быть больше 10-20мс.  А у вас там полно задержек по 200мс, причем вроде как даже по несколько за цикл. С таким кодом затевать работу с кнопками бессмысленно.

EnTeen
Offline
Зарегистрирован: 30.10.2017

Да, пересоберу код на millis. Вопрос а разве loop ходит по функциям которые не вызваны? просто все задержки в основном сидят в обработке светодиодов и по сути можно вообще оттуда убрать ... это тоже попробую сделать.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

У вас menuLED сразу секунду задержку добавляет. Если выполнять так как написано в первом сообщении, то еще можно легкой кровью отделаться. Крутитесь в лупе и сканируете клавиатуру. если * или # переходите по меню. Если нажата цифра то крутимся, например 2 секунды и считываем все нажатия (если они были). Т.е. определили что нажата цифра, запоминаете время начала сканирования и в переменную типа байт кладете key-48. Если считана еще одна цифра за эти две секунды то переменную умножаете на 10 и прибавляете key-48, если и еще одна цифра (это если надо больше 100) то снова умножаете на 10 и прибавляете key-48, но это уже в байт может не влезть. Как две секунды вышло у вас в переменной будет нужное число.

EnTeen
Offline
Зарегистрирован: 30.10.2017

Penni, спасибо

Подсмотрел в другой ветке и вроде все получается логично, программа не выдала ошибок ... будет под рукой ардуинка попробую зашить. 

Прошу посмотреть верное ли решение. я потом по факту ещё отпишусь что все нормально ...

int data=0; // инициализация переменной для ввода 2х значного числа
boolean first=true; // инициализация переменной для ввода 2х значного числа

void setup() {

  pinMode(IR_PIN, OUTPUT);
  pinMode(BTN_PIN, INPUT);

  digitalWrite(BTN_PIN, HIGH);

  Serial.begin(9600);
  Serial.println("Ready...");

  strip.begin();
  strip.show();

}


void loop() {

  char key = keypad.getKey();

  MenuLED(LevelMenu, 1);

  if (LevelMenu == 1) {

    if (key) {
      if (first) {
        first = false;
        if (isDigit(key)) {
          data = data * 10 + key - 48;
        } 
      }
    } else if (!first) {
      first = true;
    }

    switch (data) {
      case '1':
        Serial.println("+1 Live");
        fire (0x80, data, 0xE8);
        MenuLED2();
        break;