работа библиотеки LedControl

leks
Offline
Зарегистрирован: 22.10.2017

Добрый вечер. Собирал летом светодиодный куб в несколько слоёв на мах7219. Скетч управления строил на простой и понятной библиотеке LedControl. Одной из вариаций было вращение-движение плоскости. 

#include <LedControl.h>

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Arduino UNO, Pro Mini
//
////////////////////////
//
//программа для LED куба на шести матрицах 6*6, и max7219  //

#include "LedControl.h"//подключаем данную библиотеку
int i=0;int j=0;int k=0;int k1=5;
int n=5;//5 миллисекунд- единица длительности паузы переключений

 


LedControl LC = LedControl(12, 11, 10, 6);// создаём объект класса для 6 индикаторов
// при этом выводы 12-DIN 11-CLK 10-CS //

void setup() 
{
   for (i=0;i<=5;i++)
   {  
  LC.shutdown(i, false);//выключаем энергосберегающий режим
  LC.setIntensity(i,4 );// устанавливаем интенсивность в 4 единиц между 0 и 15
  LC.clearDisplay(i);//очищаем матрицу i
   }
  
}
void loop() 
{
  ///////////////////////////////////// ПРОГРАММА ФАНЕРА ///////////////////////////////////
   for (k=0;k<=161;k=k+3)
   {
   for (i=0;i<=k1;i++) //цикл в цикле для перебора элементов матриц
   {
   for (j=0;j<=k1;j++)
   {
  int tabl[162]={0,i,j, i,j,5-i, i,j,5, i,j,i, 5,i,j, i,j,5-i, i,j,0, i,j,i,
                0,i,j, i,i,j, i,0,j, i,1,j, i,2,j, i,3,j, i,4,j, i,5,j, i,4,j, i,3,j, i,2,j, i,1,j, i,0,j,
                i,5-i,j, 5,i,j, i,i,j, i,5,j, i,5-i,j,
                0,i,j, 1,i,j, 2,i,j, 3,i,j, 4,i,j, 5,i,j, 4,i,j, 2,i,j, 1,i,j,
                0,i,j, i,j,5-i, i,j,5, i,j,4, i,j,3, i,j,2, i,j,2, i,j,1, i,j,0,
                i,j,1, i,j,2, i,j,3, i,j,4, i,j,5, i,j,i, 5,i,j, i,j,5-i, i,j,0, i,j,i};
  LC.setLed(tabl[k],tabl[k+1],tabl[k+2],1);
  
   }
   
   }
   delay(5*n);
   LC.clearDisplay(0);LC.clearDisplay(1);LC.clearDisplay(2);
   LC.clearDisplay(3);LC.clearDisplay(4);LC.clearDisplay(5);
   }
 
   }
  
   

Заметил мерцание плоскости при движении. Связываю это с несовершенством библиотеки. Есть ли возможность улучшения её работы? Простите за наивность. 

 

SLKH
Offline
Зарегистрирован: 17.08.2015

Что считать "несовершенством", а что "улучшением"?

leks
Offline
Зарегистрирован: 22.10.2017

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

SLKH
Offline
Зарегистрирован: 17.08.2015

leks пишет:

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

т.е. не хватает скорости?

 

Сначала попробовать "легким движением руки " - в LedControl в функции spiTransfer (она последняя в файле cpp) заменить вызов стандартной функции shiftOut() на вызов своей, которую написать надо. В ней вместо digitalWrite() прописать прямое управление пинами DIO и CLK (см., например, CyberLib ).

Если нужно еще быстрее - переписать скетч и кое-что перепаять, чтобы обращаться к каждой мс 7219 отдельно, пинов для CS вроде бы хватает. 

 

 

========

да, и подумать о массиве - не лепо ли будет объявить его глобальным один раз в начале программы ("byte tabl[162]; "), а не 100500 раз во вложенном цикле?

 

kalapanga
Offline
Зарегистрирован: 23.10.2016

Массив здесь кончно замудрёный. Чтобы зажечь светодиод нужно три числа. А здесь перед каждым зажиганием светодиода рассчитываются 162 элемента массива. Ещё в библиотеке вроде есть функции для зажигания нужных диодов сразу в строке/колонке. Я бы переделал хранение последовательности картинок с учётом использования этих функций, с ними и очистка возможно не потребуется.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Разумеется библиотека не подходит. А раз не подходит библиотека , то ее надо написать. Но если вы не можите, то надо нанимать людей. Опять если вам нужна программа, то одни расценки. А вот научить как и почему это уже другие. Образование уже не бесплатное. Тем более специально для вас надо писать учебник по этой тематике. А это труд и время. 

leks
Offline
Зарегистрирован: 22.10.2017

