Chúng ta sẽ kết nối cảm biến với VĐK như sau:
SCL --> PC0
SDA --> PC1
INT --> PD2
VCC --> 3.3V
GND --> GND
*Chú ý: Chân PC0, PC1, INT các bạn sử dụng trở 4k7 để kéo lên 3.3V.
II. Lập trình phần mềm
APDS-9960 là cảm biến được tích hợp các loại cảm biến: cảm biến màu, cảm biến cường độ ánh sáng, cảm biến tiệm cận, cảm biến cử chỉ.
Ở bài viết này mình sẽ sử dụng nó là một cảm biến cử chỉ. Trong thư viện mình để ở cuối bài viết là thư viện đầy đủ cho tất cả các chức năng của APDS-9960, các bạn có thể sử dụng thư viện này để lập trình các chức năng khác của cảm biến.
Đầu tiên ta có một số định nghĩa và khai báo các biến toàn cục:
Mã:
// Pins
#define APDS9960_INT PD2 // Needs to be an interrupt pin
#define detachInterrupt(X) (GICR &= ~(1<<X)) //cấm ngắt ngoài
#define attachInterrupt(Y) (GICR |= (1<<Y)) // kích hoạt ngắt ngoài
int isr_flag = 0;
Tiếp theo ở hàm main() chúng ta khởi tạo đầu vào cho chân ngắt, kích hoạt ngắt, khởi tạo UART(mình sử dụng UART để gửi các cử chỉ cảm biến nhận dạng được lên terminal):
Mã:
//Set chan interrupt la input
PORTD |= (1<<APDS9960_INT);
DDRD &= ~(1<<APDS9960_INT);
// khoi tao UART
UART_init(UART_BAUD_SELECT(9600, F_CPU));
// Initialize interrupt service routine
MCUCR |= (1<<ISC01); // ngat INT0 là ngat canh xuong
GICR |= (1<<INT0); //cho phép ngat INT0 hoat dong
sei(); //set bit I cho phép ngat toàn cuc
Tiếp theo, ta cần khởi tạo APDS-9960 và kích hoạt cảm biến cử chỉ:
Mã:
// khoi tao APDS-9960(cau hinh I2C va cac gia tri ban dau)
if (ADPS9960_init())
{
UART_puts("APDS-9960 initialization complete\r\n");
}
else
{
UART_puts("Something went wrong during APDS-9960 init!\r\n");
}
// kich hoat cam bien cu chi
if ( ADPS9960_enableGestureSensor(true))
{
UART_puts("Gesture sensor is now running\r\n");
}
else
{
UART_puts("Fail, Reset module!\r\n");
}
Ở vòng lặp while(1) ta sẽ kiểm tra khi có sự kiện ngắt trên chân PD2 ta sẽ tiến hành so sánh và gửi dữ liệu qua giao tiếp UART:
Mã:
while (1)
{
if( isr_flag == 1 )
{
detachInterrupt(0);
handleGesture();
isr_flag = 0;
attachInterrupt(0);
_delay_ms(500);
}
}
Trong đoạn code trên, biến isr_flag được set lên 1 khi có sự kiện ngắt xảy ra, và hàm handleGesture() là hàm so sánh dữ liệu nhận được từ cảm biến và gửi dữ liệu qua UART.
Mã:
ISR(INT0_vect)
{
isr_flag = 1;
}
void handleGesture()
{
if ( ADPS9960_isGestureAvailable() )
{
switch ( ADPS9960_readGesture() )
{
case DIR_UP:
UART_puts("UP\r\n");
break;
case DIR_DOWN:
UART_puts("DOWN\r\n");
break;
case DIR_LEFT:
UART_puts("LEFT\r\n");
break;
case DIR_RIGHT:
UART_puts("RIGHT\r\n");
break;
case DIR_NEAR:
UART_puts("NEAR\r\n");
break;
case DIR_FAR:
UART_puts("FAR\r\n");
break;
default:
UART_puts("NONE\r\n");
}
}
}
Code ví dụ và thư viện các bạn có thể tải về tại đây. Thư viện cho module mình chuyển từ thư viện C++ của arduino trên github sang thư viện C cho AVR. Các bạn dùng arduino có thể sử dụng thư viện cho arduino mình đã đính kèm cùng file ở trên.