Бинарные часы

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Захотелось сделать бинарные часы. Нарыл схему. Собрал на макете но есть проблема. Необходимые лампочки загораются НО некоторые которые не должны гореть горят очень тускло. Никак не могу от этого избавиться. В чём может быть эта проблема?

 


int LED1[] = {
  0,0,1,0,0,1,1,1,1,1
};
int LED2[] = {
  0,0,0,1,0,1,1,1,1,1
};
int LED3[] = {
  1,0,0,0,1,0,1,1,1,1
};
int LED4[] = {
  0,1,0,0,1,0,1,1,1,1
};
int LED5[] = {
  0,0,1,0,1,0,1,1,1,1
};
int LED6[] = {
  0,0,0,1,1,0,1,1,1,1
};
int LED7[] = {
  0,1,0,0,1,1,0,1,1,1
};
int LED8[] = {
  0,0,1,0,1,1,0,1,1,1
};
int LED9[] = {
  0,0,0,1,1,1,0,1,1,1
};
int LED10[] = {
  1,0,0,0,1,1,1,0,1,1
};
int LED11[] = {
  0,1,0,0,1,1,1,0,1,1
};
int LED12[] = {
  0,0,1,0,1,1,1,0,1,1
};
int LED13[] = {
  0,0,0,1,1,1,1,0,1,1
};
int LED14[] = {
  0,1,0,0,1,1,1,1,0,1
};
int LED15[] = {
  0,0,1,0,1,1,1,1,0,1
};
int LED16[] = {
  0,0,0,1,1,1,1,1,0,1
};
int LED17[] = {
  1,0,0,0,1,1,1,1,1,0
};
int LED18[] = {
  0,1,0,0,1,1,1,1,1,0
};
int LED19[] = {
  0,0,1,0,1,1,1,1,1,0
};
int LED20[] = {
  0,0,0,1,1,1,1,1,1,0
};
int LEDPins[] = {
  12,11,10,9,8,7,6,5,4,3};


void vivod(int LED[])
{
  for(int i=0;i<=9; i++)
  digitalWrite(LEDPins[i], LED[i]);
  delay(1);
}

int second=5, minute=5, hour=2; //start the time on 00:00:00
int munit = 4;
int hunit = 9;
int suc = 5;
void setup() { 
  
  for(int i=0;i<=9; i++)
pinMode(LEDPins[i], OUTPUT);

}

void loop() {


  if(suc == 1 || suc == 3 || suc == 5 || suc == 7 || munit == 9) vivod(LED20);
  if(suc == 2 || suc == 3 || suc == 6 || suc == 7) vivod(LED19);
  if(suc == 4 || suc == 5 || suc == 6 || suc == 7) vivod(LED18);
  if(suc == 8 || suc == 9) vivod(LED17);

  //minutes 
  if(second == 1 || second == 3 || second == 5 || second == 7 || second == 9) vivod(LED16);
  if(second == 2 || second == 3 ) vivod(LED15);
  if(second == 4 || second == 5 ) vivod(LED14);
  
//minutes units
  if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) vivod(LED13);
  if(munit == 2 || munit == 3 || munit == 6 || munit == 7) vivod(LED12);
  if(munit == 4 || munit == 5 || munit == 6 || munit == 7) vivod(LED11);
  if(munit == 8 || munit == 9) vivod(LED10);

  //minutes 
  if(minute == 1 || minute == 3 || minute == 5 || minute == 7 || minute == 9) vivod(LED9);
  if(minute == 2 || minute == 3 ) vivod(LED8);
  if(minute == 4 || minute == 5 ) vivod(LED7);
  

  //hour units
  if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) vivod(LED6);
  if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) vivod(LED5);
  if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) vivod(LED4);
  if(hunit == 8 || hunit == 9) vivod(LED3);

  //hour
  if(hour == 1)  vivod(LED2);
  if(hour == 2)  vivod(LED1);

}









 

Zaliv
Offline
Зарегистрирован: 05.03.2011

 А менять местами яркие и неяркие светодиоды пробовали? Может просто светодиод бракованный или подпаленный? Можно еще попробовать махнуть местами резистры, мало ли?

Adessit
Adessit аватар
Offline
Зарегистрирован: 12.04.2011

Приведите схему подключения светодиодов.

А то светодиодов много, а резисторов мало...

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011
leshak
Offline
Зарегистрирован: 29.09.2011

 Попробуйте в конце функции loop, добавить delay(500); и сообщите перестали-ли гореть "в пол-накала" часть диодов.

Если я не ошибаюсь в своих подозрениях, то должны перестать. Правда часы будут показывать "только час" (минут и секуд не будет), но зато мы будем знать что "на правильном пути".

 

 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

нет не перестали. диоды которые не должны гореть всё равно загораются. Я заметил что проблема только с нижнем рядом диодов.

leshak
Offline
Зарегистрирован: 29.09.2011

 > диоды которые не должны гореть всё равно загораются

А характер загорания изменился? Я не совсем правильно выразился что должно "произойти", перестать должны были именно "тускло". Правильно или неправильно, пока вторично. Главное что должны начать горет "четко". Либо горит, либо нет. Наблюдается такое?

Zaliv
Offline
Зарегистрирован: 05.03.2011

