ИВ-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);} }