Показать сообщение отдельно
Старый 07.11.2013, 21:29   #585
Glouck
Старший Пользователь
 
Регистрация: 03.10.2006
Возраст: 50
Город: Moscow
Регион: 77, 97, 99, 177
Машина: Nissan Elgrand
Сообщений: 246
Glouck will become famous soon enough
По умолчанию

Цитата:
Сообщение от OsDima Посмотреть сообщение
Конечно надо.
Вот кусок прошивки отвечающий за кнопки. Сделано на основе прошивки Андрея. Писал левой ногой, сильно не пинайте...
Код:
#include <EEPROM.h>
#define RES_KEY_FLAG_ 0x16  // Флаг первого запуска скетча

byte bytes[4];

//-----------------------------------------
//- входы(пины) ардуино                   -
//-----------------------------------------

const int RES_PIN = 5 ;       // аналоговый вход(пин) для резестивных(рулевых) кнопок 

//-----------------------------------------
//- переменные включения функций скетча   -
//-----------------------------------------

boolean is_res_keys = false;

//-----------------------------------------
//- Новые переменные для кнопок

#define RES_BT_CNT 50  // макс кол-во кнопок
#define VOL_BT_CNT 2  // кол-во кнопок с автоповтором
#define RES_DT_MIN 5  // мин значение АЦП
#define  RES_DT_MAX 1020  // макс значение АЦП
unsigned long res_key_wait_long = 600;  // задержка длинного нажатия кнопки (ms)
unsigned int key_to_send = 0;
boolean res_key_hold = false;

//-----------------------------------------
//- Переменные для резистивных кнопок     -
//-----------------------------------------

unsigned long  res_dt = 0; 
unsigned long  res_dt_sum = 0; 
#define RES_DT_COUNT 400 // Количество считываемых данных
#define RES_DT_SKIP_COUNT 100 // Количество данных, которые надо пропустить при нажатии
#define RES_DT_POINT 6 // Точность
int res_dt_n = 0;
unsigned long res_key = 0;
unsigned long res_key_old = 0;
unsigned long res_key_wait_next = 200;  // задержка автоповтора (ms)
unsigned long res_key_wait_millis = 0;
unsigned long res_key_millis;
unsigned long res_key_array[RES_BT_CNT + 1][2];
unsigned int res_key_count = 0;
unsigned int res_key_delta = 3;

//-----------------------------------------
void setup() {                

  Serial.begin(115200); 
    res_key_millis = millis();
    
    unsigned int first_run_key = EEPROM.read(0);
    if ( first_run_key == RES_KEY_FLAG_ )
    {
      res_key_count = EEPROM.read(1);
      //EEPROM.write(addr, val);
      for(int i=0; i<res_key_count;i++) 
      { 
        res_key_array[i][0] = (EEPROM.read(i+2) * 256) + EEPROM.read(i+2+RES_BT_CNT) - res_key_delta; res_key_array[i][1] = res_key_array[i][0] + res_key_delta + res_key_delta; 
      }
    }
    for(int i=res_key_count; i<(RES_BT_CNT+1);i++) 
    { 
      res_key_array[i][0] = 0xFFFFFFFF; res_key_array[i][1] = 0xFFFFFFFF; 
    }

}

//-----------------------------------------
void loop() {

  if (Serial.available() >= 1) // Проверяем наличие команд от компьютера
  {
    switch (Serial.read())
    {
     case 0x06: // включить передачу данных от резестивных кнопок
       is_res_keys = true;
     break;

     case 0x86: // выключить передачу данных от резестивных кнопок
       is_res_keys = false;
     break;

    }
  }
  if( is_res_keys ) res_keys();                        //  резистивные кнопки
//  res_keys();
  
}

