На основе микроконтроллера ATmega8 используя среду программирования Arduino ШВУ можно собрать простые часы на газоразрядных индикаторах типа ИН-16 (ИН-14, ИН-18 и др.). ИН-16 представляет собой индикатор тлеющего разряда имеющий десять катодов выполненных в виде цифр и два катода для запятых. Ток индикации 2 мА, напряжение возникновения тлеющего разряда не более 170 В, яркость свечения 150 кд/м².
Назначение выводов:
- 1 — анод
- 2 — цифра 1
- 3 — цифра 7
- 4 — цифра 3
- 5 — знак «запятая»
- 6 — цифра 4
- 7 — цифра 5
- 8 — цифра 6
- 9 — цифра 2
- 10 — знак «запятая»
- 11 — цифра 8
- 12 — цифра 9
- 13 — цифра 0
Управление цифрами газоразрядных индикаторов осуществляется при помощи высоковольтного двоично-десятичного дешифратора К155ИД1 (динамическая индикация), управление анодами осуществляется при помощи высоковольтных транзисторных оптронов (TLP627) со схемой Дарлингтона на выходе. Плата Arduino коммутирует управление газоразрядных индикаторов и управляет работой высоковольтного DC-DC преобразователя. В схеме используются часы реального времени DS3231 (DS1307).
Как добавить микроконтроллер Atmega8 в среду программирования Arduino IDE и прошивать микроконтроллер можно узнать из статьи http://rcl-radio.ru/?p=82486
#define ADDR_DS3231 0b1101000 #define CPU_F 12000000 // Clock Speed #define SCL_F 100000 // // I2C Speed unsigned long times_sec,millis_time; int i,segm,times,hh,mm; byte a[4],an,sec,min,hour,set; void setup() { TWBR = (((CPU_F)/(SCL_F)-16 )/2) ; TWSR = 0; DDRB &=~(1 << PB0);DDRD &=~(1<<PD6)|(1<<PD7); DDRB |= (1 << PB1);// pin 15 output pwm DDRB |= (1 << PB2);// pin 16 output second in-3 DDRC |= (1 << PC0)|(1 << PC1)|(1 << PC2)|(1 << PC3);// H0-H3 ANOD DDRD |= (1 << PD0)|(1 << PD1)|(1 << PD2)|(1 << PD3);// 1 2 4 8 K155ID1 PORTB |= (1 << PB0);PORTD |= (1 << PD6)|(1 << PD7); // F=12000000/512/1/1=23437.5 Hz TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1A |= (1<<COM1A1); TCCR1B |= (1<<WGM12); TCCR1A |= (1<<WGM11); TCCR1B |= (1 << CS10); ICR1 = 511; OCR1A = 505; // Ureg_180V // (12000000/((233+1)x256))=200.32051282051 Hz OCR2 = 233; TCCR2 |= (1 << WGM21); TCCR2 |= (1 << CS22) | (1 << CS21); TIMSK |= (1 << OCIE2); // set time // set_time(21,1,12,26,8,9,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59 } void loop(){ /// read time sec = (i2c_read_1bit(ADDR_DS3231,0) & 0x0F) + (((i2c_read_1bit(ADDR_DS3231,0) & 0x70) >> 4) * 10); min = (i2c_read_1bit(ADDR_DS3231,1) & 0x0F) + (((i2c_read_1bit(ADDR_DS3231,1) & 0x70) >> 4) * 10); hour = ((i2c_read_1bit(ADDR_DS3231,2) & 0x0F) + ((i2c_read_1bit(ADDR_DS3231,2) & 0x70) >> 4) * 10); // temper = (i2c_read_1bit(ADDR_DS3231,0x11)*100 + ((i2c_read_1bit(ADDR_DS3231,0x12) & 0b11000000) >> 6)*25) ; /// set time hh=hour;mm=min; if(((PINB >> PB0) & 1) == 0){set++;if(set>2){set=0;}_delay_ms(200);} if(set==1&&((PIND >> PD6)&1)==0){hh++;if(hh>23){hh=23;}set_time(21,1,12,26,hh,mm,0);_delay_ms(100);} if(set==1&&((PIND >> PD7)&1)==0){hh--;if(hh<0){hh=0;}set_time(21,1,12,26,hh,mm,0);_delay_ms(100);} if(set==2&&((PIND >> PD6)&1)==0){mm++;if(mm>59){mm=59;}set_time(21,1,12,26,hh,mm,0);_delay_ms(100);} if(set==2&&((PIND >> PD7)&1)==0){mm--;if(mm<0){mm=0;}set_time(21,1,12,26,hh,mm,0);_delay_ms(100);} /// output sec in-3 if(millis_time-times_sec<100){PORTB |= (1 << PB2);} if(millis_time-times_sec>=100){PORTB &=~(1 << PB2);} if(millis_time-times_sec>200){times_sec=millis_time;} times = hour*100+min; if(min == 30 && sec < 10 && set == 0){ switch(sec){ case 0: times=0;break; case 1: times=1111;break; case 2: times=2222;break; case 3: times=3333;break; case 4: times=4444;break; case 5: times=5555;break; case 6: times=6666;break; case 7: times=7777;break; case 8: times=8888;break; case 9: times=9999;break; } } a[0]=times/1000%10; a[1]=times/100%10; a[2]=times/10%10; a[3]=times%10; //_delay_ms(50); } void segment(){ switch(segm){ case 0: PORTD &= ~(1 << PD3);PORTD &=~ (1 << PD2);PORTD &= ~(1 << PD1);PORTD &= ~(1 << PD0);break; // DEC 0 = 0b0000 case 1: PORTD &= ~(1 << PD3);PORTD &=~ (1 << PD2);PORTD &= ~(1 << PD1);PORTD |=(1 << PD0); break; // DEC 1 = 0b0001 case 2: PORTD &= ~(1 << PD3);PORTD &=~ (1 << PD2);PORTD |= (1 << PD1);PORTD &= ~(1 << PD0);break; // DEC 2 = 0b0010 case 3: PORTD &= ~(1 << PD3);PORTD &=~ (1 << PD2);PORTD |= (1 << PD1);PORTD |= (1 << PD0);break; // DEC 3 = 0b0011 case 4: PORTD &= ~(1 << PD3);PORTD |= (1 << PD2);PORTD &= ~(1 << PD1);PORTD &= ~(1 << PD0);break; // DEC 4 = 0b0100 case 5: PORTD &= ~(1 << PD3);PORTD |= (1 << PD2);PORTD &= ~(1 << PD1);PORTD |= (1 << PD0);break; // DEC 5 = 0b0101 case 6: PORTD &= ~(1 << PD3);PORTD |= (1 << PD2);PORTD |= (1 << PD1);PORTD &= ~(1 << PD0);break; // DEC 6 = 0b0110 case 7: PORTD &= ~(1 << PD3);PORTD |= (1 << PD2);PORTD |= (1 << PD1);PORTD |= (1 << PD0);break; // DEC 7 = 0b0111 case 8: PORTD |= (1 << PD3);PORTD &=~ (1 << PD2);PORTD &= ~(1 << PD1);PORTD &= ~(1 << PD0);break; // DEC 8 = 0b1000 case 9: PORTD |= (1 << PD3);PORTD &=~ (1 << PD2);PORTD &= ~(1 << PD1);PORTD |= (1 << PD0);break; // DEC 9 = 0b1001 }} void anod(){ switch(an){ case 0: PORTC |= (1 << PC0);PORTC &= ~(1 << PC1);PORTC &= ~(1 << PC2);PORTC &= ~(1 << PC3);break; case 1: PORTC &= ~(1 << PC0);PORTC |= (1 << PC1);PORTC &= ~(1 << PC2);PORTC &= ~(1 << PC3);break; case 2: PORTC &= ~(1 << PC0);PORTC &= ~(1 << PC1);PORTC |= (1 << PC2);PORTC &= ~(1 << PC3);break; case 3: PORTC &= ~(1 << PC0);PORTC &= ~(1 << PC1);PORTC &= ~(1 << PC2);PORTC |= (1 << PC3);break; }} void cl(){PORTC &= ~(1 << PC0);PORTC &= ~(1 << PC1);PORTC &= ~(1 << PC2);PORTC &= ~(1 << PC3);} ISR(TIMER2_COMP_vect){ switch(i){ case 0: segm=a[0]; an=0; cl(); if(set==2){_delay_ms(5);}_delay_ms(1); segment();anod();break; case 1: segm=a[1]; an=1; cl(); if(set==2){_delay_ms(5);}_delay_ms(1); segment();anod();break; case 2: segm=a[2]; an=2; cl(); if(set==1){_delay_ms(5);}_delay_ms(1); segment();anod();break; case 3: segm=a[3]; an=3; cl(); if(set==1){_delay_ms(5);}_delay_ms(1); segment();anod();break; } i++;if(i>3){i=0;} millis_time++; } int i2c_read_i2c_2bit(byte i2c_addr, byte i2c_reg){ TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // START while (!(TWCR & (1<<TWINT))); TWDR = i2c_addr << 1; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWDR = i2c_reg; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // START while (!(TWCR & (1<<TWINT))); TWDR = (i2c_addr << 1) | 1; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA); while(~TWCR&(1<<TWINT)); int i2c_data0 = TWDR; TWCR = (1<<TWINT) | (1<<TWEN); while(~TWCR&(1<<TWINT)); int i2c_data1 = TWDR; TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // СТОП int i2c_data = (i2c_data0<<8)+i2c_data1; return i2c_data; } int i2c_read_1bit(byte i2c_addr, byte i2c_reg){ TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // START while (!(TWCR & (1<<TWINT))); TWDR = i2c_addr << 1; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWDR = i2c_reg; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // START while (!(TWCR & (1<<TWINT))); TWDR = (i2c_addr << 1) | 1; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); while(~TWCR&(1<<TWINT)); byte i2c_data = TWDR; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // СТОП return i2c_data; } void i2c_write(byte i2c_addr, byte i2c_reg, byte i2c_dat){ TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // START while (!(TWCR & (1<<TWINT))); TWDR = i2c_addr << 1; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWDR = i2c_reg; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWDR = i2c_dat; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // СТОП } void i2c_write_1bit(byte i2c_addr, byte i2c_reg){ TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN); // START while (!(TWCR & (1<<TWINT))); TWDR = i2c_addr << 1; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWDR = i2c_reg; TWCR = (1<<TWINT) | (1<<TWEN); while (!(TWCR & (1<<TWINT))); TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); // СТОП } void set_time(byte years, byte days, byte monts, byte datas, byte hours ,byte minute, byte second){ if(second < 255){i2c_write(ADDR_DS3231,0x00,(second/10<<4)+second%10);} if(minute < 255){i2c_write(ADDR_DS3231,0x01,(minute/10<<4)+minute%10);} if(hours < 255){i2c_write(ADDR_DS3231,0x02,(hours/10<<4)+hours%10);} if(days < 255){i2c_write(ADDR_DS3231,0x03,days);} if(datas < 255){i2c_write(ADDR_DS3231,0x04,(datas/10<<4)+datas%10);} if(monts < 255){i2c_write(ADDR_DS3231,0x05,(monts/10<<4)+monts%10);} if(years < 255){i2c_write(ADDR_DS3231,0x06,(years/10<<4)+years%10);} }
Транзистор IRF740 необходимо установить на небольшой радиатор, дроссель L1 состоит из ферритового сердечника (гантельный сердечник) на который до заполнения намотан провод диаметром 0,27…0,32 мм.
Высоковольтный преобразователь содержит индикатор наличия высокого напряжения на ИН-3 и R7. Для настройки выходного напряжения высоковольтного преобразователя необходимо изменить следующий параметр в скетче:
OCR1A = 255; // 255…505
При увеличении значения регистра OCR1A изменяется скважность ШИМ сигнала, чем выше значение регистра тем выше выходное напряжение преобразователя и тем выше ток потребления преобразователя (до 0,48 А при питании 5 В). OCR1A должен быть не больше 505. Частота ШИМ сигнала 23,5 кГц.
Кнопки SET UP и DW служат для корректировки времени часов реального времени.
В часах имеется функция антиотравления катодов, раз в час, ровно в 30 минут осуществляется перебор всех цифр индикаторов.
При корректировке минут яркость отображения часов снижается.
При корректировке часов яркость отображения минут снижается.
Форум — http://forum.rcl-radio.ru/viewtopic.php?pid=7090#p7090