Проблемы с библиотекой "IRremote.h"

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Добрый день.

Стал замечать какие-то непонятные ситуации со скетчами, использующими библиотеку "IRremote.h".

Сразу должен сказать что язык только еще изучаю и по этому прошу относиться к моим скечам некритично.

Ситуация #1.

Есть вот такой скетч:

#include "IRremote.h"

#include <LiquidCrystal.h>

IRrecv irrecv(8);             
decode_results results;

LiquidCrystal lcd (7, 6, 5, 4, 3, 2);
// нестандартное подключение дисплея 1602, но мне так удобней: одной фишкой почти все контакты!

int pos=0, col=1;
/* нарисовать свой бегунок
byte cur[8] =
{
   B11111,
   B11011,
   B11011,
   B00000,
   B00000,
   B11011,
   B11011,
   B11111,
};*/
void setup()
{
 // lcd.createChar(1, cur);

  pinMode(9, OUTPUT);         //  ЗАДЕЙСТВОВАТЬ 9-фй ПИН 
  analogWrite(9, 10);         // УСТАНОВИТЬ КОНТРАСТ на 9-ом пине в 10
                              // лень припаять переменный резистор на контраст
  pinMode(13, OUTPUT);        //
  digitalWrite(13, LOW);      // Потушить светодиод, который сильно бъёт в глаза

  lcd.begin (16, 2);          // Start LCD
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.setCursor (0,0);
  lcd.write ("key: ");

  irrecv.enableIRIn();
  
}
 
void loop() 
{
 key_a();
}

//************************************************************************************
// ***********************     Функция:  Нарисовать бегунок
//************************************************************************************
          void bar(int pos, int col)   
          {
              
                 lcd.setCursor (13,0);
                 lcd.print("   ");
                 lcd.setCursor (13,0);
                 lcd.print(pos+1);
                                  
                 lcd.setCursor (pos,col);
                 lcd.write("1");
                    
                         
                  }
          

//*************************************************************************************
// ***********   Функция:    Отобразить название нажатой на пульте кнопки
//*************************************************************************************
      void key_dsp (String key)
          {
                  lcd.setCursor (5,0);
                  lcd.print ("          ");
                  lcd.setCursor (5,0);
                  lcd.print (key); 
                         
          }
      

//************************************************************************************* 
//*** Функция:  Считать код нажатой на пульте кнопки и отобразить его  ***
//*************************************************************************************
 
     void key_a()
              {
              if (irrecv.decode(&results)) 
                {

// если нажатая кнопка "VolUp" и бегунок не уперся в правую часть строки:
     
                      if (results.value == 9249 && pos <16) 
                          {
                          key_dsp("VolUp");
                          lcd.setCursor (pos-1,col);
                          lcd.write(" ");
                          bar(pos, col);
                          pos++;
                          }                                                                }
// если нажатая кнопка "VolDown" и бегунок не уперся в левую часть строки:

                      if (results.value == 25633 && pos>-1)
                          {
                          key_dsp("VolDown");
                          lcd.setCursor (pos+1,col);
                          lcd.write(" ");
                          bar(pos, col);
                          pos--;
                          }           
                                                         
    irrecv.resume();  
    delay(100);
    
          } 



 

Вот пока по экрану бегала еденичка, было всё нормально: она бегала вправо по "VolUp" и влево по "VolDown". Но как только я решил нарисовать какой-то особый бегунок, по "VolDown" бегунок стал бежать влево, независимо от того нажимаю я кнопку на пульте или уже отпустил. То есть - стоит один раз прижать "VolDown" и бегунок тут же бежит влево до упора. Причем ситуация не меняется даже если поместить всё что касается нового бегунка в комментарные скобки!

Смысл происходящего меня ставит в тупик, если честно...

 

Ситуация #2.

Любой скетч с использованием этой библиотеки работает только когда плата подключена к работающему компьютеру. Если просто подать питание - на пульт не реагирует. Вернее работает всё, кроме считывания импульсов.

 

Ситуация #3.

Пробовал стандартный скетч из примеров библиотеки "TVout.h" и тоже: как только в тело программы включается строка: "irrecv.enableIRIn();" - всё что было написано на экране до этого превращается в какие-то чёрточки. Причем кадр стоит на месте, а портятся именно выведенные до этого символы.

Что это всё может значить?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Не хватает одной фигурной скобки в конце скетча, но это потому что я корректировал текст программы и случайно удалил закрывающую скобку от самого верхнего "if"  в  "void key_a()".

Просто опечатка. Как редактировать свой пост - я не нашёл...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

потому что я корректировал текст программы и случайно удалил 

Нельзя корректировать текст программы! Он должен быть помещён сюда тупым копи-пастом, чтобы желающий Вам помочь видел ИМЕННО ТОТ текст, который исполняется, а не какой-то бред без скобок.

Откуда мне знать, что Вы там ещё накорректировали?

Был тут случай, сидел минут сорок, разбирался, выложил ТС описание ошибки, а он мне "да, нет, этого куска там нет, я его вставил только при публикации скетча". Угдадайте с трёх раз, что я сказал про себя и стал ли дальше заморачиваться проблемами этого человека?

Выложите нормальный скетч.

Тоже самое, Вы пишете: "Пробовал стандартный скетч из примеров библиотеки "TVout.h" и тоже: как только в тело программы включается строка: "irrecv.enableIRIn();"". Пожалуйста, скетч с включённой строкой.

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

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Я тоже об этом подумал, но первый пост в теме, очевидно, не корректируется. Спасибо за критику ))))

Вот полный текст первого скетча (As Is): (кстати - как тут прятать код ? Что бы можно было его развернуть и свернуть)

#include "IRremote.h"
/*
#######################################
#   Syntax Coloring Map For IRremote  # 
#######################################

#######################################
#       Datatypes (KEYWORD1)          #
#######################################

decode_results  KEYWORD1
IRrecv          KEYWORD1
IRsend          KEYWORD1

#######################################
#   Methods and Functions (KEYWORD2)  #
#######################################

blink13           KEYWORD2
decode            KEYWORD2
enableIRIn        KEYWORD2
resume            KEYWORD2
enableIROut       KEYWORD2
sendNEC           KEYWORD2
sendSony          KEYWORD2
sendRaw           KEYWORD2
sendRC5           KEYWORD2
sendRC6           KEYWORD2
#
#######################################
#       Constants (LITERAL1)          #
#######################################

NEC             LITERAL1
SONY            LITERAL1
RC5             LITERAL1
RC6             LITERAL1
UNKNOWN         LITERAL1
REPEAT          LITERAL1  
*/
#include <LiquidCrystal.h>
/*
#######################################
# Syntax Coloring Map For LiquidCrystal
#######################################

#######################################
#     Datatypes (KEYWORD1)            #
#######################################

LiquidCrystal KEYWORD1  LiquidCrystal

#######################################
#   Methods and Functions (KEYWORD2)  #
#######################################

begin               KEYWORD2
clear               KEYWORD2
home                KEYWORD2
print               KEYWORD2
setCursor           KEYWORD2
cursor              KEYWORD2
noCursor            KEYWORD2
blink               KEYWORD2
noBlink             KEYWORD2
display             KEYWORD2
noDisplay           KEYWORD2
autoscroll          KEYWORD2
noAutoscroll        KEYWORD2
leftToRight         KEYWORD2
rightToLeft         KEYWORD2
scrollDisplayLeft   KEYWORD2
scrollDisplayRight  KEYWORD2
createChar          KEYWORD2
setRowOffsets       KEYWORD2

#######################################
#           Constants (LITERAL1)      #
#######################################
 */


IRrecv irrecv(8);               // Указываем пин, к которому подключен приемник
decode_results results;
LiquidCrystal lcd (7, 6, 5, 4, 3, 2);
int pos=0, col=1;
/*byte cur[8] =
{
   B11111,
   B11011,
   B11011,
   B00000,
   B00000,
   B11011,
   B11011,
   B11111,
};*/
void setup()
{
// ----------------  LCD SECTION TOP -------------------

 // lcd.createChar(1, cur);
  pinMode(9, OUTPUT);  //  ЗАДЕЙСТВОВАТЬ 9-фй ПИН как ВЫХОДНОЙ ШИМ
  analogWrite(9, 10);  // УСТАНОВИТЬ КОНТРАСТ на 9-ом пине в 10
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  lcd.begin (16, 2);   // Start LCD
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.setCursor (0,0);
  lcd.write ("key: ");
  
  
// ----------------  LCD SECTION BOTTOM  ---------------

  irrecv.enableIRIn(); // -------------->  Запускаем прием
  
}
 
void loop() {
 key_a();
}





