Проект с использованием MCC часть 10

Просмотров: 638


Алгоритм управления освещением от нажатия кнопки.

Обработка удержания кнопки:

  1. Мы должны проверить кнопка в настоящий момент нажата и флаг удержания установлен, если да
  2. Проверить таймер удержания “отработал” – это значит, что кнопка нажата и удерживается, если да
  3. Включить модуль, естественно он включиться на ранее заданной яркости. После чего в зависимости от состояния флага NAP1 начать изменять переменную яркости канал brightness_chn1 на увеличение или на уменьшение. Естественно проверяя её, чтобы она не вылезла за установленные пределы.
  4. После чего необходимо инициализировать таймер timer_delay1 константой SPEEDIZ которая будет задавать скорость изменения яркости.
  5. Это забегая в перед обнуляет переменную regim1 – это у нас указатель выполнения функции от кратковременного нажатия кнопки.

Как это выглядит в программе:

        if(!BOT1 && bot1_retention)// кнопка нажата
        {
            if(!timer_delay1)
            {
                PWM1EN=1;       // включить модуль
                if(NAP1)
                {
                    // увеличиваем яркость
                    brightness_chn1++;
                    if(brightness_chn1>1023)brightness_chn1=1023;
                    PWM1_LoadDutyValue(brightness_chn1); 
                }
                else
                {
                    // уменьшать яркость
                    brightness_chn1--;
                    if(brightness_chn1<0)brightness_chn1=0;
                    PWM1_LoadDutyValue(brightness_chn1);
                }
                timer_delay1=SPEEDIZ;   // инициализировать задержку
                regim1=0;
            }
        }

Надеюсь вопросов не возникнет, по коду, а если возникнут не стесняйтесь пишите в комментах.

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

Теперь остается придумать как будет выполняться функция кратковременного нажатия. например, включение выключение канала. Логика работы предполагается следующая:

  1. Таймер timer_delay1 при первой инициализации предполагается использовать для определения кратковременное нажатие или удержание. В последующем его задача формировать задержку в изменении параметра переменной яркости и естественно наблюдаемой яркости нами самого канала. Если нажатие кратковременной менее 400 мс, то мы проверим, это при помощи, следующей конструкции else if(!timer_delay1 && bot1_retention) котороя будет следовать после первого блока if(!BOT1 && bot1_retention)// кнопка нажата. Т.е. если кнопка не нажата, таймер “отработал” и флаг bot1_retention установлен.
  2. Выбрать при помощи  оператора switch по значению regim1 какой включить режим работы канала
  3. Если regim1 = 0 – ничего не делать.
  4. Если regim1 = 1 – перевести на противоположное значение бита PWM1EN = !PWM1EN; тем самы включить или выключить канал.
  5. Если regim1 = 2 – запустить таймер для автоотключения.

По такой логике можно придумать по количеству кратковременных нажатий клавиш множество режимов работы канала. Для начала реализуем первый: включить – выключить. Это будет выглядеть так:

        else if(!timer_delay1 && bot1_retention)// таймер выполнения команды == 0, флаг 
        {
            // определение команды
            switch (regim1)
            {
                case 1: // включить выключить
                    PWM1EN = !PWM1EN;       // включить выключить канал 1
                break;    
                case 2: // отключение по таймеру

                break;  
                case 3:

                break;  
                case 4:

                break;  
            }
            bot1_retention=0; // сбросить флаг нажатия кноки  
            regim1=0;
        }

конструкцию

                case 3:

                break;  
                case 4:

                break;

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


Значок

Проект с использованием MCC часть 10 865.35 KB 50 downloads

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

Теперь придумаем функцию автоотключения. Для этого для начала добавим флаги автоотключения, назовем их AUTO_OFF1 и AUTO_OFF2. Их функция если они будут установлены запустить таймер автоотключения и отсчитать заданные 30 секунд и отключить канал.

