Bài 2 : Lập trình Raspberry giao tiếp I2C
18:15 - 14/01/2019
Bài 2 : Lập trình Raspberry giao tiếp I2C
Remote Desktop Raspberry Pi không cần Wifi, mạng LAN và IP
Camera nhiệt giải pháp tuyệt vời cho mùa Covid-19
Lập trình cơ bản với OpenPLC trên Raspberry Pi
Hướng dẫn cài đặt OpenPLC trên Raspberry Pi
1. Giới thiệuTrong tập hợp những bài lập trình cơ bản cho Raspberry. Sau khi kết thúc bài lập trình GPIO, chúng ta chuyển sang lập trình giao tiếp ngoại vi cho Pi. Những giao tiếp ngoại vi mà Raspberry Pi hỗ trợ: - I2C - SPI - Uart (serial) - USB - Ethernet Tùy theo nhu cầu và mục đích sử dụng mà bạn có thể chọn loại giao tiếp trên để sử dụng. Thông thường để giao tiếp với các dòng vi xử lý như AVR,PIC hay ARM và các thiết bị ngoại vi khác các bạn có thể chọn UART, I2C, SPI. Cả 3 giao thức đều rất phổ biến. Hai giao thức mới hơn là USB và Ethernet là chuẩn mới hơn dành cho giao tiếp tốc độ cao. Trong phần này mình sẽ không đề cập tới kiến thức của các chuẩn giao tiếp mà chỉ đề cập tới cách kết nối và lập trình. Một số tham khảo cho bạn : - Khi giao tiếp với các phần cứng khác như cảm biến thì đa phần phải chọn lựa theo giao tiếp mà thiết bị đó hỗ trợ. - Khi muốn thành lập một mạng lưới giao tiếp với nhau có thể chọn I2C hay SPI. I2C phù hợp vì kết cấu kết nối đơn giản hơn. Nhưng tốc độ SPI đạt tốc độ cao hơn. USB hay Ethernet cũng rất phù hợp nhưng đa số các thiết bị cấp thấp không hỗ trợ. - Giao tiếp thực sự cần tốc độ cao thì USB và Etherrnet phù hợp nhất, ngoài ra cũng có thể dùng SPI. Nếu ai quan tâm tới tốc độ có thể tham khảo bảng thông số về tốc độ truyền tin của các chuẩn dưới đây :
Tốc độ bên trên chỉ trên lý thuyết của chuẩn và thường chạy trên các dòng vi xử lý cỡ nhỏ và trung bình. Trong hệ thống có thể có điểm gây thắt cổ chai tốc độ. Giả như với SPI tốc độ phụ thuộc vào tần số vi xử lý đạt được, khi kết nối với dòng vi xử lý hỗ trợ tần số thấp hơn thì phải giảm tốc độ SPI xuống cho phù hợp. Và dù tốc độ truyền tin nhanh nhưng nếu vi xử lý không cần truyền tin liên tục hay không kịp xử lý với dữ liệu thì cũng không cần sử dụng phương thức truyền tin nhanh. 2. I2CĐầu năm 1980 Phillips đã phát triển một chuẩn giao tiếp nối tiếp 2 dây được gọi là I2C. I2C là tên viết tắt của cụm từ Inter-Intergrated Circuit. Đây là đường Bus giao tiếp giữa các IC với nhau. I2C mặc dù được phát triển bới Philips, nhưng nó đã được rất nhiều nhà sản xuất IC trên thế giới sử dụng. I2C trở thành một chuẩn công nghiệp cho các giao tiếp điều khiển. I2C có thể hoạt động ở nhiều chế độ khác nhau : - Một chủ một tớ (one master - one slave) - Một chủ nhiều tớ (one master - multi slave) - Nhiều chủ nhiều tớ (Multi master - Multi slave) Các thiết bị được phân biệt với nhau bằng 7 bit địa chỉ, cũng tức là có tối đa 128 thiết bị slave được kết nối. a) kết nối phần cứng Đa phần các chân giao tiếp I2C được thiết kế dưới dạng cực háng mở. Nó không thể tự đưa thiết lập mức cao hoặc thấp mà phải nối thêm điện trở lên dương nguồn. Tuy nhiên chân giao tiếp I2C được nối điện trở treo bên trong 1.8kΩ nên không cần nối thêm điện trở treo. Trong bài này mình sẽ lấy ví dụ là giao tiếp I2C giữa Raspberry và Arduino. Các bạn kết nối như sau
b) Lập trình giao tiếp I2C Chọn thiết lập Raspberry làm master, Arduino làm Slave. Raspbian mặc định không mở thiết lập I2C, chúng ta cần phải thiết lập mở I2C trước. 1. Mở terminal lên sửa Raspi-config sudo raspi-config
Lựa chọn Advanced options → I2C → Yes.→ Finish 2. Sửa file modules sudo nano /etc/modules Thêm 2 dòng này ở cuối file i2c-bcm2708
i2c-dev 3. Cài đặt thư viện cho I2C (thư viện cho python) sudo apt-get install python-smbus
sudo apt-get install python3-smbus
4. Reboot sudo reboot 5. Sau khi reboot xong có thể kiểm tra lại xem thiết lập có đúng không lsmod | grep i2c_ Câu lệnh sẽ liệt kê các cổng I2C hoạt động. Nếu kết quả hiện ra là “i2c_bcm2708” thì việc thiết lập đã chính xác. Lập trinh với C Thư viện sử dụng “WiringPi” đã được đề cập ở bài viết trước Chương trình Master "i2c-master.c" cho Raspberry #include <stdio.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#define addrSlave 0x08
int val = 0x10; // DEC = 16
int main(){
int fd = wiringPiI2CSetup(addrSlave);
while(1){
wiringPiI2CWrite(fd,val);
printf("%d",val);
fflush(stdout);
delay(1000);
}
return 0;
} - Thư viện <wiringPiI2C.h> - Chọn địa chỉ slave, wiringPiI2CSetup(addrSlave): địa chỉ là 0x08. - Gửi dữ liệu tới Arduino, wiringPiI2CWrite(fd,val) : lệnh gửi 1 byte tới slave và có dữ liệu là val. (val ở dạng hex đổi ra thập phân bằng = 16) Câu lệnh đọc dữ liệu được thư viện WiringPi hỗ trợ là : int wiringPiI2CRead (int fd) : dữ liệu trả về dạng int. Chương trình Slave cho arduino #include <Wire.h>
void setup() {
Wire.begin(0x08); // dia chi #0x08
Wire.onReceive(receiveEvent); // ham goi event I2C
Serial.begin(9600);
}
void loop() {
delay(100);
}
void receiveEvent(int n) {
while(Wire.available()) // chay lien tuc den khi het data
{
byte c = Wire.read(); // Doc 1 byte du lieu
Serial.print(c); // In len man hinh qua uart
}
} Chương trình này sẽ tạo một hàm dựa trên ngắt của I2C, khi I2C có dữ liệu sẽ tự động gọi hàm nhận, ở đây là receiveEvent(). Hàm này đọc liện tục từng byte dữ liệu cho đế khi hết dữ liệu và in lên màn hình qua Uart. Các bạn có thể tham khảo thêm các chương trình cho I2C khác của Arudino Sau khi kết nối I2C giữa arduino và Raspberry và arduino chạy chương trình slave. Gõ câu lệnh sau trên Pi để địa chỉ slave. sudo i2cdetect -y 1 Kết quả hiện ra địa chỉ của kết nối của Slave là 0x08. Giống địa chỉ đã thiết lập bên trên pi@raspberrypi:~/Tutorial/Python $ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- 08 -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- Kết quả : Lập trình bằng Python Chương trình Master "i2c-master.py" của Raspberry #!/usr/bin/python3
import smbus
from time import sleep
bus = smbus.SMBus(1)
addr = 0x08
val = 0x10
while True:
bus.write_byte(addr, val)
print(val)
sleep(1) Thư viện smbus - smbus.SMBus(1) : chọn cổng I2C, trong 40 chân GPIO thì chúng ta chỉ có thể sử dụng I2C port 1. - write_byte(addr, val) : câu lệnh gửi 1 byte tới địa chỉ “addr”. Chúng ta chọn địa chỉ slave là 0x08, khi viết chương trình cho arduino phải chọn địa chỉ tương ứng là 0x08. Bảng câu lệnh được thư viện smbus hỗ trợ : addr : địa chỉ thiết bị, val : dữ liệu, cmd : lệnh
Các bạn có thể xem thêm tại đây Kết quả giống như chương trình với C 3. Hướng dẫn setup chân I2C mềm cho Raspberry Pi
|
Để cập nhật các tin tức công nghệ mới các bạn làm theo hướng dẫn sau đây :
Các bạn vào Trang chủ >> Tin tức. ở mục này có các bài viết kỹ thuật thuộc các lĩnh vực khác nhau các bạn có thể lựa chọn lĩnh vực mà mình quan tâm để đọc nhé !!!
Các bạn cũng có thế kéo xuống cuối trang để xem những tin tức công nghệ mới nhất.