//***************************************************************************************
//***************************************************************************************
//***************************************      ******************************************
//************************************  V O I D S  **************************************
//***************************************      ******************************************
//***************************************************************************************
// <==========================>   MY FUNCTIONAL SECTION  <==============================>


          void bar(int pos, int col)
          {
              
                 lcd.setCursor (13,0);
                 lcd.print("   ");
                 lcd.setCursor (13,0);
                 lcd.print(pos+1);
                                  
                 lcd.setCursor (pos,col);
                 lcd.write("1");
                    
                         
                  }
          



      void key_dsp (String key)
          {
                  lcd.setCursor (5,0);
                  lcd.print ("          ");
                  lcd.setCursor (5,0);
                  lcd.print (key); 
                         
          }
      

 // ----------------- KEYS DESCRIPTION $$ DISPLAY PRESSED -----------------

 
   void key_a()
              {
              if (irrecv.decode(&results)) // Если данные пришли 
                {
    
                      if (results.value == 9249 && pos <16)
                          {
                          key_dsp("VolUp");
                          lcd.setCursor (pos-1,col);
                          lcd.write(" ");
                          bar(pos, col);
                          pos++;
                          }                                                                }
                      if (results.value == 25633 && pos>-1)
                          {
                          key_dsp("VolDown");
                          lcd.setCursor (pos+1,col);
                          lcd.write(" ");
                          bar(pos, col);
                          pos--;
                          }                         

                                  
                      if (results.value == 26145)   {
                          key_dsp("Up");
                          
        }        
                      if (results.value == 9761)    {
                          key_dsp("Down");
                          
        }         
                      if (results.value == 22049)   {
                          key_dsp("Left");
                          
        }         
                      if (results.value == 5665)    {
                          key_dsp("Right");
                          
        }         
                      if (results.value == 22561)   {
                          key_dsp("Off");
                          
        }         
                      if (results.value == 5153)    {
                          key_dsp("Att");
                          
        }         
                      if (results.value == 12577)   {
                          key_dsp("Source");
                          
        }
                      if (results.value == 17441)   {
                          key_dsp("Select");
                          
        }       
                      if (results.value == 28961)   {
                          key_dsp("Mute");
                          
        }       
                      if (results.value == 2593)    {
                          key_dsp("Display");
                          
        }
                      if (results.value == 25121)   {
                          key_dsp("Scroll");
                          
        }       
                      if (results.value == 33)      {
                          key_dsp("1");
                          
        } 
                      if (results.value == 16417)   {
                          key_dsp("2");
                          
        }                     
                      if (results.value == 8225)    {
                          key_dsp("3");
                          
        }    
                      if (results.value == 24609)   {
                          key_dsp("4");
                          
        }                     
                      if (results.value == 4129)    {
                          key_dsp("5");
                          
        }              
                      if (results.value == 20513)   {
                          key_dsp("6");
                          
        }              
                                                          
    irrecv.resume();  // ========>   Принимаем следующую команду
    delay(100);
    
          } 

 

Вторая ситуация так же касается этого скетча. Собственно, это финальная версия двух задач: научиться работать с пультом и с помощью пульта осуществлять навигацию по экрану.

Третяя ситуация и второй скетч у меня на работе, так как только там у меня есть маленький настольный TFT телевизор и только там я пытаюсь что-то вывести на экран с помощью библиотеки ""TVout.h"". Выложу чуть позже. Сочинять что-то на скорую руку без отладки, я так понял - не солидно.

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

 (кстати - как тут прятать код ? Что бы можно было его развернуть и свернуть)

Там флажок есть. Читайте внимательно.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Какая-то лишняя скобка обнаружилась перед строкой "if (results.value == 25633 && pos>-1)" Странно. Я выложил всё как есть и компилятор  на работе на нее ничего не сказал, вот буквально еще сегодня утром... Но ей там явно не место. Сейчас попробую прогнать на ошибки дома..

Вообще-то я заметил отличия в работе одного и того же IDE дома(Windows 8.1 (x64)) и на работе(XP).

Проверил. Выскочило только:

Несколько библиотек найдено для "IRremote.h"
 Используется: F:\!ARDUINO\arduino-nightly-windows\libraries\IRremote
Не используется: F:\!ARDUINO\arduino-nightly-windows\libraries\RobotIRremote

Больше ничего. Лишняя скобка стоит. Странно...

 

Когда убираешь ту скобку, выскакивет вот что:

Arduino: 1.6.8 Hourly Build 2016/02/19 10:33 (Windows 8), Плата:"Arduino/Genuino Uno"

C:\Users\Admin\Documents\Arduino\IR_Move_Bar\IR_Move_Bar.ino: In function 'void key_a()':

IR_Move_Bar:262: error: expected '}' at end of input

           }

           ^

Несколько библиотек найдено для "IRremote.h"
 Используется: F:\!ARDUINO\arduino-nightly-windows\libraries\IRremote
Не используется: F:\!ARDUINO\arduino-nightly-windows\libraries\RobotIRremote
exit status 1
expected '}' at end of input

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Сейчас посчитаю скобки...

------------------------

Выяснилось что не хватает одной закрывающей скобки в самом низу, очевидно для последнего "void()"... Подключаю плату.

------------------------

После удаления той скобки, всё стало на свои места. Да вот как бывает... И без компьютера - тоже работает теперь. Вот интересно.

Спасибо. Буду разбираться дальше. Мне что-то алгоритм не совсем нравится. Да и навигация по меню с пульта тоже не очень удобна. Пульт посылает серии импульсов, в конце каждого ставя другой, какой-то одинаковый код и все эти ситуации приходится отлавливать.

Если использовать пульт в других целях, то вполне хватит и такого алгоритма. Надо только как-то отследить его привычку посылать серии...

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Ctrl-T форматирует текст

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:

Buzzer2010 пишет:

 (кстати - как тут прятать код ? Что бы можно было его развернуть и свернуть)

Там флажок есть. Читайте внимательно.

Спасибо. Но в следующий раз теперь. Уже изменить не даёт.

kisoft пишет:

Ctrl-T форматирует текст

Внутри кода?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Да, всё работает нормально и с "самодельным" бегунком тоже.

Единственное что доставляет неудобства - это неустойчивая работа IR-приёмника: не реагирует на пульт пока не пошевелишь его лапки или перестаёт реагировать после загрузки нового скетча. Возможно это потому что он покдлючен, как было где-то сказано: "не по феншую" - без резистора и коненсатора. А в остальном, вроде как, по феншую: на 3.3V и на 8-й пин.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Buzzer2010 пишет:

Спасибо. Но в следующий раз теперь. Уже изменить не даёт.

kisoft пишет:

Ctrl-T форматирует текст

Внутри кода?

В IDE. Форматирует текст (Ctrl-T) к более читабельному виду, твой код читать - глаза сломать. На вкус и цвет товарищей нет, но всё-таки лучше придерживаться каких либо общепринятых стандартов (единого, увы нет), вылезая и своей норы, тогда и помощь будет более весомой.

Используя форматирование также поможет избежать наличие/отсутствие скобок. Совсем не исправит, но будет легче.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

kisoft пишет:

Buzzer2010 пишет:

Спасибо. Но в следующий раз теперь. Уже изменить не даёт.

kisoft пишет:

Ctrl-T форматирует текст

Внутри кода?

В IDE. Форматирует текст (Ctrl-T) к более читабельному виду, твой код читать - глаза сломать. На вкус и цвет товарищей нет, но всё-таки лучше придерживаться каких либо общепринятых стандартов (единого, увы нет), вылезая и своей норы, тогда и помощь будет более весомой.

Используя форматирование также поможет избежать наличие/отсутствие скобок. Совсем не исправит, но будет легче.

А, ну да. В чужой монастырь, типа....

Я до этого последний раз писал на PL/1 и еще с тех времен притащил этот стиль.

Сейчас посмотрим обо что теперь народ глаза ломает...

----------

Нажал Ctrl-T - всё прибило к левому краю да и всё. Как по мне - не читабельно: все строки начинаются почти с первого столбца и не видно уровней вложенности операторов...

А хотя  - нет. Форматирование-таки сдвигает вправо вложенные if-ы, но очень уж экономно.

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

Да. Наверно буду начинать привыкать к IDE-шному форматированию, а то его компилятор следит только за четностью скобок, а где и почему они стоят - его уже не интересует.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

А теперь, буду благодарен если кто-то раскритикует мой скетч с точки зрения оптимизации и вообще, с любой точки зрения.

Например вот я уже заметил что совсем не использовал директиву "#define", хотя можно было бы забить туда все возвращаемые пультом коды, освободив тем самым немного памяти. Только как потом это использовать в программе - понятия не имею...

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Buzzer2010 пишет:

А, ну да. В чужой монастырь, типа....

Я до этого последний раз писал на PL/1 и еще с тех времен притащил этот стиль.

Сейчас посмотрим обо что теперь народ глаза ломает...

----------

Нажал Ctrl-T - всё прибило к левому краю да и всё. Как по мне - не читабельно: все строки начинаются почти с первого столбца и не видно уровней вложенности операторов...