Zaliv пишет:

 А менять местами яркие и неяркие светодиоды пробовали? Может просто светодиод бракованный или подпаленный? Можно еще попробовать махнуть местами резистры, мало ли?

Я прошу прощения, я плохо прочитал сообщение и ответил невпопад.

Starpom
Offline
Зарегистрирован: 06.03.2011

 На всякий случай спрошу. На схеме светодиоды подключаются к выходам 4-13, а в коде у Вас 3-12. Подключили Вы как в коде или как на схеме? 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

у меня подключено 3-12 как в коде. диоды: если вставить delay(500) в конце как вы говорили то загорается и стабильно горит только один диод. Остальные те которые должны гореть без этой строчки кода загораются и гаснут + загораются и те которые не должны гореть. Все они вспыхивают ярко.

 

Вопрос: Я работал с Цифровым сегментным индикатором и там не было таких проблем. Может внутри есть схема которая убирает эту проблему? Или там тупо светодиоды.

Adessit
Adessit аватар
Offline
Зарегистрирован: 12.04.2011

Светодиоды могут еле еле светиться если где-то есть "недоконтакт" к плюсу или минусу(в моём случае это был не смытый флюс) в вашем может быть некрасивая схема матрицы, перепроверьте всё 

leshak
Offline
Зарегистрирован: 29.09.2011

OK. Значит "догадка" подтвердилась. Ошибка - в коде. Это не исключает ошибку в схеме подключения, но вначале нужно разобратся с кодом. Задержку delay(500) можно убрать. Она нужна была только "для проверки догадки".

Проблема в том что во время одного прохода loop вызываете несколько раз vivod(...). Не решив до конца "какае диодны должны гореть", вы используя промежуточные результаты вычислений, уже пытаетесь "показать их на диодах". Например для показа часа hunit = 9, у вас выполнится vivod(LED6) и vivod(LED3) . Посмотрим, например, на  PIN9. vivod(LED6) его включит, а vivod(LED3) его тут же выключит. Так как looup() крутится быстро, то если нет задержки delay(500), мы получаем на этом пине "мерцание" и диод горит "тускло".

Ну и так же возникает эффект, что более поздние "промежутночные" решения что должно гореть "перекрывают" более ранние.

Если посмотреть изначальную статью в которой описаны эти часы, то там написано примерно так:""I used following calculation....When done, the colum values are passed on to port C ". Что можно перевести как "я выполняют следующие вычисления.... когда они закончены, я отправлю результат в portC (поджигаю светодиоды)".

То есть вам нужно завести некий промежуточный буффер, и все вычисления "что включать, а что нет", должны писать в него и только уже в конце, когда все решения приняты, на основании инормации из буфера, нужно включать/выключать светодиоды. Функция vidod должна вызываться только один раз. И параметром иметь этот буфер. Попробуйте это реализовать, если не получится... попозже может набросаю как это в коде должно выглядет.

Так же, при подключении не забудте следующие: на этой схеме номера выводов это номера ног "микроконтроллера". Которые могут и не совпадать с нумерацией пинов ардуины (которые вы используете в коде). Соответсвие между ними вы можете найти вот тут www.arduino.cc/en/Hacking/PinMapping

Например то что в вашей схеме нарисована как "вывод 5", в коде должно соотвествовать digitalWrite(3,....)

Вообщем посмотрите эту шпаргалку и сверте нумерацию в своем LEDPins. Если там будут значения взятые просто "из схемы", то естествено диоды будут поджигатся неправильно.

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >на этой схеме номера выводов это номера ног "микроконтроллера"

Все еще несколько "путаней". На схеме это даже не номера ног котроллера. А номера ног разъема который придумал автор этой статьи. Рядом он там дал еще одну схемку в которой видно соотвествие ног контроллера, пинам этого разъема. 

То есть вам нужно "смотреть номер пина на разъеме", выяснить "какой ноге контроллера он соотвествует", потом смотреть в PinMapping и узнавать какой digital-пин ардуины соответсвует этой ноге контроллера.

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

leshak пишет:

 

То есть вам нужно завести некий промежуточный буффер, и все вычисления "что включать, а что нет", должны писать в него и только уже в конце, когда все решения приняты, на основании инормации из буфера, нужно включать/выключать светодиоды. Функция vidod должна вызываться только один раз. И параметром иметь этот буфер. Попробуйте это реализовать, если не получится... попозже может набросаю как это в коде должно выглядет.
 

 

