Часы на ИВ-18 (Arduino)

ИВ-18 — индикатор вакуумный люминесцентный многоразрядный для отображения информации в виде цифр, точки и знаков. Оформление — стеклянное. Индикация производится через боковую поверхность баллона. Размер знакоместа 5,4×10,5 мм. Число разрядов девять (9 разряд знак минус и точка). Изображение формируется из светящихся анодов-сегментов. Цвет свечения — зеленый. Масса 30 г.

Основные параметры индикатора ИВ-18:

  • Яркость свечения одного разряда 200-500 кд/м²
  • Угол обзора  ≥ 80°
  • Ток накала 85 ± 10 мА
  • Ток анода-сегмента при напряжении на аноде и сетке в 50 В  ≤ 1,3 мА
  • Ток анодов-сегментов восьми разрядов суммарный  40 … 80 мА
  • Напряжение накала  4,3 … 5,5 В
  • Напряжения анодов и сетки в импульсном режиме  ≤ 70 В

На платформе Arduino с использованием индикатора ИВ-18 можно собрать часы, которые будут отображать текущее время (hh-mm-ss), дату (DD.MM.YYYY) и температуру.

Вакуумный люминесцентный индикатор ИВ-18 имеет выводы рассчитанные для использования только динамической индикации. Для питания часов необходим источник постоянного напряжения 9 В (можно 5 В, но яркость свечения индикатора будет низкой). Для нормальной работы индикатора на катод (нить накала) необходимо подавать напряжение от 4,3 … 5,5 В, которое подается со стабилизатора напряжения 7805. Для питания сеток и анодов напряжение должно быть в пределах от 30 до 50 В, для получения такого напряжения в схеме часов используется преобразователь на NE555. Питание на аноды и сетки подается при помощи 16 транзисторных ключей (BC547). При настройки выходного напряжения преобразователя (R35 30-40 кОм — чем больше сопротивление, тем выше выходное напряжение) нельзя повышать напряжение больше 50 В, это предельное напряжение коллектор-эмиттер для транзистора BC547.

В качестве платы Arduino можно использовать плату Nano (ATmega168, ATmega328), а так же микроконтроллер ATmega8 (с небольшой правкой кода и схемы подключения). В схеме так же используется модуль часов реального времени DS3231. Время часов можно установить двумя способами: установка времени по времени компиляции и кнопками.

Установка времени по времени компиляции:

раскоментируйте строчку, установите нужно время и загрузите скетч