kalapanga пишет:

Массив здесь кончно замудрёный. Чтобы зажечь светодиод нужно три числа. А здесь перед каждым зажиганием светодиода рассчитываются 162 элемента массива. Ещё в библиотеке вроде есть функции для зажигания нужных диодов сразу в строке/колонке. Я бы переделал хранение последовательности картинок с учётом использования этих функций, с ними и очистка возможно не потребуется.

Поднять массив в скетче выше не удаётся - переключение светодидов нарушается.

Функция SetRow() это включение светодиодов порядно, единственная в библиотеке при которой мерцание светиков изчезает, тоесть она самая быстрая.

Остаётся попробовать другую библиотеку, Mах72ххPanel, но доходчивой до меня инструкции по её применению пока не нашёл.

kalapanga
Offline
Зарегистрирован: 23.10.2016

leks пишет:

Поднять массив в скетче выше не удаётся - переключение светодидов нарушается.

Ну это само собой. Я имел ввиду, создать полностью рассчитанный массив. 

leks пишет:

Функция SetRow() это включение светодиодов порядно, единственная в библиотеке при которой мерцание светиков изчезает, тоесть она самая быстрая.

Так а почему Вы её не используете?

leks пишет:

Остаётся попробовать другую библиотеку, Mах72ххPanel, но доходчивой до меня инструкции по её применению пока не нашёл.

А зачем Вам библиотеки? Работайте с микросхемой напрямую, примеры в сети есть.

leks
Offline
Зарегистрирован: 22.10.2017

kalapanga пишет:

 

Так а почему Вы её не используете?

 

А зачем Вам библиотеки? Работайте с микросхемой напрямую, примеры в сети есть.

Да с точками как то логичней работать чем со строками. И для куба при рисовании плоскостей, скажем XY, XZ условно - порядное включение пройдёт быстрее, а для плоскости YZ не известно.

Про работу напрямую с мах примеров не видел, но подозреваю, что скетчи будут большими?

kalapanga
Offline
Зарегистрирован: 23.10.2016

leks пишет:

Да с точками как то логичней работать чем со строками. И для куба при рисовании плоскостей, скажем XY, XZ условно - порядное включение пройдёт быстрее, а для плоскости YZ не известно.

Про работу напрямую с мах примеров не видел, но подозреваю, что скетчи будут большими?

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

А библиотеки, которые Вы сравнить хотите, Вы в код-то их загляните. Может они кроме названия ничем по сути и не отличаются?

leks
Offline
Зарегистрирован: 22.10.2017

#include <SPI.h>

// выбор вывода на Ардуино UNO для LOAD/CS (DIN 11,CS 10,CLK 13 )
#define LOAD_PIN 10


void maxTransfer(uint8_t address, uint8_t value)
{
  // функция загрузки данных в регистры
  digitalWrite(LOAD_PIN, LOW);
  SPI.transfer(address); 
  SPI.transfer(value);
  digitalWrite(LOAD_PIN, HIGH);
}
 

void setup() {
 
  
  pinMode(LOAD_PIN, OUTPUT);

  // отправка старшего бита первым
  SPI.setBitOrder(MSBFIRST);
 
  // включение SPI
  SPI.begin();
 
 //очищаем регистр DisplayTest, для перехода в нормальный режим работы
   maxTransfer(0x0F, 0x00);
  // отключаем дешифратор, путем записи 0 в регистр Decode Mode
  maxTransfer(0x09, 0x00);
 
 //записываем значение яркости дисплея, в данном случае — «0», почти минимальное значение Use lowest intensity
  maxTransfer(0x0A, 0x00);
 
  //записываем в ScanLimit максимальное значение «7», что позволяет отображать содержимое всех регистров дисплея от Digit 0 до Digit 7 
  maxTransfer(0x0B, 0x07);
 
  //записываем «1» в регистр MAX7219, тем самым выводя микросхему из режима Shutdown, обычно ей требуется 250 мкс на включение, но это не мешает принимать команды
  maxTransfer(0x0C, 0x01);
 
 
 
}

void loop() 
{
  for (uint8_t i = 1; i <= 0x08; i=i+2)
  {
    maxTransfer(i, 0x55);maxTransfer(i+1, 0xAA); 
  }
  delay(500);
  
  for (uint8_t i = 1; i <= 0x08; i=i+2)
  {
    maxTransfer(i, 0xAA);maxTransfer(i+1, B01010101); 
  }
  delay(500);
}

 Пробую управлять одной матрицей на мах7219 через библиотеку spi. Светодиоды включаются в шахматном порядке, через один - половина горит, половина нет. Через полсекунды половины перемигиваются. Вопрос: как управлять каскадом из шести последовательно включённых модулей ? (должно ли быть отражено это число в скетче) Сколько их может быть в цепочке?  

