DMD_STM32 - версия библиотеки DMD для СТМ32Дуино

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 - а сколько матриц всего подключено? Реально по три на каждый канал, как указано в коде?

 

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 - собрал заново свой макет с матрицами, тестирую - что-то у меня тоже не работает первый SPI. Ни в паре со вторым, ни отдельно

Буду разбираться.

b707
Offline
Зарегистрирован: 26.05.2017

еще раз привет, похоже нашел проблему. Когда мы тут с одним из участников подбирали настройки таймеров, чтобы не было мерцания - я их тестировал только на SPI2. Оказывается, Timer3_CH1 несовместим с SPI1. Поменял на CH4 - все заработало.

В твоем примере строчки 88 - 92 нужно заменить вот на эти:

 // initialize Timer
    Timer3.setMode(TIMER_CH4, TIMER_OUTPUTCOMPARE);
    Timer3.setPeriod(1000);          // in microseconds
    Timer3.setCompare(TIMER_CH4, 1); // overflow might be small
    Timer3.attachInterrupt(TIMER_CH4, ScanDMD);

Проверил, теперь все работает.

Отпишись, плиз, о результате.

lean_74
Offline
Зарегистрирован: 22.12.2015

Подключено по три панели, строчки поменял, даже не компилируется

double_dmd2:21:19: error: no matching function for call to 'SPIClass::SPIClass(int)'

In file included from C:\Arduino\arduino-1.8.9\libraries\DMD_STM32-master/DMD_STM32.h:37:0,

                 from C:\Users\****\Documents\Arduino\double_dmd2\double_dmd2.ino:13:

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note: candidate: constexpr SPIClass::SPIClass()

 class SPIClass {

       ^

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note:   candidate expects 0 arguments, 1 provided

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note: candidate: constexpr SPIClass::SPIClass(const SPIClass&)

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note:   no known conversion for argument 1 from 'int' to 'const SPIClass&'

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note: candidate: constexpr SPIClass::SPIClass(SPIClass&&)

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note:   no known conversion for argument 1 from 'int' to 'SPIClass&&'

double_dmd2:22:20: error: no matching function for call to 'SPIClass::SPIClass(int)'

In file included from C:\Arduino\arduino-1.8.9\libraries\DMD_STM32-master/DMD_STM32.h:37:0,

                 from C:\Users\****\Documents\Arduino\double_dmd2\double_dmd2.ino:13:

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note: candidate: constexpr SPIClass::SPIClass()

 class SPIClass {

       ^

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note:   candidate expects 0 arguments, 1 provided

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note: candidate: constexpr SPIClass::SPIClass(const SPIClass&)

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note:   no known conversion for argument 1 from 'int' to 'const SPIClass&'

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note: candidate: constexpr SPIClass::SPIClass(SPIClass&&)

C:\Arduino\arduino-1.8.9\hardware\arduino\avr\libraries\SPI\src/SPI.h:156:7: note:   no known conversion for argument 1 from 'int' to 'SPIClass&&'

double_dmd2:34:19: error: 'PB11' was not declared in this scope

C:\Users\****\Documents\Arduino\double_dmd2\double_dmd2.ino:40:9: note: in expansion of macro 'DMD_PIN_A'

double_dmd2:35:19: error: 'PB10' was not declared in this scope

C:\Users\****\Documents\Arduino\double_dmd2\double_dmd2.ino:40:20: note: in expansion of macro 'DMD_PIN_B'

double_dmd2:45:22: error: 'PA8' was not declared in this scope

C:\Users\****\Documents\Arduino\double_dmd2\double_dmd2.ino:49:34: note: in expansion of macro 'DMD2_PIN_nOE'

double_dmd2:46:23: error: 'PB8' was not declared in this scope

C:\Users\****\Documents\Arduino\double_dmd2\double_dmd2.ino:49:48: note: in expansion of macro 'DMD2_PIN_SCLK'

C:\Users\****\Documents\Arduino\double_dmd2\double_dmd2.ino: In function 'void setup()':

double_dmd2:94:5: error: 'Timer3' was not declared in this scope

double_dmd2:94:20: error: 'TIMER_CH4' was not declared in this scope

double_dmd2:94:31: error: 'TIMER_OUTPUTCOMPARE' was not declared in this scope

exit status 1
no matching function for call to 'SPIClass::SPIClass(int)'

IDE 1.8.9 , может тут проблема?

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 - судя по выводу ошибок, вы пытаетесь компилировать для платы avr, а это код для СТМ32

lean_74
Offline
Зарегистрирован: 22.12.2015

пардон, сам заметил поздно, комп глюканул, перегрузил , заработало.

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

пардон, сам заметил поздно, комп глюканул, перегрузил , заработало.

уточните - работает по три матрицы на каждый канал? А то у меня всего 2 матрицы. тестировать не на чем :)

 

lean_74
Offline
Зарегистрирован: 22.12.2015

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

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:
Работают все три, но как было замечено выше, загораются паразитные пиксели и иногда притормаживает, потом опять бежит нормально. Вечером видео сниму, выложу на Ютуб.

понятно. Если видео для меня - можете не снимать :) У меня все так же.

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

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

 

 

