[SOLVED]LCD Shown Black Blocks (PMS 5003 Interfacing)

Hi Everyone,
I was trying to use LCD 20x4 i will give the link for the products , at the first time i use i2c and then its works but 1 week later we change it to the new one. At the first time its work for showing 1 particle counter program, and i try combine the code because i have 2 particle counter. At the first time the LCD shown clear display no black box, but suddenly i change the code with the new one theres the black box. Do you guys have suggestion for me? critiques and suggestion accepted. By the way this is the code

// On Leonardo/Micro or others with hardware serial, use those!
// uncomment this line:
// #define pmsSerial Serial1

// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
// comment these two lines if using hardware serial
#include <SoftwareSerial.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;
const int LCD_COLS = 20;
const int LCD_ROWS = 4;


void getText(); void updateLCD();
unsigned char line1[20]; unsigned char line2[20];
unsigned char line3[20]; unsigned char line4[20];
SoftwareSerial pmsSerial(7, 3); // outlet
SoftwareSerial pmSerial2(6, 3); // inlet

void setup() {
  // our debugging output
  Serial.begin(115200);

  // sensor baud rate is 9600
  pmsSerial.begin(9600);
  int sum();
  int sumb();
}

struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t particles_03um2, particles_05um2, particles_10um2, particles_25um2, particles_50um2, particles_100um2;
  uint16_t unused;
  uint16_t checksum;
};

struct pms5003data data;

void loop() {
  if (readPMSdata(&pmsSerial)) {
    // reading data was successful!
    float sum = 0;
    int status;
    status = lcd.begin(LCD_COLS, LCD_ROWS);
    float sum2 = 0;
    sum = data.particles_03um + data.particles_05um + data.particles_10um + data.particles_25um + data.particles_50um + data.particles_100um;
    sum2 = data.particles_03um2 + data.particles_05um2 + data.particles_10um2 + data.particles_25um2 + data.particles_50um2 + data.particles_100um2;
    if (status) // non zero status means it was unsuccesful
    {
      status = -status; // convert negative status value to positive number

      // begin() failed so blink error code using the onboard LED if possible
      hd44780::fatalError(status); // does not return
    }
    //Serial.print("Sum of the Particle"); Serial.println(sum);
    //Serial.print("Sum of the Particle2 "); Serial.println(sum2);
    lcd.setCursor(0, 0); //First line
    lcd.print("Sum of the Particle After ESP = ");
    lcd.print(sum);
    lcd.setCursor(0, 1); //Second line
    lcd.print("Sum of the Particle Before ESP= ");
    lcd.print(sum2);
  }
}

boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }

  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }

  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }

  uint8_t buffer[32];
  uint16_t sum = 0;
  uint16_t sum2 = 0;
  s->readBytes(buffer, 32);

  // get checksum ready
  for (uint8_t i = 0; i < 30; i++) {
    sum += buffer[i];
  }

  /* debugging
    for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
    }
    Serial.println();
  */

  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i = 0; i < 15; i++) {
    buffer_u16[i] = buffer[2 + i * 2 + 1];
    buffer_u16[i] += (buffer[2 + i * 2] << 8);
  }

  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);

  if (sum != data.checksum) {
    lcd.print("Checksum failure ");
    return false;
  }
  if (sum2 != data.checksum) {
    lcd.print("Checksum2 failure");
    return false;
  }
  // success!
  return true;
}

Thank you for your attention

https://www.winstar.com.tw/products/character-lcd-display-module/20x4-lcd-display.html

One issue I see is that the hd44780 library initialization is being done in loop() and is done each time readPMSdata() reads a packet. Is this really what you wanted?
The LCD will remain un-initialized (showing the blocks) until a packet comes in and then is re-initialized each time a packet comes in.
Normally lcd.begin() is done in setup() as it only needs to be done once.

You have also provided some conflicting & missing information.

You sketch is using the hd44780 library with the hd44780_I2Cexp i/o class but the tutorial in
this link How to use an I2C LCD 16x2 with Arduino - Ardumotive Arduino Greek Playground
is for a different library.
Both the hd44780 library with the hd44780_I2Cexp i/o class and the newLiquidCrystal library with the LiquidCrystal_I2C i/o class mentioned in the tutorial, work with hd44780 displays that are connected to a PCF8574 based i2c backpack.

Which LCD do you have? WH2004G, WH2004G1, WH2004G2

Do you have a WH2004G that is soldered to a PCF8574 based i2c backpack that you have not shown or mentioned?

--- bill

