RGB термометр на микроконтроллере ATtiny2313 и ds18b20
Трехцветные светодиоды хороши тем, что с их помощью можно отобразить любой оттенок цвета. Мне пришла в голову идея, почему не собрать простенький термометр на микроконтроллере например ATtiny13 и отображать температуру в виде оттенков цвета с помощью этого же RGB светодиода.
Проблемы реализации устройства:
Цвет генерируется при помощи ШИМ, оттенок формируется разной интенсивностью свечения трех основных цветов, синего, зеленого и красного. То есть для того, что бы отобразить оттенок необходимо иметь три канала ШИМ.
Для опроса датчика температуры необходимо время, на это время микроконтроллер не будет заниматься генерированием ШИМ и светодиод моргнет. Так как отобразить сразу три цвета с разной интенсивностью при помощи микроконтроллера семейства AVR нельзя. Для отображения разных оттенков при помощи ШИМ используется хитрость, инерционность человеческого глаза.
На данном этапе в коде расположенном ниже реализован термометр, который выдает информацию о температуре на RGB светодиод не используя все возможные оттенки. Для отображения используется всего 3 степени свободы (три режима). Логика следующая: при достижении определенного значения температуры, термометр зажигает соответствующий цвет их трех. Таким образом термометр может отображать только три диапазона температур, которые должны быть заранее заданы.
В данном коде трем цветам светодиода соответствуют следующие температуры:
Синий - 20 градусов,
Зеленый - 30 градусов,
Красный - 40 градусов.
//PB0=DS18b20_data #define F_CPU 7372800UL #include<avr/io.h> #include <util/delay.h> #define TIME 10 #define PORTB_MASK 0x01 unsigned int temperature=0; unsigned char temperature_sign=0; void USART_Init( unsigned int baudrate ); void US_Tr( unsigned char data ); void USART_Init( unsigned int baudrate ) //Функция инициализации USART { UBRRH = (unsigned char) (baudrate>>8); UBRRL = (unsigned char) baudrate; UCSRA = (1<<U2X); //Удвоение скорости UCSRB = ( ( 1 << RXEN ) | ( 1 << TXEN ) ); //Разрешение на прием и н апередачу через USART UCSRC = (1<<USBS) | (3<<UCSZ0); } void US_Tr( unsigned char data ) //Функция отправки данных { while ( !(UCSRA & (1<<UDRE)) ); //Ожидание опустошения буфера приема UDR = data; //Начало передачи данных } void pause (unsigned int a) { unsigned int i; for (i=a;i>0;i--);} unsigned char present_ds18b20(void) { unsigned char res; DDRB|= PORTB_MASK; _delay_loop_2(475); //480ms DDRB&=~PORTB_MASK; _delay_loop_2(65); //70ms if ((PINB&PORTB_MASK) == 0x00) res=1; else res=0; _delay_loop_2(405); // 410ms return res; } void send_ds18b20(unsigned char command) { unsigned char i, data; data=command; for(i=0;i<8;i++) { if ((data&0x01)==0x01) { //???????? ???. 1 DDRB|=PORTB_MASK; _delay_loop_2(2); //6 DDRB&=~PORTB_MASK; _delay_loop_2(60); //64 } else { DDRB|=PORTB_MASK; _delay_loop_2(55); //60 DDRB&=~PORTB_MASK; _delay_loop_2(2); //10 } data=data>>1; } } void receive_ds18b20(void) { unsigned char i; temperature_sign=0; for(i=0;i<16;i++) { DDRB|=PORTB_MASK; _delay_loop_2(2); DDRB&=~PORTB_MASK; _delay_loop_1(6); if ((PINB & PORTB_MASK)==0x00) temperature&=~_BV(i); else {temperature|=_BV(i); if (i==12) temperature_sign=1; } _delay_loop_2(50); } } void show_temp (void) { unsigned int temp_des=0, temp_int=0; unsigned char h,d,o; US_Tr('T'); US_Tr('e'); US_Tr('m'); US_Tr('p'); US_Tr('='); //Вывод слова "Temp=" if (temperature_sign==1) {temperature=65536-temperature; US_Tr('-');} else US_Tr(' '); temp_des=temperature&0b00001111; temp_int=temperature>>4; h=temp_int / 100; d=(temp_int-h*100)/10; o=temp_int-h*100-d*10; if ((temp_int-h*100)/10==2) PORTB=0xFC; else if ((temp_int-h*100)/10==3) PORTB=0xFA; else if ((temp_int-h*100)/10==4) PORTB=0xF6; if (h!=0) US_Tr(0x30+h); //сотни if (d!=0) US_Tr(0x30+d); //десятки US_Tr(0x30+o); //единицы US_Tr('.'); if(temp_des==0) US_Tr(0x30); else if(temp_des==1 || temp_des==2) US_Tr(0x31); else if(temp_des==3) US_Tr(0x32); else if(temp_des==4 || temp_des==5) US_Tr(0x33); else if(temp_des==6 || temp_des==7) US_Tr(0x34); else if(temp_des==8) US_Tr(0x35); else if(temp_des==9 || temp_des==10) US_Tr(0x36); else if(temp_des==11) US_Tr(0x37); else if(temp_des==12 || temp_des==13)US_Tr(0x38); else if(temp_des==14 || temp_des==15)US_Tr(0x39); // US_Tr(0xdf); US_Tr('C'); US_Tr(0x0d);//переход в начало строки US_Tr(0x0a);//переход на новую строку } void no_sensor (void) { unsigned char i; US_Tr ('N'); US_Tr ('o'); US_Tr (' '); US_Tr ('s'); US_Tr ('e'); US_Tr ('n'); US_Tr ('s'); US_Tr ('o'); US_Tr ('r'); US_Tr(0x0d);//переход в начало строки US_Tr(0x0a);//переход на новую строку for (i=0;i<9;i++) pause (32000); } int main(void) { unsigned char i; PORTB&=~PORTB_MASK; DDRB&=~PORTB_MASK; DDRB = 0b1111110; USART_Init( 47 ); //Скорость соединения 19200 бит/с 7,3728 MHz while (1) { if (present_ds18b20()==1) {send_ds18b20(0xcc); send_ds18b20(0x44); for (i=0;i<6;i++) pause (32000); if (present_ds18b20()==0) no_sensor(); else {send_ds18b20(0xcc); send_ds18b20(0xbe); receive_ds18b20(); show_temp();} } else no_sensor(); } return 0; };
Если получится реализовать время опроса датчика минимальным, то есть таким за которое глаз не заметит выключения свечения светодиода, тогда и получится реализовать RGB термометр именно таким, как он был описан в начале заметки.
Датчик температуры я использовал ds1b20, который подключен к порту B0 микроконтроллера.
- блог extremist'а
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии


Недавние комментарии
2 дней 17 часов назад
2 дней 1 час назад
3 дней 4 часов назад
3 дней 5 часов назад
3 дней 7 часов назад
3 дней 10 часов назад
3 дней 11 часов назад
5 дней 5 часов назад
1 неделя 1 day назад
1 неделя 2 дней назад