А хотя  - нет. Форматирование-таки сдвигает вправо вложенные if-ы, но очень уж экономно.

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

Да. Наверно буду начинать привыкать к IDE-шному форматированию, а то его компилятор следит только за четностью скобок, а где и почему они стоят - его уже не интересует.

Да, всё верно про чужой монастырь, не я придумал, сам понимаешь.

Если уж так хочется, сделай Ctrl-T, Ctrl-A, Ctrl-C, потом Ctrl-Z (даже не отпуская клавишу Ctrl, нажми последовательно 4 клавиши TACZ) и продолжай любоваться своими кривыми скобками. После этого в клипбоарде будет лежать отформатированный исходник.

"где и почему они стоят - его уже не интересует" собственно и не дОлжно компилятору знать, где стоят скобки, иначе он тебя и меня загнал бы в жесткие рамки, а оно надо? Лично мне - нет. Prolog не юзал, да и не было нужды/желания.

На счет форматирования, найди файл: Arduino/lib/formatter.conf исправь строчку

indent=spaces=2
на
indent=spaces=8
 
Потом запусти Arduino IDE и сформатируй (Ctrl-T) свой скетч, текст будет шире. Только не забудь оставить копию этого файла, или, как там рекомендуют, скопировать из него то, что хочешь поменять в preferences.txt.
 
Короче, кто-то ищет решения, а кто-то проблем, выбирай сам, что тебе нужно ;) Удачи!
 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В строках 172 - 256 у Вас огромная куча if'ов, при этом если какой-то из них дал истину, очевидно, что уже никакой другой истины не даст, а Вы зачем-то продолжаете отрабатывать все сравнения. Зачем?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

kisoft пишет:

Если уж так хочется, сделай Ctrl-T, Ctrl-A, Ctrl-C, потом Ctrl-Z (даже не отпуская клавишу Ctrl, нажми последовательно 4 клавиши TACZ) и продолжай любоваться своими кривыми скобками. После этого в клипбоарде будет лежать отформатированный исходник.

"где и почему они стоят - его уже не интересует" собственно и не дОлжно компилятору знать, где стоят скобки, иначе он тебя и меня загнал бы в жесткие рамки, а оно надо? Лично мне - нет. Prolog не юзал, да и не было нужды/желания.

На счет форматирования, найди файл: Arduino/lib/formatter.conf исправь строчку

indent=spaces=2
на
indent=spaces=8
 
Потом запусти Arduino IDE и сформатируй (Ctrl-T) свой скетч, текст будет шире. Только не забудь оставить копию этого файла, или, как там рекомендуют, скопировать из него то, что хочешь поменять в preferences.txt.
 
Короче, кто-то ищет решения, а кто-то проблем, выбирай сам, что тебе нужно ;) Удачи!
 
 
Спасибо огромное!

ЕвгенийП пишет:

В строках 172 - 256 у Вас огромная куча if'ов, при этом если какой-то из них дал истину, очевидно, что уже никакой другой истины не даст, а Вы зачем-то продолжаете отрабатывать все сравнения. Зачем?

Так я же не могу все кнопки нажать за один раз? Один раз сработает один "if", в следующий раз - другой...

А что есть какой-то другой способ отследить нажатую клавишу не перебирая все возможные? Интересно какой.

Можно еще применить "Case", но их тоже будет столько же сколько и кнопок.

И расскажите мне лучше как обращаться с директивой "#define" в этом случае. Можно же как-то?

vk007
Offline
Зарегистрирован: 16.06.2015

Buzzer2010 пишет:

Можно еще применить "Case", но их тоже будет столько же сколько и кнопок.

Не можно, а нужно. "case" для таких случаев и создан. И не важно, сколько там условий, главное, что не будет перебора по всему списку, даже если совпадение будет первым.

Buzzer2010 пишет:

И расскажите мне лучше как обращаться с директивой "#define" в этом случае. Можно же как-то?

Что может быть проще - компилятор ищет одну комбинацию символов и заменяет ее другой.

Например, в процессе программирования решили вы, что какой-то условно скажем светодиод будет висеть на пине D13, но в процессе разводки печатной платы обнаружили, что к D13 провести дорожку не совсем просто, зато совсем рядом оказался свободный пин D7. Вспоминать, где у вас по всему скетчу используется тринадцатый пин и менять его на седьмой неблагодарное занятие. Зато можете написать #define LED_PIN 13 и везде, где в коде встретится LED_PIN (например, digitalWrite(LED_PIN, LOW)), компилятор поменяет его на 13 и это будет равнозначно digitalWrite(13, LOW). А при необходимости использовать другой пин, достаточно его будет поменять только в одном месте - #define LED_PIN 7.

Так же и у вас, решили вы поменять пульт, а у него оказывается другая кодировка кнопок. Или кто-то еще решил повторить вашу конструкцию. Хорошо еще, если эти коды используются единожды и в одном месте, а если несколько раз и в разных местах?

Поэтому проще в начале программы определить эти коды через #define, например:

#define KEY_UP 26145
#define KEY_DOWN 9761 // и т.д.

а в программе прописать:

if (results.value == KEY_UP)
  {
    key_dsp("Up");
  }       
if (results.value == KEY_DOWN)
  {
    key_dsp("Down");
  }

Этим использование #define не ограничивается. В него, например, также очень удобно заворачивать относительно громоздкие конструкции, которые и в функцию нет смысла выделять, и затрудняют чтение кода.

В ардуино многие функции определены через #define, например, bitRead() прописана не иначе как

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)

А HIGH и LOW всего лишь

#define HIGH 0x1
#define LOW  0x0

В общем, не так страшен черт...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Buzzer2010 пишет:

А что есть какой-то другой способ отследить нажатую клавишу не перебирая все возможные? Интересно какой.

Можно еще применить "Case", но их тоже будет столько же сколько и кнопок.

Вы же говорили, что программировали на PL/1!?! 

Если использовать switch или хотя бы if с else, строк то будет столько же, но она не буде проверять ВСЕ условия, а только до первого выполнившегося. У Вас же всегда проверяются ВСЕ условяи, даже если выполнилось первое и остальные уже никак выполниться не могут.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

vk007 пишет:

Buzzer2010 пишет:

Можно еще применить "Case", но их тоже будет столько же сколько и кнопок.

Не можно, а нужно. "case" для таких случаев и создан. И не важно, сколько там условий, главное, что не будет перебора по всему списку, даже если совпадение будет первым.

Buzzer2010 пишет:

И расскажите мне лучше как обращаться с директивой "#define" в этом случае. Можно же как-то?

Что может быть проще - компилятор ищет одну комбинацию символов и заменяет ее другой.

Например, в процессе программирования решили вы, что какой-то условно скажем светодиод будет висеть на пине D13, но в процессе разводки печатной платы обнаружили, что к D13 провести дорожку не совсем просто, зато совсем рядом оказался свободный пин D7. Вспоминать, где у вас по всему скетчу используется тринадцатый пин и менять его на седьмой неблагодарное занятие. Зато можете написать #define LED_PIN 13 и везде, где в коде встретится LED_PIN (например, digitalWrite(LED_PIN, LOW)), компилятор поменяет его на 13 и это будет равнозначно digitalWrite(13, LOW). А при необходимости использовать другой пин, достаточно его будет поменять только в одном месте - #define LED_PIN 7.

Так же и у вас, решили вы поменять пульт, а у него оказывается другая кодировка кнопок. Или кто-то еще решил повторить вашу конструкцию. Хорошо еще, если эти коды используются единожды и в одном месте, а если несколько раз и в разных местах?

Поэтому проще в начале программы определить эти коды через #define, например:





#define KEY_UP 26145
#define KEY_DOWN 9761 // и т.д.

а в программе прописать:





if (results.value == KEY_UP)
  {
    key_dsp("Up");
  }       
if (results.value == KEY_DOWN)
  {
    key_dsp("Down");
  }

Этим использование #define не ограничивается. В него, например, также очень удобно заворачивать относительно громоздкие конструкции, которые и в функцию нет смысла выделять, и затрудняют чтение кода.

В ардуино многие функции определены через #define, например, bitRead() прописана не иначе как





#define bitRead(value, bit) (((value) >> (bit)) & 0x01)

А HIGH и LOW всего лишь





#define HIGH 0x1
#define LOW  0x0

В общем, не так страшен черт...

По ощущениям - Вы мне разжевали, как могли, именно то чего мне не доставало и тут сокрыта бОльшая, если не вся часть всей возможной оптимизации моего скетча. Однако сказать что я так сразу и всё понял - было бы неправдой.

Большое спасибо - буду разбираться прямо сейчас...

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

Это что касается среды IDE.

Что же касается самого С++ - я вообще молчу, начиная с его возможности работать с окнами, о которых во времена DOS 3.0 и МВМ (Монитор Виртуальных Машин, на  ЕС-1035, ЕС-1046), никто и не мечтал!