Попробую

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Что то я не соображу( ведь 2 верхних ряда работают нормально 

leshak
Offline
Зарегистрирован: 29.09.2011

 Это ни о чем не говорит. Значит им повезло. И все множественные вызовы vivod(...) в данном конкретном случае их либо включают, либо все вызовы выключают. А, как только у вас попадается ситуация что одны вызовы включают, а другие выключают - вы получаете мерцание.

leshak
Offline
Зарегистрирован: 29.09.2011

 Попробуйте как то так:

int LEDPinsBuff[10];

void clearBuff()
{
  for(int i=0;i<=9; i++)LEDPinsBuff[i]=0;
}

void vivod2buff(int LED[])
{
  for(int i=0;i<=9; i++)
    if(LED[i]==1)LEDPinsBuff[i]=1; // если LEDPinsBuff[i] уже установлен в единицу, то он не будет сбрасываться даже если LED[i]==0. Этим мы "накапливаем" принятые решения
  
}

Далее,

  1. в начале свого loop вставляете вызов clearBuff();
  2. заменяете все вызовы vivod(...) на vivod2buff(...)
  3. в конце loop делаете вызов vivod(LEDPinsBuff)

"Мерцания" должны исчезнуть даже без delay(500).

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Что-бы дальше было удобней отлаживать логику  можно в setup добавить инициализацию порта 
Serial.begin(9600); // если необходимо - подправте скорость.

Добавте функцию 

void vivod2serial(int LED[])
{
  for(int i=0;i<=9; i++){
    Serial.print( LED[i],DEC);
    Serial.print(',');
 }
  Serial.println();
  delay(5000); // задержка что-бы можно было в терминале неспеша прочитать какие пины зажгли
}

И вызов vivod2serial(LEDPinsBuff) в конец loop.

Тогда в окне терминала вы сможете увидеть "какие же пины собиралась включать" ваша логика. Если "не то что вы думали" - ищите ошибку в логике, если "тут все правильно, но горят не правильные диоды" - проверяйте схему подключения держа в уме необходимость маппинга пинов (пин разъема->нога контроллера->пин ардуины).

 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Блин не знаю даже чо за фигня. Ваш код вообще не работает. Но я решил сделать по другому. И всё равно не нужные диоды тускло горят. Проверил через порт. Всё четко))))


int LED1[] = {
  1,0,0,1,1,1,1,1,0,1
};
int LED2[] = {
  1,0,0,1,1,1,1,1,1,0
};
int LED3[] = {
  1,0,0,0,1,1,1,1,1,1
};
int LED4[] = {
  1,0,0,1,1,0,1,1,1,1
};
int LED5[] = {
  1,0,0,1,1,1,0,1,1,1
};
int LED6[] = {
  1,0,0,1,1,1,1,0,1,1
};
int LED7[] = {
  0,1,0,1,0,1,1,1,1,1
};
int LED8[] = {
  0,1,0,1,1,1,1,1,0,1
};
int LED9[] = {
  0,1,0,1,1,1,1,1,1,0
};
int LED10[] = {
  0,1,0,0,1,1,1,1,1,1
};
int LED11[] = {
  0,1,0,1,1,0,1,1,1,1
};
int LED12[] = {
  0,1,0,1,1,1,0,1,1,1
};
int LED13[] = {
  0,1,0,1,1,1,1,0,1,1
};
int LED14[] = {
  0,0,1,1,0,1,1,1,1,1
};
int LED15[] = {
  0,0,1,1,1,1,1,1,0,1
};
int LED16[] = {
  0,0,1,1,1,1,1,1,1,0
};
int LED17[] = {
  0,0,1,0,1,1,1,1,1,1
};
int LED18[] = {
  0,0,1,1,1,0,1,1,1,1
};
int LED19[] = {
  0,0,1,1,1,1,0,1,1,1
};
int LED20[] = {
  0,0,1,1,1,1,1,0,1,1
};
int LEDPins[] = {
  12,11,10,9,8,7,6,5,4,3};

void vivod2(int var , int nom)
{
  switch (var) {
  case 1:
    if (nom==1){
      vivod(LED2);
    }

    if (nom==2){
      vivod(LED6);
    }

    if (nom==3){
      vivod(LED9);
    }

    if (nom==4){
      vivod(LED13);
    }

    if (nom==5){
      vivod(LED16);
    }

    if (nom==6){
      vivod(LED20);
    }

    break;

  case 2:
    if (nom==1){
      vivod(LED1);
    }

    if (nom==2){
      vivod(LED5);
    }

    if (nom==3){
      vivod(LED8);
    }

    if (nom==4){
      vivod(LED12);
    }

    if (nom==5){
      vivod(LED15);
    }

    if (nom==6)
    {
      vivod(LED19);
    }
    break;

  case 3:
    /*if (nom==1){
    }*/

    if (nom==2){
      vivod(LED6);
      vivod(LED5);
    }

    if (nom==3){
      vivod(LED9);
      vivod(LED8);
    }

    if (nom==4){
      vivod(LED13);
      vivod(LED12);
    }

    if (nom==5){
      vivod(LED16);
      vivod(LED15);
    }

    if (nom==6)
    {
      vivod(LED20);
      vivod(LED19);
    }
    break;

  case 4:
    /*if (nom==1){
    }*/

    if (nom==2){
      vivod(LED4);
    }

    if (nom==3){
      vivod(LED7);
    }

    if (nom==4){
      vivod(LED11);
    }

    if (nom==5){
      vivod(LED14);
    }

    if (nom==6){
      vivod(LED18);
    }
    break;

  case 5:
    /*if (nom==1){
    }*/

    if (nom==2){
      vivod(LED6);
      vivod(LED4);
    }

    if (nom==3){
      vivod(LED9);
      vivod(LED7);
    }

    if (nom==4){
      vivod(LED13);
      vivod(LED11);
    }

    if (nom==5){
      vivod(LED16);
      vivod(LED14);
    }

    if (nom==6){
      vivod(LED20);
      vivod(LED18);
    }
    break;

  case 6:
   /* if (nom==1){
    }*/

    if (nom==2){
      vivod(LED5);
      vivod(LED4);
    }

   /* if (nom==3){
    }*/

    if (nom==4){
      vivod(LED12);
      vivod(LED11);
    }

   /* if (nom==5){
    }*/

    if (nom==6){
      vivod(LED19);
      vivod(LED18);
    }
    break;

  case 7:
    /*if (nom==1){
    }*/

    if (nom==2){
      vivod(LED6);
      vivod(LED5);
      vivod(LED4);
    }

    /*if (nom==3){
      vivod(LED9);
    }*/

    if (nom==4){
      vivod(LED13);
      vivod(LED12);
      vivod(LED11);
    }

    /*if (nom==5){
      vivod(LED16);
    }*/

    if (nom==6){
      vivod(LED20);
      vivod(LED19);
      vivod(LED18);
    }
    break;

  case 8:
    /*if (nom==1){
    }*/

    if (nom==2){
      vivod(LED3);
    }

    /*if (nom==3){
    }*/

    if (nom==4){
      vivod(LED10);
    }

    /*if (nom==5){
    }*/

    if (nom==6){
      vivod(LED17);
    }
    break;

  case 9:
    /*if (nom==1){
    }*/

    if (nom==2){
      vivod(LED6);
      vivod(LED3);
    }

    /*if (nom==3){
      vivod(LED9);
    }*/

    if (nom==4){
      vivod(LED13);
      vivod(LED10);
    }

   /* if (nom==5){
      vivod(LED16);
    }*/

    if (nom==6){
      vivod(LED20);
      vivod(LED17);
    }
    break;

  }
}

