Led matrix 8x8 - зажечь определенные светодиоды.

Fekla
Offline
Зарегистрирован: 16.12.2012

Поскажите, как при такой схеме подключения можно зажечь определенный светодиод?

maksim
Offline
Зарегистрирован: 12.02.2012

А чем вас статья откуда вы картинку взяли не устроила?

Fekla
Offline
Зарегистрирован: 16.12.2012

maksim, эту статью я читала(хотя картинку взяла на английском форуме), но там рассматривается лишь подключение и два примера, а мне нужно немного другое - как программно зажешь определенные светодиоды? Ну к примеру, как зажешь 4 светодиода по углам матрицы, или как зажешь 4 светодиода в центре?

maksim
Offline
Зарегистрирован: 12.02.2012

Еще раз перечитйте статью, уберите лишнее из кода, уберите анимацию, добавьте четыре точки по углам:

#define PAINTS { \
     {1, 0, 0, 0, 0, 0, 0, 1}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1}  \
 }

и вуаля... готово.

И поверьте мне вам нужно именно тоже самое, что и в статье, вам нужно понять принцип работы динамической индикации.

Fekla
Offline
Зарегистрирован: 16.12.2012

Ну вот убрала я все лишнее. Угловые светодиоды горят, но очень слабо. Что можно еще сделать?

#define TEST { \
     {1, 0, 0, 0, 0, 0, 0, 1},  \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1} \
 } 

byte col = 0;
byte leds[8][8];  
int pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};         
int cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06], pins[11], pins[15], pins[16]};        
int rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1], pins[7], pins[2], pins[5]};
int pattern = 0;
const int numPatterns = 1;
byte patterns[numPatterns][8][8] = {
   TEST
};


void setup(){
  for (int i = 1; i <= 16; i++) {
     pinMode(pins[i], OUTPUT);
   }
 setPattern(pattern);
}


void setPattern(int pattern) {
   for (int i = 0; i < 8; i++) {
     for (int j = 0; j < 8; j++) {
       leds[i][j] = patterns[pattern][i][j];
     }
   }
}


void loop(){
  display();
   pattern = ++pattern % numPatterns; 
}


void display() {
   digitalWrite(cols[col], HIGH); 
   col++;
   if (col == 8) {
     col = 0;
   }
   for (int row = 0; row < 8; row++) {
     if (leds[col][7 - row] == 1) {
       digitalWrite(rows[row], HIGH);  
     }
     else {
       digitalWrite(rows[row], LOW); 
     }
   }
   digitalWrite(cols[col], LOW); 
}

 

maksim
Offline
Зарегистрирован: 12.02.2012
maksim
Offline
Зарегистрирован: 12.02.2012

А попробуйте так

#define TEST { \
     {1, 0, 0, 0, 0, 0, 0, 1}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1}  \
 } 

char pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};         
byte cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06], pins[11], pins[15], pins[16]};        
byte rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1], pins[7], pins[2], pins[5]};
bool mem[8][8] = TEST;


void setup()
{
  for(int i = 0; i < 8; i++) pinMode(cols[i], OUTPUT);
}

void loop()
{
  Display();
}

void Display() 
{
   static byte row;
   for (byte col = 0; col < 8; col++) digitalWrite(cols[col], mem[row][col]);  
   pinMode(rows[row], 1);
   delayMicroseconds(10);
   pinMode(rows[row], 0);
   row++;
   if(row == 8) row = 0;
}

Тоже тускло?

Fekla
Offline
Зарегистрирован: 16.12.2012

А так вообще не работает :(

 

maksim
Offline
Зарегистрирован: 12.02.2012

Так а вы матрицу как на картинке подключаете?
Сейчас пересмотрел код и не пойму зачем вообще вот это:

int pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};         
int cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06], pins[11], pins[15], pins[16]};        
int rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1], pins[7], pins[2], pins[5]};

в cols и rows должны быть номера элентов массива pins, а у вас там номера выводов. Тогда так:

#define TEST { \
     {1, 0, 0, 0, 0, 0, 0, 1}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1}  \
 } 
     
