Библиотека для управления светодиодными матрицами

valmat
Offline
Зарегистрирован: 15.03.2016

Всем добрый день!

Хочу представить библиотеку для управления светодиодными матрицами 8x8 на чипах MAX7219 и MAX7221. https://github.com/valmat/LedMatrix

Заметка о библиотеке на Гиктаймс: https://geektimes.ru/post/272588/

Русскоязычное Readme: https://github.com/valmat/LedMatrix/blob/master/README.RU.md

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Посмотрел краем глаза. Большая работа проделана. Снимаю шляпу!

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

работа действительно большая в плане универсальности.

Но не хватает заметки (или просто примера) как использовать ее для вывода бегущих строк - ведь матрицы в 95% используют именно для этого. Дочитано полностью, но фраза "Библиотека не реализует средств для печати текстовых строк на каскаде матриц" все равно непонятна - что мешает определиться с количеством и ориентацией матриц и, уже используя эти данные, выводить текст?

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

valmat
Offline
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:
Посмотрел краем глаза. Большая работа проделана. Снимаю шляпу!

Tomasina пишет:
работа действительно большая в плане универсальности.

Спасибо за отзывы.

Tomasina пишет:

Но не хватает заметки (или просто примера) как использовать ее для вывода бегущих строк - ведь матрицы в 95% используют именно для этого. Дочитано полностью, но фраза "Библиотека не реализует средств для печати текстовых строк на каскаде матриц" все равно непонятна - что мешает определиться с количеством и ориентацией матриц и, уже используя эти данные, выводить текст?

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

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

На самом деле, даже сейчас это совсем не сложная задача. Вот два примера:
https://github.com/valmat/LedMatrix/blob/master/examples/MultiShift/Mult...
https://github.com/valmat/LedMatrix/blob/master/examples/HelloHabr/Hello...

Если кратко, то нужно с помощью метода `void setCol(const Col &col, buint8_t value);` установить соответствующие столбцы.

Сейчас нет интерфейса для конвертации строки в набор символов с автоматической установкой и в матрицу. Т.е. что бы работать с чем то вроде `const char *`/`const wchar_t *`.
Но как я уже сказал, это отдельная задача, которая должна быть (и возможно, будет) реализована в отдельной библиотеке.

Tomasina пишет:

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

Я думал на счет использования namespace. К сожалению, в Arduino сообществе существует какая то странная традиция не использовать пространства имен. Я не решился пойти против нее. Как вы считаете, уместно ли ввести пространство имен?

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

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

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Arduino UNO
//
////////////////////////
//  РЕДАКТОР и ИСПОЛНИТЕЛЬ ЭФФЕКТОВ ДЛЯ СВЕТОДИОДНОГО КУБА 6*6*6

#include <ps2.h>//библиотеку подключаем для работы с мышью по протоколу ps/2
#include <SPI.h>
#include <SD.h>
#include <LedControl.h>
///////////////////////////////////////////

const uint8_t PIN_CS = 10;//CS-10;SCK,CLK-13;MISO-12;MOSI-11 подключение выводов платы                         
File myFile;     
///////////////////////////////////////////
#define k1 6
 int x=0;int y=0;int z=0;
 int n=150;//единица длительности переключений в мс
 const int N=500;//размер массива
 int N1=0;
 long Y1=0;//переменная хранения значения времени
 long C=0;//переменная для обработки данных с пикселя
boolean flag_A=0;//сигнальный флажoк
boolean flag_B=0;//сигнальный флажoк
boolean flag_C=0;//сигнальный флажoк
boolean flag_D=0;//сигнальный флажoк
byte mas_buf[216]={};//массив для текущего хранения состояния светодиодов куба 
byte massiv_A[N]={};//массив для хранения записанных картинок-кадров
int i=0;//счётчик
int j=0;//счётчик
int l=0;//счётчик
int m=0;//счётчик
int h=0;//счётчик 
int s=0;//счётчик
int p=0;//счётчик
int i1=0;//счётчик
String inputString="";//переменная хранения строки
////////////////////////////////////////////
PS2 mouse(4, 5);//к Pin 5 -  подключена линия Data (оранжевый провод), а к pin 4 – линия Clock (белый провод),Vcc - синий, GND- зелёный
  int mstat;//значение указывает на состояние кнопок и направление движения или покоя мыши
  int mx;//приращение координаты x
  int my;//приращение координаты y
  int mz;//приращение координаты z
  char IM_mouse_flag = 0; // флаг, что у нас включено расширение Intellimouse