void vivod(int LED[])
{
  for(int i=0;i<=9; i++)
  {
    digitalWrite(LEDPins[i], LED[i]);
    Serial.print( LED[i],DEC);
    Serial.print(',');
  }
  Serial.println();
  delay(1);

}

int second=0, minute=0, hour=2; //start the time on 00:00:00
int munit = 0;
int hunit = 2;
int suc = 2;
void setup() { 

  for(int i=0;i<=9; i++)
    pinMode(LEDPins[i], OUTPUT);
Serial.begin(9600);
}

void loop() {

  vivod2(suc,6);
  vivod2(second,5);
  vivod2(munit,4);
  vivod2(minute,3);
  vivod2(hunit,2);
  vivod2(hour,1);
  Serial.println('iiiiiiiiiiiiiiiiiiiiiii');
//delay(5000);
}
  /*if(suc == 1 || suc == 3 || suc == 5 || suc == 7 || suc == 9) vivod(LED20);
   if(suc == 2 || suc == 3 || suc == 6 || suc == 7) vivod(LED19);
   if(suc == 4 || suc == 5 || suc == 6 || suc == 7) vivod(LED18);
   if(suc == 8 || suc == 9) vivod(LED17);
   
   
   if(second == 1 || second == 3 || second == 5 || second == 7 || second == 9) vivod(LED16);
   if(second == 2 || second == 3 ) vivod(LED15);
   if(second == 4 || second == 5 ) vivod(LED14);
   
   //minutes units
   if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) vivod(LED13);
   if(munit == 2 || munit == 3 || munit == 6 || munit == 7) vivod(LED12);
   if(munit == 4 || munit == 5 || munit == 6 || munit == 7) vivod(LED11);
   if(munit == 8 || munit == 9) vivod(LED10);
   
   //minutes 
   if(minute == 1 || minute == 3 || minute == 5 || minute == 7 || minute == 9) vivod(LED9);
   if(minute == 2 || minute == 3 ) vivod(LED8);
   if(minute == 4 || minute == 5 ) vivod(LED7);
   
   
   //hour units
   if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) vivod(LED6);
   if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) vivod(LED5);
   if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) vivod(LED4);
   if(hunit == 8 || hunit == 9) vivod(LED3);
   
   //hour
   if(hour == 1)  vivod(LED2);
   if(hour == 2)  vivod(LED1);
   delay(1);*/

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >Ваш код вообще не работает

В чем проявляется "вообще не работает"? Горят "не те" или "не те горят тускло"?

>Проверил через порт.

Всмысле вывели к ком-порт лог "какие пины включаются"? Включаются правильные, но "горят лишние"?

Тогда только проверять схему подключения.

Уже самого "заело". Попробую, чуть позже, в симуляторе воспроизвести вашу схему (нет под руками нужных деталей) и посмотреть "как оно работает". Если у вас получится решить проблему раньше - отпишитесь. Что-бы я не тратил время.

 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

вообще не горят

>Всмысле вывели к ком-порт лог "какие пины включаются"? Включаются правильные, но "горят лишние"? 

горят лишнии но в логе только те которые должны гореть написаны.

Я немного видоизменил схему подключения сделал как Цифрового сегментного индикатора. Глюков стало меньше но они есть

leshak
Offline
Зарегистрирован: 29.09.2011

Посмотрел сейчас видео в статье. Похоже что "мерцание" это "так задуманно". На видео его тоже видно. Одновременно несколько диодов не зажигаются. Эффект одновременности достигается delay(1); в функции vivod(...)  (можно кстати будет поигратся с этим параметром).