byte cols[8] = {13, 3, 4, 10, 6, 11, 15, 16};        
byte rows[8] = {9, 14, 8, 12, 1, 7, 2, 5};
bool mem[8][8] = TEST;

void setup()
{
  for(int i = 0; i < 8; i++) pinMode(cols[i], OUTPUT);
}

void loop()
{
  Display();
}

void Display() 
{
   static byte row;
   for (byte col = 0; col < 8; col++) digitalWrite(cols[col], mem[row][col]);  
   pinMode(rows[row], 1);
   delayMicroseconds(10);
   pinMode(rows[row], 0);
   row++;
   if(row == 8) row = 0;
}

 

Fekla
Offline
Зарегистрирован: 16.12.2012

>Так а вы матрицу как на картинке подключаете?

Да, пример с бегущей строкой у меня работает.

>Сейчас пересмотрел код и не пойму зачем вообще вот это

Ну это я по вашему совету все лишнее из кода той статьи пыталась убрать.

>Тогда так:

Так горят, только не те диоды, а вот эти:

0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0
1, 0, 1, 1, 0, 0, 1, X
0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0
1, 0, 1, 1, 0, 0, 1, X

Х - это тусклые светодиоды.

 

Может мне все таки лучше на сдвиговых регистрах сделать? Можете подсказать схему подключения для 74HC595? Гугл только на трехцветные матрицы схемы выдает, а там несколько запутано.

maksim
Offline
Зарегистрирован: 12.02.2012

А причем тут сдвиговые регистры? С помощью регистров вы освободите выводы дуины и ничего больше, то есть будут заняты не 16, а 4 вывода. Вот транзисторная сборка ULN2803 и токоограничивающие резисторы нужны для нормального свечения светодиодов. Скорее всего простое не совпадение выводов.
Сейчас попробую разобраться...

maksim
Offline
Зарегистрирован: 12.02.2012

Если я нигде не ошибся и вы подключили все по схеме, то вот так должно работать:

#define TEST { \
     {1, 0, 0, 0, 0, 0, 0, 1}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1}  \
 } 
     
byte cols[8] = {9, 3, 2, 12, A1, 11, 7, 6};        
byte rows[8] = {13, 8, A3, 10, 5, A2, 4, A0};
bool mem[8][8] = TEST;

void setup()
{
  for(int i = 0; i < 8; i++) pinMode(cols[i], OUTPUT);
}

void loop()
{
  Display();
}

void Display() 
{
   static byte row;
   for (byte col = 0; col < 8; col++) digitalWrite(cols[col], mem[row][col]);  
   pinMode(rows[row], 1);
   delayMicroseconds(10);
   pinMode(rows[row], 0);
   row++;
   if(row == 8) row = 0;
}
Fekla
Offline
Зарегистрирован: 16.12.2012

>А причем тут сдвиговые регистры?

Где-то читала, что при помощи сдвиговых регистров можно избежать не ровномерного свечения.

>Если я нигде не ошибся и вы подключили все по схеме, то вот так должно работать:

Да, так работает, но диоды опять еле светятся :(

Забыла добавить, что я каждую ножку матрицы подключила через резисторы в 250 Ом, а не напрямую, как на картинке. Может быть из за этого? Хотя, если сравнивать с примером бегущей строки, то там светятся достаточно ярко.

maksim
Offline
Зарегистрирован: 12.02.2012

Fekla пишет:
Забыла добавить, что я каждую ножку матрицы подключила через резисторы в 250 Ом, а не напрямую, как на картинке. Может быть из за этого?
Естественно из-за этого, уберите резисторы и все будет нормально. Но все равно без транзисторов на катодах свечение будет не равномерным.

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

Максим, а вы строки зажигаете подтягивающими резисторами случайно или так задумано? Не вникал сильно, но pinMode в строках 30,32 настораживает.

maksim
Offline
Зарегистрирован: 12.02.2012

Нет, строка поджигается когда на ней 0(GND), то есть она настроена на выход, когда она настроена на вход на ноге Z-состояние, в общем строки поджигаются как NPN-транзисторами.
Да понятно почему тускло, если на всех ногах матрицы резисторы по 250 Ом, если даже в строке горит только один светодиод, то к нему еще плюсом 500 Ом, а если больше светодиодов то вообще потухнуть могут...

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

 

maksim пишет:

Нет, строка поджигается когда на ней 0(GND), 

Ну значит я запутался по какой же схеме подключались. Если из #5 (картинка), что-бы зажечь самый верхний левый диод, нужно на ногу R1 дать HIGH, и на первый пин ULN-ки тоже HIGH!!

ULN-ка же, в отличает от ULS инвертирует сигнал. Что-бы она свой выход подключила к земле, ей же, если не ошибась, HIGH на вход дать нужно?

Но при любых раскладах, зачем тут Z-состояние примешивать? Чем обычный OUTPUT режим не подходит и на нем HIGH/LOW менять?

maksim
Offline
Зарегистрирован: 12.02.2012

Не, не, схема из самого первого сообщения топик-стартера - прямое подключение матрицы к дуине, поэтому и Z-состояние нужно.

Fekla
Offline
Зарегистрирован: 16.12.2012

Все резисторы убрать? А не сгорят диоды-то? Ведь даже в оригинальной статье сказанно "Note: DON'T FORGET CURRENT-LIMITING RESISTORS."

maksim
Offline
Зарегистрирован: 12.02.2012

Не сгорят, так как каждый вывод дуины имеет сопротивление 20 Ом, так диод оказывается между двух выводов получается 40 Ом. Вот когда через ULN будете подключать, вот тогда обязательно нужно ставить резисторы, НО только на аноды.

maksim
Offline
Зарегистрирован: 12.02.2012

Можете еще уменьшить время подсветки строки с 10 до 1 мкс delayMicroseconds(1);, но тогда это может повлиять на снижение яркости.

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

>Да, так работает, но диоды опять еле светятся :(

Попробуйте увеличить, в строке 31, delayMicroseconds(10); на что-то побольше.

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

maksim
Offline
Зарегистрирован: 12.02.2012

leshak пишет:

>Да, так работает, но диоды опять еле светятся :(

Попробуйте увеличить, в строке 31, delayMicroseconds(10); на что-то побольше.

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

с 500 Омами не поможет.

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

maksim пишет:

Можете еще уменьшить время подсветки строки с 10 до 1 мкс delayMicroseconds(1);, но тогда это может повлиять на снижение яркости.

А зачем же уменьшать время подсветки, если проблема в "тускло"? IMHO наоборот - увеличить попытатся.

Чем больше соотношение времени "подстветка"/остальной скетч - тем визуально ярче будет.

Крайний случай - светить кажду строчку минуту :)  Будет максимальная яркость :)  (и перемигивание).

maksim
Offline
Зарегистрирован: 12.02.2012

leshak пишет:

maksim пишет:

Можете еще уменьшить время подсветки строки с 10 до 1 мкс delayMicroseconds(1);, но тогда это может повлиять на снижение яркости.

А зачем же уменьшать время подсветки, если проблема в "тускло"? IMHO наоборот - увеличить попытатся.

Чем больше соотношение времени "подстветка"/остальной скетч - тем визуально ярче будет.

Крайний случай - светить кажду строчку минуту :)  Будет максимальная яркость :)  (и перемигивание).

Fekla пишет:
я каждую ножку матрицы подключила через резисторы в 250 Ом, а не напрямую, как на картинке.

maksim пишет:
уберите резисторы и все будет нормально.

maksim
Offline
Зарегистрирован: 12.02.2012

Короче, хотите, что бы хоть как-то светила матрица без транзисторов - убираете все резисторы, потому как когда у вас будут в одной строке гореть 3 светодиода и выше, яркость строки будет уменьшаться при увеличении количества светящихся светодиодов. При таком подключении максимум на что повлияеет завышенный ток - это на срок службы светодиодов, быть может в 2 раза при условии, что светодиод может служить лет 15 при постоянном использовании.
И на будующее, когда у вас спрашивают: "точно как на схеме подключаете" и вы говорите "да", то оно так и должно быть иначе вы будете создовать себе лишние сложности.