//////////////////////////////////////////////////////////////
void mouse_init()
{
  mouse.write(0xff);  // reset
  mouse.read();  // ack byte
  mouse.read();  // blank */
  mouse.read();  // blank */
  mouse.write(0xf0);  // remote mode
  mouse.read();  // ack
  delayMicroseconds(100);
}
///////////////////////////////////////////////////////////////
LedControl LC = LedControl(9, 8, 7, 6);// создаём объект класса для 6 индикаторов
// при этом выводы 9-DIN 8-CLK 7-CS //
///////////////////////////////////////////////////////////////
void setup()
{
  ///////////////////////
  pinMode(6,INPUT);
 if(digitalRead(6)==HIGH){flag_D=1;}else{flag_D=0;}//условие переключения редактора (0) на исполнителя (1)
  //////////////////////
 for(i=0;i<N;i++){massiv_A[i]=255;}//начальное заполнение массива
 
//  strip1.begin();
  Serial.begin(9600);
  mouse_init();
  SD.begin(PIN_CS);
  for (i=0;i<=5;i++)
   {  
  LC.shutdown(i, false);//выключаем энергосберегающий режим
  LC.setIntensity(i,4 );// устанавливаем интенсивность в 4 единиц между 0 и 15
  LC.clearDisplay(i);//очищаем матрицу i
   }
  ///////////////////////////////////////////
   // Посылаем 200, 100, 80
  mouse.write(0xF3); // set sample rate to...
  mouse.write(200);  // 200
  mouse.read();      // ignore ack
  mouse.write(0xF3); // set sample rate to...
  mouse.write(100);  // 100
  mouse.read();      // ignore ack
  mouse.write(0xF3); // set sample rate to...
  mouse.write(80);   // 80
  mouse.read();      // ignore ack

  mouse.write(0xF2); // get device ID
  mouse.read();      // ignore ack
  IM_mouse_flag = (mouse.read() == 0x03); // если подключена мышь с колёсиком
 
}

//////////////////////////////////////////////////////////////
void loop()
{
  if(flag_D==1)//если режим исполнитель
  {
      for(p=0;;p++)//верхний предел для p 10 (по числу эффектов в файле на карте)
  {
        funkz_ispolnitel_SD (p);//загрузить эффект под номером p
metka3: funkz_proigr (5);//повторить 5 раз
        if(flag_C==1){goto metka3;}//условие зацикливания одного и того же эффекта
  }
    }
  else {funkz_cursor();}//иначе режим редактор

}

///////////////////////////////////////////////////////////////////
void funkz_moise ()//функция запроса данных от мышки 
{
  mouse.write(0xeb);  // команда на чтение данных
  mouse.read();      //  игнорируем ack
  mstat = mouse.read();//например,когда мышь неподвижна и кнопки отпущены значение равно 8, при движении по четвертям принимает значения 8,24,40,56
  mx = mouse.read();if(mx>127){mx=mx-255;}//меняется в диапазоне -127 +127
  my = mouse.read();if(my>127){my=my-255;}//меняется в диапазоне -127 +127
  if(IM_mouse_flag)
  mz = mouse.read();if(mz>7){mz=mz-255;}//меняется в диапазоне -7 +7 
  }