//----------------------------------------------------------------------------------
// Функция работы с резистивными кнопками
//----------------------------------------------------------------------------------
void res_keys()
{  
  {
    res_dt = analogRead(RES_PIN); // прочитать данные АЦП 
    if( res_dt >= RES_DT_MIN && res_dt <= RES_DT_MAX )
    { 
      res_dt_n++;
      if( res_dt_n > RES_DT_SKIP_COUNT )
      {
        res_dt_sum += (res_dt << RES_DT_POINT);
        if( res_dt_n == RES_DT_COUNT)
        { 
//          res_key = (res_dt_sum / (RES_DT_COUNT - RES_DT_SKIP_COUNT));
          res_key = (((((( res_dt_sum / (( RES_DT_COUNT - RES_DT_SKIP_COUNT ) + (2^(RES_DT_POINT-1)-1) ) >> (RES_DT_POINT-1)) + 1) >> 1) + 1)>> 1)); // + 1) >> 1;
          res_dt_sum = 0; res_dt_n = 0;
        }
       }
    }
    else
    {
      res_dt_sum = 0; res_dt_n = 0; res_key = 0;
      res_key_wait_millis = 0;
    }
  }

//  обработка нажатия
  int key_code = 0;

  if (res_key != 0)  // что-то нажато
  {
    key_code = keyCode(res_key);
    if (key_code <= VOL_BT_CNT)  // первые кнопки с автоповтором
    {
      if (res_key_old == res_key)  // удержание кнопки
      {
        if (millis() - res_key_wait_millis > res_key_wait_next)  // задержка автоповтора
        {
          sendKey(key_code);
          res_key_wait_millis = millis();
        }
      }
      else
      {
        sendKey(key_code);
        res_key_wait_millis = millis();
        res_key_old = res_key;
      }
    }
    else  // кнопки с долгим нажатием
    {
      if (res_key_old == res_key)  // удержание кнопки
      {
        if (millis() - res_key_wait_millis > res_key_wait_long)   // длинное нажатие
        {
          if (!res_key_hold)
          {
            sendKey(key_code+RES_BT_CNT);
            res_key_wait_millis = millis();
            res_key_hold = true;
          }
        }
      }
      else
      {
        key_to_send = key_code;
        res_key_wait_millis = millis();
        res_key_old = res_key;
      }
    }
  }
  else  // ничего не нажато
  {
    res_key_old = 0;
    if (key_to_send != 0 && !res_key_hold) sendKey(key_to_send);
    res_key_hold = false;
    key_to_send = 0;
  }
}

void sendKey(int key_code)
{
  bytes[0] = 0xAA;          // преобразовать в 4-байта  
  bytes[1] = 0;  
  bytes[2] = RES_PIN; 
  bytes[3] = key_code; 
  Serial.write( bytes,4); // отправить прочитаное значение компьютеру
/*
  Serial.write(bytes[3]+0x30); // отправить прочитаное значение компьютеру
  Serial.print(" ");
  Serial.print(res_key,DEC);
  Serial.println("");
*/
}

unsigned int keyCode(unsigned long key_res)
{
  int i = 0; boolean exit = false;
  while( res_key_array[i][0] != 0xFFFFFFFF && (!exit) )
  {  // проверяем новая ли кнопка
    if( (res_key_array[i][0] <= key_res) && (key_res <= res_key_array[i][1]) ) exit = true; else i++;
  }
  if ( exit )  // кнопкка уже известная
  {
    return (i+1);
  }
  else {  // кнопка новая
    if ( res_key_count < RES_BT_CNT )
    {
      res_key_array[res_key_count][0] = key_res - res_key_delta;
      res_key_array[res_key_count][1] = key_res + res_key_delta;
      res_key_count++;
            
      EEPROM.write(1, res_key_count); // Запоминаем количество кнопок
      byte one_byte = key_res / 256;
      EEPROM.write(res_key_count+1, one_byte ); // Запоминаем старший байт значения кнопки
      one_byte = key_res - one_byte * 256;
      EEPROM.write(res_key_count+1+RES_BT_CNT, one_byte ); // Запоминаем младший байт значения кнопки
      EEPROM.write(0, RES_KEY_FLAG_);
            
      return res_key_count;
    }
    else
    {  // переполнение - больше кнопок не запоминаем
      bytes[0] = 0xAA;          // преобразовать в 4-байта  
      bytes[1] = 0xAA;  
      bytes[2] = (key_res & 0xFF00) >> 8; 
      bytes[3] = key_res & 0xFF; 
      Serial.write( bytes,4); // отправить прочитаное значение компьютеру
    }
  }
}
После заливки этого кода при первом включении, первые две нажатые кнопки будут с автоповтором (для регулировки громкости), остальные - обычные. Короткое нажатие работает на отпускание, длинное - по задержке в 600 мс.
Если надо переопределить кнопки для автоповтора - поменяйте значение RES_KEY_FLAG_ на любое другое число, и перезалейте прошивку. Если нужно больше двух кнопок с автоповтором - поменяйте значение VOL_BT_CNT.
Glouck вне форума   Ответить с цитированием