27 января 2012 г.

Arduino и часовой 7-сегментный дисплей

Сегодня у нас в студии часовой 7-сегментный дисплей с четырьмя цифрами и двоеточием посередине. Чтобы его завести, никаких революций совершать не придется - ведь в прошлый раз мы уже подробненько разобрали динамическую индикацию на тройном дисплее.

Сейчас нам понадобится всего лишь подключить один новый проводок к старой схеме и переключить 4 других. Программку тоже модифицируем совсем немного.


Часовой дисплей 

Часовой дисплей имеет 12 ног, из которых 7 - катоды светящихся сегментов, 4 - аноды разных цифр, и еще один - катод двоеточия.



Хоть на этом устройстве есть точки справа от каждой цифры - зажечь их не удастся, так как их ногу отдали двоеточию. Я не очень расстроился, поскольку все-равно никогда не использовал эти точки. Однако если вы собираете дисплей измерительного прибора, который отображает величины с точкой, будьте внимательны - не покупайте модели с 12 ногами из которых одна предназначена для двоеточия!

Схема расположения ног у дисплея такова:


Она отличается от схемы тройного дисплея только наличием com4 (у тройного там вообще не было ноги) и заменой dp на colon-.

Собираем схему

Она о-о-о-очень похожа на прошлую схему, однако присутствуют следующие изменения:

  1. правый ("анодный") регистр управляет уже не тремя, а четырьмя анодами, поэтому вы видите 4 зеленых провода, подключенных к нему: Q1 -> com1, Q2 -> com2, Q3 -> com3, Q4 -> com4.
  2. раньше выход Q7 левого ("катодного") регистра был подключен к катоду dp, а теперь у дисплея вместо него катод двоеточия и мы включим его сразу на землю, чтобы он двоеточие горело всегда вместе со второй цифрой. Выход Q7 останется болтаться.



Кодим без страха и упрека

Раз уж мы взялись искать отличия нынешнего случая и предыдущего, то продолжим в том же ключе. Для начала пересчитаем катодные байты с учетом четырех цифр:

  1. первая цифра: 11000111 (читаем справа налево) = 0xE3;
  2. вторая цифра: 10100111 = 0xE5;
  3. третья цифра: 10010111 = 0xE9;
  4. четвертая цифра: 10001111 = 0xF1.

Загоняем их в массивчик:


static uint8_t pos[4]= {0xE3,0xE5,0xE9,0xF1};


"Катодные" байты у нас снова остаются без изменения (заметьте, с самого первого момента их расчета).

Вместо прошлых переменных ones, tens и hundreds, хранящих единицы, десятки и сотни числа f соответственно, заведем сейчас secondsOnes, secondsTens, minutesOnes и minutesTens, которые будут хранить единицы и десятки секунд и минут. f как число вообще выпиливаем, оно нам не понадобится. Функция вывода output() чуть-чуть модифицируется и становится вот такой:




void output(){


        digitalWrite(reg, LOW); 
        SPI.transfer(digit[minutesTens]); 
        SPI.transfer(pos[0]);
        digitalWrite(reg, HIGH); 
        delay(3); 
        
        digitalWrite(reg, LOW); 
        SPI.transfer(digit[minutesOnes]); 
        SPI.transfer(pos[1]);
        digitalWrite(reg, HIGH); 
        delay(3); 
        
        digitalWrite(reg, LOW); 
        SPI.transfer(digit[secondsTens]); 
        SPI.transfer(pos[2]);
        digitalWrite(reg, HIGH); 
        delay(3); 
        
        digitalWrite(reg, LOW); 
        SPI.transfer(digit[secondsOnes]); 
        SPI.transfer(pos[3]);
        digitalWrite(reg, HIGH); 
        delay(3); 
}


Осталось написать коротенький алгоритм тикания времени и вперед!



void loop()
{
  timer=millis();
  if (timer-timerPrev>999){
    secondsOnes+=1;
    if (secondsOnes==10){
      secondsOnes=0;
      secondsTens+=1;
    }
    if (secondsTens==6){
      secondsTens=0;
      minutesOnes+=1;
    }
    if (minutesOnes==10){
      minutesOnes=0;
      minutesTens+=1;
    }
    if(minutesTens==6){
      minutesTens=0;
    }
    timerPrev=timer;
  }
  output();
}




Долгожданное видео


Далее по теме Arduino и SPI