Fekla
Offline
Зарегистрирован: 16.12.2012

Спасибо за помощь. Убрала резисторы:)

Но теперь слишком ярко светит:) Можно ли как-то понизить яркость для всех светодиодов, ну например как тут http://arduino.ru/Tutorial/Fade ?

maksim
Offline
Зарегистрирован: 12.02.2012

maksim пишет:

Можете еще уменьшить время подсветки строки с 10 до 1 мкс delayMicroseconds(1);, но тогда это может повлиять на снижение яркости.

maksim
Offline
Зарегистрирован: 12.02.2012

Если все равно ярко то тогда так 

pinMode(rows[row], 1);
delayMicroseconds(1);
pinMode(rows[row], 0);
delayMicroseconds(3);

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

Fekla
Offline
Зарегистрирован: 16.12.2012

maksim пишет:

maksim пишет:

Можете еще уменьшить время подсветки строки с 10 до 1 мкс delayMicroseconds(1);, но тогда это может повлиять на снижение яркости.

Точно. Спасибо еще раз.

Fekla
Offline
Зарегистрирован: 16.12.2012

maksim пишет:

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

А вот это интересно. Попробую сделать.

Fekla
Offline
Зарегистрирован: 16.12.2012

Вот, вроде получилось

void Display() 
{
  int SV = 0;
  int RR ;
   static byte row;
   for (byte col = 0; col < 8; col++) {
   digitalWrite(cols[col], mem[row][col]);
   if (mem[row][col] == 1) SV +=1;
 } 
 if (SV ==8) RR =80;
 if (SV ==7) RR =70;
 if (SV ==6) RR =60;
 if (SV ==5) RR =50;
 if (SV ==4) RR =40;
 if (SV ==3) RR =30;
 if (SV ==2) RR =20;
 if (SV ==1) RR =10;
   pinMode(rows[row], 1);
   delayMicroseconds(RR);
   pinMode(rows[row], 0);
   row++;
   if(row == 8) row = 0;
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Если зависимость задержка/яркость получилась линейной как у вас в коде, то можно чуть-чуть оптимизировать код:

void Display() 
{
  byte SV = 0;
  static byte row;
  for (byte col = 0; col < 8; col++) 
  {
    digitalWrite(cols[col], mem[row][col]);
    SV += mem[row][col];
  } 
  pinMode(rows[row], 1);
  delayMicroseconds(SV*10);
  pinMode(rows[row], 0);
  row++;
  if(row == 8) row = 0;
}

 

Fekla
Offline
Зарегистрирован: 16.12.2012

maksim пишет:

delayMicroseconds(SV*10);

Я тоже хотела так упростить код, но так почему-то тускло маргает.

И еще вопрос. Если мне придется отказаться от delay, то чем его можно заменить? Смотрела тему и пример, где без delay можно мигать светодиодом, но там задержка в милисекундах,  а тут в микро.

maksim
Offline
Зарегистрирован: 12.02.2012

Так же как и в примере только в микросекундах, есть такая функция micros().

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

Fekla пишет:

И еще вопрос. Если мне придется отказаться от delay, то чем его можно заменить? 

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

 

  1. Начинаем светить
  2. Запоминаем, в какую-то переменную когда мы начали это действие
  3. Время от времени проверяем сколько времени прошло с того момента (текущие время минус время в переменной). Если прошло больше 3 sec - выключаем диод

Небольшая вариация. Принципиальных отличий нет, дело вкуса (если только не предполагается беспрерывная работа больше 49-дней, тогда лучше первый вариант).

  1. Начинаем светить
  2. Вычисляем время "когда нужно будет выключить" (текущие время+сколько светить)
  3. Время от времени сравниваем вычесленное время с текущим. Если текущие больше или равное - выключаем

В коде это выглядить примерно так:


#define TURN_ON_DELAY 3000 // время сколько нужно светить
#define LED 13

unsigned long offTime=0; // время когда светик нужно будет выключить

void setup(){
  pinMode(LED,OUTPUT);
}

bool turnOnCondition(){
 return true; // ТУТ_ПИШЕМ_УСЛОВИЕ_ВКЛЮЧЕНИЯ СВЕТИКА, например по нажатию какой-то кнопки
}

void loop(){
  
  if(!offTime &&  turnOnCondition()){
    digitalWrite(LED,HIGH); // включили
    offTime=millis()+TURN_ON_DELAY; // вычислили "когда выключать"
  }
  
  if(offTime && offTime<=millis()){ // проверяем не пора ли выключать
     digitalWrite(LED,LOW); // включили
     offTime=0; // выключили проверку "пора"
  }
}

 

 

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

 

Fekla пишет:

maksim пишет:

delayMicroseconds(SV*10);

Я тоже хотела так упростить код, но так почему-то тускло маргает.

Можно, что-бы не выполнять относительно ресурсоемкое вычисление, загнать значения заранее в массив (плюс это позволит задавать нелинейную зависимосить). Очень похоже на ваши if, только чуть-чуть компактней.

 

unsigned int RRs[]={0,10,20,30,40,50,60,70,80}; // время задержки

void loop(){
  ......
  delayMicroseconds(RRs[SV]);  // но нужно быть аккуратным  SV не приняло значение больше чем длина массива RRs
  .....
}

И еще, советую почитать, в разделе программирование, подраздел "типы данных". И обращать внимание, в документации на функции, какие типы параметров она принимает и какие возвращает.

В вашем случае, для переменной SV достаточным будет тип byte, а для переменной RR желателен unsigned int, а не int (так как delayMicroseconds ждет именно unsigned int). С конкретными вашими цифрами задержками "будет работать и так". Просто повезло, но лучше заранее привыкать "делать правильно". Это, убережет и от неоправданного расхода ресурсов проца и ваших нервов при поиски трудноуловимых ошибок из-за небрежности с типами.

Fekla
Offline
Зарегистрирован: 16.12.2012

leshak пишет:

если только не предполагается беспрерывная работа больше 49-дней

А почему так? Переполнение?

leshak пишет:

unsigned int RRs[]={0,10,20,30,40,50,60,70,80}; // время задержки

void loop(){
  ......
  delayMicroseconds(RRs[SV]);  // но нужно быть аккуратным  SV не приняло значение больше чем длина массива RRs
  .....
}

Хм, все равно почему-то тускло мигает, а не светит, как при if. Но все равно спасибо за пример и советы.

 

maksim
Offline
Зарегистрирован: 12.02.2012

Fekla пишет:
Хм, все равно почему-то тускло мигает, а не светит, как при if. Но все равно спасибо за пример и советы.

Покажите весь код.

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

Fekla пишет:

leshak пишет:

если только не предполагается беспрерывная работа больше 49-дней

А почему так? Переполнение?

leshak пишет:

unsigned int RRs[]={0,10,20,30,40,50,60,70,80}; // время задержки

void loop(){
  ......
  delayMicroseconds(RRs[SV]);  // но нужно быть аккуратным  SV не приняло значение больше чем длина массива RRs
  .....
}

Хм, все равно почему-то тускло мигает, а не светит, как при if. Но все равно спасибо за пример и советы.

Ну значит причина не в этом. Если вы сейчас сюда вставите IF-вы - будет точно также. Хотя.... возможно просто время чуть увеличить нужно. С IF-вами у вас еще есть задержка в неявном виде. Постоянная проверка IF-вов тоже время занимает. То есть у вас, к этим цифрам, в лучае if еще какие-то микросекунды добавляются (что плохо, так как оно будет изменятся в случае увеличение количества проверок, плохо предсказуемо и т.п.).

Или причина в другом (тогда и с if-вами будет тускло), и тогда нужен код целиком.

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

Fekla пишет:

leshak пишет:

если только не предполагается беспрерывная работа больше 49-дней

А почему так? Переполнение?

Совершенно верно. Сколько микросекунд может влезть в unsigned long (это примерно 49.1 дней). В случае когда мы плюсуем, при переполнении у нас получится маленький offTime, явно меньше текущего времени в "выключится сразу", а вот разница (millis()-КОГДА_ВКЛЮЧИЛИ) посчитается правильно даже при переполнении (если только само время "сколько светить" не будет больше 49-ти дней).

При переполнении она получится отрицательной, но так как тип беззнаковый, то произойдет "переполнение в обратную сторону" и все будет хорошо.

Что-бы понять, можете завести переменную типа байт (она переполняется на 255), и попытася повычитать из нее, что-то типа (5-253) . И посмотреть какая разница выходит :)

