Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 10 из 14
  1. #1
    Пользователь
    Регистрация
    22.07.2010
    Возраст
    49
    Сообщений
    20
    Вес репутации
    174

    По умолчанию All-IN-One (дружественная многозадачность)

    Выкладываю свой проект, написанный для Фсе-В-Адном имени CHIP-а Выкладываю "как есть" т.к. довылизывать нет времени.

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

    Вопрос: Что значит "как есть"?
    Ответ: Скетч рабочий. Для внедрения может потребоваться доделка напильником для настройки. На вопросы буду отвечать, но не факт, что очень быстро.

    Вопрос: какие еще есть отличия от оригинала?
    Ответ: см. скетч, что вспомнил:
    - переключение на камеру сделано для монитора (нажание кнопки ав), для usb переделать не сложно
    - запоминает состояние для камеры зв
    - "виртуальные кнопки" для ик-пульта. Сейчас их три: две изменение функции яркости (у разных моников разная подсветка) и переключение A/V.
    - разные интервалы опроса для событий
    - программный ремот усилителя
    - ик-приемник сидит на другом вход
    - режим отладки - удобно отлаживать в простой терминалке. Для работы с софтом CHIP-а должно быть отключено


    Спасибо Chip-у за оригинальный проект!

    Код:
    // http://compcar.ru  
    #include <IRremote.h>  
    #include <EEPROM.h>
    //
    //#define DEBUG 1
    //
    #define p_delay(VAR,MS) mills_poll_##VAR = millis()+MS
    #define POLL(NAME)   if (mills_poll_##NAME<millis()) poll_##NAME()
    #define POLL_BUT(SW)   if (SW.press_cnt>0&&SW.next_poll<millis()) poll_button(&SW)
    
    //------------------------------
    // назначение пинов ардуино
    #define RECV_PIN      10    //вход ИК приемника
    #define REVL_PIN      12    //вход ЛАМПОЧКИ заднего хода
    #define JOYSTICK_PIN  5     // Вход для рулевых Кнопок 
    #define AVSW_PIN      8     //выход на переключатель A/V для заднего хода
    #define AMP_PIN       7     // Выход для включения усилителя
    
    #define LIGHT_SENS   0 // Вход датчика освещености 
    #define VOLT_SENS    1 // Вход датчика напряжения 
    #define FUEL_SENS    2 // Вход датчика уровня топлива 
    
    
    #define encoder0PinA     2 //Вывод А энкодера 
    #define encoder0PinB     3 //Вывод В энкодера 
    #define encoder_botton   4 //Вход кнопки энкодера 
    
    //-------------------------------
    // Энкодер 
    #define ENC_DELAY0 50 // интервал для повторяющихся срабатываний
    #define ENC_DELAY 1000 // интервал опроса
    int X2400=0,X1500=0; // сколько раз срабатывал триггер левый и правый
    
    // -----------------------------
    // AUTO_LIGHT 
    #define AUTO_LIGHT_DELAY 1000 // 10 секунд цикл поверки датчика освещения
    #define MAX_ULK 6    // сдвиг 3 вверх/3 вниз по градации яркости по "половинке" 
    byte ulk=MAX_ULK/2; // коэффициент для ручной правки яркости
    
    // JOYSTICK
    #define JOYSTICK_DELAY 250
    #define JOYSTICK_DELAY0 100
    
    // VOLTMETER
    #define VOLTMETER_DELAY 1000 // опрос 1 раз в секунду
    
    // IR
    #define IR_DELAY_R 120
    #define IR_DELAY_P 250
    
    // Rear Lamp
    // Количество нажатий кнопки для перехода : (задний ход)
    #define TO_AV 1 // VGA->AV
    #define TO_VGA 2 // AV->VGA
    // задержка на переключение на камеру заднего вида при включении задней передачи
    #define REVL_DELAY 500
    byte revl_state=0; // в задержке ли находится триггер заднего хода
    #define REVL_STATE_OFFSET 10 // адрес eeprom для хранения состояния
    
    // структура для кнопки
    typedef struct bbb{ // есть баг в компиляторе - при вызове функции не работает typedef тип
      byte pin;
      byte press_cnt;
      byte state;
      unsigned long next_poll;
    } BUTTON;
    
    // кнопка аудио-видео
    BUTTON av;
    
    // длительность нажатия и между нажатиями (МС)
    #define BUT_DELAY 100    // пауза между нажатиями
    #define BUT_MS    100    // время нажатия
    
    
    // через сколько после старта включить усь
    #define AMP_DELAY 15000  // 15 секунд задержка до включения усилителя
    
    
    IRrecv irrecv(RECV_PIN);  
    decode_results results;  
    unsigned long old_ir,old_al,res_dt; 
    
    // циклы опроса процедур
    unsigned long mills_poll_ENC=0,
                  mills_poll_REVL=0,
                  mills_poll_VOLTMETER=0,
                  mills_poll_JOYSTICK=0,
                  mills_poll_IR=0,
                  mills_poll_AUTO_LIGHT=0,
                  mills_poll_AMP=AMP_DELAY,
                  mills_poll_BUT=0;
    
    // флаги
    boolean need_ir_resume=false; // продолжение чтения для ИК
    boolean send_data=false; // готовы данные для отправки
    // структура в 13 байт для отправки в ALL_IN_ONE
    struct all_in_one{
      unsigned long ir_dt;
      byte light,
           volt,
           fuel,
           reserved[5];
    };
    
    struct all_in_one aino;
     
    void setup(){  
      int cnt=0;
      int cnt1;
      Serial.begin(115200);  
      irrecv.enableIRIn(); // включить приемник  
      
      revl_state=EEPROM.read(REVL_STATE_OFFSET);
      
      
      pinMode(AVSW_PIN, OUTPUT);   
      pinMode(REVL_PIN, INPUT); 
      digitalWrite(REVL_PIN, HIGH); //Подключить внутренний подтягивающий резистор 
      digitalWrite(AVSW_PIN, LOW); 
      digitalWrite(AMP_PIN, LOW); 
      pinMode(AMP_PIN, OUTPUT);   
      //----------------
      pinMode(encoder0PinA, INPUT);  
      digitalWrite(encoder0PinA, HIGH);     // подключить подтягивающий резистор 
      pinMode(encoder0PinB, INPUT);  
      digitalWrite(encoder0PinB, HIGH);    // подключить подтягивающий резистор 
      pinMode(encoder_botton, INPUT);  
      digitalWrite(encoder_botton, HIGH);    // подключить подтягивающий резистор 
      attachInterrupt(0, doEncoderA, FALLING);  // настроить прерывание interrupt 0 на pin 2 
      attachInterrupt(1, doEncoderB, FALLING);  // настроить прерывание interrupt 0 на pin 3   
      //-----------------
     
      aino.ir_dt=0;
      aino.light=0;
      aino.volt=0;
      aino.fuel=0;
     
      av.pin=AVSW_PIN;
      av.press_cnt=0;
    }  
    
    
    void loop(){
      // если текущие миллисекунды больше интервала поллинга
      POLL(IR); // пущаю ИК
      POLL(AUTO_LIGHT);
      POLL(AMP);
      POLL(VOLTMETER);
      POLL(REVL);
      POLL(JOYSTICK);
      POLL(ENC);
      POLL_BUT(av);
    
      if (send_data) virt_keys(); // если есть данные для отправки - проверяем на свои действия
      
      if (send_data) {
    #ifndef DEBUG
        Serial.write( (byte*)&aino,sizeof(struct all_in_one)); 
    #else
        Serial.print(millis());
        Serial.print("\tKey:");
        Serial.print(aino.ir_dt);
        Serial.print("\tLight:");
        Serial.print(int(aino.light));
        Serial.print("\tVolt:");
        Serial.print(int(aino.volt));
        Serial.print("\tFuel:");
        Serial.println(int(aino.fuel));
    #endif
        send_data=false;
        aino.ir_dt=0; // устанавливаем состояние ик приемника в неопределенное
      }
    }
    
    void press_button(struct bbb* b,byte count){ // установка задачи на нажимание
      b->press_cnt+=count;
    }
    
    void poll_button(struct bbb* b){ // нажатие кнопки
     if (b->state==1) { //отпускаем нажатую кнопку
       digitalWrite(b->pin, LOW);
       b->press_cnt--;
       b->state=0;
       if (b->press_cnt>0){ //еще надо нажимать, устанавливаю промежуток между нажатиями
         b->next_poll=BUT_DELAY+millis();   
       }
     } else { // нажимаем кнопку
       digitalWrite(b->pin, HIGH);
       b->next_poll=BUT_MS+millis();   // сколько ms удерживать кнопку
       b->state=1;
     }
    } 
    
    // ---------------------------------
    // обработчик "виртуальных кнопок" - нужен для назначения действий на кнопки
    // пульта внутри ардуино (например сменить режим монитора, увеличить/уменьшить яркость и т.д.
    void virt_keys(){
      switch (aino.ir_dt){
       case (83585175): // source button
             press_button(&av,1);
             send_data=false;
             aino.ir_dt=0;
             break;
       case (83599965): // view button - увеличиваем яркость
             if (ulk<=MAX_ULK) ulk++;
             mills_poll_AUTO_LIGHT=0;         
             send_data=false;
             aino.ir_dt=0;
             break;
       case (83602005): // back music - уменьшаем яркость
             if (ulk>0) ulk--;
             mills_poll_AUTO_LIGHT=0;
             send_data=false;
             aino.ir_dt=0;
             break;
      }
    }
    //------------------------------------------
    //****************резистивные кнопки************************** 
    void poll_JOYSTICK() 
    {   
      unsigned long temp;
      temp = analogRead(JOYSTICK_PIN); // прочитать данные АЦП  
      if( temp < 1023 && aino.ir_dt==0) { // Приоритет ИК выше джойстика
          if (temp==res_dt) {// нету дребезга
            aino.ir_dt=temp;//+0x110000;
            p_delay(JOYSTICK,JOYSTICK_DELAY); // задержка между повторами 
            send_data=true;
          } else {
            p_delay(JOYSTICK,JOYSTICK_DELAY0); // задержка на дребезг
          }
      }     
      res_dt=temp;
    }  
    //------------------------------------------
    // вольтметр
    void poll_VOLTMETER(){ 
     int sens = analogRead(VOLT_SENS)>>2;   // /4 :) 
     if (sens!=aino.volt) {
       aino.volt=sens;
       send_data=true;
     }
     p_delay(VOLTMETER,VOLTMETER_DELAY); // задержка для следующего опроса.
    }
    //------------------------------------------
    // Включение усилителя
    void poll_AMP(){ 
      digitalWrite(AMP_PIN, HIGH);
      p_delay(AMP,3600*24*1000); // задержка для следующего опроса -сутки
    }
    //--------------------------------
    // Опрос автоматической корретировки света
    // алгоритм работы взят у ув. CHIP-а (all-in-one project)
    // изменения: сравнения с кратностью 30 заменены на сдвиг вправо на 5 битов (деление на 32)
    //            введен сдвиговый коэфициент для корректировки яркости с пульта
    //            свет=(свет>>4 + коэф_свет - МАКС_СВЕТ_КОЭФФ/2)
    // для простоты показываю изменение яркости в винде от датчика и кнопок на пульте
    // думаю, что будет удобно. если не настраивать кнопок работать будет по алгоритму CHIP
    // \датчик| 0       32      64      128     160     192     224
    // коэф \ |-----------------------------------------------------
    // 0      | 2       2       2       64      96      128     160
    // 1      | 2       2       64      96      128     160     192
    // 2      | 2       2       64      96      128     160     192
    // 3      | 2       64      96      128     160     192     255
    // 4      | 2       64      96      128     160     192     255
    // 5      | 64      96      128     160     192     255     255
    // 6      | 64      96      128     160     192     255     255
    
    void poll_AUTO_LIGHT(){ // управление яркостью
     byte light;   
     int sens = analogRead(LIGHT_SENS)>>2;   // /4 :) // интенсивность
     sens=((sens>>4)+ulk-MAX_ULK/2)>>1;  // обработка коэффициента
     light=sens<=0?2:(sens>=6?255:(sens+1)<<5);
     if (light!=aino.light) {
       aino.light=light;
       send_data=true;
     }
      p_delay(AUTO_LIGHT,AUTO_LIGHT_DELAY); // задержка для следующего опроса.
    }
    
    //--------------------------------
    // обработка переключения моника на камеру заднего вида
    // задача не требуется обработки в реальном времени, 
    // поэтому упрощаем алгоритм до срабатывания 1 раз в REVL_DELAY мс
    void poll_REVL(){ 
    byte temp;
    temp=revl_state;
      if (digitalRead(REVL_PIN) != HIGH){
        switch (revl_state) {
          case 0:
            revl_state=1;
            break;
          case 1:
            revl_state=2;
            press_button(&av,TO_AV);
        }
      } else {
        if (revl_state==2) {
          press_button(&av,TO_VGA);
        }
       
        revl_state=0;
       
      }
       p_delay(REVL,REVL_DELAY); // задержка для следующего опроса.
    
    if (temp!=revl_state){
        EEPROM.write(REVL_STATE_OFFSET,revl_state);
    }
    }
    
    //--------------------------------
    // обработчик ИК пульта
    // простая защита от ложных повторов от ИК-пульта
    void poll_IR() {  
      if (need_ir_resume) { // восстанавливаем прием на IR
        need_ir_resume=false;
        irrecv.resume();  
        return;
      }
      if (irrecv.decode(&results)) { 
        need_ir_resume=true; // устанавливаю флаг восстановление приема
        if (results.value > 0 && results.value < 0xFFFFFFFF) {
          aino.ir_dt = results.value;  
          p_delay(IR,IR_DELAY_P); // Пауза после первого нажатия и перед удержанием (перед повторами)
          old_ir = aino.ir_dt; 
        }  
        if (results.value == 0xFFFFFFFF ) 
        {
          aino.ir_dt=old_ir; 
          p_delay(IR,IR_DELAY_R); //пауза между повторами 
        }  
        send_data=true;
      }  
    }   
    
    //----------------------------------
    // обработчик энкодера
    void poll_ENC() 
    {   
      if( aino.ir_dt==0 ) { // Не занят отправкой
        if (X2400>0){
          aino.ir_dt=0x2400;
          X2400--;
          send_data=true;
       } else 
       if (X1500>0) {
          aino.ir_dt=0x1500;
          X1500--;
          send_data=true;
       }
      }
      p_delay(ENC,X2400>0||X1500>0?ENC_DELAY0:ENC_DELAY); // если есть еще срабатывания - короткая задержка
    }  
    
    //*******************обработка прерывания*********************** 
    void doEncoderA() 
    { 
      if(digitalRead(encoder0PinB)==HIGH){X2400++;}else{X1500++;}  
    }   
    //*******************обработка прерывания*********************** 
    void doEncoderB() 
    { 
      if(digitalRead(encoder0PinA)==HIGH){X1500++;}else{X2400++;}  
    }
    Последний раз редактировалось echo; 06.11.2010 в 10:17.

  2. #2
    Администратор Аватар для Chip
    Регистрация
    08.06.2007
    Возраст
    54
    Сообщений
    13,379
    Вес репутации
    10

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    А про нажатие на энкодер забыл?

  3. #3
    Пользователь
    Регистрация
    22.07.2010
    Возраст
    49
    Сообщений
    20
    Вес репутации
    174

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    Цитата Сообщение от Chip Посмотреть сообщение
    в алл-ин-ване нажатия тоже небыло я-же признался, что у тебя идея взята. На неделе допишу.

    +++ длительное нажатие надо отрабатывать?
    Последний раз редактировалось echo; 06.11.2010 в 16:50.

  4. #4
    Администратор Аватар для Chip
    Регистрация
    08.06.2007
    Возраст
    54
    Сообщений
    13,379
    Вес репутации
    10

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    Так вроде все работает http://www.compcar.ru/forum/showpost...39&postcount=1

  5. #5
    Пользователь
    Регистрация
    22.07.2010
    Возраст
    49
    Сообщений
    20
    Вес репутации
    174

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    Цитата Сообщение от Chip Посмотреть сообщение
    Так вроде все работает http://www.compcar.ru/forum/showpost...39&postcount=1
    работает длительное нажатие+прокрутка. Длительное нажатие без прокрутки не реализовано? Оно не нужно?

  6. #6
    Администратор Аватар для Chip
    Регистрация
    08.06.2007
    Возраст
    54
    Сообщений
    13,379
    Вес репутации
    10

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    Нужно конечно

  7. #7
    Пользователь
    Регистрация
    11.12.2008
    Возраст
    45
    Сообщений
    95
    Вес репутации
    234

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    А нельзя ли для этого скетча схемку нарисовать. Или может уже есть у кого. Выложите плиз.

  8. #8
    Пользователь
    Регистрация
    08.02.2009
    Возраст
    45
    Сообщений
    30
    Вес репутации
    194

    По умолчанию Re: All-IN-One (дружественная многозадачность)

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

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

    PHP код:
    void poll_AUTO_LIGHT(){ // управление яркостью
     
    byte light;   
     
    byte last_light;
     
    int AUTO_LIGHT_DELAY 1000;
    //int sens = analogRead(LIGHT_SENS);

    //Начало цикла усреднения значения
    int i;
    int Count 1000//Количество значений для усреднения
    int In 0//Начальная точка суммирования
    int sens//Усредненное значение со входа 
    for (0Counti++) {
    In In analogRead(LIGHT_SENS);
    }
    sens In Count//Вычисляем среднее значение 
    //Конец цикла усреднения значения


    //регулировка по датчику освещенности------------
    if ((sens 950) && (sens<960)) {light 10;}
    if ((
    sens 960) && (sens<970)) {light 60;}
    if ((
    sens 970) && (sens<980)) {light 100;}
    if ((
    sens 980) && (sens<990)) {light 130;}
    if ((
    sens 990) && (sens<1000)) {light 160;}
    if ((
    sens 1000) && (sens<1010)) {light 200;}
    if ((
    sens 1010) && (sens<1020)) {light 230;}
    if (
    sens 1020) {light 255;}
    //-------------------

     
    if (light!=last_light) {
        
    analogWrite(LIGHT_PINlight);
        
    last_light=light;
     }
      
    p_delay(AUTO_LIGHT,AUTO_LIGHT_DELAY); // задержка для следующего опроса.


  9. #9
    Администратор Аватар для Chip
    Регистрация
    08.06.2007
    Возраст
    54
    Сообщений
    13,379
    Вес репутации
    10

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    У тебя сенсор не правильно подключен, схему подправил .
    Последний раз редактировалось Chip; 07.03.2011 в 18:23.

  10. #10
    Пользователь
    Регистрация
    22.07.2010
    Возраст
    49
    Сообщений
    20
    Вес репутации
    174

    По умолчанию Re: All-IN-One (дружественная многозадачность)

    Цитата Сообщение от indy Посмотреть сообщение
    А как бы загрубить показания фоторезистора?
    Скажем постоянно опрашивать датчик и усреднять за последние 30 секунд, не портя многозадачность?
    Сейчас он на каждый фонарь на трассе реагирует...
    смысл такой: опрашиваем датчик 1 раз в AUTO_LIGHT_DELAY мс, проводим AUTO_LIGHT_COUNT замеров, для которых вычисляем среднее арифметическое, которое мы используем при изменении освещенности:

    убрать
    // AUTO_LIGHT
    #define AUTO_LIGHT_DELAY 1000 // 10 секунд цикл поверки датчика освещения
    добавить вместо
    PHP код:
    // AUTO_LIGHT 
    #define AUTO_LIGHT_DELAY 500 // цикл опроса датчика освещения
    #define AUTO_LIGHT_COUNT 10  // количество опросов датчика перед усреднением
    int al_count=0;              // счетчик опросов
    int al_acc=0;                // аккумулятор 

    после
    byte light = analogRead(LIGHT_SENS)>>2; // /4 // интенсивность
    добавить

    PHP код:
     //усреднение
     
    if (al_count++<AUTO_LIGHT_COUNT){
       
    al_acc+=light;                
       
    light=aino.light;              // используем как флаг "необновления"
     
    } else {
       
    light=al_acc/AUTO_LIGHT_COUNT;
       
    al_count=0// можно поставить >0 для "взять первые n замеров по усредненным данным"
       
    al_acc=0//для al_count>0 "0" заменить  на "al_count*light";
     


Страница 1 из 2 12 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •