0

I faced a problem in my graduation project and I hope you can help me to solve it :)


My project is connecting Arduino Uno to 16x32 Dot Matrix Display(DMD) and display messages on it from VB.net program. I wrote my VB.net program to convert the input text into 2D binary array. The number of columns depend on the text width. as we know Arduino Uno SRAM is too small just 2 KBytes, so can't receive all the columns and display it.

I tried to receive 100 columns in the Arduino code and display it, then send star * to computer to receive the second 100 columns and display it and so on but it didn't work. I see the RX and TX of Arduino LEDs flicker but then nothing gets displayed on the DMD.

Can anyone tell me where is the error part in the code, or if you have another idea to solve this problem :)

VB.net Code for sending the 2D array 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++ Code for receiving 100 columns and display them:

#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();
    //String Language = 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); 
  }
}

This VB code works for me when sending just 100 columns of the array:

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++ code:

#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); 
  }
}
4
  • 1
    but it didn't work. - what happens? Does anything get displayed?
    – Nick Gammon
    Feb 27 '16 at 20:52
  • nothing get displayed but there is flicker in RX and TX of arduino leds Feb 27 '16 at 20:59
  • I make some edit on my post please read it again :) Feb 27 '16 at 21:15
  • I suggest some debugging displays. It seems weird to me to convert characters into pixels and send them one byte at a time from one processor to another. Can't you at least send as 8 bits in one byte? I'm not going to guess what is being generated on one end, and how that is being processed on the other. That is why you put debugging "prints" inside your code. To find out for yourself.
    – Nick Gammon
    Feb 28 '16 at 19:59
3
  boolean pixls[16][100];

You are running out of RAM, amongst other possible problems.

That array alone takes 1600 bytes out of 2048 on the Uno. Since you are using Serial that also takes:

  • 34 bytes for the HardwareSerial instance (Serial)
  • 64 bytes for the Serial transmit buffer
  • 64 bytes for the Serial receive buffer
  • 4 bytes for the Serial transmit buffer head and tail pointers
  • 4 bytes for the Serial receive buffer head and tail pointers

That's another 170 bytes.

SoftDMD dmd(1,1);

I presume that also uses RAM.

You need to rework. You don't need to store 100 bytes before displaying. How about reading each byte and displaying it? That saves almost 1600 bytes.

2
  • i tried to receive just 100 columns and displaying them ,and it works well Feb 27 '16 at 21:03
  • @HaithamAL-Cigeary I suggest sending the ASCII text to the Arduino and then letting the font library within SoftDMD convert it to pixels.
    – sa_leinad
    Oct 9 '18 at 14:36
2

You have likely run out of RAM.

The following use up large chunks of your SRAM:

  • pixls array = 1600 bytes
  • Serial = 170 bytes
  • DMD > 64 bytes

This is in addition to all your other variables and function calls.

The problem is that the compiler promotes boolean variables to bytes. So where you need 1600 pixels it takes 1600 bytes. Alternatively, you could pack 8 pixels into that byte. This method would only consume 200 bytes instead of 1600.

Also, I don't understand why you have a 16 by 100 array. From the code I can see that you are using a single DMD which has 32 pixels wide by 16 pixels high. Why send/buffer more pixels than needed? A single DMD would only need an array of 64 bytes.

The Arduino Uno only has 2KB of SRAM.

Solutions:

  1. I suggest sending the ASCII text to the Arduino and then letting the font library within SoftDMD convert it to pixels. That is why you are using the DMD2 library.

However if you want to stick to the approach you have taken:

  1. Pack 8 pixels into every byte in the array. This will save 1400 bytes of precious SRAM.

  2. Only send one DMD word of data at a time. This will save 1536 bytes of precious SRAM.

  3. You could use an Arduino with a greater amount of SRAM.

    • Arduino Mega - 8KB SRAM
    • Arduino ZERO - 32KB SRAM
    • Arduino Due - 96KB SRAM
    • Arduino MKR 1000/1010/1400/ZERO - 32KB SRAM

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.