На основе микроконтроллера 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