/////////////////////////////////////////////////////////////////
 void funkz_cursor ()//функция движения - рисования курсором
 {
funkz_moise ();
 if(mstat==9||mstat==25||mstat==41||mstat==57){flag_A=1;}
 if(flag_A==1){ LC.setLed(z, x, y,1);N1=x+k1*y+k1*k1*z;mas_buf[N1]=1; }//если левая кнопка кратко нажата курсор оставляет след
 if(flag_A==0) { LC.setLed(z, x, y,0);N1=x+k1*y+k1*k1*z;mas_buf[N1]=0; }// иначе гашение предыдущего положения курсора
  ///////////////////
  if(mx>15){z++;if(z>5){z=5;}} if(mx<-15){z--;if(z<0){z=0;}}//условия присвоения новых значений координат курсора по приращениям 
  if(my<-15){y++;if(y>5){y=5;}} if(my>15){y--;if(y<0){y=0;}}//координат от мыши (ориентация осей z и x систем координат разная)
  if(mz<0){x++;if(x>5){x=5;}} if(mz>0){x--;if(x<0){x=0;}}
  ///////////////////
  if(mx>5||mx<-5||my>5||my<-5||mz>0||mz<0){flag_A=0;}
  LC.setLed(z, x, y,1);  //включение нового положения курсора 
  ///////////////////////////////////////////
  if(mstat==10||mstat==26||mstat==42||mstat==58){funkz_zapis ();}//загрузка текущего кадра в массив по нажатию правой кнопки
 
  
  if(mstat==12){funkz_ispol ();}//воспроизведение кадров из массива по нажатию средней кнопки-колеса
 // if(mstat==28||mstat==44||mstat==60){r=!r;g=!g;b=random(0,2);funkz_ispol ();}//воспроизведение кадров из массива по нажатию средней кнопки-колеса со сменой цвета кадров при движениях мышью
  
  if(mstat==11||mstat==27||mstat==43||mstat==59){funkz_zapis_SD ();}//запись массива кадров на SD карту по нажатию дублем левой и правой кнопки

  
  ///////////////////////////////////////////
  delay(n);//регулировка чуствительности мыши  
 
 }
////////////////////////////////////////////////////////////////
void funkz_ispol ()//функция проигрывания записанных картинок-кадров из массива
{
  //for(i=0;i<125;i++){strip1.setPixelColor(i, strip1.Color(0,0,0));}//выключаем все пиксели
  funkz_ekran();//очистка матриц куба,выключаем все светодиоды
  for(j=0;j<N;j++)
  {
  if(massiv_A[j]<216){N1=massiv_A[j];z=N1/(k1*k1);y=(N1-k1*k1*z)/k1;x=N1-k1*k1*z-k1*y;LC.setLed(z, x, y,1);}
  if(massiv_A[j]==227)
  {
   delay(n); funkz_ekran();//выключаем все светодиоды 
  }
  if(massiv_A[j]==255){break;}
  }
   x=0;y=0;z=0;//возвращение курсора в исходную точку
  }
  //////////////////////////////////////////////////////////////
  void funkz_zapis ()//функция записи текущей картинки-кадра
  {
   
   for(i=0;i<216;i++)
   {
     if(mas_buf[i]==1){massiv_A[l]=i;l++;if(l>N-1){l=0;}mas_buf[i]=0;}
   }
   massiv_A[l]=227;l++;if(l>N-1){l=0;}// окончание кадра - число 227
   funkz_ekran(); x=0;y=0;z=0;//обновление картинки и возвращение курсора в исходную точку
  }
  /////////////////////////////////////////////////////////////
  void funkz_zapis_SD ()//функция записи массива кадров на карту памяти
  { 
     m=0;//счётчик числа элементов массива
   if(massiv_A[0]!=255){
    myFile = SD.open("DANMAS.txt", FILE_WRITE);
   if(myFile)
   {
   
    while(massiv_A[m]!=255)//пока не дошли до конца данных по пикселям
    {
      if(massiv_A[m]<216){myFile.print(massiv_A[m]);myFile.print(',');}
      if(massiv_A[m]==227){myFile.print(massiv_A[m]);myFile.print('\n');}
      m++; 
    }
    myFile.print(255);myFile.print('\n');//символы завершения набора кадров одного эффекта
     myFile.close(); 
   }
   }
   //////////////////////////////////////////////////////////////////////////
   for(i=0;i<N;i++){massiv_A[i]=255;}l=0;//очистка или начальное заполнение массива программы после записи на карту
  }
  /////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////
  //////////////////////////////////////////////////////////////
  void funkz_moise_ISPOL ()//функция запроса данных от мышки в режиме исполнитель 
{
  mouse.write(0xeb);  // команда на чтение данных
  mouse.read();      //  игнорируем ack
  mstat = mouse.read();//например,когда мышь неподвижна и кнопки отпущены значение равно 8, при движении по четвертям принимает значения 8,24,40,56
  mx = mouse.read();if(mx>127){mx=mx-255;}//меняется в диапазоне -127 +127
  my = mouse.read();if(my>127){my=my-255;}//меняется в диапазоне -127 +127
  if(IM_mouse_flag)
  mz = mouse.read();if(mz>7){mz=mz-255;}//меняется в диапазоне -7 +7 
  ///////////////////////////////////////////////
 
  if (mstat==9){n=n+1;if(n>500){n=500;}}//левая кнопка - медленнее скорость переключения
  if (mstat==10){n=n-1;if(n<20){n=20;}}//правая кнопка - быстрее скорость переключения
  if (mstat==11){flag_C=!flag_C;}//правая и левая кнопка дублем-смена режима исп.эфф.
 
  if (mstat==12){delay(5000);}//стоп-кадр или пауза на 5 секунд
  }
/////////////////////////////////////////////////////////////////
  void funkz_ispolnitel_SD (int st)//функция чтения файла с карты в массив программы 
  {
   for(i=0;i<N;i++){massiv_A[i]=255;}// начальное заполнение массива программы для чтения с карты
   i=0;// обнулили значение счётчика
   s=0;// обнулили значение счётчика
   flag_A=0;//взведение флага
   myFile = SD.open("DANMAS.txt");
   if (myFile) {
    while (myFile.available()) {
  char inChar = (char)myFile.read();
    if (inChar==','||inChar=='\n'){//если считали символ запятой или переноса строки...
     int perem=inputString.substring(0).toInt();//...преобразовали и занесли в массив предшествующее число
     ////////////////////////////////
     
     if (i>=N){goto metka;}
     if (s==st&&flag_A==0){flag_A=1;}
     if(flag_A==1){massiv_A[i]=(byte)perem;if (massiv_A[i]==255){goto metka;}i++;}
     if(perem==255){s++;}
     
     inputString="";// обнулили переменную 
     ////////////////////////////////
    }
    else {
     inputString += inChar;//пишем цифры символами в переменную 
    }
    }
    p=-1;//условие зацикливания исполнений неограниченного числа эффектов в файле
  metka: myFile.close();
   }
   
  }
  /////////////////////////////////////////////////////////////
  void funkz_proigr (int v)//повторение эффекта v раз
{
  h=0;//
  while (h<v)//условие числа повторений одного эффекта
  {
  for(i=0;i<N;i++)
   {
     if(massiv_A[i]==255){h++;break;}
      if(massiv_A[i]==227){ delay_(n); funkz_ekran();}
      if (massiv_A[i]!=227&&massiv_A[i]!=255){N1=massiv_A[i];z=N1/(k1*k1);y=(N1-k1*k1*z)/k1;x=N1-k1*k1*z-k1*y;LC.setLed(z, x, y,1);}
    } 
  }
 
}
 //////////////////////////////////////////////////////////////////////////////////////////////////////
 ////  ФУНКЦИИ ОПИСАНИЕ // вместо задержки времени через delay  ///////////////////////////////////////
void delay_(int T1)
{
long Y=millis();
flag_B=1;
 while(millis()-Y<T1) 
  {
  if(flag_B==1){funkz_moise_ISPOL ();if(mstat!=8){flag_B=1;}}//если мышь побескоили 
  }
}
 ///////////////////////////////////////////////////////////////////////////////////////////////////////
void funkz_ekran()// функция очистки слоёв куба
  {
     for (i1=0;i1<=5;i1++)
   {  
    LC.clearDisplay(i1);//очищаем матрицу i
   }
    }
  ///////////////////////////////////////////////////////////// 

 

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

Уважаемый автор библиотеки!, собрал куб на 6 матрицах с использованием библиотеки "ледконтролл" для рисования эффектов без программирования. Вы вроде её как исходную использовали. Всё работает нормально, но краем глаза видно мерцание при смене кадров. Связываю это с тем, что "поточечно" библиотека отрисовывает медленно. Подскажите, Ваша будет работать быстрее? Пробывал на ранних вариантах аппаратный SPI - мерцание такое же.

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

Лекс, насчёт LedControl всё понятно: в ней используется своя spiTransfer(), в котором делается shiftOut(), внутре которой сплошные digitalWrite(). А с хардварным SPI ты работал руками или библиотечке какой-то поверил?

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

sadman41 пишет:

Лекс, насчёт LedControl всё понятно: в ней используется своя spiTransfer(), в котором делается shiftOut(), внутре которой сплошные digitalWrite(). А с хардварным SPI ты работал руками или библиотечке какой-то поверил?