Hello Bperry,
Thank you for your response i thought my thread will be never answered.
Talking about the library, i think the library works really well. Since previously i used a different sensor and its works really well. It can be show volt and the dust density(Sharp GP2Y1014AU0F). Right now, i change to the particle counter PMS 5003. I tried trial and error,i delete the doubled initialization and its work same the lcd doesnt work. The fun fact i tried to change the lcd.print inside the "if" and the outside "if" then its have different result. When i put the lcd. print inside the if like this :

if (readPMSdata(&pmsSerial)) {
    // reading data was successful
    // Coba pakai serial print bisa bisa untuk menguji if nya apakah terpenuhi atau ngak
    sum = data.particles_03um + data.particles_05um + data.particles_10um + data.particles_25um + data.particles_50um + data.particles_100um;
    sumb = data.particles_03um2 + data.particles_05um2 + data.particles_10um2 + data.particles_25um2 + data.particles_50um2 + data.particles_100um2;
    lcd.setCursor(0, 0); //First line
    lcd.print("After ESP = ");
    lcd.print(sum);
    lcd.setCursor(0, 1); //Second line
    lcd.setCursor(0, 1); //Second line
    lcd.print("Before ESP= ");
    lcd.print(sumb); * /
  }
}

The result will be the LCD will not shown anything ( the blocks is about the contrast). Even theres no single character shown in this LCD

When i put the lcd.print outside if like this :

if (readPMSdata(&pmsSerial)) {
    // reading data was successful
    // Coba pakai serial print bisa bisa untuk menguji if nya apakah terpenuhi atau ngak
    sum = data.particles_03um + data.particles_05um + data.particles_10um + data.particles_25um + data.particles_50um + data.particles_100um;
    sumb = data.particles_03um2 + data.particles_05um2 + data.particles_10um2 + data.particles_25um2 + data.particles_50um2 + data.particles_100um2;

  }
  lcd.setCursor(0, 0); //First line
  lcd.print("After ESP = ");
  lcd.print(sum);
  lcd.setCursor(0, 1); //Second line
  lcd.setCursor(0, 1); //Second line
  lcd.print("Before ESP= ");
  lcd.print(sumb); *
}

The result will be only shown After ESP= 0 , and Before ESP = 0 .
its like its not read nothing

By the way i found my product is LCD 20x4 2004a, and the i2c is i2c 16x2 then i solder it by my own self . Hope this information help you, and i also try to change the code.

To test the LCD, run the I2CexpDiag sketch that comes with the hd44780 library under the hd44780_I2Cexp examples.
This will test and verify that the LCD is working properly.

For your code, please show the entire sketch that is working / not-working, not just a small portion of the code so we can see all the code since the issue could be outside of the portion of code you posted.

Can you also post some photos of the LCD display so we can see what is on the display ?

--- bill

Hi billy Perry,
Thank you for your response. So i just notice that youre the library maker for that example hahaha.
Then i tried it so this is what happen to the LCD when i do the test code.
I think theres no eror in my LCD so this is good sign.
So i attach a file called test, for the result of testing my LCD.

So talking about the code i will emphasizes about the difference when the LCD print put inside if and outside if.

Case 1. Outside if, the code is :

// On Leonardo/Micro or others with hardware serial, use those!
// uncomment this line:
// #define pmsSerial Serial
// cari indicator semisal sensornya nyala, cek tegangan nang 5v sensor. Lek uwes lek onok tegangan cek komdat.
// Coba pakai TX RX sensor.

// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
// comment these two lines if using hardware serial
#include <SoftwareSerial.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;
const int LCD_COLS = 20;
const int LCD_ROWS = 4;
int status;
int sum;
int sumb;


void getText(); void updateLCD();
unsigned char line1[20]; unsigned char line2[20];
unsigned char line3[20]; unsigned char line4[20];
SoftwareSerial pmsSerial(7, 3); // outlet
SoftwareSerial pmSerial2(6, 3); // inlet

void setup() {
  // our debugging output
  Serial.begin(115200);
  lcd.begin(20, 4);

  // sensor baud rate is 9600
  pmsSerial.begin(9600);
  int sum();
  int sumb();
}

struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t particles_03um2, particles_05um2, particles_10um2, particles_25um2, particles_50um2, particles_100um2;
  uint16_t unused;
  uint16_t checksum;
};

struct pms5003data data;

void loop() {
  if (readPMSdata(&pmsSerial)) {
    // reading data was successful
    // Coba pakai serial print bisa bisa untuk menguji if nya apakah terpenuhi atau ngak
    sum = data.particles_03um + data.particles_05um + data.particles_10um + data.particles_25um + data.particles_50um + data.particles_100um;
    sumb = data.particles_03um2 + data.particles_05um2 + data.particles_10um2 + data.particles_25um2 + data.particles_50um2 + data.particles_100um2;
    lcd.setCursor(0, 1); //First line
    lcd.print("After ESP = ");
    lcd.print(sum);
    lcd.setCursor(0, 3); //Second line
    lcd.print("Before ESP= ");
    lcd.print(sumb);
  }
  lcd.setCursor(0, 1); //First line
  lcd.print("After ESP = ");
  lcd.print(sum);
  lcd.setCursor(0, 3); //Second line
  lcd.print("Before ESP= ");
  lcd.print(sumb);
}

boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }

  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }

  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }

  uint8_t buffer[32];
  uint16_t sum = 0;
  uint16_t sumb = 0;
  s->readBytes(buffer, 32);

  // get checksum ready
  for (uint8_t i = 0; i < 30; i++) {
    sum += buffer[i];
  }

  /* debugging
    for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
    }
    Serial.println();
  */

  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i = 0; i < 15; i++) {
    buffer_u16[i] = buffer[2 + i * 2 + 1];
    buffer_u16[i] += (buffer[2 + i * 2] << 8);
  }

  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);

  if (sum != data.checksum) {
    lcd.print("Checksum failure ");
    return false;
  }
  if (sumb != data.checksum) {
    lcd.print("Checksumb failure");
    return false;
  }
  // success!
  return true;

}

Case 2, inside the if and the code is:

// On Leonardo/Micro or others with hardware serial, use those!
// uncomment this line:
// #define pmsSerial Serial
// cari indicator semisal sensornya nyala, cek tegangan nang 5v sensor. Lek uwes lek onok tegangan cek komdat.
// Coba pakai TX RX sensor.

// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
// comment these two lines if using hardware serial
#include <SoftwareSerial.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;
const int LCD_COLS = 20;
const int LCD_ROWS = 4;
int status;
int sum;
int sumb;


void getText(); void updateLCD();
unsigned char line1[20]; unsigned char line2[20];
unsigned char line3[20]; unsigned char line4[20];
SoftwareSerial pmsSerial(7, 3); // outlet
SoftwareSerial pmSerial2(6, 3); // inlet

void setup() {
  // our debugging output
  Serial.begin(115200);
  lcd.begin(20, 4);

  // sensor baud rate is 9600
  pmsSerial.begin(9600);
  int sum();
  int sumb();
}

struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t particles_03um2, particles_05um2, particles_10um2, particles_25um2, particles_50um2, particles_100um2;
  uint16_t unused;
  uint16_t checksum;
};

struct pms5003data data;

void loop() {
  if (readPMSdata(&pmsSerial)) {
    // reading data was successful
    // Coba pakai serial print bisa bisa untuk menguji if nya apakah terpenuhi atau ngak
    sum = data.particles_03um + data.particles_05um + data.particles_10um + data.particles_25um + data.particles_50um + data.particles_100um;
    sumb = data.particles_03um2 + data.particles_05um2 + data.particles_10um2 + data.particles_25um2 + data.particles_50um2 + data.particles_100um2;
    lcd.setCursor(0, 1); //First line
    lcd.print("After ESP = ");
    lcd.print(sum);
    lcd.setCursor(0, 3); //Second line
    lcd.print("Before ESP= ");
    lcd.print(sumb);
    lcd.setCursor(0, 1); //First line
    lcd.print("After ESP = ");
    lcd.print(sum);
    lcd.setCursor(0, 3); //Second line
    lcd.print("Before ESP= ");
    lcd.print(sumb);
  }
}

boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }

  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }

  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }

  uint8_t buffer[32];
  uint16_t sum = 0;
  uint16_t sumb = 0;
  s->readBytes(buffer, 32);

  // get checksum ready
  for (uint8_t i = 0; i < 30; i++) {
    sum += buffer[i];
  }

  /* debugging
    for (uint8_t i=2; i<32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
    }
    Serial.println();
  */

  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i = 0; i < 15; i++) {
    buffer_u16[i] = buffer[2 + i * 2 + 1];
    buffer_u16[i] += (buffer[2 + i * 2] << 8);
  }

  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);

  if (sum != data.checksum) {
    lcd.print("Checksum failure ");
    return false;
  }
  if (sumb != data.checksum) {
    lcd.print("Checksumb failure");
    return false;
  }
  // success!
  return true;

}

I attach the LCD picture in the attachment, by the way the sensor using TX RX communication ( UART) and i only use common digital pin arduino. Do you think this is the problem ?
Thank you billy Perry , Pleasure to meet you and have a discussion with you.

I solved the problem, it was because the Software Serial (7,3), i just realized that not all pins in arduino mega can be used in software serial. You guys need to check out your arduino mega pins shich one can be used, i hope this thread can help you to solve your problem. If you choose wrong pin the serial monitor or LCD will be never come out .
Hope this help !!

1 Like