Так что буферезирование, наверное таки лишние. Нужно разбиратся только с "зажигаются неправильные".

Что-бы мы копали "в одном направлении". Какие, по вашему, диоды должны зажигатся при при 

int second=0, minute=0, hour=2; //start the time on 00:00:00
int munit = 0;
int hunit = 2;
int suc = 2;

 И какие зажигают в реальности? По нумерации схемы (которые там нарисованы LED1, LED2,LED...)

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

>Эффект одновременности достигается delay(1); в функции vivod(...) (можно кстати будет поигратся с этим параметром). 

я пробовал менять этот параметр. при 0 ненужные светодиоды горят ярко как и все при 1-10 горят тускло при10+++ начинается мерцание.

при данных параметрах горят LED2,4,18 

тусклоLED15

leshak
Offline
Зарегистрирован: 29.09.2011

 Кстати, пока я пробую воспроизвести схему. Можете сделать еще одну проверочку:

Выкинуть все из loop. И написать в него

vivod(LED1);
delay(300);

vivod(LED2);
delay(300);

vivod(LED3);
delay(300);

vivod(LED4);
delay(300);
........

В результате это должно начать зажигать диоды "по очереди" (как они называются на схеме). Если "зажигает" в правильном порядке - значит схема собрана правильно, если нет, то...

 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 ))))) я так уже делал и не раз. последовательно зажигал каждый светодиод. и всё ок. Даже всё схему разобрал и собрал заново таже проблема! И светодиоды менял без результатно(

leshak
Offline
Зарегистрирован: 29.09.2011

>последовательно зажигал каждый светодиод. и всё ок

Да быть такого не может. Вот если в loop у вас будет vivod(LED20) неужели зажигается именно LED20? (самый верхний правый на схеме).

Что-бы он зажегся только он должен быть LOW на четвертом PIN-е разъема и HIGH на 13-том.

По коду, по это должны быть (судя из ваших объяснений как вы подключили) 3 PIN арудины и 12-тый.

Смотрим в (первый ваш пример кода) 

int LED20[] = { 0,0,0,1,1,1,1,1,1,0};
int LEDPins[] = { 12,11,10,9,8,7,6,5,4,3};

Как видим "крайние пины" у нас оба LOW. Следовательно LED20 гореть никак не может. На нем с обоих сторон 0. Зато, зачем-то "включили" кучу других пинов 9,8,7,6,5,4. 

Вывод: либо пины у вас подключены как-то "совсем не так", либо никакого "LED-ы загораются последовательно нормально" нет и в помине.

Откуда вы брали последовательности LED1,LED2,LED3...?

На эмуляторе собрал упрощеную схему. Игрался именно с LED20. Правда "подключал" я по тому как нарисовано на схеме (то есть LEDPins у меня были свои), но пока не поправил int LED20[] на что-то подобное "int LED20[] = { 1,0,0,0,0,0,0,0,0,0};

vivod(LED20) у меня ничего не включал. Так что перепроверяйте свои включающие последовательности.

leshak
Offline
Зарегистрирован: 29.09.2011

 Кстати, только что рассмотрел на вашей фотке  шпаргалку в клеточку. Если я правильно понял, то это ваша нумерация LED-дов. Сравните ее с нумерацией LED-ов в статье. Они, мягко говоря, отличаются. Возможно отсюда и пошла путаница в LEDxx[] последовательностях?

Что-то мне это уже начало дико напоминать детский водобпроводный ребус "какой шланг к какому крану идет". Вообщем "распутывайте"  :)

leshak
Offline
Зарегистрирован: 29.09.2011

 Получилось у меня в симуляторе воспроизвести "помаргивание лишними диодами".

Подобно уже завтра "распишу".

В двух словах: "собака в том", что пины мы устанавливаем не одновременно, а "по очереди". Между вызовами  digitalWrite есть небольшая задержка. Диоды мы зажигаем по такому принципу: подаем HIGH на аноды сразу нескольких диодов (аноды у них соеденены), LOW на катод того который должен гореть, и HIGH на катоды тех которые оказались "лишними" (так сказать лишили их "земли").

Так вот вначале у нас устанавливаются пины 12,11,10,9 - которые отвечают за аноды, и потом уже 8,7,6,5,4,3 которые отвечают за катоды. И вот в этом промежутке когда мы уже установили 12,11,10,9, но еще не успели установить в правильное состояние 8,7,6,5,4,3 (запретить лишние) у нас происходит кратковременное моргание "тех которых не ожидали".

Выход либо отказатся от digitalWrite и устанавливать состояние ног "одновременно". Это можно сделать через прямую запись в порт (как и делается в оригинальность статье). Либо попытатся вначале устанавливать "катоды", а потом "аноды". Как-то так (мне на симуляторе помогло):

void vivod(int LED[])
{
  for(int i=0;i<=4;i++) digitalWrite(LEDPins[i],LOW); // снимаем напряжение с анодов, если оно там есть от предыдущего вызова
  for(int i=9;i>=0; i--) // проходим по пинам в обратном порядке, что-бы вначале установились катоды
  digitalWrite(LEDPins[i], LED[i]);
  delay(1);
}

 Когда вы зажигали LED-ы "по очереди" с большими паузами, этих кратковременных лишних "подмаргиваний" видно небыло (трудно увидеть один милисекундный миг), а когда вы пускаете это в "цикл". И это лишние подмаргивание возникает несколько тысяч раз в секунду - его становится видно как "горит в пол накала".