есть библиотека LedControl, допиленная под хардв. SPI. (LedControl_HW_SPI-master.zip). Кубами я не мигал, а вывод на китайский 8-разрядный 7-сегм. модуль реально значительно быстрее (автор обещает Speed increase is 20x or greater).

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

sadman41 пишет:

Лекс, насчёт LedControl всё понятно: в ней используется своя spiTransfer(), в котором делается shiftOut(), внутре которой сплошные digitalWrite(). А с хардварным SPI ты работал руками или библиотечке какой-то поверил?

Не, у меня нет таких способностей, проверял этой же библиотекой, только на других выводах платы (где сейчас  SD карта висит). Просто аналогичный куб 555 на WS2812b с "почти таким же скетчем" без мерцаний сколь угодно быстро (пока глаз не перестаёт различать кадры по отдельности), а здесь жестко-медленно. Опять же думалось, что есть библиотека без "дигитал..." внутри. 

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

leks пишет:

Не, у меня нет таких способностей, проверял этой же библиотекой, только на других выводах платы (где сейчас  SD карта висит). 

Вобщем, библиотеке без разницы, какие пины ей передают - всё равно будет digitalWrite(). SLKH выше привёл вариант - спытай.

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

leks пишет:

sadman41 пишет:

Лекс, насчёт LedControl всё понятно: в ней используется своя spiTransfer(), в котором делается shiftOut(), внутре которой сплошные digitalWrite(). А с хардварным SPI ты работал руками или библиотечке какой-то поверил?

Не, у меня нет таких способностей, проверял этой же библиотекой, только на других выводах платы (где сейчас  SD карта висит). Просто аналогичный куб 555 на WS2812b с "почти таким же скетчем" без мерцаний сколь угодно быстро (пока глаз не перестаёт различать кадры по отдельности), а здесь жестко-медленно. Опять же думалось, что есть библиотека без "дигитал..." внутри. 

я про неё писал. 

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

Попробую разобраться с ней.

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

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

leks пишет:

17:45 Попробую разобраться с ней.

leks пишет:
18:09  Почитал быстренько, ума не хватает

Слишком "быстренько". Почитайте пообстоятельнее, тогда хватит.

leks пишет:
обе библиотеки (для SD тоже) используют одни и те же выводы, 11,12,13.
И ещё 100500 библиотек тоже. Это особые пины. Они всем нравятся. Вот и читайте.

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

CS-ы разные назначай всем, кто на SPI сидит, библиотеки потом сами разберутся (теоретически).

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

http://www.gaw.ru/html.cgi/txt/interface/spi

Навскидку нашёл такой материал, но матрицы явно по другой схеме включены.

По ходу такая. То есть получается SD по одной, матрицы по другой. А так можно?

nik182
Offline
Зарегистрирован: 04.05.2015

Очень уж на вскидку. Последняя картинка только показывает что читают 3 модуля одновременно, а вот ответить может только третий. Два других отвечают следующему. Это очень специфическая схема включения. По матрицам информация гонится до конца, да линия активации где? 

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

leks пишет:

Это твоя схема. SPI #0 - Max-ы, SPI #1 - SD и т.п.

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

nik182 пишет:

Очень уж на вскидку. Последняя картинка только показывает что читают 3 модуля одновременно, а вот ответить может только третий. Два других отвечают следующему. Это очень специфическая схема включения. По матрицам информация гонится до конца, да линия активации где? 

Ну вот такие у меня модули с входами-выходами. Да, возврата от крайнего модуля нет. Три "сигнальных" входят и выходят, а на карте 4. Вот и получается хитрая комбинация - "параллельно-последовательному каскаду" (CS или SS на отдельный пин для матриц и карты).

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

leks пишет:

Вот и получается хитрая комбинация - "параллельно-последовательному каскаду" (CS или SS на отдельный пин для матриц и карты).

Load, он же CS. Остальные модули по цепочке к первому присоединить, полагаю.

Image result for max7219 spi

nik182
Offline
Зарегистрирован: 04.05.2015

Согласно мануалу данные гонятся в 16 бит - 4 адрес и 8 дата. Так что не в подряд, а адресно. Вот команды на активацию нет. Данные сразу вываливаются на выход в выбранном разряде, зато можно менять в любом порядке. Каскадировать можно. 

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

nik182 пишет:

Согласно мануалу данные гонятся в 16 бит - 4 адрес и 8 дата. Так что не в подряд, а адресно. Вот команды на активацию нет. Данные сразу вываливаются на выход в выбранном разряде, зато можно менять в любом порядке. 

Прозвонил контакты тестером, похоже такая схема должна быть. Или нет? И как карту ставить? Параллельно к CLK, MOSI, MISO и отдельно SS?

nik182
Offline
Зарегистрирован: 04.05.2015

Да такая. На микросхеме MISO это 24 нога DOUT. MOSI -1, CS - нет у 7219 - она по положительному фронту CS работает LOAD называется 12. 

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

То есть так можно собрать-переподключить, поменять в скетче номера соответствующих (для матриц) выводов и куб хотя бы сможет работать? А потом менять библиотеку .

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

Или работать не будет, так как "ледконтролл" не поддерживает аппаратный SPI?, и сразу надо менять библиотеку.

nik182
Offline
Зарегистрирован: 04.05.2015

Не лазил в ледконтрол, но правил другие библиотеки на предмет общения с железом. В часности к аппаратному i2c добавлял программный для общения с несколькими АЦП MCP3421 c одним адресом. Обычно в библиотеках аппаратный вывод сосредоточен в виде нескольких функций в приватной секции. Даже если ледконтрол не заточен под аппратный SPI не вижу никаких препятствий его туда допилить. 

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

nik182 пишет:

Не лазил в ледконтрол, но правил другие библиотеки на предмет общения с железом. В часности к аппаратному i2c добавлял программный для общения с несколькими АЦП MCP3421 c одним адресом. Обычно в библиотеках аппаратный вывод сосредоточен в виде нескольких функций в приватной секции. Даже если ледконтрол не заточен под аппратный SPI не вижу никаких препятствий его туда допилить. 

Что то я совсем дремучий... Есть в "природе" библиотеки работающие с матрицами по аппаратному SPI (автор библиотеки данной темы), есть встроенные в "ИДЕ"библиотеки "SPI"  и "SD". Но совместимы они между собой в работе по схеме (последней)? Или искать может быть бесполезно. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

leks пишет:

Что то я совсем дремучий ... есть встроенные в "ИДЕ"библиотеки "SPI"  и "SD". Но совместимы они между собой

Что Вам мешает открыть их текст и посмотреть? Вы бы легко обнаружили в тексте SD такую кончтрукцию

#include <SPI.h>

и поняли бы, что она (SD) работает с SPI не сама по себе, а через штатную библиотеку SPI.

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

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

:) Намёк понял - рыться в библиотеках, есть ли там ссылка на SPI... Но такая только библиотека из 7 сообщения. Но заработают ли они вместе с SD?, по такой схеме. 

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

Должны заработать. С CS там, вроде правильно обращаются:

void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
...
 digitalWrite(SPI_CS,LOW);
    //Now shift out the data
    SPI.beginTransaction(SPISettings(100000000, MSBFIRST, SPI_MODE0));
    for(int i=maxbytes;i>0;i--)
	SPI.transfer(spidata[i-1]);
//       shiftOut(MOSI,SCK,MSBFIRST,spidata[i-1]);
    //latch the data onto the display
    SPI.endTransaction();
    digitalWrite(SPI_CS,HIGH);
}

Даже, можно, думаю её подфиксить и цикл с трансфером байта заменить на SPI.transfer(buffer, size)

PRC
Offline
Зарегистрирован: 03.02.2019

Есть мнение, что строку №5 лучше перенести с секцию инициализации)))

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

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

Ну или придётся все исходники прожекта перековырять и "оптимизировать" на предмет однократной настройки SPI.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

"Трансферы" из других библиотек могут перестраивать режимы, 

Дело даже не в этом. Если в приложени используется несколько устройств и не дай Бог что-то используется из прерывания, то пара "скобок" BeginTransaction - EndTransaction предохраняет от вклинивания одного в другое. Пока не отработает EndTransaction новая BeginTransaction не сунется.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

PRC пишет:

Есть мнение, что строку №5 лучше перенести с секцию инициализации)))

Тогда уж строку 10 надо перенести "на".

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

ЕвгенийП пишет:

Дело даже не в этом. Если в приложени используется несколько устройств и не дай Бог что-то используется из прерывания, то пара "скобок" BeginTransaction - EndTransaction предохраняет от вклинивания одного в другое. Пока не отработает EndTransaction новая BeginTransaction не сунется.

А, не... я только про SPISettings писал. Других осмысленных оптимизаций в том фрагменте не вижу. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

А, не... я только про SPISettings писал. Других осмысленных оптимизаций в том фрагменте не вижу. 

Ну, тогда я вообще не вижу оптимизации. BeginTransaction по-любому инициализирует SPI - без вариантов.

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

То есть можно скачивать, ставить и разбираться чем отличается от оригинальной в плане написания функций в скетче моём.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

leks пишет:

То есть можно скачивать, ставить и разбираться чем отличается от оригинальной в плане написания функций в скетче моём.

Вы как-то неуверенно, дрожащими руками ... не бойтесь Вы ничего!!! Ставьте, пробуйте, смотрите. Только так научитесь. Что значит "можно скачивать"? Вам кто-то запрещал? Вы разрешения спрашиваете? Вы не нуждаетесь ни в чьём разрешении!!!  Делайте, наступайте на грабли, прикладывайтё лёд к шишке и делайте по-другому. Только так Вы будете совершенстоваться.

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

ЕвгенийП пишет:

leks пишет:

То есть можно скачивать, ставить и разбираться чем отличается от оригинальной в плане написания функций в скетче моём.

Вы как-то неуверенно, дрожащими руками ... не бойтесь Вы ничего!!! Ставьте, пробуйте, смотрите. Только так научитесь. Что значит "можно скачивать"? Вам кто-то запрещал? Вы разрешения спрашиваете? Вы не нуждаетесь ни в чьём разрешении!!!  Делайте, наступайте на грабли, прикладывайтё лёд к шишке и делайте по-другому. Только так Вы будете совершенстоваться.

Ну вот попробовал через IDE и zip архив. В папке с библиотеками есть, а в меню нет. Мешает "старая LedControl"?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Не знаю. Я никогда не ставил библиотек через какие-то архивы и никогда не смотрел какие там библиотеки в меню у IDE (даже не знаю где они там, слышал, что есть). Всегда руками копирую в фолдер libraries, руками вставляю #include и никогда на этот счёт не парюсь.

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

ЕвгенийП пишет:

Не знаю. Я никогда не ставил библиотек через какие-то архивы и никогда не смотрел какие там библиотеки в меню у IDE (даже не знаю где они там, слышал, что есть). Всегда руками копирую в фолдер libraries, руками вставляю #include и никогда на этот счёт не парюсь.

Распаковал архив, папку с новой библиотекой вставил вместо старой в "либрарис", библиотека опозналась с таким же именем. Попробовал проверить свой скетч - выскочила ошибка в строке инициализации матриц.

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

59 строка в моём скетче.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, читайте чо за ошибка и решайте проблемы. Чего Вы с каждым сраным сообщением компилятора сюда-то бежите. Работайте.

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

Ёлки - моталки, должна же быть преемственность, раз имя тоже.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

leks пишет:

должна 

Кому это она так задолжала?

nik182
Offline
Зарегистрирован: 04.05.2015

Нет такого требования. Каждый пишет как хочет. Дисплей пример. Библиотек полно с одними и  теми же именем. А даже инициализация разная, не  говоря об прочих готолайн.

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

nik182 пишет:

Нет такого требования. Каждый пишет как хочет. Дисплей пример. Библиотек полно с одними и  теми же именем. А даже инициализация разная, не  говоря об прочих готолайн.

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

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

Да и разбираться придётся не 5 минут с примерами (если они там есть)... раз так делают.

nik182
Offline
Зарегистрирован: 04.05.2015

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

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

nik182 пишет:

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

Почему не разбираясь. Про "ледконтрол" читал год или больше назад, доходчивых статей за функции библиотеки хватает - всё ясно, просто и по русски. В данном поделии как раз не хватало функции считывания состояния светодиода куба, но обошёлся и без неё (в ущерб ресурсам платы).

Разбираться под настроение надо - в этом наверно затык.

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

Сравнил примеры в библиотеках - одинаковы (в инициализации 4 аргумента). Сравнил  cpp. у двух библиотек, в "спишной" вроде 2 против 4 у исходной аргумента. Не для моих это средних умов. Но на досуге можно поэкспериментировать.