Lỗi phổ thông khi dùng LCD I2C và lưu ý cách sử dụng với thư viện LCD I2C

I. Lỗi chữa "H ám ảnh" và dòng đầu "Đen Xì" thường gặp khi dùng LCD với I2C.

Như các bạn đã biết, LCD phổ thông khi giao tiếp "chay" với Arduino thì tốn rất nhiều chân(như bài Này), để khắc phục tình trạng đó mà mô đun I2C ra đời, giao tiếp với Arduino với LCD chỉ còn 2 chân, nhưng khi dùng với I2C các bạn thường bị lỗi (các bạn bị lỗi thường do theo dõi bài Này). Nguyên văn bài đó thì "0x27 là địa chỉ màn hình trong bus I2C. Phần này chúng ta không cần phải quá bận tâm vì hầu hết màn hình (20x4,...) đều như thế này!"

Tuy vậy, giờ đây các LCD đi kèm với I2C lại không theo 0x27 nữa (khi đó chương trình sẽ lỗi như lỗi chữ "H", các bạn chơi qua LCD I2C bằng code mẫu trên ARDUINO.VN gần như đều đã gặp lỗi này), và chắc chắn thời gian tới nữa thì nó sẽ vẫn còn thay đổi thêm nữa, vì vậy cần một cách tìm chung để fix lỗi. Sau đây mình xin trình bày phương pháp fix vĩnh viễn lỗi này.

Lỗi chữ "H" khi bạn khi dùng LCD kết hợp với I2C khi in ra màn hình một kí tự hoặc chuỗi ký tự nào đó nhưng chữ "H" hiện lên hoặc dòng màn hình trên cùng Hiện Lên Đen Xì, đó là do địa chỉ bus của LCD trong I2C bị sai, để fix các bạn nạp code tìm địa chỉ, khi đó địa chỉ bus LCD "thực sự" của bạn hiện lên. Các bạn sẽ copy mã này thay cho dòng "0x27" vậy là xong, sau đây mình xin hướng dẫn từng bước.

Bước 1: Kết Nối I2C theo thứ tự bình thường

Module màn hình LCD (16x2) Arduino
GND GND
Vcc 5V
SDA A4
SCL A5

Bước 2: Nạp code tìm địa thật

Các bạn nạp code sau vào và bật Serial Monitor lên và sẽ thấy địa chỉ.

// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
 
#include <Wire.h>
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for n
}

Code được trích từ http://playground.arduino.cc/Main/I2cScanner

Mình làm xong dự án rồi gửi đi luôn, chưa kịp chụp màn hình nên mượn Ành trong video của thầy Huỳnh Minh Phú vậy.

Bước 3: Thay địa chỉ bạn vừa scan được vào địa chỉ cũ bị lỗi ở dòng "LiquidCrystal_I2C lcd(AxBC, M, N)", trong đó AxBC là địa chỉ cũ bị lỗi.

Cụ thể các bạn xem hình.

II. Lỗi chữ cũ bị lưu lại khi in chữ mới có độ dài ngắn hơn chữ cũ

Rất nhiều trường hợp gặp lỗi này, ví dụ như mình gặp lỗi này như khi mình hiển thị %, ban đầu mình in ra 100%, sau đó cảm biến của mình giảm, thông số in ra là 70%, nhưng thay vì in ra 70% đẹp đẽ thì nó lại in ra 700%. Why????????

Thực ra đây không phải lỗi, một ô trong LCD khi bạn chưa xóa thì nó vẫn còn, khi bạn gọi ô mới thì chỉ các ô mới bị thay thế, còn các kí tự ở ô cũ thì giữ nguyên, trong ví dụ "%" ở trên thì cách tốt nhất lúc này là:

  1. in ra ô mới đồng thời in ra khoảng trắng trong ô cũ không dùng đến( ví dụ như số '0' của số 100 cũ bị thừa khi số mới hiển thị lên chỉ là 70, lúc này màn hình sẽ hiển thị " 70 %").
  2. in thụt vào 1 ô, đồng thời in khoảng trắng ra ô trước đó (lúc này màn hình sẽ hiển thị " 70%").