P.S. А управляющие последовательности проверте.

 

 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Я вчера как раз думал об том чтобы все пины сбрасывать в 0. попробовал ваш код. РАБОТАЕТ)))) но они светят тускло. И я изменил и всё стало нормально гореть)))))) Спасибо большое)))

void vivod(int LED[])
{
  for(int i=9;i>=0; i--)
  {
    digitalWrite(LEDPins[i], LED[i]);
  }
  delay(1);
  for(int i=0;i<=3; i++)
    digitalWrite(LEDPins[i], 0);
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну мне мой вариант все-таки кажется более предпочтительным. А с тусклостью в нем я бы преложил бороться небольшим увеличением delay(1)->delay(10).

Какие минусы я вижу в вашем коде: пока идет "вычисление логики" в вашем варинаты леды выключены, в моем - включены. Поэтому, теоретически, мой вариант должен быть ярче (хотя вы говорите что наоборот - непонятно). Так же вы сделали i<=3 вместо i<=4, теоретически, на некоторых комбинациях это опять может привести к "паразитам" (в нижнем ряду, удивляюсь почему не привело, видимо все-таки разные у нас схемы подключения).

Но конечно любой "профи" от нашего решения упал-бы в обморок. "Правильно" это нужно решать прямой записью в порт. И хранить необходимые состояния не в виде массивов, а в виде битовых масок. Тогда сама собой уйдет и проблема "одновременности" и код станет компактней, и прошивка меньше.

Делается "прямая запись", например вот так:

PORTD = B10101000; // синхронно-одновременно устанавливаем 7,5,3 пины в HIGH, остальные в LOW

подробнее можно почитать тут:www.arduino.cc/en/Reference/PortManipulation

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Кстати прямая запись в порт еще и работает в несколько раз быстрее чем через digitalWrite

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

>Но конечно любой "профи" от нашего решения упал-бы в обморок. ДААА это точно)))))

Про прямую запись в порт ничего не знал. Так что ща полезу посмотрю. Большое спасибо. что помогли разобраться.)))

leshak
Offline
Зарегистрирован: 29.09.2011

 >вы сделали i<=3 вместо i<=4

Похоже все-таки в этом вы больше правы. Вчера в три ночи дописывал этот код и прощитался с индексаторами. Ваш вариант более аккуратен.

А прямую запись в порт все-таки попробуйте. Это будет намного более правильное решение.

И пытаясь предугадать дальнейшие действия: вы же будуте кнопки обрабатывать? Возможно ловить их "нажатия" будет лучше через arduino.ru/Reference/AttachInterrupt

leshak
Offline
Зарегистрирован: 29.09.2011

 >Про прямую запись в порт ничего не знал

Если бы знали, то у нас бы небыло такого увлекательно квеста :)  . Суть-то всех подобных хобби в "узнавании чего-то нового". Если бы сразу сделали "на портах", то про такой нюанс как "в каком порядке" включать ноги возможно и не подумали бы никогда.

А я бы так и не попробовал симуляцию-отладку ардуины в протеусе. Знал что "это возможно", но все "руки не доходили". Так что "время потрачено не зря".

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 Полностью согласен)))

leshak
Offline
Зарегистрирован: 29.09.2011

 Кстати сказать что вы "все делали неверно" тоже нельзя. С точки зрения ардуино-идеологии digitalWrite более правильно (понятней что происходит, легче переносить на другие контроллеры). Она и создавалась что-бы "скрыть технически детали от чайников".

Но как видите это не всегда благо (поэтому "профи" и называют ардуину "от лукавого"). Работа с портами это больше С/ASM идеология. Когда нужно хоть немного представлять внутренюю архитектуру контроллера на котором "все крутится". И при переходе на другой контроллер код может потребовать "небольшого допиливания".

Alexander
Offline
Зарегистрирован: 25.04.2010

LEVV2006 пишет:

Про прямую запись в порт ничего не знал. Так что ща полезу посмотрю.

Добавили перевод по использованию регистров микроконтроллера для прямой записи в порты. Читать тут - http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

ОООООООООооооо. Спасибо!!!!! 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Ура!!! Ура!!! Ура!!! Наконец то, сегодня, Я завершил постройку бинарных часов!

И с радостью показываю их вам.

Сразу хочу выразить благодарность «leshak» за помощь в программировании.

Часы умеют показывать дату и время. На передней стороне имеются (кроме числовых светодиодов) одна кнопка, которая отвечает за переключением между режимами Дата/Время, и два маленьких светодиода (с права) показывающих, что в данный момент показывают числовые светодиоды.

На задней стороне имеются три кнопки настройки. Верхние две отвечают за + и – к времени а нижняя вводит часы в режим настройки. Также в нижнем левом углу есть рычажок выкл/вкл часов.

Ну я думаю что лучше перейти к фото части))))