set_time(21,5,4,29,9,57,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59

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

Установка (коррекция) времени кнопками:

Установить текущее время можно при помощи кнопок SET и UP. Кнопка SET позволяет перекачать параметр времени (часы, минуты, секунды, дата, месяц и год), кнопка UP меняет параметр времени (только на увеличение), а режиме настройки секунд обнуляет их. В режиме коррекции времени выбранный параметр времени мигает.

Информация об температуре берется из часов реального времени DS3231.

Время

Дата

Температура

#define SDA PC4 
#define SCL PC5 
 
int i, a[8], segm, an,dp=0b10000000,zz,yy,sett,mig;
long times;
 
void setup() {
  DDRD = 0B11111111;
  DDRB = 0B00111111;
  DDRC = 0B00000011;
  PORTC |= (1 << 2) | (1 << 3);
  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  OCR1A = 100;
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS11) | (1 << CS10); 
  TIMSK1 |= (1 << OCIE1A);
  sei();
    // set_time(21,5,4,29,9,57,0);// год 00-99, ДН 1-7 (1=ВС), месяц 1-12, дата 1-31, час 0-23, минуты 0-59, секунды 0-59
}
 
 
void loop() {
  byte sec =  (ds_read(0) & 0x0F) + (((ds_read(0) & 0x70) >> 4) * 10);
  byte min =  (ds_read(1) & 0x0F) + (((ds_read(1) & 0x70) >> 4) * 10);
  byte hour = ((ds_read(2) & 0x0F) + ((ds_read(2) & 0x70) >> 4) * 10);
  byte day =  (ds_read(3) & 0x0F);
  byte datat = ((ds_read(4) & 0x0F) + ((ds_read(4) & 0x70) >> 4) * 10);
  byte mont = ((ds_read(5) & 0x0F) + ((ds_read(5) & 0x70) >> 4) * 10);
  byte year = ((ds_read(6) & 0x0F) + ((ds_read(6) & 0x70) >> 4) * 10);
  int temper = (ds_read(0x11)*100 + ((ds_read(0x12) & 0b11000000) >> 6)*25) ;
 
  if(((PINC >> 2) & 1) == 0){sett++;if(sett>6){sett=0;}}
  if(((PINC >> 3) & 1) == 0 && sett == 1){hour++;if(hour>23){hour=0;}set_time(255,255,255,255,hour,255,255);}
  if(((PINC >> 3) & 1) == 0 && sett == 2){min++;if(min>59){min=0;}set_time(255,255,255,255,255,min,255);}
  if(((PINC >> 3) & 1) == 0 && sett == 3){sec=0;set_time(255,255,255,255,255,255,sec);}
  if(((PINC >> 3) & 1) == 0 && sett == 4){datat++;if(datat>31){datat=1;}set_time(255,255,255,datat,255,255,255);}
  if(((PINC >> 3) & 1) == 0 && sett == 5){mont++;if(mont>12){mont=1;}set_time(255,255,mont,255,255,255,255);}
  if(((PINC >> 3) & 1) == 0 && sett == 6){year++;if(year>50){year=21;}set_time(year,255,255,255,255,255,255);}
 
 
  if(sec>=30&&sec<35&&sett==0||sett>3){
  zz=1;yy=0;
  if(sett==4&&mig==2){a[0]=10;}else{a[0] = datat / 10;}
  if(sett==4&&mig==2){a[1]=10;}else{a[1] = datat % 10;}
  if(sett==5&&mig==2){a[2]=10;}else{a[2] = mont / 10;}
  if(sett==5&&mig==2){a[3]=10;}else{a[3] = mont % 10;}
  if(sett==6&&mig==2){a[4]=10;}else{a[4] = 2;}
  if(sett==6&&mig==2){a[5]=10;}else{a[5] = 0;}
  if(sett==6&&mig==2){a[6]=10;}else{a[6] = year / 10;}
  if(sett==6&&mig==2){a[7]=10;}else{a[7] = year % 10;}
  }
  else if(sec>=35&&sec<40&&sett==0){
  zz=0;yy=1;
  a[0] = 10;
  a[1] = 10;
  a[2] = temper / 1000;
  a[3] = temper / 100 % 10;
  a[4] = temper / 10 % 10;
  a[5] = 12;
  a[6] = 13;
  a[7] = 10;
  }  
  else{
  zz=0;yy=0;  
  if(sett==1&&mig==2){a[0]=10;}else{a[0] = hour / 10;}
  if(sett==1&&mig==2){a[1]=10;}else{a[1] = hour % 10;}
  a[2] = 11;
  if(sett==2&&mig==2){a[3]=10;}else{a[3] = min / 10;}
  if(sett==2&&mig==2){a[4]=10;}else{a[4] = min % 10;}
  a[5] = 11;
  if(sett==3&&mig==2){a[6]=10;}else{a[6] = sec / 10;}
  if(sett==3&&mig==2){a[7]=10;}else{a[7] = sec % 10;}
  }
  delay(200);
  mig++;
  if(mig>2){mig=0;}
}// loop
 
 
ISR(TIMER1_COMPA_vect) {
  switch (i) {
    case 0:  dp=0b10000000;segm = a[0]; an = 0; anod(); segment(); break;
    case 1:  if(zz==1){dp=0;}else{dp=0b10000000;}segm = a[1]; an = 1; anod(); segment(); break;
    case 2:  dp=0b10000000;segm = a[2]; an = 2; anod(); segment(); break;
    case 3:  if(zz==1||yy==1){dp=0;}else{dp=0b10000000;}segm = a[3]; an = 3; anod(); segment(); break;
    case 4:  dp=0b10000000;segm = a[4]; an = 4; anod(); segment(); break;
    case 5:  dp=0b10000000;segm = a[5]; an = 5; anod(); segment(); break;
    case 6:  dp=0b10000000;segm = a[6]; an = 6; anod(); segment(); break;
    case 7:  dp=0b10000000;segm = a[7]; an = 7; anod(); segment(); break;
  } i++; if (i > 7) {
    i = 0;
  }
}
 
