INT 21h

Hi, I am Vladimir Smagin, SysAdmin and Kaptain. Telegram Email / GIT / RSS / GPG

Программное управление освещением в комнате

№ 3704 В разделах: Electronics Programming от September 17th, 2011,
В подшивках:

Железная часть

Сейчас запрограммировано 3 режима: режим простоя, режим демонстрации (оба диодика медленно разгораются и тухнут) и режим ручного управления.

Клевенкий индикатор от Futaba. Показывает отладочную информацию: оба канала PWM, свободное место в буфере (при ошибке передачи сбрасывается, чтобы передача могла начаться заново), 4 управляющих байта (команда и 3 параметра).

Моя отладочная плата, на которой собрано все устройство. Подключается к компьютеру через UART-USB преобразователь.

Управляющая программа. Подключается к UART-USB адаптеру и посылает команды в устройство. Сейчас устройство приняло команду ручного режима, зеленый диод светит с яркостью 10 (0A на дисплее). Яркость определяется в диапазоне от 0 до 255.

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

Программное обеспечение

Программа управления первой версии. Написана на Delphi на скорую руку.

Вторая версия программы. Как видите, умеет гораздо больше функционала и написана на Qt и C++.

А теперь как устроена программа микроконтроллера

Команды с компьютера отсылаются по UART в виде 4 байтов – управляющий код и 3 параметра. Я не использовал свою UART библиотеку и сделал прием команды с помощью прерывания, буфера и счетчика его заполненности. Прерывание сработает на приём 1 символа и уменьшит счетчик на единицу. По достижении счетчика нуля сработает условие, которое запишет байты из буффера в специальные переменные, с которыми будет идти дальнейшая работа. Использовать этот буффер напрямую я не рекомендую, т.к. прием данных идет медленно (в моем случае 9600 бод), а программа работает аж на 8 МГц. Получится так, что команда пришла одна, а параметры еще прийти не успели и что-то сработает не так как должно 🙂

volatile char uart_buffer[4]; 
volatile uint8_t uart_buffer_flag = 4; 

ISR(USART_RX_vect) {
    unsigned char data = UDR;
    uart_buffer_flag--;
    uart_buffer[uart_buffer_flag] = data; 
}

Следует обратить внимание на то, что при инициализации UART вы должны включить прерывание на приём (RXCIE). Это очень важно, иначе код работать не будет.

UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);

Иногда у вас в линии может появиться ошибка и придет не 4 символа, а 3. А может даже 5. Для таких целей создан таймер, который сбросит счетчик буффера. Это немного неправильно, т.к. делает невозможным использование PWM1 и позже таймер будет заменен на обычный счетчик в теле основной программы, который сбросится при приёме очередного символа.

ISR(TIMER1_OVF_vect)
{
    //command sequence timeout
    uart_buffer_flag = 4;
    TCNT1 = 0x00FF;
}

void Init_Timer()
{
    TCCR1B = (1 << CS12);
    TCNT1 = 0x00FF;
    TIMSK = (1 << TOIE1);
}

Инициализация аппаратных ШИМов для управления 2 лентами (PWM0 и PWM2). Скоро будет еще добавлено 2 ленты, где будет использован 16 битный PWM1. Полезно прочитать статью , где хорошо описана реализация.

void Init_MOSFET1()             // OC0
{
    TCCR0 = (1 << WGM01) | (1 << WGM00) | (1 << CS00);  // setup PMW, no prescaler
    OCR0 = pwm1;
    DDRB |= (1 << DDB3);
}

void Init_MOSFET2()             // OC2
{
    TCCR2 = (1 << WGM21) | (1 << WGM20) | (1 << CS20);  // setup PMW, no prescaler
    OCR2 = pwm2;
    DDRD |= (1 << DDD7);
}

Разбор полученных команд я сделал в теле основной программы с помощью switch … case.

   while (1) {
        // if uart buffer full
        if (uart_buffer_flag == 0) {
            uart_command = uart_buffer[3]; //command
            uart_param1 = uart_buffer[2]; //param 1
            uart_param2 = uart_buffer[1]; //param 2
            uart_param3 = uart_buffer[0]; //param 3
            uart_buffer_flag = 4;       // make buffer empty
        }

        switch (uart_command) {
            case 0x30:
		// IDLE MODE
                //fprintf_P(&display, PSTR("\rIdle mode       \n                "));
                break;
            case 0x31: //31:00:00:XX - delay
		// DEMO MODE
		_delay_ms(uart_param3);
		sei();
		...

А теперь о самом главном. 4 шимов на mega88 мне конечно же не хватит. Нужны более маленькие МК для управления 10 лампами. Я хочу использовать attiny, отдавая им команды и принимая с них данные об освещенности через шину TWI (она же I2C). Когда я дополню свою TWI библиотеку функциями для slave устройств (), все микроконтроллеры смогут без проблем общаться и главный МК будет автоматически принимать решения на основе имеющихся данных от своих “деток”.

Я планирую сделать настенную панель управления, на которой будет всего 1 круговой шифратор, 1 кнопка и дисплей. Шифратором будет выставляться максимальный уровень освещенности. Кнопка будет служить переключателем между умным режимом и простой регулировкой яркости ламп. BlueTooth модуль (будет установлен в будущем) как и настольный компьютер работает с МК по UART и позволит сделать приложение для управления светом с помощью обычного сотового телефона.

Для управления 10 лампами и чтения данных с датчиков заказал 2 микросхемы ATtiny461-20PU. На них целых 6 ШИМов, TWI и куча ADC. Они будут располагаться в центре комнаты, чтобы расстояние между чипами не сильно влияло на качество передачи данных через шину TWI.

3 комментариев »

3 responses to “Программное управление освещением в комнате”

  1. Alexus100 says:

    прикольно

  2. ZiB says:

    Молодец, не стоишь на месте
    Пиками не хочешь побаловаться, а то я себе свежий проггер собрал, старый жалко выбрасывать 🙂
    http://ziblog.ru/2011/04/13/programmator-dlya-pic/

  3. 21h says:

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

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

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Облачная платформа
Яндекс.Метрика

Fortune cookie: Today's spam: more girls waiting!