Fekla
Offline
Зарегистрирован: 16.12.2012

Вот весь код

#define TEST { \
     {1, 0, 0, 0, 0, 0, 0, 1}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1}  \
 } 
     
byte rows[8] = {9, 3, 2, 12, A1, 11, 7, 6};        
byte cols[8] = {A0, 4, A2, 5, 10, A3, 8, 13};
bool mem[8][8] = TEST;
unsigned int RRs[]={0,10,20,30,40,50,60,70,80};

void setup()
{
  for(int i = 0; i < 8; i++) pinMode(cols[i], OUTPUT);
}

void loop()
{
  Display();
}

void Display() 
{
  int SV = 0;
  int RR ;
   static byte row;
   for (byte col = 0; col < 8; col++) {
   digitalWrite(cols[col], mem[row][col]);
   if (mem[row][col] == 1) SV +=1;
 } 
 
   pinMode(rows[row], 1);
  delayMicroseconds(RRs[SV]);
   pinMode(rows[row], 0);
   row++;
   if(row == 8) row = 0;
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Подробнее опишите что и как мигает.

Fekla
Offline
Зарегистрирован: 16.12.2012

leshak пишет:

Ну значит причина не в этом. Если вы сейчас сюда вставите IF-вы - будет точно также. Хотя.... возможно просто время чуть увеличить нужно. С IF-вами у вас еще есть задержка в неявном виде. Постоянная проверка IF-вов тоже время занимает. То есть у вас, к этим цифрам, в лучае if еще какие-то микросекунды добавляются (что плохо, так как оно будет изменятся в случае увеличение количества проверок, плохо предсказуемо и т.п.).

Или причина в другом (тогда и с if-вами будет тускло), и тогда нужен код целиком.

Ну вот я увеличила задержку

unsigned int RRs[]={0,110,120,130,140,150,160,170,180}; 

Стало по ярче светить, но все равно моргает.

leshak пишет:

С IF-вами у вас еще есть задержка в неявном виде.

Непойму, ведь тут задержка не должна приводить к миганию, а только к увеличению или уменьшению яркости?

Fekla
Offline
Зарегистрирован: 16.12.2012

maksim, ну светодиоды по углам сначала загараются, а потом гаснут. Как будто задержка стоит после Display(); в функции loop.

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

 

Fekla пишет:

Непойму, ведь тут задержка не должна приводить к миганию, а только к увеличению или уменьшению яркости?

Неверно. Оно приводить и к тому и к другому. И тут "искать баланс". Чем дольше вы держите строку включенной тем он светит ярче, но при этом тем дольше выключенными являеются другие строки (и это в том числе "когда мы светим другими").

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

Варианты:

1. Все таки брать ULN/транзисторы и увеличивать проходящий ток (c тем что-бы можно было уменьшить задержку до "не моргает").

2. Пытаться "ускорить" скетч путем отказа от digitalWrite и перехода на прямую запись в регистр (не факт что поможет).

3. Попытатся ускорить, заранее высчитав sv для каждой строки брать готовые задержки (зачем нам каждый раз вычислять? их можно пересчитывать только если поменялся массив mem).

4. Может Максиму что-то еще в голову прийдет :)