b707
Offline
Зарегистрирован: 26.05.2017

Обновил версию на Гитхабе с учетом последних замечаний и исправлений

 - добавлен вертикальный скролл с примерами для СТМ и Уно

- исправлены ошибки в примерах

- изменены настройки таймера в примерах для СТМ

 

О ошибках сообщайте

lean_74
Offline
Зарегистрирован: 22.12.2015

Дима, а может вывод на матрицу повлиять на работу аппаратного UART1 или UART2 ? пробовал "поженить" ПроМини и stm32 на обоих Serial1 и  Serial2,  Мастер ПроМини, слэйф stm32, последняя какой-то бред выдает. Думал может сам чего накосячил в коде - проверил на двух мегах все нормально. И если это так , как передать данные от меги в stm-ку по UART или как-то еще? Передаю несколько цифр от 0 до 9, разделенные запятыми. что-то типа этого

1,5,5,5,5
0,5,5,5,5
1,5,5,5,5
2,5,5,5,5
2,5,6,5,5
2,5,7,5,5
2,5,8,5,5
2,5,9,5,5
1,5,9,5,5
2,5,9,5,5
3,5,9,5,5
3,5,9,4,5
3,5,9,3,5

 

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

Дима, а может вывод на матрицу повлиять на работу аппаратного UART1 или UART2 ?

ну так это ж легко проверить - временно закомментируйте в коде вывод на матрицу и посмотрите, наладится ли Сериал

lean_74
Offline
Зарегистрирован: 22.12.2015

разобрался, пока мега отправляет очередной символ по Uart-у, stm32  успевает несколько сотен, а может и больше циклов loop() выполнить.

lean_74
Offline
Зарегистрирован: 22.12.2015

Вопрос остался открытым: Как передать данные с Меги на STM32, при одновременном использоваться двух независимых экземпляров DMD? читаю так

 String bufer="";

void setup(){ 
  Serial.begin(9600); 
  Serial.println("duino started");
}

void loop(){
  read_serial();

}

void read_serial() {
  if (Serial.available() > 0) {
    char ByteRead=Serial.read();  //чтение данных с порта
    if (ByteRead==13) {  //возврат каретки
      analyzer();   //передача данных на обработку
      bufer="";
    }  //освобождение буфера
    else {
      ///накопление данных в буфер
      if(ByteRead!=10)bufer=bufer+char(ByteRead); // символ "новая строка" \n, нам в буффере не нужен
    }   
  }
}

void analyzer() {
  if (bufer.length()>0) {
    Serial.println(bufer);
  } //если буфер не пустой

}

Дим может все же подскажешь как победить? а я тебе платку такую готовую с часиками пришлю

b707
Offline
Зарегистрирован: 26.05.2017

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

Я сейчас до завтрашнего вечера уеду, но если ты напишешь - я завтра посмотрю.

lean_74
Offline
Зарегистрирован: 22.12.2015

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

b707
Offline
Зарегистрирован: 26.05.2017

А какой длины пакет данных, что передаешь?

lean_74
Offline
Зарегистрирован: 22.12.2015

с пробелами 24 байта, Дима напиши мне на почту, пож.

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

с пробелами 24 байта, Дима напиши мне на почту, пож.

я что-то адреса теперь не вижу, а вроде днем был. И еще ты днем коды выкладывал - я с телефона заходил, видел. А домой приехал, захожу в конфу - кодов уже нет. Что случилось? Решил вопрос сам?

lean_74
Offline
Зарегистрирован: 22.12.2015

почта МойНик@mail.ru. Решил можно сказать с костылем(#66), естественно, когда отключаю прерывания, экран дергается.Код подправленный, могу выложить только вечером, т.к он на домашнем компе.Ты на почту мне обязательно напиши. 

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

Ты на почту мне обязательно напиши. 

написал

lean_74
Offline
Зарегистрирован: 22.12.2015

код ПроМини

#include <IRremote.h>
#include <EEPROM.h>
//#include <EasyTransfer.h>
//
////create object
//EasyTransfer ET; 
//
//struct SEND_DATA_STRUCTURE{
//  //put your variable definitions here for the data you want to send
//  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
//  byte Send_rejim;
//  byte Send_Rub_Kop[12];
//};
//
////give a name to the group of data
//SEND_DATA_STRUCTURE mydata;

IRrecv irrecv(12); // Указываем пин, к которому подключен приемник
decode_results results;

byte rejim=0;
byte Oldrejim=0;
byte Total_DISPLAYS=3; // всего Экранов 2х3 максимум 7
byte Rub_Kop[12];  // массив со значениями рублей и копеек

void readSet(){
  if (Total_DISPLAYS>7 || Total_DISPLAYS<1){
      Total_DISPLAYS=1; EEPROM.write(50, 3); // в 50-й ячейке храним кол-во экранов
  }else {
//      Total_DISPLAYS= EEPROM.read(50);  // еще надо сделать ввод кол-ва экранов 
  }

//первый запуск  
  for (byte i =0; i < (Total_DISPLAYS*4); i++){
    Rub_Kop[i] = EEPROM.read(i);
    
    if (Rub_Kop[i]>9) {Rub_Kop[i]=8;EEPROM.write(i, Rub_Kop[i]);} 
     
  }
  

 
//первый запуск  
}
void setup()
{
  Serial.begin(9600); // Выставляем скорость COM порта
//  ET.begin(details(mydata), &Serial);
   
  irrecv.enableIRIn(); // Запускаем прием
  readSet();
  rejim=0;
  delay(2000); //  подождем пока stm32 загрузиться
  SendData();
   
}
  void SendData(){
    String dataSennd;
 //   mydata.Send_rejim = rejim;

  //send the data
 
    dataSennd=rejim;
 //  Serial.print(rejim);
//   Serial.print(",");
  for (byte i =0; i < (Total_DISPLAYS*4); i++){ 
    dataSennd=dataSennd+ ",";   

    dataSennd=dataSennd+ Rub_Kop[i];   
//   Serial.print(Rub_Kop[1]);
//  mydata.Send_Rub_Kop[i]=Rub_Kop[i];  
  } 
   Serial.println(dataSennd);
 //  ET.sendData();     
  }

void loop() {
  if (irrecv.decode(&results)) // Если данные пришли 
  {
    switch ( results.value ) {
    case 0xBC253F00:  //меню
//    case 0x807F8A75:  //меню
//    OldKod=0xBC253F00;
        rejim=1;
        SendData();

        break;
    case 0x95AFFB4D:  //право
//    case 0x807F7A85:  //право
//    OldKod=0x95AFFB4D;
if(rejim>0){
  rejim++;
if (rejim>Total_DISPLAYS*4) rejim=1;
  
}
        SendData();
       
        break;
    case 0x845E5420:  // лево
 //   case 0x807FB24D:  // лево
 //   OldKod=0x845E5420; 
if(rejim>0){    
        rejim--;
if ( rejim==0) rejim=Total_DISPLAYS*4;
  
}
        
        SendData();
   
        break;
    case 0x5985AF7D:  // ок
//    case 0x807F827D:  // ок
//    OldKod=0x5985AF7D;     
        rejim=0;
        SendData();

        
        break;
    case 0xEC9A30D9:  //верх
//    case 0x807F9A65:  //верх
//    OldKod=0xEC9A30D9; 
if(rejim>0){ 
Rub_Kop[rejim-1]=Rub_Kop[rejim-1]+1;
if (Rub_Kop[rejim-1]>9) Rub_Kop[rejim-1]=0;
EEPROM.write(rejim-1, Rub_Kop[rejim-1]);  
}
   
        SendData();
        break;
    case 0x99247EBA:  // низ
//    case 0x807FAA55:  // низ
//    OldKod=0x99247EBA;
if(rejim>0){  
Rub_Kop[rejim-1]=Rub_Kop[rejim-1]-1;
if (Rub_Kop[rejim-1]==255) Rub_Kop[rejim-1]=9;
EEPROM.write(rejim-1, Rub_Kop[rejim-1]);    
}
     
        SendData();

       break;
    }
//    Serial.print(results.value, HEX);
//    Serial.print("    DEC  ");
//    Serial.println(results.value, DEC);
//    Serial.print("rejim  ");//Total_DISPLAYS
//    Serial.println(rejim);
//    Serial.print("Total_DISPLAYS  ");//Total_DISPLAYS
//    Serial.println(Total_DISPLAYS);
    delay(100); //пауза между повторами //    
    irrecv.resume(); // принимаем следующую команду
  }

  
}

код stm32

/*--------------------------------------------------------------------------------------
  0 1 4 6 5 4 3 2 1 0 9 0 1
  double_dmd

  Using of two instances of DMD class on SPI(1) and SPI(2)
*/



/*--------------------------------------------------------------------------------------
  Includes
  --------------------------------------------------------------------------------------*/
#include <DMD_STM32.h>
//#include "fonts/SystemFont5x7.h"
#include "st_fonts/Arial_Black_16_ISO_8859_1.h"
#include "st_fonts/UkrRusArial14.h";
//#include "gfx_fonts/GlametrixLight12pt7b.h"
//#include "gfx_fonts/GlametrixBold9pt7b.h"
//#include <EasyTransfer.h>
//

String Str;
String Str2;
const char * msg;

byte rejim = 0;
byte Oldrejim = 0;
byte Total_DISPLAYS = 3; // всего Экранов 2х3 максимум 7
byte Rub_Kop[12];  // массив со значениями рублей и копеек
unsigned long lastMillis = millis();
boolean flag = 0;
boolean clockTime = false; // флаг того что выводим
byte timeRead = 5;
boolean refresh_screen = false;
// We'll use SPI_1 for first DMD and SPI_2 for second
SPIClass dmd_spi(1);
SPIClass dmd_spi2(2);

#define DISPLAYS_ACROSS 3
#define DISPLAYS_DOWN 1

// ----- Select pins for P10 matrix connection ------------
// pins A, B, SCLK may be any digital I/O, pin nOE should be PWM pin as PB1,PA8

// SPI specific pins as CLK and R_DATA has predefined values:
//   for SPI(1) CLK = PA5  R_DATA = PA7
//   for SPI(2) CLK = PB13  R_DATA = PB15
// --------------------------------------------------------
#define DMD_PIN_A PB11
#define DMD_PIN_B PB10
#define DMD_PIN_nOE PB1
#define DMD_PIN_SCLK PB0

//Fire up the DMD library at first as dmd
DMD dmd(DMD_PIN_A, DMD_PIN_B, DMD_PIN_nOE, DMD_PIN_SCLK, DISPLAYS_ACROSS, DISPLAYS_DOWN, dmd_spi );


#define DMD2_PIN_A PB7
#define DMD2_PIN_B PB6
#define DMD2_PIN_nOE PA8
#define DMD2_PIN_SCLK PB8

// and at second as dmd2
DMD dmd2(DMD2_PIN_A, DMD2_PIN_B, DMD2_PIN_nOE, DMD2_PIN_SCLK, DISPLAYS_ACROSS, DISPLAYS_DOWN, dmd_spi2 );

// --- Define fonts ----
// DMD.h old style font
DMD_Standard_Font UkrRusArial_F(UkrRusArial_14);

// GFX font with sepatate parts for Latin and Cyrillic chars
//DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b, (uint8_t*)&GlametrixLight12pt8b_rus, 0x80, 13);
/*--------------------------------------------------------------------------------------
  Interrupt handler for Timer1 (TimerOne) driven DMD refresh scanning, this gets
  called at the period set in Timer1.initialize();
  --------------------------------------------------------------------------------------*/
void ScanDMD()
{
  dmd.scanDisplayBySPI();
  dmd2.scanDisplayBySPI();
}

/*--------------------------------------------------------------------------------------
  setup
  Called by the Arduino architecture before the main loop begins
  --------------------------------------------------------------------------------------*/
int utf8_rus(char* dest, const unsigned char* src) {

  uint8_t i, j;
  for ( i = 0, j = 0; src[i]; i++) {
    if ((src[i] == 0xD0 ) && src[i + 1])  {
      dest[j++] = src[++i] - 0x10;
    }
    else if ((src[i] == 0xD1 ) && src[i + 1]) {
      dest[j++] = src[++i] + 0x30;
    }
    else dest[j++] = src[i];
  }
  dest[j] = '\0';
  return j;
}

void setup(void)
{
  Serial2.begin(9600); //тут получаем данные по UART2
      Serial.begin(115200);
  //    Serial.println("Workin....");

  // initialize Timer
  //    Timer3.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE);
  //    Timer3.setPeriod(1000);          // in microseconds
  //    Timer3.setCompare(TIMER_CH1, 1); // overflow might be small
  //    Timer3.attachInterrupt(TIMER_CH1, ScanDMD);

  Timer3.setMode(TIMER_CH4, TIMER_OUTPUTCOMPARE);
  Timer3.setPeriod(3000);          // in microseconds
  Timer3.setCompare(TIMER_CH4, 1); // overflow might be small
  Timer3.attachInterrupt(TIMER_CH4, ScanDMD);//detachInterrupt

  //clear/init the DMD pixels held in RAM
  dmd.clearScreen( true );   //true is normal (all pixels off), false is negative (all pixels on)
  dmd2.clearScreen( true );

  for (byte i =0; i < (Total_DISPLAYS*4); i++){
   Rub_Kop[i]=8;
   }
   sendChar(clockTime); 
}

/*--------------------------------------------------------------------------------------
  loop
  Arduino architecture main loop
  --------------------------------------------------------------------------------------*/
 boolean pech=0;

void sendChar(boolean blinking) {
  // dmd.drawChar(const int bX, const int bY, const unsigned char letter, byte bGraphicsMode)
  //#define GRAPHICS_NORMAL    0
  //#define GRAPHICS_INVERSE   1
  //#define GRAPHICS_TOGGLE    2
  //#define GRAPHICS_OR        3
  //#define GRAPHICS_NOR       4
  dmd.selectFont(&UkrRusArial_F);
  dmd.setBrightness(2000);
  for (byte i = 0; i < (Total_DISPLAYS * 4); i++) {
    if (rejim != 0) {
      if (rejim == i + 1 && blinking == 1) {
        dmd.drawChar(0 + i * 22 + ((i == 2 || i == 6 || i == 10) ? 8 : 0), 0, ' ', GRAPHICS_NORMAL);
      } else {
        dmd.drawChar(0 + i * 22 + ((i == 2 || i == 6 || i == 10) ? 8 : 0), 0, '0' + Rub_Kop[i], GRAPHICS_NORMAL);
      }
    } else {
      dmd.drawChar(0 + i * 22 + ((i == 2 || i == 6 || i == 10) ? 8 : 0), 0, '0' + Rub_Kop[i], GRAPHICS_NORMAL);
    }
  }
  dmd2.selectFont(&UkrRusArial_F);
  dmd2.setBrightness(2000);
  for (byte i = 0; i < (Total_DISPLAYS * 4); i++) {
    if (rejim != 0) {
      if (rejim == i + 1 && blinking == 1) {
        dmd2.drawChar(0 + i * 22 + ((i == 2 || i == 6 || i == 10) ? 8 : 0), 0, ' ', GRAPHICS_NORMAL);
      } else {
        dmd2.drawChar(0 + i * 22 + ((i == 2 || i == 6 || i == 10) ? 8 : 0), 0, '0' + Rub_Kop[i], GRAPHICS_NORMAL);
      }
    } else {
      dmd2.drawChar(0 + i * 22 + ((i == 2 || i == 6 || i == 10) ? 8 : 0), 0, '0' + Rub_Kop[i], GRAPHICS_NORMAL);
    }
  }  
}

 
void loop(void)
{
  if (read_serial()>0){
    if (Str.length()>0) {
        Timer3.detachInterrupt(TIMER_CH4);//detachInterrupt
     }else{
         Timer3.attachInterrupt(TIMER_CH4, ScanDMD);//detachInterrupt      
     }
  }

  if (flag == 0){
    lastMillis = millis();
    clockTime = !clockTime;
    flag = 1;
  sendChar(clockTime);    
  }

  if (millis() - lastMillis >= timeRead * 100) {
    flag = 0;
  }
 if(refresh_screen){

  process_data();
  sendChar(clockTime);    
  refresh_screen=0;  
  }
}

boolean read_serial() {
  if (Serial2.available() > 0) {
    char ByteRead=Serial2.read();  //чтение данных с порта
    
    if (ByteRead==13) {  //возврат каретки
      analyzer();   //передача данных на обработку
      Str="";
    }  //освобождение буфера
    else {
      ///накопление данных в буфер
//      if(ByteRead!=10)Str=Str+char(ByteRead); // символ "новая строка" \n, нам в буффере не нужен
     Str=Str+char(ByteRead); 
 //    Str += ByteRead;
    return 1; 
    }   
  }else{
    return 0;
  }


}

void analyzer() {
  if (Str.length()>0) {
//    Serial.print("Str= ");
//   Serial.println(Str); // вот тут выводит муть всякую
   Str2=Str;
   refresh_screen=1;
//   msg = Str.c_str(); //преобразовываем массив String в массив char
//   sscanf(msg, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",//берем в десятичном значении
//              rejim,Rub_Kop[0],Rub_Kop[1],Rub_Kop[2],Rub_Kop[3],Rub_Kop[4],Rub_Kop[5],Rub_Kop[6],Rub_Kop[7],Rub_Kop[8],Rub_Kop[9],Rub_Kop[10],Rub_Kop[11] );
//  for (byte i =0; i < (Total_DISPLAYS*4); i++){
//Serial.print("Rub_Kop[");
//Serial.print(i);
//Serial.print("]=");
//Serial.print(Rub_Kop[i]);
//Serial.print(" ");      
//   }
//Serial.println(" ");           
  } //если буфер не пустой
}

void process_data(){
  Serial.println(Str2);
   msg = Str2.c_str(); //преобразовываем массив String в массив char


  for (byte i =0; i < (Total_DISPLAYS*4); i++){
Serial.print("Rub_Kop[");
Serial.print(i);
Serial.print("]=");
Serial.print(Rub_Kop[i]);
if(i==6){
Serial.println(" ");
}else{
Serial.print(" ");  
}

   
}
}


//Скетч использует 26356 байт (40%) памяти устройства. Всего доступно 65536 байт.
//Глобальные переменные используют 5312 байт (25%) динамической памяти, оставляя 15168 байт для локальных переменных. Максимум: 20480 байт.

 

b8hri11
Offline
Зарегистрирован: 11.05.2019

А просто без этой библиотеки передается корректно?
Я где-то читал что uart реализован не аппаратно, а программно, в ядре стм32 для ардуино.
Попробуй сначала прерывание остановить, а потом уже проверить uart, так же были проблемы с кодировкой новой строки попробуй выставить символ какой вместо него.

lean_74
Offline
Зарегистрирован: 22.12.2015

Остановив прерывание передается корректно, но при этом экран дергается. но на это я уже плюнул.

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

Остановив прерывание передается корректно, но при этом экран дергается. но на это я уже плюнул.

Посмотрел код в сообщении #72

ИМХО, ты зря читаешь из сериала по одному символу. Как только в буфере что-то появилось - читай в буфер не один символ, а все что есть. Если надо, могу поправить твой код (но только вечером)

 

lean_74
Offline
Зарегистрирован: 22.12.2015

не одна засада, так другая - это яркость на 20000

а это на 2000

и вообще сколько панелей можно подключить на каждый spi? подключил 9, изображение мигает... замена digitalWrite  в библиотеке на прямую запись в порт решит проблемы? 

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

 сколько панелей можно подключить на каждый spi? подключил 9, изображение мигает... замена digitalWrite  в библиотеке на прямую запись в порт решит проблемы? 

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

lean_74
Offline
Зарегистрирован: 22.12.2015

результаты такие: один spi работает устойчиво 9 панелей, до 11 панелей еще кое-как работает, при 12 панелях происходит срыв изображения. обновление таймера 1000 мксек., надо чтобы работало мин 18 панелей, как победить?

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

результаты такие: один spi работает устойчиво 9 панелей, до 11 панелей еще кое-как работает, при 12 панелях происходит срыв изображения. обновление таймера 1000 мксек., надо чтобы работало мин 18 панелей, как победить?

а что ты туда выводишь? - в смысле строку символов, бегущую строку или статичное изображение?

И еще - попробуй поднять скорость SPI шины - параметр DMD_SPI_CLOCK , примерно 42 строчку файла DMD_STM32.h

 

lean_74
Offline
Зарегистрирован: 22.12.2015

изображение статичное, пробовал SPI_CLOCK_DIV4 и SPI_CLOCK_DIV2, существенной разницы нет, работает на 9 панелях, больше уже дрожит изображение, левые пикселы загораются.

 

lean_74
Offline
Зарегистрирован: 22.12.2015

Еще вопрос, как правильно остановить прерывания по таймеру, и потом снова их запустить, вот так останавливаю



Timer3.detachInterrupt(TIMER_CH4);

потом снова так:

        Timer3.setMode(TIMER_CH4, TIMER_OUTPUTCOMPARE);
        Timer3.setPeriod(1000);          // in microseconds
        Timer3.setCompare(TIMER_CH4, 1); // overflow might be small    
       Timer3.attachInterrupt(TIMER_CH4, ScanDMD);//detachInterrupt

 не запускаются...

b707
Offline
Зарегистрирован: 26.05.2017

Обновление библиотеки - версия v0.3.2 (для СТМ32)
(код на Гитхабе, ссылка в первом сообщении)

с подачи lean_74 найдена и исправлена ошибка задания частоты шины SPI, добавлен вывод через DMA(синхронный)

Главное внешнее изменение - скорость вывода на матрицы выросла примерно в 10-12 раз, в режиме бегущей строки полностью исчезли все "притормаживания" текста. Судя по таймингам вывода, библиотека должна без проблем работать с 16 матрицами на канал без заметного замедления другого кода программы.

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

Cпасибо lean_74 за тестирование кода

 

b707
Offline
Зарегистрирован: 26.05.2017

Обновление  - версия v0.4.1 (для СТМ32)
(ссылка на гит в первом сообщении)

Основные изменения:

 - вывод данных на матрицы через DMA в асинхронном режиме, то есть почти без загрузки микроконтроллера
 - проведена работа по устранению мерцаний и паразитной засветки пикселей, для чего увеличена частота ШИМ регулировки яркости матриц
 - все настройки таймеров "убраны" внутрь библиотеки, пользователю не нужно ничего настраивать
 - восстановлена совместимость с АВР Атмега328(надеюсь :)

Изменения повлекли за собой некоторые изменения в интерфейсе. Для СТМ32 при начале работы с матрицами обязательна функция dmd.init(), вызываемая в setup(). Яркость теперь регулируется от 0 до 255. Подробнее см. примеры.

Важно: Пины n_OE теперь нужно выбирать только из числа тактируемых Timer3 - то есть PB0 PB1 PB5.

b707
Offline
Зарегистрирован: 26.05.2017

Библиотека нуждается в бета-тестерах :) В принципе, по таймингам на осциллографе последние версии выглядят очень неплохо. Теоретически :) на массовой плате blue pill STM32F103C8T6 библиотека должна работать с 30- 40 матрицами на каждом канале. К сожалению, у меня нет достаточного числа матриц, чтобы проверить это вживую. Так что если кто-то захочет сделать свой проект на моей библиотеке - обращайтесь, обещаю авторскую поддержку :)