III. Lỗi khi in thì bị delay toàn bộ chương trình => chương trình hoạt động chậm hơn dự kiến

Đây là một lỗi cực kì nguy hiểm khi sử dụng thư viện màn hình LCD I2C.  

Ví dụ dự án mình là đọc giá trị cảm biến A và triết áp B, nếu giá trị A > B thì cho led X sáng. Một hàm là "hienthitrietap" mình để cho màn hình hiển thị thông số của triết áp, mình làm như sau:

void loop()
{

    A = analogRead(A0);
    B = analogRead(A1);

    hienthitrietap(b);

    if (a > b) {
        digitalWrite(13, HIGH);
        delay(100);
        digitalWrite(13, LOW);
    }
}

Khi chạy thực tế, khi giá trị A đã lớn hơn B rồi nhưng phải đợi 1 delay thời gian khoảng 1-3 giây thì đèn 13 mới sáng. Bởi vì khi code trên thực thi, một khoảng thời gian bị delay do phải in thông số lên màn hình liên tục. Với những dự án không yêu cầu tính lập tức cao thì nó không thành vấn đề, nhưng với những dự án cần sự tác động ngay lập tức thì bị delay khiến cho hệ thống gần như bỏ đi. để khắc phục trên mình đề xuất 2 cách.

Cách 1: để hàm in ra sau khi điều kiện đã đúng

Ví dụ code trên sẽ sửa lại như sau:

void loop()
{

    int a = analogRead(A0);
    int b = analogRead(A1);

    if (a > b) {
        digitalWrite(13, HIGH);
        delay(100);
        digitalWrite(13, LOW);

        hienthitrietap(b);
    }
}

Cách này có nhước điểm là sau khi chạy rồi thì thông số điều chỉnh mới hiện lên được.

Cách 2

Cách này mình xin phép gợi ý vì mỗi dự án là khác nhau: Các bạn tính đúng thời điểm màn hình bị delay để in, gọi thời gian này là x, nếu hành động A > B theo chu kì a giây thì trong khoảng thời gian mà A <= B thì ta sẽ vẫn tiếp tục tin ra số n lần, trong đó x*n < a, khi đó ta vẫn in ra được trong khi vẫn đảm bảo để in ra để cập nhật giá trị B khi ta thay đổi.

Mở rộng: để giải quyết vấn đề 3 thì còn rất nhiều cách, mong được sự góp ý nhiệt tình về vấn đề này, nhằm tìm ra phương án tối ưu nhất.

lên
34 thành viên đã đánh giá bài viết này hữu ích.
Từ khóa: 
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results

Các bài viết cùng tác giả

Giới thiệu ethernet shield - ứng dụng điều khiển thiết bị ở mọi nơi trên thế giới khi có internet

Ethernet shield là một mạch mở rộng cho arduino, giúp arduino có thể kết nối với thế giới internet rộng lớn. Ứng dụng của shield này là truyền nhận thông tin giữa arduino với thiết bị bên ngoài sử dụng internet, shield này đặc biệt hữu ích cho các ứng dụng IoT, điều khiển và kiểm soát hệ thống vì internet luôn liên tục, dữ liệu truyền đi nhanh, khoảng cách là vô tận( trong Trái Đất thôi, với phải có mạng nữa) ăn đứt sóng RF , rẻ hơn với cách truyền từ xa bằng tin nhắn. Hôm nay mình sẽ hướng dẫn mọi người cách sử dụng nó để điều khiển thiết bị bằng đường truyền internet. 

lên
59 thành viên đã đánh giá bài viết này hữu ích.

Tạo một module rơ-le, module triac cho các dự án dùng mạch điện dân dụng

Các dự án thí nghiệm thông thường ta đọc trên diễn đàn thường là các dự án thử nghiệm với led, nhưng nếu các dự án lớn, yêu cầu áp dụng thực vào đời sống thì led không làm được điều đó. Bài viết này sẽ giới thiệu tới các bạn cách tạo module rơ-le, module triac chạy ổn định, cấu tạo đơn giản mà ai cũng có thể làm được.

lên
37 thành viên đã đánh giá bài viết này hữu ích.