int LED1[] = {
  1,0,0,1,1,1,1,1,0,1
};
int LED2[] = {
  1,0,0,1,1,1,1,1,1,0
};
int LED3[] = {
  1,0,0,0,1,1,1,1,1,1
};
int LED4[] = {
  1,0,0,1,1,0,1,1,1,1
};
int LED5[] = {
  1,0,0,1,1,1,0,1,1,1
};
int LED6[] = {
  1,0,0,1,1,1,1,0,1,1
};
int LED7[] = {
  0,1,0,1,0,1,1,1,1,1
};
int LED8[] = {
  0,1,0,1,1,1,1,1,0,1
};
int LED9[] = {
  0,1,0,1,1,1,1,1,1,0
};
int LED10[] = {
  0,1,0,0,1,1,1,1,1,1
};
int LED11[] = {
  0,1,0,1,1,0,1,1,1,1
};
int LED12[] = {
  0,1,0,1,1,1,0,1,1,1
};
int LED13[] = {
  0,1,0,1,1,1,1,0,1,1
};
int LED14[] = {
  0,0,1,1,0,1,1,1,1,1
};
int LED15[] = {
  0,0,1,1,1,1,1,1,0,1
};
int LED16[] = {
  0,0,1,1,1,1,1,1,1,0
};
int LED17[] = {
  0,0,1,0,1,1,1,1,1,1
};
int LED18[] = {
  0,0,1,1,1,0,1,1,1,1
};
int LED19[] = {
  0,0,1,1,1,1,0,1,1,1
};
int LED20[] = {
  0,0,1,1,1,1,1,0,1,1
};
int LEDPins[] = {
  2,3,4,12,13,11,10,9,7,8};

int PinKnop1=14;
int PinKnop2=16;
int PinKnop3=15;
int PinKnop4=17;
int PinKontrotLED1=6;
int PinKontrotLED2=5;


#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(byte second,        // 0-59
byte minute,        // 0-59
byte hour,          // 1-23
byte dayOfWeek,     // 1-7
byte dayOfMonth,    // 1-28/29/30/31
byte month,         // 1-12
byte year)          // 0-99
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(decToBcd(second));    
  Wire.send(decToBcd(minute));
  Wire.send(decToBcd(hour));     
  Wire.send(decToBcd(dayOfWeek));
  Wire.send(decToBcd(dayOfMonth));
  Wire.send(decToBcd(month));
  Wire.send(decToBcd(year));
  Wire.endTransmission();
}

void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

void vivod(int LED[])
{

  for(int i=9;i>=0; i--)
  {
    digitalWrite(LEDPins[i], LED[i]);
  }
  delay(1);
  for(int i=0;i<=3; i++)
    digitalWrite(LEDPins[i], 0);
}

int second1=0, minute1=0, hour1=0; 
int munit = 0;
int hunit = 0;
int suc = 0;

void setup() { 

  for(int i=0;i<=9; i++)
    pinMode(LEDPins[i], OUTPUT);
  pinMode (PinKontrotLED1,OUTPUT);
  pinMode (PinKontrotLED2,OUTPUT);
  pinMode(PinKnop1, INPUT);
  pinMode(PinKnop2, INPUT);
  pinMode(PinKnop3, INPUT);
  pinMode(PinKnop4, INPUT);

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
  Serial.begin(9600);

//  second = 11;
//  minute = 53;
//  hour = 18;
//  dayOfWeek = 5;
//  dayOfMonth = 15;
//  month = 10;
//  year = 11;
//  setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}
int knopka1=0;
int knopka2=0;
int knopka3=0;
int knopka4=0;
int k=0;
int h=0;
int f=0;
void loop() {

  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);


  if(digitalRead(PinKnop1)==HIGH&&knopka1==0)
  {
    k=!k;
    knopka1++;
  }
  if(digitalRead(PinKnop1)==LOW&&knopka1==1)
    knopka1=0;


  if(digitalRead(PinKnop2)==HIGH&&knopka2==0)
  {
    h++;
    if (h==4)h=0;
    knopka2++;
  }
  if(digitalRead(PinKnop2)==LOW&&knopka2==1)
    knopka2=0;


  if(digitalRead(PinKnop3)==HIGH&&knopka3==0)
  {
    if (k==0)
    {
      if(h==3)second++;
      if(h==2)minute++;
      if(h==1)hour++;

      setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
    }
    if (k==1)
    {
      if(h==3)year++;
      if(h==2)month++;
      if(h==1)dayOfMonth++;
      setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
    }


    knopka3++;
  }
  if(digitalRead(PinKnop3)==LOW&&knopka3==1)
    knopka3=0;



  if(digitalRead(PinKnop4)==HIGH&&knopka4==0)
  {
    if (k==0)
    {
      if(h==3)second--;
      if(h==2)minute--;
      if(h==1)hour--;

      setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
    }
    if (k==1)
    {
      if(h==3)year--;
      if(h==2)month--;
      if(h==1)dayOfMonth--;
      setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
    }
    knopka4++;
  }
  if(digitalRead(PinKnop4)==LOW&&knopka4==1)
    knopka4=0;



  if (k==0)
  {
    digitalWrite(PinKontrotLED1, 1);
    digitalWrite(PinKontrotLED2, 0);
    if (h==0||h==3)
    {

      second1 = second/10;
      suc = second - pow((second/10), 1)*10; 
    }
    if (h==0||h==2)
    {
      minute1 = minute/10;
      munit = minute - pow((minute/10), 1)*10; 
    }
    if (h==0||h==1)
    {

      hour1 = hour/10;
      hunit = hour - pow((hour/10), 1)*10;
    }


  }
  if (k==1)
  {
    digitalWrite(PinKontrotLED1, 0);
    digitalWrite(PinKontrotLED2, 1);
    if (h==0||h==3)
    {
      second1 = year/10;
      suc = year - pow((year/10), 1)*10; 
    }
    if (h==0||h==2)
    {
      minute1 = month/10;
      munit = month - pow((month/10), 1)*10; 
    }
    if (h==0||h==1)
    {

      hour1 = dayOfMonth/10;
      hunit = dayOfMonth - pow((dayOfMonth/10), 1)*10;
    }
  }



  if(suc == 1 || suc == 3 || suc == 5 || suc == 7 || suc == 9) vivod(LED20);
  if(suc == 2 || suc == 3 || suc == 6 || suc == 7) vivod(LED19);
  if(suc == 4 || suc == 5 || suc == 6 || suc == 7) vivod(LED18);
  if(suc == 8 || suc == 9) vivod(LED17);


  if(second1 == 1 || second1 == 3 || second1 == 5) vivod(LED16);
  if(second1 == 2 || second1 == 3 ) vivod(LED15);
  if(second1 == 4 || second1 == 5 ) vivod(LED14);

  //minutes units
  if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) vivod(LED13);
  if(munit == 2 || munit == 3 || munit == 6 || munit == 7) vivod(LED12);
  if(munit == 4 || munit == 5 || munit == 6 || munit == 7) vivod(LED11);
  if(munit == 8 || munit == 9) vivod(LED10);

  //minutes 
  if(minute1 == 1 || minute1 == 3 || minute1 == 5) vivod(LED9);
  if(minute1 == 2 || minute1 == 3 ) vivod(LED8);
  if(minute1 == 4 || minute1 == 5 ) vivod(LED7);


  //hour units
  if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) vivod(LED6);
  if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) vivod(LED5);
  if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) vivod(LED4);
  if(hunit == 8 || hunit == 9) vivod(LED3);

  //hour
  if(hour1 == 1|| hour1 == 3)  vivod(LED2);
  if(hour1 == 2|| hour1 == 3)  vivod(LED1);


  second1=0, minute1=0, hour1=0; //start the time on 00:00:00
  munit = 0;
  hunit = 0;
  suc = 0;

}

 