Так что мне еще предстоит "поднять" конкретную целину в этой области...

Так же хотелось бы "победить" структурное программирование, которое широко использовалось в те времена и, признаться, было очень удобно: каждая частоиспользуемая процедура писалась отдельным файлом и при необходимости, ею могли пользоваться все программисты, которым она была нужна. Подключались такие процедуры, кажись, по тому же "INCLUDE" или просто вызывались из тела других процедур или из главной программы (Procedure Options (main)).

Теперь, я догадываюсь, структурное программирование реализовано отчасти подключением библиотек или же, как Вы указали, диретивой #define. 

Еще один непонятный для меня момент в Си это - классы.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:

Buzzer2010 пишет:

А что есть какой-то другой способ отследить нажатую клавишу не перебирая все возможные? Интересно какой.

Можно еще применить "Case", но их тоже будет столько же сколько и кнопок.

Вы же говорили, что программировали на PL/1!?! 

Если использовать switch или хотя бы if с else, строк то будет столько же, но она не буде проверять ВСЕ условия, а только до первого выполнившегося. У Вас же всегда проверяются ВСЕ условяи, даже если выполнилось первое и остальные уже никак выполниться не могут.

Дело в том, что PL/1 я осваивал сам, хоть и работал проектном институте. Однако же моих наставников вполне устраивал и такой перебор по "if". Скажу даже больше - именно они мне его и подсунули тогда. А так как документация по программированию была доступна лишь на техническом английском, то, понятное дело, никто не листал эти огромные талмуды, распечатанные на перфорированных листах формата А3.

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

Так что каждое сказанное здесь слово в пользу оптимизации - на вес золота. Темболее что, всё что доступно, это 32кб.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Ну вот, "подправил" скетч учитывая советы бывалых:





#include "IRremote.h"

#include <LiquidCrystal.h>

#define VolUp   9249
#define VolDown 25633
#define Up      26145
#define Down    9761
#define Left    22049
#define Right   5665
#define Off     22561
#define Att     5153
#define Source  12577
#define Select  17441
#define Mute    28961
#define Display 2593
#define Scroll  25121
#define _1      33
#define _2      16417
#define _3      8225
#define _4      24609
#define _5      4129
#define _6      20513

IRrecv irrecv(8);               // Указываем пин, к которому подключен приемник
decode_results results;

LiquidCrystal lcd (7, 6, 5, 4, 3, 2);
int pos = 0, col = 1;

byte cur[8] =
  {
   B11111,
   B11011,
   B11011,
   B00000,
   B00000,
   B11011,
   B11011,
   B11111,
  };
  
void setup()
{
  // ----------------  LCD SECTION TOP -------------------

  lcd.createChar(1, cur);
  pinMode(9, OUTPUT);  //  ЗАДЕЙСТВОВАТЬ 9-фй ПИН как ВЫХОДНОЙ ШИМ
  analogWrite(9, 10);  // УСТАНОВИТЬ КОНТРАСТ на 9-ом пине в 10
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  lcd.begin (16, 2);   // Start LCD
  lcd.clear();
  lcd.setCursor (0, 0);
  lcd.write ("key: ");


  // ----------------  LCD SECTION BOTTOM  ---------------

  irrecv.enableIRIn(); // -------------->  Запускаем прием

}

void loop() {
  key_a();
}





//***************************************************************************************
//***************************************************************************************
//***************************************      ******************************************
//************************************  V O I D S  **************************************
//***************************************      ******************************************
//***************************************************************************************



void bar(int pos, int col)
{

  lcd.setCursor (13, 0);
  lcd.print("   ");
  lcd.setCursor (13, 0);
  lcd.print(pos + 1);

  lcd.setCursor (pos, col);
  lcd.write("\1");


}




void key_dsp (String key)
{
  lcd.setCursor (5, 0);
  lcd.print ("          ");
  lcd.setCursor (5, 0);
  lcd.print (key);

}


// ----------------- KEYS DESCRIPTION $$ DISPLAY PRESSED -----------------


void key_a()
{
  if (irrecv.decode(&results)) // Если данные пришли
  { 
   // lcd.setCursor (0, 1); 
   // lcd.print (results.value);
   
    switch ( results.value )
    {
    case VolUp:
      key_dsp("VolUp");
      lcd.setCursor (pos - 1, col);
      lcd.write(" ");
      bar(pos, col);
      if (pos <16) {pos++;}
    break;
      
    case VolDown:
      key_dsp("VolDown");
      lcd.setCursor (pos + 1, col);
      lcd.write(" ");
      bar(pos, col);
      if  (pos>-1){pos--;}
    break;
    
    case Up:
      key_dsp("Up");
    break;
  
    case Down:
      key_dsp("Down");
    break;
  
    case Left: 
      key_dsp("Left");
    break;
    
    case Right:
      key_dsp("Right");
    break;
    
    case Off:
      key_dsp("Off");
    break;
    
    case Att:
      key_dsp("Att");
    break;

    case Source:
      key_dsp("Source");
    break;
    
    case Select:
      key_dsp("Select");
    break;
    
    case Mute:
      key_dsp("Mute");
    break;
    
    case Display:
      key_dsp("Display");
    break;
    
    case Scroll:
      key_dsp("Scroll");
    break;
    
    case _1:
      key_dsp("1");
    break;
    
    case _2:
      key_dsp("2");
    break;

    case _3:
      key_dsp("3");
    break;

    case _4:
      key_dsp("4");
    break;

    case _5:
     key_dsp("5");
    break;
    
    case _6:
      key_dsp("6");
    break;
    }
   }
  irrecv.resume();  // ========>   Принимаем следующую команду
  delay(300);
}


 

Сэкономил 1% памяти.

Получил отображаемое на дисплее значение в переменной "pos" 17 (хотя в скетче с "if"-ами отображалось, как положено - 16).

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

Если убрать последний "delay()" - вообще перестаёт реагировать на пульт.  

Условия по "if" не менял.

Где я допустил ошибку?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Как будет время - загляните сюда пожалуста.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы это мне? Или кому-то другому?

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

ЕвгенийП пишет:

Вы это мне? Или кому-то другому?

Это я всем, кто соизволит.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Для начала:

irrecv.resume перемести выше в строку между 203 и 204 (между строками с фигурными скобками), тогда delay не так будет влиять на прием сигнала с ИК. В противном случае (если убрать delay), IRremote постоянно будет сбрасывать прием сигнала и не сможет успеть его принять.

Далее:

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

pos у тебя может принимать значения от 0 до 16 включительно. Но при отображении оно отображается как (pos + 1), это так, для акцента, а не как "критика".

Мелочи:

Если уменьшить громкость до 0, а потом увеличить на шаг, то выполнится "lcd.setCursor (pos - 1, col)". Аналогично если увелчить до максимум, а потом уменьшить на шаг. Возможно это пофиг и не будет видно, но это говорит об авторе, что он на мелочи особо внимания не обращает.

Я бы заменил сравнение if (pos > -1) на if (pos >= 0), что более логично, хотя чисто математически одинаково. Сравнение с 0 более предпочтительно, потому что для этого сравнения МК достаточно проверить всего один флаг, а для сравнения с -1, придется сравнивать с константой, можешь посмотреть ассемблерный код, чтобы было понятней. Это всё мелочи, но если хочешь, используй это.

Не совсем понятно, зачем тебе три знакоместа для pos (отрицательные значения будут?). Это я про функцию bar. Хотя на время отладки, возможно это будет лучше оставить как есть.

Еще, это не обязательно, но иногда можно использовать. Я считываю код из irrecv в переменную и делаю примерно так:

unsigned long ir_code;
...
  if (irrecv.decode(&results)) {
    ir_code = results.value;
    irrecv.resume();
    switch(ir_code)
    ...

Это позволит irrecv подготовиться к приему следующего кода быстрее, независимо от задержек, которые происходят дальше по коду. Например, как у тебя сейчас, пока выведешь данные на экран, irrecv у тебя не готов принимать следующий код. Минус этого приема, нельзя использовать другие члены структуры results, потому что они могут измениться в любое время. Из плюсов - не забудешь вызвать resume().

Я смотрю библиотечку IRremote (v2.0.1) подшаманили, надо будет заглянуть в исходники на досуге.

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

kisoft пишет:

Для начала:

irrecv.resume перемести выше в строку между 203 и 204 (между строками с фигурными скобками), тогда delay не так будет влиять на прием сигнала с ИК. В противном случае (если убрать delay), IRremote постоянно будет сбрасывать прием сигнала и не сможет успеть его принять.

Это очень интересный момент, потому что я тут сейчас, как-раз, пытаюсь "заменить" в одном скетче аналоговые кнопки на управление с пульта и у меня ничего не получается! Расскажу чуть позже...

kisoft пишет:

Далее:

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

 

С этого места вкратце, но поподробнее если можно, а то я еще не готов наступать на грабли. Я так понимаю, что глобальные переменные резервируют место в памяти? Эта переменная pos стала глобальной только на период отладки.

kisoft пишет:

pos у тебя может принимать значения от 0 до 16 включительно. Но при отображении оно отображается как (pos + 1), это так, для акцента, а не как "критика".

 

Отчего же: критика это хороший повод чему-нибудь научиться. Я просто пытаюсь восстановить давно утраченные навыки компилирования программ в голове, потому что компилятор следит только за синтаксисом, а что реально мне нужно - это уже зависит от качества поставленой задачи. Вот этим я сейчас и занимаюсь: вспоминаю, а в большинстве случаев учусь заново, как с помощью доступных средств языка, достичь цели. В общем я понял что с позицией и с отображением переменной pos не всё впорядке...

kisoft пишет:

Мелочи:

Если уменьшить громкость до 0, а потом увеличить на шаг, то выполнится "lcd.setCursor (pos - 1, col)". Аналогично если увелчить до максимум, а потом уменьшить на шаг. Возможно это пофиг и не будет видно, но это говорит об авторе, что он на мелочи особо внимания не обращает.

Я бы заменил сравнение if (pos > -1) на if (pos >= 0), что более логично, хотя чисто математически одинаково. Сравнение с 0 более предпочтительно, потому что для этого сравнения МК достаточно проверить всего один флаг, а для сравнения с -1, придется сравнивать с константой, можешь посмотреть ассемблерный код, чтобы было понятней. Это всё мелочи, но если хочешь, используй это.

 

Интересно почему выполняется "lcd.setCursor (pos - 1, col)" в тот момент, когда я нажимаю уже совсем другую кнопку?... Напортачил с условием? При изменении кнопки все равно сначала еще раз выполняется последнее действие. Пока что я не могу понять почему. Я ставил if (pos >= 0), но потом меня сбило с толку то, что отображается все равно -1 и я вернул как было. Не думаю что ассемблер мне сейчас будет более поняте чем Си, за который я взялся первый раз в жизни, но поверю наслово.

kisoft пишет:

Не совсем понятно, зачем тебе три знакоместа для pos (отрицательные значения будут?). Это я про функцию bar. Хотя на время отладки, возможно это будет лучше оставить как есть.

 

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

kisoft пишет:

Еще, это не обязательно, но иногда можно использовать. Я считываю код из irrecv в переменную и делаю примерно так:

unsigned long ir_code;
...
  if (irrecv.decode(&results)) {
    ir_code = results.value;
    irrecv.resume();
    switch(ir_code)
    ...

Это позволит irrecv подготовиться к приему следующего кода быстрее, независимо от задержек, которые происходят дальше по коду. Например, как у тебя сейчас, пока выведешь данные на экран, irrecv у тебя не готов принимать следующий код. Минус этого приема, нельзя использовать другие члены структуры results, потому что они могут измениться в любое время. Из плюсов - не забудешь вызвать resume().

 

На самом деле это очень важно, особенно если учитывать тайминг цикла и время срабатывания IR-приемника. С моей стороны было абсолютно неграмотно не учесть этот момент: после использования конструкции "switch-case" очевидно что програмка начала себя более свободно чувствовать и irrecv просто не успевал сделать то, что он там делает. "results" я больше нигде не планирую использовать, кроме как в считывании кодов, так что этот минус меня не коснется.

kisoft пишет:

Я смотрю библиотечку IRremote (v2.0.1) подшаманили, надо будет заглянуть в исходники на досуге.

 

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

Спасибо за столь развернутый ответ и ценные советы! Сейчас буду пытаться исправить свои ошибки.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Buzzer2010 пишет:

kisoft пишет:

Далее:

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

 

С этого места вкратце, но поподробнее если можно, а то я еще не готов наступать на грабли. Я так понимаю, что глобальные переменные резервируют место в памяти? Эта переменная pos стала глобальной только на период отладки.

Одинаковое название глобальной переменной и параметра функции (у тебя здесь это pos). Можно с горяча перепутать и подумать, что изменится глобальная переменная, ан нет, изменится только локальный параметр функции. Хотя никто не запрещает написать для глобальной переменной "::pos = 15;". На именование переменных, параметров нет общего стандарта, потому кто-то добавляет префиксы, кто-то еще как-то.

Buzzer2010 пишет:

kisoft пишет:

pos у тебя может принимать значения от 0 до 16 включительно. Но при отображении оно отображается как (pos + 1), это так, для акцента, а не как "критика".

 

Отчего же: критика это хороший повод чему-нибудь научиться. Я просто пытаюсь восстановить давно утраченные навыки компилирования программ в голове, потому что компилятор следит только за синтаксисом, а что реально мне нужно - это уже зависит от качества поставленой задачи. Вот этим я сейчас и занимаюсь: вспоминаю, а в большинстве случаев учусь заново, как с помощью доступных средств языка, достичь цели. В общем я понял что с позицией и с отображением переменной pos не всё впорядке...

 

Это я про то, что отображаться 17 может вполне.

Buzzer2010 пишет:

kisoft пишет:

Мелочи:

Если уменьшить громкость до 0, а потом увеличить на шаг, то выполнится "lcd.setCursor (pos - 1, col)". Аналогично если увелчить до максимум, а потом уменьшить на шаг. Возможно это пофиг и не будет видно, но это говорит об авторе, что он на мелочи особо внимания не обращает.

Я бы заменил сравнение if (pos > -1) на if (pos >= 0), что более логично, хотя чисто математически одинаково. Сравнение с 0 более предпочтительно, потому что для этого сравнения МК достаточно проверить всего один флаг, а для сравнения с -1, придется сравнивать с константой, можешь посмотреть ассемблерный код, чтобы было понятней. Это всё мелочи, но если хочешь, используй это.

 

Интересно почему выполняется "lcd.setCursor (pos - 1, col)" в тот момент, когда я нажимаю уже совсем другую кнопку?... Напортачил с условием? При изменении кнопки все равно сначала еще раз выполняется последнее действие. Пока что я не могу понять почему. Я ставил if (pos >= 0), но потом меня сбило с толку то, что отображается все равно -1 и я вернул как было. Не думаю что ассемблер мне сейчас будет более поняте чем Си, за который я взялся первый раз в жизни, но поверю наслово.

Про "lcd.setCursor (pos - 1, col)" не совсем понял. Это по моему объяснению? Так это по алгоритму так запрограммировано. Снизили громкость, pos = 0, затем нажали VolumeUp и выполнился другой кусок с "lcd.setCursor (pos - 1, col)". Для этой строки нужно добавить проверку, что если pos == 0, то чистить нечего. Аналогично и для "lcd.setCursor (pos + 1, col)".

Buzzer2010 пишет:

kisoft пишет:

Еще, это не обязательно, но иногда можно использовать. Я считываю код из irrecv в переменную и делаю примерно так:

unsigned long ir_code;
...
  if (irrecv.decode(&results)) {
    ir_code = results.value;
    irrecv.resume();
    switch(ir_code)
    ...

Это позволит irrecv подготовиться к приему следующего кода быстрее, независимо от задержек, которые происходят дальше по коду. Например, как у тебя сейчас, пока выведешь данные на экран, irrecv у тебя не готов принимать следующий код. Минус этого приема, нельзя использовать другие члены структуры results, потому что они могут измениться в любое время. Из плюсов - не забудешь вызвать resume().

 

На самом деле это очень важно, особенно если учитывать тайминг цикла и время срабатывания IR-приемника. С моей стороны было абсолютно неграмотно не учесть этот момент: после использования конструкции "switch-case" очевидно что програмка начала себя более свободно чувствовать и irrecv просто не успевал сделать то, что он там делает. "results" я больше нигде не планирую использовать, кроме как в считывании кодов, так что этот минус меня не коснется.

На счет "неграмотно" - это совсем не обязательно, тут очень много факторов. Для короткого периода между анализом results.value и irrecv.resume() можно не париться, а если подольше, тогда может и стоит задуматься. Зависит от обстоятельств.

 

DonVorlon
Offline
Зарегистрирован: 24.03.2016
120     case VolUp:
121       key_dsp("VolUp");
122       lcd.setCursor (pos - 1, col);
123       lcd.write(" ");
124       bar(pos, col);
125       if (pos <16) {pos++;}
126     break;
 

МОжет я ошибаюсь, но строка 125 должна идти после 121. Ход мысли такой - если нажата кнопка то следует изменить pos , а затем уже отобразить результат новой позиции бегунка на экране.  

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Ну да. Так и должно было быть. Только не песле 121, а после 124. Функция "key_dsp" только отображает название нажатой клавиши, а вот "bar(pos, col);"  - как раз и двигает бегунок на новую позицию... Странно, почему я этого не заметил... А вот еще вопрос: можно ли в "case" указывать несколько условий? Ну вот мне надо бы еще туда как-то нижний "if" приделать.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

kisoft пишет:

Одинаковое название глобальной переменной и параметра функции (у тебя здесь это pos). Можно с горяча перепутать и подумать, что изменится глобальная переменная, ан нет, изменится только локальный параметр функции. Хотя никто не запрещает написать для глобальной переменной "::pos = 15;". На именование переменных, параметров нет общего стандарта, потому кто-то добавляет префиксы, кто-то еще как-то.

 

Так дело в том, что значение "pos" нужно мне и для передвижения бегунка и для отображения в целях отладки. Ну и, естественно, я хотел бы там видеть тоже что и есть на самом деле.

kisoft пишет:
Это я про то, что отображаться 17 может вполне.

А оно так и делает. Ниже нуля не идет, но 17 - показывает. Хотя в первом варианте скетча с "if"-ами было всё нормально. В смысле: 17 не отображалось, а в остальном - такой же бардак и был.

kisoft пишет:

Про "lcd.setCursor (pos - 1, col)" не совсем понял. Это по моему объяснению? Так это по алгоритму так запрограммировано. Снизили громкость, pos = 0, затем нажали VolumeUp и выполнился другой кусок с "lcd.setCursor (pos - 1, col)". Для этой строки нужно добавить проверку, что если pos == 0, то чистить нечего. Аналогично и для "lcd.setCursor (pos + 1, col)".

Так эту проверку только для счетчика надо делать или можно ее поместить в "case"? Это "case", вообще, можно вполнять по нескольким условиям? Потому что если бегунок упёрся влево - мне не надо ни "pos" наращивать ни отображать ничего.
kisoft пишет:

На счет "неграмотно" - это совсем не обязательно, тут очень много факторов. Для короткого периода между анализом results.value и irrecv.resume() можно не париться, а если подольше, тогда может и стоит задуматься. Зависит от обстоятельств.

 

Ничего не понял, но тут еще есть над чем подумать...

DonVorlon
Offline
Зарегистрирован: 24.03.2016
Если я Вас правильно понял то несколько условий можно описать так ...
switch (Color){
  case Red:
  case Orange:
  case Yellow:
     // Теплая гамма;
     break;
  case Green:
  case Blue:
  case Guan:
  case Magenta:
    // Холодная гамма;
    break;
  default:
  //  Цвет не из радуги
}

код взят из книги по с++

DonVorlon
Offline
Зарегистрирован: 24.03.2016
 
    case VolUp:
      key_dsp("VolUp");
      if (pos <16) {
        pos++;
        lcd.setCursor (pos - 1, col);
        lcd.write(" ");
        bar(pos, col);
      } 
     break;
 

Наверно как так....

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

Если я Вас правильно понял то несколько условий можно описать так ...
switch (Color){
  case Red:
  case Orange:
  case Yellow:
     // Теплая гамма;
     break;
  case Green:
  case Blue:
  case Guan:
  case Magenta:
    // Холодная гамма;
    break;
  default:
  //  Цвет не из радуги
}

код взят из книги по с++

 

Спасибо. Буду пробовать...

DonVorlon пишет:

case VolUp:
key_dsp("VolUp");
if (pos <16) {
pos++;
lcd.setCursor (pos - 1, col);
lcd.write(" ");
bar(pos, col);
}
break;

Наверно как так....

Да, только меня тут разнесли за "if" и я попробую сейчас оба варианта и с "case" и с "if" ...

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

 
    case VolUp:
      key_dsp("VolUp");
      if (pos <16) {
        pos++;
        lcd.setCursor (pos - 1, col);
        lcd.write(" ");
        bar(pos, col);
      } 
     break;
 

Наверно как так....

Вот при таком варианте происходит следующее: дёргание в обратную сторону бегунка пропало, но добавилась проблема с кнопокой "VolUp" - бегунок убегает за край экрана как и раньше, но теперь после 17 "pos" затирается, то есть - не отображается. Тоже самое происходит и с "VоlDown", с той разницей что только затирается всё, что меньше нуля. Но бегунок остаётся на первой позиции (на первой на дисплее, адрес ее в скетче - 0).

Вот этот участок, где я только что менял:

 switch ( results.value )
    {
    case VolUp:
        key_dsp("VolUp");
            if (pos <16) {
                pos++;
                lcd.setCursor (pos - 1, col);
                lcd.write(" ");
                bar(pos, col);
                         }
    break;
      
    case VolDown:
      key_dsp("VolDown");
          if (pos>=0 ) {
              pos--;
              lcd.setCursor (pos+1, col);
              lcd.write(" ");
              bar(pos, col);
                       }
    break;
      
         

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Странное дело... Если по "VolUp" в "if" поставить вот так:

 if (pos <= 16)

 

, то бегунок продолжает улетать за правую область дисплея, но позиция теперь бывает еще и 18, перед тем как затереться...

DonVorlon
Offline
Зарегистрирован: 24.03.2016
081 void bar(int pos, int col)
082 {
083  
084   lcd.setCursor (13, 0);
085   lcd.print("   ");
086   lcd.setCursor (13, 0);
087   lcd.print(pos + 1);
088  
089   lcd.setCursor (pos, col);
090   lcd.write("\1");
091  
092  
093 }
 

Прежде следует исправить строку 087 на - lcd.print(pos);

это уберет значение 17.

13    case VolDown:
14      key_dsp("VolDown");
15          if (pos>=0 ) {
16              pos--;
17              lcd.setCursor (pos+1, col);
18              lcd.write(" ");
19              bar(pos, col);
20                       }
21    break;
22

 

тут в 15 строке условие if (pos>0) {

так позиция не будет меньше 0

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

В целях отладки я спрятал всё под "if", что бы отображалась реальная позиция:

#include "IRremote.h"

#include <LiquidCrystal.h>

#define VolUp   9249
#define VolDown 25633
#define Up      26145
#define Down    9761
#define Left    22049
#define Right   5665
#define Off     22561
#define Att     5153
#define Source  12577
#define Select  17441
#define Mute    28961
#define Display 2593
#define Scroll  25121
#define _1      33
#define _2      16417
#define _3      8225
#define _4      24609
#define _5      4129
#define _6      20513

IRrecv irrecv(8);               // Указываем пин, к которому подключен приемник
decode_results results;

LiquidCrystal lcd (7, 6, 5, 4, 3, 2);
int pos = 0, col = 1;

byte cur[8] =
  {
   B11111,
   B11011,
   B11011,
   B00000,
   B00000,
   B11011,
   B11011,
   B11111,
  };
  
void setup()
{
  // ----------------  LCD SECTION TOP -------------------

  lcd.createChar(1, cur);
  pinMode(9, OUTPUT);  //  ЗАДЕЙСТВОВАТЬ 9-фй ПИН как ВЫХОДНОЙ ШИМ
  analogWrite(9, 10);  // УСТАНОВИТЬ КОНТРАСТ на 9-ом пине в 10
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  lcd.begin (16, 2);   // Start LCD
  lcd.clear();
  lcd.setCursor (0, 0);
  lcd.write ("key: ");


  // ----------------  LCD SECTION BOTTOM  ---------------

  irrecv.enableIRIn(); // -------------->  Запускаем прием

}

void loop() {
  key_a();
}





//***************************************************************************************
//***************************************************************************************
//***************************************      ******************************************
//************************************  V O I D S  **************************************
//***************************************      ******************************************
//***************************************************************************************



void bar(int pos, int col)
{

  lcd.setCursor (13, 0);
  lcd.print("   ");
  lcd.setCursor (13, 0);
  lcd.print(pos);
  lcd.setCursor (pos, col);
  lcd.write("\1");


}




void key_dsp (String key)
{
  lcd.setCursor (5, 0);
  lcd.print ("          ");
  lcd.setCursor (5, 0);
  lcd.print (key);

}


// ----------------- KEYS DESCRIPTION $$ DISPLAY PRESSED -----------------


void key_a()
{
  if (irrecv.decode(&results)) // Если данные пришли
  { 
   // lcd.setCursor (0, 1); 
   // lcd.print (results.value);
   int rv = results.value;
    switch (rv)
    {
    case VolUp:
         if (pos <= 16) {
            key_dsp("VolUp");
            pos++;
            lcd.setCursor (pos-1, col);
            lcd.write(" ");
            bar(pos, col);
                         }
    break;
      
    case VolDown:
         if (pos >= 0) {
             key_dsp("VolDown");
             pos--;
             lcd.setCursor (pos+1, col);
             lcd.write(" ");
             bar(pos, col);
                       }
    break;
      
         
    case Up:
      key_dsp("Up");
    break;
  
    case Down:
      key_dsp("Down");
    break;
  
    case Left: 
      key_dsp("Left");
    break;
    
    case Right:
      key_dsp("Right");
    break;
    
    case Off:
      key_dsp("Off");
    break;
    
    case Att:
      key_dsp("Att");
    break;

    case Source:
      key_dsp("Source");
    break;
    
    case Select:
      key_dsp("Select");
    break;
    
    case Mute:
      key_dsp("Mute");
    break;
    
    case Display:
      key_dsp("Display");
    break;
    
    case Scroll:
      key_dsp("Scroll");
    break;
    
    case _1:
      key_dsp("1");
    break;
    
    case _2:
      key_dsp("2");
    break;

    case _3:
      key_dsp("3");
    break;

    case _4:
      key_dsp("4");
    break;

    case _5:
     key_dsp("5");
    break;
    
    case _6:
      key_dsp("6");
    break;
    }
    irrecv.resume(); 
   }
  
  delay(200);
}


Теперь у меня "pos" пишет и -1 и 17 и не затирается, но бегунок улетает вправо с дисплея совсем....

Вот видео как ведет себя arduino с текущим кодом : Ссылка

DonVorlon
Offline
Зарегистрирован: 24.03.2016

не затирается потому, что процедура key_dsp() теперь в рамках if. т.к. эта процедура только отображает нажатую кнопку то, как раз в целях отладки нужно держать за скобками if. что бы не было -1 и 17 нужно убрать в строчках 120 и 130 знак '='

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

не затирается потому, что процедура key_dsp() теперь в рамках if. т.к. эта процедура только отображает нажатую кнопку то, как раз в целях отладки нужно держать за скобками if. что бы не было -1 и 17 нужно убрать в строчках 120 и 130 знак '='

Вынес перед "if", убрал знаки равно.

Затирается теперь последнее значение, которое больше 16, но бегунок все равно удирает с экрана. Раньше, до вынесения за "if" предельные значения 0 и 17 не затирались. Больше - ничего не изменилось.

 case VolUp:
          key_dsp("VolUp");
         if (pos < 16) {
            pos++;
            lcd.setCursor (pos-1, col);
            lcd.write(" ");
            bar(pos, col);
                        }

 

Вроде бы и все правильно, но бегунок все равно убегает на позицию 17.

Такое впечатление что условие не срабатывает.

----------------------- небольшое отступление -----------------------

Дело в том, что пульт, в конце каждой серии кода, посылает еще один код, очевидно комманду завершения передачи, на которую "case" тоже почему-то реагирует! И поэтому иногда получаются двойные скачки бегунка. И конечно же это сказывается в крайних положениях, когда позиция принимает значения, не входящие в диапазон допустимых: между 0 и 16.

Я думаю проблема тут.

DonVorlon
Offline
Зарегистрирован: 24.03.2016

А может проблема в том, что нет 16 позиции, первая позиция на жки равна 0 а крайняя справа 15. Попробуйте исправить на следующее ...

...
if  (pos < 15) {
...

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

А может проблема в том, что нет 16 позиции, первая позиция на жки равна 0 а крайняя справа 15. Попробуйте исправить на следующее ...

...
if  (pos < 15) {
...

 

Если поставить до 15, то как раз всё как нужно. Только 0 и 15 затираются, что тоже не совпадает с конечной целью. Надо вынести ту фунцчию за "if" опять.

Однако мне не даёт покоя комманда завершения передачи. Надо ее либо отловить и исключить или поменять пульт. Причем если внести ее код в исключение по "!=" в любой "if" - это ничего не даёт. Хотя если раскомментить отладочный принт - пишется определенное число, которое потом никак не помогает.

Странно это всё...

Сейчас начало функции с "case" выглядит так:

void key_a()
{
  int rv = results.value;
  if (irrecv.decode(&results)) // Если данные пришли
  { 
  //  lcd.setCursor (0, 1); 
  //  lcd.print (results.value);
   
    switch (rv)
    {
    case VolUp:
         if (pos < 15) {
            key_dsp("VolUp");         
            pos++;
            lcd.setCursor (pos-1, col);
            lcd.write(" ");
            bar(pos, col);
                        }
  
    break;
      
    case VolDown:
         if (pos > 0) {
             key_dsp("VolDown");
             pos--;
             lcd.setCursor (pos+1, col);
             lcd.write(" ");
             bar(pos, col);
                       }
       
    break;
...................................

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Кстати еще одна странность: как видно из текста скетча, я там проверяю на все клавиши, но действия выполняются только за первыми двумя. Так вот интересно что происходит: если нажимать "VolUp", который двигает бегунок вправо, бросить кнопку и нажать любую из незадействованных, то отображается название кнопки и бегунок прыгает на 1 позицию вправо. Если до этого нажимать влево, то прыгает влево. Получается что где-то проскакивает наращивание переменной "pos", и вполне возможно что именно потому что она глобальная.

У меня не хватает таланта обойтись без ее "глобализации"...

------------------------------------------

Хватило таланта и я отвязал переменную "pos", заменив ее на "_pos" в  "#define". Это ничего не дало.

Такое впечатление что переменная наращивается 1 раз после события в "if (irrecv.decode(&results))". Это я уже сам не решу.

Последняя редакция скетча:

#include "IRremote.h"

#include <LiquidCrystal.h>

#define VolUp   9249
#define VolDown 25633
#define Up      26145
#define Down    9761
#define Left    22049
#define Right   5665
#define Off     22561
#define Att     5153
#define Source  12577
#define Select  17441
#define Mute    28961
#define Display 2593
#define Scroll  25121
#define _1      33
#define _2      16417
#define _3      8225
#define _4      24609
#define _5      4129
#define _6      20513
// #define _0      20769

IRrecv irrecv(8);               // Указываем пин, к которому подключен приемник
decode_results results;

LiquidCrystal lcd (7, 6, 5, 4, 3, 2);
int _pos = -1, _col = 1;
// boolean end_pos = false;

byte cur[8] =
  {
   B11111,
   B11011,
   B11011,
   B00000,
   B00000,
   B11011,
   B11011,
   B11111,
  };
  
void setup()
{
  // ----------------  LCD SECTION TOP -------------------

  lcd.createChar(1, cur);
  pinMode(9, OUTPUT);  //  ЗАДЕЙСТВОВАТЬ 9-фй ПИН как ВЫХОДНОЙ ШИМ
  analogWrite(9, 10);  // УСТАНОВИТЬ КОНТРАСТ на 9-ом пине в 10
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  lcd.begin (16, 2);   // Start LCD
  lcd.clear();
  lcd.setCursor (0, 0);
  lcd.write ("key: ");


  // ----------------  LCD SECTION BOTTOM  ---------------

  irrecv.enableIRIn(); // -------------->  Запускаем прием

}

void loop() {
  key_a();
}





//***************************************************************************************
//***************************************************************************************
//***************************************      ******************************************
//************************************  V O I D S  **************************************
//***************************************      ******************************************
//***************************************************************************************



void bar(int pos, int col)
{

  lcd.setCursor (13, 0);
  lcd.print("   ");
  lcd.setCursor (13, 0);
  lcd.print(pos);
  lcd.setCursor (pos, col);
  lcd.print("\1");


}




void key_dsp (String key)
{
  lcd.setCursor (5, 0);
  lcd.print ("          ");
  lcd.setCursor (5, 0);
  lcd.print (key);

}


// ----------------- KEYS DESCRIPTION $$ DISPLAY PRESSED -----------------


void key_a()
{
  int rv = results.value;
  if (irrecv.decode(&results)) // Если данные пришли
  { 
  //  lcd.setCursor (0, 1); 
  //  lcd.print (results.value);
   
    switch (rv)
    {
    case VolUp:
         if (_pos < 15 ) {       
            key_dsp("VolUp");         
            _pos++;
            lcd.setCursor (_pos-1, _col);
            lcd.write(" ");
            bar(_pos, _col);
                        }
  
    break;
      
    case VolDown:
         if (_pos > 0) {
             key_dsp("VolDown");
             _pos--;
             lcd.setCursor (_pos+1, _col);
             lcd.write(" ");
             bar(_pos, _col);
                       }
       
    break;
      
         
    case Up:
      key_dsp("Up");
    break;
  
    case Down:
      key_dsp("Down");
    break;
  
    case Left: 
      key_dsp("Left");
    break;
    
    case Right:
      key_dsp("Right");
    break;
    
    case Off:
      key_dsp("Off");
    break;
    
    case Att:
      key_dsp("Att");
    break;

    case Source:
      key_dsp("Source");
    break;
    
    case Select:
      key_dsp("Select");
    break;
    
    case Mute:
      key_dsp("Mute");
    break;
    
    case Display:
      key_dsp("Display");
    break;
    
    case Scroll:
      key_dsp("Scroll");
    break;
    
    case _1:
      key_dsp("1");
    break;
    
    case _2:
      key_dsp("2");
    break;

    case _3:
      key_dsp("3");
    break;

    case _4:
      key_dsp("4");
    break;

    case _5:
     key_dsp("5");
    break;
    
    case _6:
      key_dsp("6");
    break;
    }
    irrecv.resume(); 
   }
  
  delay(85);
}


 

DonVorlon
Offline
Зарегистрирован: 24.03.2016

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

следовательно код будет примерно таким - 

if (был код завершения) {
  switch(rv){
    ...
  }
}

но наверно понадобится еще одна переменная которая будет хранить код кнопки пока не поступит код завершения.

DonVorlon
Offline
Зарегистрирован: 24.03.2016

что бы не сомневаться в ом, кака переменная используется - они должны отличаться в имени.

Например так.

 
081 void bar(int _pos, int col)
082 {
083  
084   lcd.setCursor (13, 0);
085   lcd.print("   ");
086   lcd.setCursor (13, 0);
087   lcd.print(_pos);
088   lcd.setCursor (_pos, col);
089   lcd.write("\1");
090  
091  
092 }
093  

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

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

следовательно код будет примерно таким - 

if (был код завершения) {
  switch(rv){
    ...
  }
}

но наверно понадобится еще одна переменная которая будет хранить код кнопки пока не поступит код завершения.

Как показали исследования, код завершения, почему-то не посылается в конце серий именно этих кнопок. Однако же выяснилось другая, не менее неприятная ситуация, описанная выше.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

что бы не сомневаться в ом, кака переменная используется - они должны отличаться в имени.

Например так.

Я точно так и сделал. Еще и "col" на всякий случай развязал. См код выше.

С кодом завершения я даже не знаю что делать. Дело не в нём. "case" один раз реагирует на любую кнопку.

Вот как ведет себя бегунок на текущий момент: Видео

DonVorlon
Offline
Зарегистрирован: 24.03.2016

Вот тут, думаю, может быть проблемка..

114   int rv = results.value;
115   if (irrecv.decode(&results)) // Если данные пришли
116   {
117   //  lcd.setCursor (0, 1);
118   //  lcd.print (results.value);
119     
 

строка 114 должна быть после 116 т.к. если данные не пришли то и загружать в rv  нечего.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

Вот тут, думаю, может быть проблемка..

 

строка 114 должна быть после 116 т.к. если данные не пришли то и загружать в rv  нечего.

Переменная "rv" получит значение и до "if (irrecv.decode(&results))", хотя я могу и ошибаться. Я ее раньше и ставил внутри этого "if". Но видимых изменений не обнаружил. Сейчас попробую перенести опять. Все остальные проблемы если и не ушли, то стали не так заметны...

Да, после переноса той строки внутрь - перестало дёргать бегунок после нажатия других кнопок.Однако осталась теперь, явно заметная, проблема: бегунок может не двигаться на двойное и даже тройное нажатие кнопки (все равно какой - "VolUp" или "VolDown"), но потом перескакивает сразу на количество позиций равное числу нажатий. Даже не перескакивает, а быстро перебегает. Как буд-то клавиатура подвисла и потом буквы одна за другой спешат занять свои места.

DonVorlon
Offline
Зарегистрирован: 24.03.2016

Вот что еще, вызывает подозрение тип results.value; - Unsigned long используется для хранения положительных целых чисел в диапазоне от 0 до 4,294,967,295 и занимает 32 бита (4 байта) в памяти, а тип rv  - int целое число, занимает 2 байта памяти, и может хранить числа от -32 768 до 32 767. может стоит преобразовывать так int rv = Int(results.value);

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

Вот что еще, вызывает подозрение тип results.value; - Unsigned long используется для хранения положительных целых чисел в диапазоне от 0 до 4,294,967,295 и занимает 32 бита (4 байта) в памяти, а тип rv  - int целое число, занимает 2 байта памяти, и может хранить числа от -32 768 до 32 767. может стоит преобразовывать так int rv = Int(results.value);

Сейчас попробую, хотя не совсем понимаю что это даст.

-------------------------

Никаких изменений не произошло. Но в общем и целом, конструкцию, на данном этапе,  можно считать рабочей.

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

Хотя я видел как-то в инете - парень делал игру с управлением от пульта. Надо будет повнимательней изучить его скетч с учётом проделанной нами работы :) .

Спасибо за помощь! Пойду тот скетч поищу.

DonVorlon
Offline
Зарегистрирован: 24.03.2016

Посмотрел видео - кажется работает нормально, только былонесколько проскоков, но думаю может быстро были нажаты кнопки.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

DonVorlon пишет:

Посмотрел видео - кажется работает нормально, только былонесколько проскоков, но думаю может быстро были нажаты кнопки.

Дребезг кнопок вполне возможен. Тем более что это кнопки громкости, а они всегда страдают больше остальных. Надо попробовать поуправлять другими кнопками. Например цифровыми - их вообще никто никогда не трогает.

-----------------------

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

#include "IRremote.h"

#include <LiquidCrystal.h>

#define VolUp   9249
#define VolDown 25633
#define Up      26145
#define Down    9761
#define Left    22049
#define Right   5665
#define Off     22561
#define Att     5153
#define Source  12577
#define Select  17441
#define Mute    28961
#define Display 2593
#define Scroll  25121
#define _1      33
#define _2      16417
#define _3      8225
#define _4      24609
#define _5      4129
#define _6      20513
// #define _0      20769

IRrecv irrecv(8);               // Указываем пин, к которому подключен приемник
decode_results results;

LiquidCrystal lcd (7, 6, 5, 4, 3, 2);
int _pos = -1, _col = 1;
// boolean end_pos = false;

byte cur[8] =
  {
   B11111,
   B11011,
   B11011,
   B00000,
   B00000,
   B11011,
   B11011,
   B11111,
  };
  
void setup()
{
  // ----------------  LCD SECTION TOP -------------------

  lcd.createChar(1, cur);
  pinMode(9, OUTPUT);  //  ЗАДЕЙСТВОВАТЬ 9-фй ПИН как ВЫХОДНОЙ ШИМ
  analogWrite(9, 10);  // УСТАНОВИТЬ КОНТРАСТ на 9-ом пине в 10
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  lcd.begin (16, 2);   // Start LCD
  lcd.clear();
  lcd.setCursor (0, 0);
  lcd.write ("key: ");


  // ----------------  LCD SECTION BOTTOM  ---------------

  irrecv.enableIRIn(); // -------------->  Запускаем прием

}

void loop() {
  key_a();
}





//***************************************************************************************
//***************************************************************************************
//***************************************      ******************************************
//************************************  V O I D S  **************************************
//***************************************      ******************************************
//***************************************************************************************



void bar(int pos, int col)
{

  lcd.setCursor (13, 0);
  lcd.print("   ");
  lcd.setCursor (13, 0);
  lcd.print(pos);
  lcd.setCursor (pos, col);
  lcd.print("\1");


}




void key_dsp (String key)
{
  lcd.setCursor (5, 0);
  lcd.print ("          ");
  lcd.setCursor (5, 0);
  lcd.print (key);

}


// ----------------- KEYS DESCRIPTION $$ DISPLAY PRESSED -----------------


void key_a()
{
  
  if (irrecv.decode(&results)) // Если данные пришли
  { 
  //  lcd.setCursor (0, 1); 
  //  lcd.print (results.value);
   int rv = int(results.value);
    switch (rv)
    {
    case _1:
         if (_pos < 15 ) {       
            key_dsp("VolUp");         
            _pos++;
            lcd.setCursor (_pos-1, _col);
            lcd.write(" ");
            bar(_pos, _col);
                        }
  
    break;
      
    case _2:
         if (_pos > 0) {
             key_dsp("VolDown");
             _pos--;
             lcd.setCursor (_pos+1, _col);
             lcd.write(" ");
             bar(_pos, _col);
                       }
       
    break;
      
         
    case Up:
      key_dsp("Up");
    break;
  
    case Down:
      key_dsp("Down");
    break;
  
    case Left: 
      key_dsp("Left");
    break;
    
    case Right:
      key_dsp("Right");
    break;
    
    case Off:
      key_dsp("Off");
    break;
    
    case Att:
      key_dsp("Att");
    break;

    case Source:
      key_dsp("Source");
    break;
    
    case Select:
      key_dsp("Select");
    break;
    
    case Mute:
      key_dsp("Mute");
    break;
    
    case Display:
      key_dsp("Display");
    break;
    
    case Scroll:
      key_dsp("Scroll");
    break;
    
 /*   case _1:
      key_dsp("1");
    break;
    
    case _2:
      key_dsp("2");
    break;
*/
    case _3:
      key_dsp("3");
    break;

    case _4:
      key_dsp("4");
    break;

    case _5:
     key_dsp("5");
    break;
    
    case _6:
      key_dsp("6");
    break;
    }
    irrecv.resume(); 
   }
  
  delay(65);
}