=== технические детали, можно не читать ===
Каждое сканирование матриц состоит из двух стадий - подготовки данных и передачи. На последней версии 0.4.1 подготовка занимает примерно 15 мкс (+ 3 мкс на каждую следующую панель), передача по SPI - примерно 30 мкс каждая панель (при частоте тактирования SPI 8МГц).
  При использовании асинхронного DMA вторая стадия  (передача данных) происходит в фоновом режиме, не нагружая контроллер и оставляя его свободным для других задач. Таким образом, при подключении 30 матриц центральный контроллер будет занят около 100 мкс - при сканировании раз в 1мс это всего 10% процессорного времени.
=================================

Версия 0.4 реализует весь ранее задуманный функционал, дальше я намерен сосредоточится на исправлении ошибок и документировании.

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

 

lean_74
Offline
Зарегистрирован: 22.12.2015

Проверено на 42 матрицах. Статичные изображения выводятся отлично, в режиме бегущей строки на не задействованных в данный момент панелях, видна легкая засветка в такт бегущей строки.

FoxJone
Offline
Зарегистрирован: 19.04.2019

DIYMan пишет:

Потому как это совершенно чётко - рекламщики, там деньги есть, и не стоит бесплатно халявщиков плодить ;)

Нафиг не сдался рекламщикам DMD, учитывая, что полноценный монохромный контроллер на 20 модулей (в две строки) стоит 3 бакса (меньше 200р). А самый мощный (2048*512 пикселей, то есть 20*5 метров) из мне известных стоит 35$. Это монохром, конечно. Плюс в эти контроллеры встроены часы и поддержка датчика температуры/влажности, то есть даже для часов ДМД не нужен.

ДМД нужен для специализированных табло: весы, ценники, электронная очередь, метеостанция, всякие счетчики, спортивные табло и тому подобное. То есть, где есть необходимость получить откуда то данные и показать их на табло. С этим стандартные контроллеры не справляются.

FoxJone
Offline
Зарегистрирован: 19.04.2019

b707, я желаю с тобой пообщаться, но нигде не нашел контактов.

Черкни мне на evgeny_fox@mail.ru если не трудно