+ архив с печатной платой

Есть вопрос. Можно ли заменить atmega328 на atmega8? Вроде даже схему переделывать не надо.

P/S/ Думаю можно тему переместить в проекты.

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >Можно ли заменить atmega328 на atmega8

Думаю можно. Хотя ответить на это вопрос можете только вы. Переключите в IDE целевую плату на "Ardino NG Older with Atmega8", скомпиляйте скетч, посмотрите какой размер получился, посмотрите влезет ли он в atmega8

Только подумайте еще: "оно вам надо?". Я вначале тоже "тискался" в младшие модели, а потом прикинул и увидел что "смысла нет". У нас на рынке, более страшие модели камня стоят дороже меньше чем на $1. А, иногда, и дешевле (гримасы логистики). Плюс проезд до рынка/обратно разницу точно "скушает". Ну и к тому же, прикинул, что при моех "хобби объемах", в несколько девайсов в год, гнатся за экономией в центы - смысла нет. Проще прикупить пару "жирных камней" и не гадать "влезет/не влезет".

>Думаю можно тему переместить в проекты.

Схема, скетч - было-бы не плохо. Вдруг кто-нибудь захочет повторить вашь подвиг. Все-таки "ардуина" задумывалсь как Open Source ;)

 

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

 Да схему бы не помешало выложить.))) + плату. Я думаю что скоро добавлю (как только нарисую).

Adessit
Adessit аватар
Offline
Зарегистрирован: 12.04.2011

Аккуратно и красиво - молодцом) А корпус можно сделать просто как тонированный наглухо черный кусок стекла с приеклееными сзади часами, приклеете и крепление на стену - будет стильно и красиво. 

leshak
Offline
Зарегистрирован: 29.09.2011

Идея модернизации на будущие: датчик освещенности (или просто смотреть на текущие время) и ночью уменьшать "яркость", что-бы в темноте "по глазам" не било.

А корпус, можно сделать даже "только сзади" (что-бы прикрыть батарейку, камень), а впереди оставить "как есть". Так оно "гиковей" смотрится. Хотя и предложеный выше вариант - не плох. Дело вкуса.

Adessit
Adessit аватар
Offline
Зарегистрирован: 12.04.2011

кстати можно заняться поиском прозрачных/полупрозрачных корпусов и будет всё сразу) Удобно и гиково. Еще есть вариант это лазерная порезка акрила - круто но дорого в наших краях(особенно ломят цену за акрил)

 

я всё уже прикупил для своего проекта с часами, но нет времени(((( Я буду делать на модулях от dfrobot. и матрица 3216х2 тоесть будет явно 32 на 32, но пока всё лежит в коробочках

LEVV2006
LEVV2006 аватар
Offline
Зарегистрирован: 15.04.2011

Нащет корпуса даже не знаю. Я обычно люблю внутренности видеть )))