sadman41
Offline
Зарегистрирован: 19.10.2016

Чтобы засветить N матриц на max7219, необходимо в DOUT кинуть N*8 бит информации. Как только первый контроллер "заполнится" - начнет передавать дальше ненужные ему биты. Когда закончите пушить в DOUT - дергайте LOAD. 

Максимальное число теоретически неограничено, но есть нюансы: http://forum.arduino.cc/index.php?topic=259367.0 

SLKH
Offline
Зарегистрирован: 17.08.2015

sadman41 пишет:

Чтобы засветить N матриц на max7219, необходимо в DOUT кинуть N*8 бит информации.

N*8*2

sadman41
Offline
Зарегистрирован: 19.10.2016

SLKH пишет:

sadman41 пишет:

Чтобы засветить N матриц на max7219, необходимо в DOUT кинуть N*8 бит информации.

N*8*2

Верно. Всё думал, что написал N*8 байт, а оказалось "бит" почему-то .

leks
Offline
Зарегистрирован: 22.10.2017

sadman41 пишет:

Чтобы засветить N матриц на max7219, необходимо в DOUT кинуть N*8 бит информации. Как только первый контроллер "заполнится" - начнет передавать дальше ненужные ему биты. Когда закончите пушить в DOUT - дергайте LOAD. 

Максимальное число теоретически неограничено, но есть нюансы: http://forum.arduino.cc/index.php?topic=259367.0 

Это получается на переключение одного светодиода надо обновлять значения на всех??

sadman41
Offline
Зарегистрирован: 19.10.2016

leks пишет:
Это получается на переключение одного светодиода надо обновлять значения на всех??

Это так. Но это особенность любых соединенных а цепочку индикаторов. Хоть адресуемых светодиодов, хоть построенных на MAX7219, хоть на сдвиговых регистрах...

leks
Offline
Зарегистрирован: 22.10.2017

Ясно...не придумали пока чтоб в посылке ещё и адрес был для светодиода.

sadman41
Offline
Зарегистрирован: 19.10.2016

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

PS. Хотя, я посмотрел первую попавшуюся библиотеку LedControl - там всё так и делается. Массив выплевывается в SPI и все такое. Единственная неприятная вещь - то, что для изменения состояния каждого  "светодиода" через setLed() сразу делается SPITransfer. Несколько экономней, наверное, сначала сформировать массив так, как нужно для смены картинки, а потом уже пушить его целиком. Тогда и фреймрейт можно будет поднять, думаю,

SLKH
Offline
Зарегистрирован: 17.08.2015

leks пишет:

Ясно...не придумали пока чтоб в посылке ещё и адрес был для светодиода.

придумали, но для одной микросхемы. в первом байте номер восьмерки светодиодов (например,  знакоместа), во втором данные - какие светодиоды из этих восьми зажечь/погасить. при использовании LedControl нужно 2 раза запустить shiftOut(), т.е. 50 раз дернуть digitalWrite(), а это около 400 мксек, не так уж мало в цикле.

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

 

SLKH
Offline
Зарегистрирован: 17.08.2015

leks пишет:

sadman41 пишет:

Чтобы засветить N матриц на max7219, необходимо в DOUT кинуть N*8 бит информации. Как только первый контроллер "заполнится" - начнет передавать дальше ненужные ему биты. Когда закончите пушить в DOUT - дергайте LOAD. 

Максимальное число теоретически неограничено, но есть нюансы: http://forum.arduino.cc/index.php?topic=259367.0 

Это получается на переключение одного светодиода надо обновлять значения на всех??

нет.

sadman41
Offline
Зарегистрирован: 19.10.2016

SLKH пишет:

leks пишет:

Это получается на переключение одного светодиода надо обновлять значения на всех??

нет.

Но если цепочкой - то на всех?

SLKH
Offline
Зарегистрирован: 17.08.2015

sadman41 пишет:

SLKH пишет:

leks пишет:

Это получается на переключение одного светодиода надо обновлять значения на всех??

нет.

Но если цепочкой - то на всех?

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

для многократного ускорения ТС всего-то надо перепаять схему, чтобы сигналы CS были индивидуальными (я полагаю, свободных пинов хватает), и кое-что переписать (несколько строк).

 

leks
Offline
Зарегистрирован: 22.10.2017

С CS идея ясна, но проще использовать в другой поделке чем корячить исходную. С нулевым регистром не понятно.

 

SLKH
Offline
Зарегистрирован: 17.08.2015

leks пишет:

С нулевым регистром не понятно.

если не собираешься управлять 7219 напрямую без библиотек, он тебе не нужен.