Значит еще нудны две переменные таймеров (для каждого канала по одному), назовем их timer_OFF1 и timer_OFF2. Область из основной работы это таймер 0, поэтому мы их опишем соответственно в файлах таймера и разрешим из использовать в основной программе описав их как внешние (заодно и добавим переменную таймера для второго канала который пока еще не используем.

В заголовочном файле это будет выглядеть так tmr0.h

extern volatile uint16_t timer_delay1, timer_delay2;    // таймер задержки
extern volatile bool AUTO_OFF1, AUTO_OFF2;              // флаги автоотключения каналов 
extern volatile uint16_t timer_OFF1, timer_OFF2;        // таймер задержки

в рабочем tmr0.c, так:

volatile uint16_t timer_delay1, timer_delay2;   // таймер задержки
volatile bool AUTO_OFF1, AUTO_OFF2;             // флаги автоотключения каналов 
volatile uint16_t timer_OFF1, timer_OFF2;       // таймер задержки

Саму обработку таймера добавим в функцию TMR0_CallBack которая вызывается с периодом 0,5 секунды:

В основном цикле изменим часть отвечающим за режим работы канала:

        else if(!timer_delay1 && bot1_retention)// таймер выполнения команды == 0, флаг 
        {
            // определение команды
            switch (regim1)
            {
                case 1: // включить выключить
                    PWM1EN = !PWM1EN;       // включить выключить канал 1
                break;    
                case 2: // отключение по таймеру
                        AUTO_OFF1=1; // установить флаг автоотключение канала 1
                        timer_OFF1=TIMEOFF*2; // *2 такак отсчет идет в два раза быстерее, по 0,5 секунды
                break;  
                case 3:

                break;  
                case 4:

                break;  
            }
            bot1_retention=0; // сбросить флаг нажатия кноки  
            regim1=0;
        }

При кратковременном нажатии на кнопку установиться флаг автоотключения AUTO_OFF1=1; и будет выполнена инициализация таймера  timer_OFF1=TIMEOFF*2;

После этого в прерываниях таймера 0, будут активированы  строки:

    if(timer_OFF1)timer_OFF1--;     // уменьшить таймер на 1 если он больше нуля.
    
    if(AUTO_OFF1 && !timer_OFF1)
    {
        AUTO_OFF1=0;    // сбросить флаг функция выполнена
        PWM1EN = 0;     // отключить канал 1
    }

Так как переменная timer_OFF1 будет больше нуля, начнется её уменьшение с частотой 0,5 герца. И начнет условие if(AUTO_OFF1 && !timer_OFF1) ожидать когда таймер станет равен 0. И при выполнении это чуда флаг  AUTO_OFF1=0; будет сброшен, а канал 1 PWM1EN = 0; отключен.

Скомпилируем проект и проверим его работу.


Теперь добавим аналогичные функции для второго канала:

Для этого еще раз проверим какие необходимо внести изменения:

в файле main.c писание переменной проверим должно быть так:

// константы
#define SPEEDIZ 2   // скорость изменение яркости
#define TIMEOFF 30  // время автоотключения канала

// переменные
bool bot1_retention, bot2_retention; // флаги удержания кнопки
bool NAP1, NAP2;  // направление изменения яркости
int16_t brightness_chn1, brightness_chn2;    // состояние яркости каналов
uint8_t regim1, regim2;     // режимы управления каналами

Обработка прерываний таймера 0:

// обработка прерываний
void TMR0_ISR(void)
{
    static volatile uint16_t CountCallBack = 0;

    // Clear the TMR0 interrupt flag
    INTCONbits.TMR0IF = 0;

    TMR0 = timer0ReloadVal;
//------------------------------------------------------------------------------
    if(timer_delay1>0)timer_delay1--;   // обработка таймера
    if(timer_delay2>0)timer_delay2--;   // обработка таймера
//------------------------------------------------------------------------------
    // callback function - called every 504th pass
    if (++CountCallBack >= TMR0_INTERRUPT_TICKER_FACTOR)
    {
        // ticker function call
        TMR0_CallBack();

        // reset ticker counter
        CountCallBack = 0;
    }

    // add your TMR0 interrupt custom code
}

Обработка таймеров автоотключения:

void TMR0_CallBack(void)
{
    // Add your custom callback code here
//    LD1=!LD1;
//    LD2=!LD2;
    if(timer_OFF1)timer_OFF1--;     // уменьшить таймер на 1 если он больше нуля.
    
    if(AUTO_OFF1 && !timer_OFF1)
    {
        AUTO_OFF1=0;    // сбросить флаг функция выполнена
        PWM1EN = 0;     // отключить канал 1
    }
    
    if(timer_OFF2)timer_OFF2--;     // уменьшить таймер на 1 если он больше нуля.
    
    if(AUTO_OFF2 && !timer_OFF2)
    {
        AUTO_OFF2=0;    // сбросить флаг функция выполнена
        PWM2EN = 0;     // отключить канал 1
    }
    
    if(TMR0_InterruptHandler)
    {
        TMR0_InterruptHandler();
    }
}

В основном цикле добавим аналогичную процедуру обработки нажатия кнопки 2 для управления 2 каналом:

if(bot2_pressure)//было нажатие клавиши
        {
            bot2_pressure=0;    // сбросить флаг нажатия
            
            bot2_retention=1;   // событие нажатия произошло
            if(PWM2EN) // если модуль включен (свет горит)
            {
               NAP2=!NAP2;  // изменить напраление
            }        
            regim2++;           // выбор режима
            timer_delay2=400;   // время задержки нажатия первого нажатия 
        }
        
        if(!BOT2 && bot2_retention)// кнопка нажата
        {
            if(!timer_delay2)
            {
                PWM2EN=1;       // включить модуль
                if(NAP2)
                {
                    // увеличиваем яркость
                    brightness_chn2++;
                    if(brightness_chn2>1023)brightness_chn2=1023;
                    PWM2_LoadDutyValue(brightness_chn2); 
                }
                else
                {
                    // уменьшать яркость
                    brightness_chn2--;
                    if(brightness_chn2<0)brightness_chn2=0;
                    PWM2_LoadDutyValue(brightness_chn2);
                }
                timer_delay2=SPEEDIZ;   // инициализировать задержку
                regim2=0;
            }
        }
        else if(!timer_delay2 && bot2_retention)// таймер выполнения команды == 0, флаг 
        {
            // определение команды
            switch (regim2)
            {
                case 1: // включить выключить
                    PWM2EN = !PWM2EN;       // включить выключить канал 1
                break;    
                case 2: // отключение по таймеру
                        AUTO_OFF2=1; // установить флаг автоотключение канала 1
                        timer_OFF2=TIMEOFF*2; // *2 такак отсчет идет в два раза быстерее, по 0,5 секунды
                break;  
                case 3:

                break;  
                case 4:

                break;  
            }
            bot2_retention=0; // сбросить флаг нажатия кноки  
            regim2=0;
        }

С компилируем проект и проверим работу, протестим все режимы работы и управление каналами.


Итоговый проект двухканального регулятора освещения на светодиодах.

Функции – одно кратковременное нажатие включение выключение канала (соответствующей кнопкой), двух кратковременное нажатие кнопки (когда когда канал включен) отключает его через 30 секунд, это так намазываемый “коридорный режим”, вы уходите и пока закрываете дверь, мам необходимо, чтобы освещение было, а потом выключилось. Долговременное нажатие на кнопку изменяет яркость канала возрастает или уменьшается, т.е. например, нажали держим яркость увеличивается, опусти нажали и удерживаем, яркость теперь уменьшаться (и так по кругу).

Скорость изменения яркости и время отключения можно задать в константах  SPEEDIZ  – скорость изменение яркости и TIMEOFF – время автоотключения канала (с).

Значок

Проект с использованием MCC часть 10 (итог) 879.13 KB 228 downloads

Итоговый проект двухканального регулятора освещения...


Практические добавление к проекту в следующей главе…


Это может быть интересно


  • Проект с использованием MCC часть 15Проект с использованием MCC часть 15
    Просмотров: 1311 EUSART – Универсальный асинхронный приёмопередатчик (УАПП, англ. Universal Asynchronous Receiver-Transmitter, UART) — узел вычислительных устройств, предназначенный для организации связи с другими цифровыми устройствами. … читать на вики. Внесем изменения в нашу схему, …
  • Проект с использованием MCC часть 16Проект с использованием MCC часть 16
    Просмотров: 896 Продолжим изучение EUSART. На этом этапе отработает передачи данных с ПК и получения эха. Для этого в основной цикл программы добавим код if(EUSART_DataReady) // проверим флаг готовности данных …
  • Светодиоды со встроенным драйвером WS2812BСветодиоды со встроенным драйвером WS2812B
    Просмотров: 805 Производитель http://www.world-semi.com Краткое описание продукции фирмы Каталог продукции” catcatcat_ws_19 catcatcat_ws_15 catcatcat_ws_11 catcatcat_ws_07 catcatcat_ws_03 catcatcat_ws_18 catcatcat_ws_14 catcatcat_ws_10 catcatcat_ws_06 catcatcat_ws_02 catcatcat_ws_05 catcatcat_ws_09 catcatcat_ws_13 catcatcat_ws_17 catcatcat_ws_16 catcatcat_ws_12 catcatcat_ws_08 catcatcat_ws_04 catcatcat_ws_01 This jQuery …
  • Стабилизатор тока для светодиодов SN3350Стабилизатор тока для светодиодов SN3350
    Просмотров: 2423 SN3350 ближайший аналог ZXLD1350 Как собрать готовый вариант, читайте во второй части – http://catcatcat.d-lan.dp.ua/stabilizator-toka-na-sn3350-chast-2/ 40V  драйвер светодиодов с внутренним ключом  SN3350 – импульсный понижающий преобразователь, разработанный для того, чтобы эффективно управлять одним или …
  • MPLAB® Code Configurator and EncoderMPLAB® Code Configurator and Encoder
    Просмотров: 1249 Еще раз про энкодер… Для некоторых приложений очень удобно и экономически выгодно, для настройки и управления использовать энкодер. Такие энкодеры имеют строенную тактовую кнопку которую можно применить для выбора …
  • NeoPixel LED и PIC18NeoPixel LED и PIC18
    Просмотров: 1481   Еще раз об управлении светодиодами на драйвере WS2812 и ему подобных. Как известно эти светики управляются по однопроводной шине. Основная особенность, что программно можно описать передачу данных, …
  • MAX7219/21 и 8х8 LED дисплеиMAX7219/21 и 8х8 LED дисплеи
    Просмотров: 793 MAX7219, MAX7221 предназначены для вывода информации на 8 разрядов семисегментного индикатора, но на нем легко организовать вывод на светодиодные индикаторы 8х8. продолжение следует…. Это может быть интересно Метки:MAX7219, MAX7221
  • ch-светомузыка и AK4113ch-светомузыка и AK4113
    Просмотров: 1125 Пришло время вернуться к светомузыке. На сегодня использование аналогового входа стало непрактичным, на сегодня необходимо использовать S/PDIF и Toslink. С этим надо было как то разобрать, что это …
  • OLED RET012864E/REX012864JOLED RET012864E/REX012864J
    Просмотров: 1306 RET012864E/REX012864J ОЛЕД индикатор производитель Raystar-Optronics приобретался в http://www.microchip.ua/ к сожалению никакой информации на сайте поставщика нет. Поэтому решил работу с этой версией индикатора на драйвере SSD1305 предоставить на своем сайте. Так как …
  • Индикатор температурыИндикатор температуры
    Просмотров: 2513 Проект для начинающих, на демо плате BB-2T3D-01. Простой индикатор температуры. Проект никак не задумывался, просто на витрину магазин Ворон нужна была демонстрационная модель на макетной плате, чего нибудь работающего. Остановились на индикаторе …



Поделись этим!

Catcatcat

catcatcat

Development of embedded systems based on Microchip microcontrollers.

Комментарии

Добавить комментарий

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