еще раз привет, похоже нашел проблему. Когда мы тут с одним из участников подбирали настройки таймеров, чтобы не было мерцания - я их тестировал только на 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);
Подключено по три панели, строчки поменял, даже не компилируется
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)'
Работают все три, но как было замечено выше, загораются паразитные пиксели и иногда притормаживает, потом опять бежит нормально. Вечером видео сниму, выложу на Ютуб.
Работают все три, но как было замечено выше, загораются паразитные пиксели и иногда притормаживает, потом опять бежит нормально. Вечером видео сниму, выложу на Ютуб.
понятно. Если видео для меня - можете не снимать :) У меня все так же.
"Притормаживание" как будет время, попытаюсь найти и победить - мне кажется это какая-то простая и глупая ошибка в коде...
Паразитные пиксели убираются работой от стабильного БП (во всяком случае. у меня так)
Дима, а может вывод на матрицу повлиять на работу аппаратного UART1 или UART2 ? пробовал "поженить" ПроМини и stm32 на обоих Serial1 и Serial2, Мастер ПроМини, слэйф stm32, последняя какой-то бред выдает. Думал может сам чего накосячил в коде - проверил на двух мегах все нормально. И если это так , как передать данные от меги в stm-ку по UART или как-то еще? Передаю несколько цифр от 0 до 9, разделенные запятыми. что-то типа этого
Напиши подробнее, что именно не работает, я пока не очень понимаю. То, что СТМ32 слишком быстро читает символы - мешать не должно, гораздо хуже когда приемник не успевает.
Я сейчас до завтрашнего вечера уеду, но если ты напишешь - я завтра посмотрю.
Отключил прерывания по таймеру на момент начала приема сигнала по UART, и заново их подключил после приема, данные получил правильные, теперь посмотрю, как это отразиться на вывод на табло...
с пробелами 24 байта, Дима напиши мне на почту, пож.
я что-то адреса теперь не вижу, а вроде днем был. И еще ты днем коды выкладывал - я с телефона заходил, видел. А домой приехал, захожу в конфу - кодов уже нет. Что случилось? Решил вопрос сам?
почта МойНик@mail.ru. Решил можно сказать с костылем(#66), естественно, когда отключаю прерывания, экран дергается.Код подправленный, могу выложить только вечером, т.к он на домашнем компе.Ты на почту мне обязательно напиши.
#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 байт.
А просто без этой библиотеки передается корректно?
Я где-то читал что uart реализован не аппаратно, а программно, в ядре стм32 для ардуино.
Попробуй сначала прерывание остановить, а потом уже проверить uart, так же были проблемы с кодировкой новой строки попробуй выставить символ какой вместо него.
Остановив прерывание передается корректно, но при этом экран дергается. но на это я уже плюнул.
Посмотрел код в сообщении #72
ИМХО, ты зря читаешь из сериала по одному символу. Как только в буфере что-то появилось - читай в буфер не один символ, а все что есть. Если надо, могу поправить твой код (но только вечером)
и вообще сколько панелей можно подключить на каждый spi? подключил 9, изображение мигает... замена digitalWrite в библиотеке на прямую запись в порт решит проблемы?
сколько панелей можно подключить на каждый spi? подключил 9, изображение мигает... замена digitalWrite в библиотеке на прямую запись в порт решит проблемы?
для начала частоту обновления в таймере попробуй поменять
результаты такие: один spi работает устойчиво 9 панелей, до 11 панелей еще кое-как работает, при 12 панелях происходит срыв изображения. обновление таймера 1000 мксек., надо чтобы работало мин 18 панелей, как победить?
результаты такие: один spi работает устойчиво 9 панелей, до 11 панелей еще кое-как работает, при 12 панелях происходит срыв изображения. обновление таймера 1000 мксек., надо чтобы работало мин 18 панелей, как победить?
а что ты туда выводишь? - в смысле строку символов, бегущую строку или статичное изображение?
И еще - попробуй поднять скорость SPI шины - параметр DMD_SPI_CLOCK , примерно 42 строчку файла DMD_STM32.h
изображение статичное, пробовал SPI_CLOCK_DIV4 и SPI_CLOCK_DIV2, существенной разницы нет, работает на 9 панелях, больше уже дрожит изображение, левые пикселы загораются.
Еще вопрос, как правильно остановить прерывания по таймеру, и потом снова их запустить, вот так останавливаю
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
Обновление библиотеки - версия v0.3.2 (для СТМ32)
(код на Гитхабе, ссылка в первом сообщении)
с подачи lean_74 найдена и исправлена ошибка задания частоты шины SPI, добавлен вывод через DMA(синхронный)
Главное внешнее изменение - скорость вывода на матрицы выросла примерно в 10-12 раз, в режиме бегущей строки полностью исчезли все "притормаживания" текста. Судя по таймингам вывода, библиотека должна без проблем работать с 16 матрицами на канал без заметного замедления другого кода программы.
В ближайшее время планирую выложить версию с асинхронным DMA, что позволит снизить нагрузку на микроконтроллер еще примерно на порядок.
Обновление - версия v0.4.1 (для СТМ32)
(ссылка на гит в первом сообщении)
Основные изменения:
- вывод данных на матрицы через DMA в асинхронном режиме, то есть почти без загрузки микроконтроллера
- проведена работа по устранению мерцаний и паразитной засветки пикселей, для чего увеличена частота ШИМ регулировки яркости матриц
- все настройки таймеров "убраны" внутрь библиотеки, пользователю не нужно ничего настраивать
- восстановлена совместимость с АВР Атмега328(надеюсь :)
Изменения повлекли за собой некоторые изменения в интерфейсе. Для СТМ32 при начале работы с матрицами обязательна функция dmd.init(), вызываемая в setup(). Яркость теперь регулируется от 0 до 255. Подробнее см. примеры.
Важно: Пины n_OE теперь нужно выбирать только из числа тактируемых Timer3 - то есть PB0 PB1 PB5.
Библиотека нуждается в бета-тестерах :) В принципе, по таймингам на осциллографе последние версии выглядят очень неплохо. Теоретически :) на массовой плате blue pill STM32F103C8T6 библиотека должна работать с 30- 40 матрицами на каждом канале. К сожалению, у меня нет достаточного числа матриц, чтобы проверить это вживую. Так что если кто-то захочет сделать свой проект на моей библиотеке - обращайтесь, обещаю авторскую поддержку :)
=== технические детали, можно не читать ===
Каждое сканирование матриц состоит из двух стадий - подготовки данных и передачи. На последней версии 0.4.1 подготовка занимает примерно 15 мкс (+ 3 мкс на каждую следующую панель), передача по SPI - примерно 30 мкс каждая панель (при частоте тактирования SPI 8МГц).
При использовании асинхронного DMA вторая стадия (передача данных) происходит в фоновом режиме, не нагружая контроллер и оставляя его свободным для других задач. Таким образом, при подключении 30 матриц центральный контроллер будет занят около 100 мкс - при сканировании раз в 1мс это всего 10% процессорного времени.
=================================
Версия 0.4 реализует весь ранее задуманный функционал, дальше я намерен сосредоточится на исправлении ошибок и документировании.
Если у кого-то есть предложения - готов выслушать. Если нужно добавить в библиотеку двухцветные и полноцветные матрицы - готов заняться, если кто-то предоставит такие панели :)
Проверено на 42 матрицах. Статичные изображения выводятся отлично, в режиме бегущей строки на не задействованных в данный момент панелях, видна легкая засветка в такт бегущей строки.
Потому как это совершенно чётко - рекламщики, там деньги есть, и не стоит бесплатно халявщиков плодить ;)
Нафиг не сдался рекламщикам DMD, учитывая, что полноценный монохромный контроллер на 20 модулей (в две строки) стоит 3 бакса (меньше 200р). А самый мощный (2048*512 пикселей, то есть 20*5 метров) из мне известных стоит 35$. Это монохром, конечно. Плюс в эти контроллеры встроены часы и поддержка датчика температуры/влажности, то есть даже для часов ДМД не нужен.
ДМД нужен для специализированных табло: весы, ценники, электронная очередь, метеостанция, всякие счетчики, спортивные табло и тому подобное. То есть, где есть необходимость получить откуда то данные и показать их на табло. С этим стандартные контроллеры не справляются.
Уважаемые знатоки....) Пытаюсь вывести текст с stm-ки нопри выводе на экране белеберда. Попробовал writePixel и на экране отобразилась небольшая полоска (диода на 4-5) и так со всем. Линия становиться не 1 пикселем а целым закрашенным прямоугольником и т.д.
Уважаемые знатоки....) Пытаюсь вывести текст с stm-ки нопри выводе на экране белеберда. Попробовал writePixel и на экране отобразилась небольшая полоска (диода на 4-5) и так со всем. Линия становиться не 1 пикселем а целым закрашенным прямоугольником и т.д.
Мало информации - Какой библиотекой выводите, какая матрица, как подключена. И хорошо бы код увидеть
Да, в среде Arduino ide, плата bluepill, камень stm32f103. Что такое аддон не знаю. Сединял как написано в примере в комментариях. Фото приложу чуть позднее. На ардуино работаю редко, так что не знаю что ещё может быт нужно, извиняйте.
Да, в среде Arduino ide, плата bluepill, камень stm32f103. Что такое аддон не знаю. .
"Аддон" - это пакет для Ардуино ИДЕ, который добавляет в Ардуино поддержку не-ардуино плат.. В частности, для СТМ32 есть несколько аддонов - аддон Роджера Кларка STM32duino и аддон от производителя - STM32Genetric
Эта библиотека под STM32duino, под второй аддон ее никто не проверял пока, может не работать
И еще - другие примеры из библиотеки не пробовали?
lean_74 - а сколько матриц всего подключено? Реально по три на каждый канал, как указано в коде?
lean_74 - собрал заново свой макет с матрицами, тестирую - что-то у меня тоже не работает первый SPI. Ни в паре со вторым, ни отдельно
Буду разбираться.
еще раз привет, похоже нашел проблему. Когда мы тут с одним из участников подбирали настройки таймеров, чтобы не было мерцания - я их тестировал только на SPI2. Оказывается, Timer3_CH1 несовместим с SPI1. Поменял на CH4 - все заработало.
В твоем примере строчки 88 - 92 нужно заменить вот на эти:
Проверил, теперь все работает.
Отпишись, плиз, о результате.
Подключено по три панели, строчки поменял, даже не компилируется
IDE 1.8.9 , может тут проблема?
lean_74 - судя по выводу ошибок, вы пытаетесь компилировать для платы avr, а это код для СТМ32
пардон, сам заметил поздно, комп глюканул, перегрузил , заработало.
пардон, сам заметил поздно, комп глюканул, перегрузил , заработало.
уточните - работает по три матрицы на каждый канал? А то у меня всего 2 матрицы. тестировать не на чем :)
Работают все три, но как было замечено выше, загораются паразитные пиксели и иногда притормаживает, потом опять бежит нормально. Вечером видео сниму, выложу на Ютуб.
понятно. Если видео для меня - можете не снимать :) У меня все так же.
"Притормаживание" как будет время, попытаюсь найти и победить - мне кажется это какая-то простая и глупая ошибка в коде...
Паразитные пиксели убираются работой от стабильного БП (во всяком случае. у меня так)
Обновил версию на Гитхабе с учетом последних замечаний и исправлений
- добавлен вертикальный скролл с примерами для СТМ и Уно
- исправлены ошибки в примерах
- изменены настройки таймера в примерах для СТМ
О ошибках сообщайте
Дима, а может вывод на матрицу повлиять на работу аппаратного UART1 или UART2 ? пробовал "поженить" ПроМини и stm32 на обоих Serial1 и Serial2, Мастер ПроМини, слэйф stm32, последняя какой-то бред выдает. Думал может сам чего накосячил в коде - проверил на двух мегах все нормально. И если это так , как передать данные от меги в stm-ку по UART или как-то еще? Передаю несколько цифр от 0 до 9, разделенные запятыми. что-то типа этого
Дима, а может вывод на матрицу повлиять на работу аппаратного UART1 или UART2 ?
ну так это ж легко проверить - временно закомментируйте в коде вывод на матрицу и посмотрите, наладится ли Сериал
разобрался, пока мега отправляет очередной символ по Uart-у, stm32 успевает несколько сотен, а может и больше циклов loop() выполнить.
Вопрос остался открытым: Как передать данные с Меги на STM32, при одновременном использоваться двух независимых экземпляров DMD? читаю так
Дим может все же подскажешь как победить? а я тебе платку такую готовую с часиками пришлю
Напиши подробнее, что именно не работает, я пока не очень понимаю. То, что СТМ32 слишком быстро читает символы - мешать не должно, гораздо хуже когда приемник не успевает.
Я сейчас до завтрашнего вечера уеду, но если ты напишешь - я завтра посмотрю.
Отключил прерывания по таймеру на момент начала приема сигнала по UART, и заново их подключил после приема, данные получил правильные, теперь посмотрю, как это отразиться на вывод на табло...
А какой длины пакет данных, что передаешь?
с пробелами 24 байта, Дима напиши мне на почту, пож.
с пробелами 24 байта, Дима напиши мне на почту, пож.
я что-то адреса теперь не вижу, а вроде днем был. И еще ты днем коды выкладывал - я с телефона заходил, видел. А домой приехал, захожу в конфу - кодов уже нет. Что случилось? Решил вопрос сам?
почта МойНик@mail.ru. Решил можно сказать с костылем(#66), естественно, когда отключаю прерывания, экран дергается.Код подправленный, могу выложить только вечером, т.к он на домашнем компе.Ты на почту мне обязательно напиши.
Ты на почту мне обязательно напиши.
написал
код ПроМини
код stm32
А просто без этой библиотеки передается корректно?
Я где-то читал что uart реализован не аппаратно, а программно, в ядре стм32 для ардуино.
Попробуй сначала прерывание остановить, а потом уже проверить uart, так же были проблемы с кодировкой новой строки попробуй выставить символ какой вместо него.
Остановив прерывание передается корректно, но при этом экран дергается. но на это я уже плюнул.
Остановив прерывание передается корректно, но при этом экран дергается. но на это я уже плюнул.
Посмотрел код в сообщении #72
ИМХО, ты зря читаешь из сериала по одному символу. Как только в буфере что-то появилось - читай в буфер не один символ, а все что есть. Если надо, могу поправить твой код (но только вечером)
не одна засада, так другая - это яркость на 20000
а это на 2000
и вообще сколько панелей можно подключить на каждый spi? подключил 9, изображение мигает... замена digitalWrite в библиотеке на прямую запись в порт решит проблемы?
сколько панелей можно подключить на каждый spi? подключил 9, изображение мигает... замена digitalWrite в библиотеке на прямую запись в порт решит проблемы?
для начала частоту обновления в таймере попробуй поменять
результаты такие: один spi работает устойчиво 9 панелей, до 11 панелей еще кое-как работает, при 12 панелях происходит срыв изображения. обновление таймера 1000 мксек., надо чтобы работало мин 18 панелей, как победить?
результаты такие: один spi работает устойчиво 9 панелей, до 11 панелей еще кое-как работает, при 12 панелях происходит срыв изображения. обновление таймера 1000 мксек., надо чтобы работало мин 18 панелей, как победить?
И еще - попробуй поднять скорость SPI шины - параметр DMD_SPI_CLOCK , примерно 42 строчку файла DMD_STM32.h
изображение статичное, пробовал SPI_CLOCK_DIV4 и SPI_CLOCK_DIV2, существенной разницы нет, работает на 9 панелях, больше уже дрожит изображение, левые пикселы загораются.
Еще вопрос, как правильно остановить прерывания по таймеру, и потом снова их запустить, вот так останавливаю
потом снова так:
не запускаются...
Обновление библиотеки - версия v0.3.2 (для СТМ32)
(код на Гитхабе, ссылка в первом сообщении)
с подачи lean_74 найдена и исправлена ошибка задания частоты шины SPI, добавлен вывод через DMA(синхронный)
Главное внешнее изменение - скорость вывода на матрицы выросла примерно в 10-12 раз, в режиме бегущей строки полностью исчезли все "притормаживания" текста. Судя по таймингам вывода, библиотека должна без проблем работать с 16 матрицами на канал без заметного замедления другого кода программы.
В ближайшее время планирую выложить версию с асинхронным DMA, что позволит снизить нагрузку на микроконтроллер еще примерно на порядок.
Cпасибо lean_74 за тестирование кода
Обновление - версия v0.4.1 (для СТМ32)
(ссылка на гит в первом сообщении)
Основные изменения:
- вывод данных на матрицы через DMA в асинхронном режиме, то есть почти без загрузки микроконтроллера
- проведена работа по устранению мерцаний и паразитной засветки пикселей, для чего увеличена частота ШИМ регулировки яркости матриц
- все настройки таймеров "убраны" внутрь библиотеки, пользователю не нужно ничего настраивать
- восстановлена совместимость с АВР Атмега328(надеюсь :)
Изменения повлекли за собой некоторые изменения в интерфейсе. Для СТМ32 при начале работы с матрицами обязательна функция dmd.init(), вызываемая в setup(). Яркость теперь регулируется от 0 до 255. Подробнее см. примеры.
Важно: Пины n_OE теперь нужно выбирать только из числа тактируемых Timer3 - то есть PB0 PB1 PB5.
Библиотека нуждается в бета-тестерах :) В принципе, по таймингам на осциллографе последние версии выглядят очень неплохо. Теоретически :) на массовой плате blue pill STM32F103C8T6 библиотека должна работать с 30- 40 матрицами на каждом канале. К сожалению, у меня нет достаточного числа матриц, чтобы проверить это вживую. Так что если кто-то захочет сделать свой проект на моей библиотеке - обращайтесь, обещаю авторскую поддержку :)
=== технические детали, можно не читать ===
Каждое сканирование матриц состоит из двух стадий - подготовки данных и передачи. На последней версии 0.4.1 подготовка занимает примерно 15 мкс (+ 3 мкс на каждую следующую панель), передача по SPI - примерно 30 мкс каждая панель (при частоте тактирования SPI 8МГц).
При использовании асинхронного DMA вторая стадия (передача данных) происходит в фоновом режиме, не нагружая контроллер и оставляя его свободным для других задач. Таким образом, при подключении 30 матриц центральный контроллер будет занят около 100 мкс - при сканировании раз в 1мс это всего 10% процессорного времени.
=================================
Версия 0.4 реализует весь ранее задуманный функционал, дальше я намерен сосредоточится на исправлении ошибок и документировании.
Если у кого-то есть предложения - готов выслушать. Если нужно добавить в библиотеку двухцветные и полноцветные матрицы - готов заняться, если кто-то предоставит такие панели :)
Проверено на 42 матрицах. Статичные изображения выводятся отлично, в режиме бегущей строки на не задействованных в данный момент панелях, видна легкая засветка в такт бегущей строки.
Потому как это совершенно чётко - рекламщики, там деньги есть, и не стоит бесплатно халявщиков плодить ;)
Нафиг не сдался рекламщикам DMD, учитывая, что полноценный монохромный контроллер на 20 модулей (в две строки) стоит 3 бакса (меньше 200р). А самый мощный (2048*512 пикселей, то есть 20*5 метров) из мне известных стоит 35$. Это монохром, конечно. Плюс в эти контроллеры встроены часы и поддержка датчика температуры/влажности, то есть даже для часов ДМД не нужен.
ДМД нужен для специализированных табло: весы, ценники, электронная очередь, метеостанция, всякие счетчики, спортивные табло и тому подобное. То есть, где есть необходимость получить откуда то данные и показать их на табло. С этим стандартные контроллеры не справляются.
b707, я желаю с тобой пообщаться, но нигде не нашел контактов.
Черкни мне на evgeny_fox@mail.ru если не трудно
Уважаемые знатоки....) Пытаюсь вывести текст с stm-ки нопри выводе на экране белеберда. Попробовал writePixel и на экране отобразилась небольшая полоска (диода на 4-5) и так со всем. Линия становиться не 1 пикселем а целым закрашенным прямоугольником и т.д.
Мало информации - Какой библиотекой выводите, какая матрица, как подключена. И хорошо бы код увидеть
Библиотека предоставленая в 1 сообщении.
Матрица p10 32x16.Код - пример dmd_demo
СТМ32 в среде Ардуино? - какеой аддон установлен?
Попытайтесь более расширено сформулировать проблему... ну если хотите ее решить, конечно.
Пока же я могу только ответить в вашем же лаконичном стиле - у меня этот пример отлично работает.
Да, в среде Arduino ide, плата bluepill, камень stm32f103. Что такое аддон не знаю. Сединял как написано в примере в комментариях. Фото приложу чуть позднее. На ардуино работаю редко, так что не знаю что ещё может быт нужно, извиняйте.
"Аддон" - это пакет для Ардуино ИДЕ, который добавляет в Ардуино поддержку не-ардуино плат.. В частности, для СТМ32 есть несколько аддонов - аддон Роджера Кларка STM32duino и аддон от производителя - STM32Genetric
Эта библиотека под STM32duino, под второй аддон ее никто не проверял пока, может не работать
И еще - другие примеры из библиотеки не пробовали?
Перепробовал все примеры. Везде кроме dmd_demo чёрный экран. Аддон STM32duino
Вот это выдает dmd_demo
если готовы подождать - вечером попробую
Не плохо бы еще модуль сфоткать с другой стороны, и чипы.
В китайских контроллерах режимов сканирования штук 50+ точно есть.
судя по всему - самая распространенная одноцветная 1/4 скан, HUB12
Должна работать.
этикетку еще сфоткайте на всякий случай