Матричный дисплей с 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); 
  }
}

, 👍0

Обсуждение

но это не сработало - что происходит? Отображается *что-нибудь*?, @Nick Gammon

ничего не отображается, но есть мерцание в RX и TX светодиодов arduino, @Haitham AL-Cigeary

Я немного отредактировал свой пост, пожалуйста, прочитайте его еще раз :), @Haitham AL-Cigeary

Я предлагаю несколько отладочных дисплеев. Мне кажется странным преобразовывать символы в пиксели и отправлять их по одному байту за раз с одного процессора на другой. Вы не можете хотя бы отправить как 8 бит в одном байте? Я не собираюсь гадать, что генерируется на одном конце и как это обрабатывается на другом. Вот почему вы помещаете отладочные «отпечатки» в свой код. Чтобы узнать для себя., @Nick Gammon


2 ответа


3
  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


2

Возможно, у вас закончилась оперативная память.

Следующее использует большие куски вашей SRAM:

    Массив
  • пикселей = 1600 байт
  • Серийный номер = 170 байт
  • DMD > 64 байта

Это в дополнение ко всем другим вашим переменным и вызовам функций.

Проблема в том, что компилятор преобразует логические переменные в байты. Итак, там, где вам нужно 1600 пикселей, требуется 1600 байт. В качестве альтернативы вы можете упаковать 8 пикселей в этот байт. Этот метод будет использовать только 200 байтов вместо 1600.

Кроме того, я не понимаю, почему у вас есть массив 16 на 100. Из кода я вижу, что вы используете один DMD, который имеет ширину 32 пикселя и высоту 16 пикселей. Зачем отправлять/буферизировать больше пикселей, чем нужно? Для одного DMD потребуется только массив из 64 байтов.

У Arduino Uno всего 2 КБ SRAM.

Решения:

  1. Я предлагаю отправить текст ASCII в Arduino, а затем позволить библиотеке шрифтов в SoftDMD преобразовать его в пиксели. Вот почему вы используете библиотеку DMD2.

Однако, если вы хотите придерживаться выбранного вами подхода:

  1. Упакуйте 8 пикселей в каждый байт массива. Это сэкономит 1400 байт драгоценной памяти SRAM.

  2. Отправлять только одно слово данных DMD за раз. Это сэкономит 1536 байт драгоценной памяти SRAM.

  3. Вы можете использовать Arduino с большим объемом SRAM.

    • Arduino Mega — 8 КБ SRAM
    • Arduino ZERO — 32 КБ SRAM
    • Arduino Due — 96 КБ SRAM
    • Arduino MKR 1000/1010/1400/ZERO — 32 КБ SRAM
,