Матричный дисплей с Arduino UNO (ПРОБЛЕМА)
Я столкнулся с проблемой в выпускном проекте и надеюсь, что вы поможете мне ее решить :)
Мой проект заключается в подключении Arduino Uno к точечно-матричному дисплею 16x32 (DMD) и отображении на нем сообщений из программы VB.net. Я написал свою программу VB.net для преобразования входного текста в двумерный двоичный массив. Количество столбцов зависит от ширины текста. как мы знаем, Arduino Uno SRAM слишком мала всего 2 КБ, поэтому не может получить все столбцы и отобразить их.
Я пытался получить 100 столбцов в коде Arduino и отобразить их, затем отправить звездочку *
на компьютер, чтобы получить вторые 100 столбцов и отобразить их и так далее, но это не сработало. Я вижу, как RX и TX светодиодов Arduino мигают, но затем на DMD ничего не отображается.
Может ли кто-нибудь сказать мне, где часть кода с ошибкой, или если у вас есть другая идея для решения этой проблемы :)
Код VB.net для отправки двумерного массива ar(,)
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
SerialPort2.Open()
Dim la As String
If CheckBox1.Checked Then
la = "arabic"
Else
la = "english"
End If
SerialPort2.Write("#" + cols.ToString + "#" + "*" + la + "*")
Dim INDEX As Integer = 0
While INDEX <= cols
Dim see As String = SerialPort2.ReadLine().ToString()
If see = "*" Then
Dim BUFFER(16) As Byte
For I = INDEX To INDEX + 100
If I < cols Then
For J = 0 To rows - 1
BUFFER(J) = ar(I, J)
Next
SerialPort2.Write(BUFFER, 0, 16)
End If
Next
INDEX += 100
End If
End While
SerialPort2.Close()
End Sub
Код C++ для получения 100 столбцов и их отображения:
#include <SPI.h>
#include <DMD2.h>
SoftDMD dmd(1,1);
void setup() {
Serial.begin(9600);
dmd.setBrightness(255);
dmd.begin();
}
long Wid;
void loop() {
if(Serial.available()){
String st = String(Serial.readString());
Wid = (st.substring(st.indexOf('#')+1, st.lastIndexOf('#'))).toInt();
//Язык строк = st.substring(st.indexOf('*')+1, st.lastIndexOf('*'));
}
long ind = Wid ;
while(ind >= 0 ){
Serial.println("*");
if(Serial.available()>1 ){
boolean pixls[16][100];
getArray(pixls);
displayArray(pixls);
ind-=100;
}
if(ind >=Wid){
ind = wid ;
}
}
}
void getArray(boolean arr[16][100]){
byte serialData[16];
for(int k = 0 ; k < 100 ; k++){
Serial.readBytes(serialData,16);
for(int i = 0 ; i < 16 ; i++){
arr[i][k]= serialData[i];
}
}
}
void displayArray(boolean arr[16][100]){
for(int h = 0 ; h <= 100-33 ; h++){
for (int i = 0 ,g=h; i < 32 ,g<h+32; i++ ,g++){
for (int j = 0 ; j < 16 ; j++){
dmd.setPixel(i,j,(arr[j][g] == 1) ? GRAPHICS_ON : GRAPHICS_OFF);
}
}
delay(100);
}
}
Этот код VB работает для меня при отправке всего 100 столбцов массива:
SerialPort2.Open()
Dim BUFFER(16) As Byte
For J = 0 To 100
For I = 0 To rows - 1
BUFFER(I) = ar(J, I)
Next
SerialPort2.Write(BUFFER, 0, 16)
Next
SerialPort2.Close()
Код C++:
#include <SPI.h>
#include <DMD2.h>
SoftDMD dmd(1,1);
void setup() {
Serial.begin(9600);
dmd.setBrightness(255);
dmd.begin();
}
void loop() {
boolean pixls[16][100];
for(int i=0 ;i<100 ; i++){
for(int j=0 ;j<16 ; j++){
pixls[j][i]=0;
}
}
if(Serial.available()>0){
getArray(pixls);
for(int i=0 ; i<100 ; i++)
{
displayArray(pixls);
}
}
}
void getArray(boolean arr[16][100]){
byte serialData[16];
for(int k = 0 ; k < 100 ; k++){
Serial.readBytes(serialData,16);
for(int i = 0 ; i < 16 ; i++){
arr[i][k]= serialData[i];
}
}
}
void displayArray(boolean arr[16][100]){
for(int h = 0 ; h <= 100-33 ; h++){
for (int i = 0 ,g=h; i < 32 ,g<h+32; i++ ,g++){
for (int j = 0 ; j < 16 ; j++){
dmd.setPixel(i,j,(arr[j][g] == 1) ? GRAPHICS_ON : GRAPHICS_OFF);
}
}
delay(100);
}
}
2 ответа
boolean pixls[16][100];
Помимо других возможных проблем, у вас заканчивается оперативная память.
Один только этот массив занимает 1600 байт из 2048 на Uno. Поскольку вы используете Serial, это также требует:
- 34 байта для экземпляра HardwareSerial (Serial)
- 64 байта для буфера последовательной передачи
- 64 байта для последовательного приемного буфера
- 4 байта для указателей заголовка и конца буфера последовательной передачи
- 4 байта для указателей начала и конца буфера последовательного приема
Это еще 170 байт.
SoftDMD dmd(1,1);
Я предполагаю, что это также использует оперативную память.
Вам нужно переработать. Вам не нужно хранить 100 байт перед отображением. Как насчет чтения каждого байта и отображения его? Это экономит почти 1600 байт.
я пытался получить всего 100 столбцов и отобразить их, и это работает хорошо, @Haitham AL-Cigeary
@ HaithamAL-Cigeary Я предлагаю отправить текст ASCII в Arduino, а затем позволить библиотеке шрифтов в SoftDMD преобразовать его в пиксели., @sa_leinad
Возможно, у вас закончилась оперативная память.
Следующее использует большие куски вашей SRAM:
-
Массив
пикселей
= 1600 байт- Серийный номер = 170 байт
- DMD > 64 байта
Это в дополнение ко всем другим вашим переменным и вызовам функций.
Проблема в том, что компилятор преобразует логические переменные в байты. Итак, там, где вам нужно 1600 пикселей, требуется 1600 байт. В качестве альтернативы вы можете упаковать 8 пикселей в этот байт. Этот метод будет использовать только 200 байтов вместо 1600.
Кроме того, я не понимаю, почему у вас есть массив 16 на 100. Из кода я вижу, что вы используете один DMD, который имеет ширину 32 пикселя и высоту 16 пикселей. Зачем отправлять/буферизировать больше пикселей, чем нужно? Для одного DMD потребуется только массив из 64 байтов.
У Arduino Uno всего 2 КБ SRAM.
Решения:
- Я предлагаю отправить текст ASCII в Arduino, а затем позволить библиотеке шрифтов в SoftDMD преобразовать его в пиксели. Вот почему вы используете библиотеку DMD2.
Однако, если вы хотите придерживаться выбранного вами подхода:
Упакуйте 8 пикселей в каждый байт массива. Это сэкономит 1400 байт драгоценной памяти SRAM.
Отправлять только одно слово данных DMD за раз. Это сэкономит 1536 байт драгоценной памяти SRAM.
Вы можете использовать Arduino с большим объемом SRAM.
- Arduino Mega — 8 КБ SRAM
- Arduino ZERO — 32 КБ SRAM
- Arduino Due — 96 КБ SRAM
- Arduino MKR 1000/1010/1400/ZERO — 32 КБ SRAM
- Почему эта программа на C++ не может прочитать Serial.write() моего arduino?
- Как изменить переменную при нажатии кнопки, подключенной к контакту 2
- Как напечатать несколько номеров через Serial с очень небольшим количеством строк кода?
- Акцептант векселей ИКТ
- Проблема с массивом + последовательным монитором
- Arduino wrap или подкласс print() для работы с несколькими Serial
- Как преобразовать строку в шестнадцатеричный массив
- Замена большой таблицы поиска оператором switch
но это не сработало
- что происходит? Отображается *что-нибудь*?, @Nick Gammonничего не отображается, но есть мерцание в RX и TX светодиодов arduino, @Haitham AL-Cigeary
Я немного отредактировал свой пост, пожалуйста, прочитайте его еще раз :), @Haitham AL-Cigeary
Я предлагаю несколько отладочных дисплеев. Мне кажется странным преобразовывать символы в пиксели и отправлять их по одному байту за раз с одного процессора на другой. Вы не можете хотя бы отправить как 8 бит в одном байте? Я не собираюсь гадать, что генерируется на одном конце и как это обрабатывается на другом. Вот почему вы помещаете отладочные «отпечатки» в свой код. Чтобы узнать для себя., @Nick Gammon