maksim
Offline
Зарегистрирован: 12.02.2012

Здесь в чем то другом дело, потому как если даже взять максимальную задржку 180 микросекунд и умножить на 8, то получится 1,5 миллисекунды, ну предположим остальной код выполняется еще 1 миллисекунду получаетя 2,5. 1000/2,5 получаем 400 кадров в секунду. Ну или какаято операция занимает  несколько миллисекунд, я таких не знаю.

 

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

leshak пишет:

3. Попытатся ускорить, заранее высчитав sv для каждой строки брать готовые задержки (зачем нам каждый раз вычислять? их можно пересчитывать только если поменялся массив mem).

 

Как-то так:

#define TEST { \
     {1, 0, 0, 0, 0, 0, 0, 1}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1}  \
 } 
     
byte rows[8] = {9, 3, 2, 12, A1, 11, 7, 6};        
byte cols[8] = {A0, 4, A2, 5, 10, A3, 8, 13};
bool mem[8][8] = TEST;

unsigned int RRs[]={0,110,120,130,140,150,160,170,180}; // задержки в зависимости от того сколько светиков в строке горит
unsigned int rowsDelays[8]; // вычесленные задержки для каждой строки


void setup()
{
  for(int i = 0; i < 8; i++) pinMode(cols[i], OUTPUT);
  calcDelays();// вычисляем задержки для строк
}

