Часы на ИН-16 ATmega8 (Arduino IDE)

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

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

Войти с помощью: