Các bạn sử dụng điện thoại ắt hẳn đã từng chơi qua những game như đua xe, lắc banh… mà trong đó, các bạn phải nghiêng, xoay điện thoại phải không? Làm sao điện thoại có thể biết chính nó bị nghiêng hay xoay về hướng nào? Câu trả lời là dựa vào cảm biến gia tốc.
Trong bài học này, chúng ta sẽ cùng tìm hiểu về cảm biến gia tốc, góc nghiêng và một phương thức giao tiếp mới là I2C.
IMU (Inertial Measurement Unit) là một con chip để đo những chuyển động như đã giới thiệu ở trên. Một module IMU thường gồm 2 loại cảm biến: cảm biến gia tốc (Accelerometer) và cảm biến quay (Gyroscope).
Accelerometer (gọi tắt là accel): như tên gọi của nó, accel đơn giản là một cảm biến đo gia tốc của chính nó. Thông thường, một cảm biến accel sẽ có 3 trục xyz tương ứng với 3 chiều không gian, giúp ta biết được module đang bị nghiêng về hướng nào (trục x và y) hoặc đang bị lật hay úp (trục z).
Gyroscope (gọi tắt là gyro): đo tốc độ quay của nó quanh một trục. Tương tự với cảm biến gia tốc, thông thường, gyro sẽ có 3 trục xyz.
Lưu ý: gyro chỉ đo tốc độ quay chứ không đo trực tiếp góc quay, nên khi bạn quay module một góc nào đó rồi dừng, giá trị của gyro sẽ tăng lên rồi hạ xuống về 0.
Trên board xController đã tích hợp sẵn một module IMU tên là MPU6050.
Ở các bài trước, chúng ta đã tìm hiểu về các loại tín hiệu đơn giản là Digital và Analog. Tuy nhiên, để mạch điều khiển có thể làm việc được với các thiết bị phức tạp, chúng cần sử dụng các chuẩn giao tiếp phức tạp hơn. Một trong số đó là giao tiếp I2C (Inter-Integrated Circuit) rất phổ biến mà MPU6050 cũng sử dụng.
Giao tiếp I2C chia thiết bị làm 2 loại: Master (điều phối toàn bộ cách thức giao tiếp và truyền dữ liệu, ví dụ xController) và Slave (các cảm biến, module nối với chip điều khiển).
Có thể có nhiều kênh I2C trong một hệ thống, gọi là I2C bus. Mỗi I2C bus sử dụng hai đường truyền tín hiệu:
Nhiều thiết bị có thể được kết nối vào cùng một bus I2C, tuy nhiên điều này sẽ không gây xung đột bởi mỗi thiết bị đều được nhận diện bởi một địa chỉ I2C duy nhất.
import time while True: print('AccelX: ', motion.get_accel('x')) print('AccelY: ', motion.get_accel('y')) print('AccelY: ', motion.get_accel('z')) print('GyroX:', motion.get_gyro_roll()) print('GyroY:', motion.get_gyro_pitch()) print('GyroZ:', motion.get_gyro_yaw()) time.sleep_ms(100)
Sau khi chạy chương trình, bạn có thể xem các giá trị đọc được từ cảm biến được thay đổi trong cửa sổ dòng lệnh khi nghiêng hộp xController về các phía hoặc xoay như sau.
AccelY: 4 AccelY: 14 GyroX: -3 GyroY: 1 GyroZ: -1 AccelX: 10 AccelY: 4 AccelY: 14 GyroX: -3 GyroY: 1 GyroZ: -1 AccelX: 10 AccelY: 4 AccelY: 14 GyroX: -3 GyroY: 1 GyroZ: -1 AccelX: 10 AccelY: 4 AccelY: 14 GyroX: -4 GyroY: 1 GyroZ: -1
Giải thích chương trình
Chương trình trên liên tục đọc và in ra giá trị tất cả các trục xyz của cảm biến gia tốc.
print('AccelX: ', motion.get_accel('x')) print('AccelY: ', motion.get_accel('y')) print('AccelY: ', motion.get_accel('z'))
Ở đây chúng ta dùng một cú pháp mới của câu lệnh print(), giúp in ra giá trị của mỗi trục và có thêm chữ ở đầu dòng in ra.
print('GyroX:', motion.get_gyro_roll()) print('GyroY:', motion.get_gyro_pitch()) print('GyroZ:', motion.get_gyro_yaw())
Tượng tự là các câu lệnh để in ra giá trị xoay của các trục xyz của cảm biến gyroscope.
Các giá trị pitch, roll và yaw thể hiện trạng thái xoay của robot quanh các trục x, y và z. Bạn có thể xem hình sau để dễ hiểu hơn.
Ngoài ra, thư viện motion còn có hàm motion.is_shaked() để xác định hộp điều khiển xController có đang bị lắc hay không.