void loop()
{
  Display();
}

void calcDelays(){ // заполняет массив rowsDelays исходя из текущего содержимого mem[][]
 int sv = 0; // сколько светиков в строке горит
 
  for(byte r=0;r<8;r++){ // по строкам
        sv=0;
        for(byte col=0;col<8;col++)if (mem[r][col]) sv++;
        rowsDelays[r]=RRs[sv]; // запоминаем какая задержка должна быть для этой строки
  }
  
}

void Display() 
{
   static byte row;
   
   for (byte col = 0; col < 8; col++) {
       digitalWrite(cols[col], mem[row][col]);
   } 
 
   pinMode(rows[row], 1);
   delayMicroseconds(rowsDelays[row]); // берем уже вычисленую для этой строки задержку
   pinMode(rows[row], 0);
   row++;
   if(row == 8) row = 0;
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Так я понять не могу, вот так

#define TEST { \
     {1, 1, 1, 1, 1, 1, 1, 1}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {0, 0, 0, 0, 0, 0, 0, 0}, \
     {1, 0, 0, 0, 0, 0, 0, 1}  \
 }

byte rows[8] = {9, 3, 2, 12, A1, 11, 7, 6};        
byte cols[8] = {A0, 4, A2, 5, 10, A3, 8, 13};
bool mem[8][8] = TEST;

void setup()
{
  for(int i = 0; i < 8; i++) pinMode(cols[i], OUTPUT);
}

void loop()
{
  Display();
}

void Display() 
{
  int SV = 0;
  static byte row;
  for (byte col = 0; col < 8; col++) {
    digitalWrite(cols[col], mem[row][col]);
    SV += mem[row][col];
  } 

  pinMode(rows[row], 1);
  delayMicroseconds(SV*10+10);
  pinMode(rows[row], 0);
  delayMicroseconds(100-(SV*10+10));
  row++;
  if(row == 8) row = 0;
}

тускло горит или мигает???

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

Можно еще попобовать вот так дополнить Display(), что-бы не дуплить на пустных строках вообще:

void Display() 
{
   static byte row;
   if(rowsDelays[row]){ // Что-то делать только если в строке есть хоть один горящий светик (задержка не равна нулю)
     for (byte col = 0; col < 8; col++) digitalWrite(cols[col], mem[row][col]);
     
   
     pinMode(rows[row], 1);
     delayMicroseconds(rowsDelays[row]); // берем уже вычисленую для этой строки задержку
     pinMode(rows[row], 0);
     
     for (byte col = 0; col < 8; col++) digitalWrite(cols[col], 0); // выключаем все, так как следующая строка может быть пустой
   }
   row++;
   if(row == 8) row = 0;
}

 

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

2Максим: и все-таки муляет мне это pinMode в display. Там реально нужно Z-состояние или можно, все-таки на digitalWrite заменить?

Кстати, а что вы думаете про такой "финт ушами"?:

что-бы не разбиратся к какому порту какая нога принадлежит, выводим один раз все с помощью digitalWrite-тов, запоминаем состояния PORTB,PORTD и т.п.

и потом вызываем displayFast(), который использует прямую запись в порт из подготовленных значений?

Поможет такое или "выжатых тактов" за счет отказа от digitalWrite все равно не хватит?