void segment() {
  switch (segm) {
    //
    case 0: PORTD = 0B01000000 + dp; break; // 0 0000001
    case 1: PORTD = 0B01111001 + dp; break; // 1 1001111
    case 2: PORTD = 0B00100100 + dp; break; // 2 0010010
    case 3: PORTD = 0B00110000 + dp; break; // 3 0000110
    case 4: PORTD = 0B00011001 + dp; break; // 4 1001100
    case 5: PORTD = 0B00010010 + dp; break; // 5 0100100
    case 6: PORTD = 0B00000010 + dp; break; // 6 0100000
    case 7: PORTD = 0B01111000 + dp; break; // 7 0001111
    case 8: PORTD = 0B00000000 + dp; break; // 8 0000000
    case 9: PORTD = 0B00010000 + dp; break; // 9 0000100
    case 10:PORTD = 0B01111111 + dp; break; // ПУСТО
    case 11:PORTD = 0B00111111 + dp; break; // -
    case 12:PORTD = 0B00011100 + dp; break; // ГРАДУС
    case 13:PORTD = 0B01000110 + dp; break; // С
 
  }
}
void anod() {
  switch (an) {
    case 0: PORTC &= ~(1 << 1); PORTC |= (1 << 0); PORTB |= (1 << 5); PORTB |= (1 << 4); PORTB |= (1 << 3); PORTB |= (1 << 2); PORTB |= (1 << 1); PORTB |= (1 << 0); break;
    case 1: PORTC |= (1 << 1); PORTC &= ~(1 << 0); PORTB |= (1 << 5); PORTB |= (1 << 4); PORTB |= (1 << 3); PORTB |= (1 << 2); PORTB |= (1 << 1); PORTB |= (1 << 0); break;
    case 2: PORTC |= (1 << 1); PORTC |= (1 << 0); PORTB &= ~(1 << 5); PORTB |= (1 << 4); PORTB |= (1 << 3); PORTB |= (1 << 2); PORTB |= (1 << 1); PORTB |= (1 << 0); break;
    case 3: PORTC |= (1 << 1); PORTC |= (1 << 0); PORTB |= (1 << 5); PORTB &= ~(1 << 4); PORTB |= (1 << 3); PORTB |= (1 << 2); PORTB |= (1 << 1); PORTB |= (1 << 0); break;
    case 4: PORTC |= (1 << 1); PORTC |= (1 << 0); PORTB |= (1 << 5); PORTB |= (1 << 4); PORTB &= ~(1 << 3); PORTB |= (1 << 2); PORTB |= (1 << 1); PORTB |= (1 << 0); break;
    case 5: PORTC |= (1 << 1); PORTC |= (1 << 0); PORTB |= (1 << 5); PORTB |= (1 << 4); PORTB |= (1 << 3); PORTB &= ~(1 << 2); PORTB |= (1 << 1); PORTB |= (1 << 0); break;
    case 6: PORTC |= (1 << 1); PORTC |= (1 << 0); PORTB |= (1 << 5); PORTB |= (1 << 4); PORTB |= (1 << 3); PORTB |= (1 << 2); PORTB &= ~(1 << 1); PORTB |= (1 << 0); break;
    case 7: PORTC |= (1 << 1); PORTC |= (1 << 0); PORTB |= (1 << 5); PORTB |= (1 << 4); PORTB |= (1 << 3); PORTB |= (1 << 2); PORTB |= (1 << 1); PORTB &= ~(1 << 0); break;
  }
}
 
bool i2c_read_bit() {
    bool i2c_bit = 1;        
    DDRC &= ~(1 << SDA);            
    delayMicroseconds(10); 
    DDRC &= ~(1 << SCL);                
    if((PINC >> SDA) & 1) i2c_bit=0;                            
    delayMicroseconds(10);  
    DDRC |= (1 << SCL);              
    return i2c_bit;  
}
 
byte i2c_write_byte(byte data){
    for (byte i=0; i<8; i++){i2c_write_bit((data&0x80)==0);data<<=1;}    
    return i2c_read_bit(); 
}
 
byte i2c_read_byte(byte a){
    byte i, data=0;                
    for(i=0; i<8; i++){if (!i2c_read_bit()) data++;if(i!=7) data<<=1;}        
    i2c_write_bit(a);return data;  
}
 
void i2c_write_bit(byte b){
    delayMicroseconds(5);
    if(b){DDRC |= (1 << SDA);}else{DDRC &= ~(1 << SDA);}
    delayMicroseconds(5);
    DDRC &= ~(1 << SCL);       
    delayMicroseconds(10);
    DDRC |= (1 << SCL);
}
 
void i2c_start(){
     delayMicroseconds(10);  
     DDRC &= ~(1 << SDA); DDRC &= ~(1 << SCL); 
     delayMicroseconds(10); 
     DDRC |= (1 << SDA);  PORTC &= ~(1 << SDA);
     delayMicroseconds(10); 
     DDRC |= (1 << SCL);  PORTC &= ~(1 << SCL);   
     delayMicroseconds(10);
}
 
void i2c_stop()  {
     DDRC |= (1 << SDA);            
     delayMicroseconds(10);
     DDRC &= ~(1 << SCL);               
     delayMicroseconds(10); 
     DDRC &= ~(1 << SDA);             
}
 
byte ds_read(byte reg){
     byte data = 0;
     i2c_start();
     i2c_write_byte(0b11010000);
     i2c_write_byte(reg);
     i2c_start(); 
     i2c_write_byte(0b11010001); 
     data = i2c_read_byte(0);
     i2c_stop();
     return data;
  }
 
void ds_write(byte reg, byte data){
     i2c_start();
     i2c_write_byte(0b11010000);
     i2c_write_byte(reg);
     i2c_write_byte(data);
     i2c_stop();
  }  
 
void set_time(byte years, byte days, byte monts, byte datas, byte hours ,byte minute, byte second){
    if(second < 255){ds_write(0x00,(second/10<<4)+second%10);}
    if(minute < 255){ds_write(0x01,(minute/10<<4)+minute%10);} 
    if(hours < 255){ds_write(0x02,(hours/10<<4)+hours%10);}
    if(days < 255){ds_write(0x03,days);}
    if(datas < 255){ds_write(0x04,(datas/10<<4)+datas%10);}
    if(monts < 255){ds_write(0x05,(monts/10<<4)+monts%10);}
    if(years < 255){ds_write(0x06,(years/10<<4)+years%10);}
  }

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=299

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

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