Sử dụng LED ma trận với AVR ATmega8

LED matrix hay ma trận điểm là một loại thiết bị rất phổ biến trong hiển thị thông báo và quảng cáo. Hiện nay, các chip hỗ trợ và thư viện phần mềm khá nhiều nên mọi người thường bỏ qua tìm hiểu nguyên tắc hoạt động của LED ma trận. Tuy nhiên, dưới góc độ người học lập trình thì làm việc với LED ma trận giúp chúng ta học được một số điều.

Trong bài này, chúng ta sẽ sử dụng LED matrix 8×8 với vi điều khiển ATmega8 để hiển thị các chữ cái. Một LED 8×8 có 64 đèn LED với 8 hàng 8 cột bố trí theo dạng ma trận nên cái tên LED ma trận có từ đó. Hiện nay, các đèn LED ma trận có cách thức bố trí chân thống nhất và có thể hiển thị nhiều màu.

Mặt sau có 2 hàng chân. Càng nhiều màu càng nhiều chân

Bước đầu chúng ta sẽ sử dụng LED 8×8 có 1 màu, 16 chân. Sau khi nắm rõ nguyên tắc hoạt động thì có thể mở rộng ra nhiều màu.

Kết nối đơn giản chưa có transistor kéo dòng.

Hình trên minh họa một kiểu kết nối đơn giản, trong đó chỉ có điện trở hạn dòng mà không có transisitor kéo dòng. Khi mô phỏng thì không có vấn đề gì nhưng thực tế sẽ khiến đèn LED sáng không đều và các chân vi điều khiển chịu tải thay đổi liên tục. Do vậy, khi triển khai các hệ thống thực tế, chúng ta cần bổ sung mạch kéo dòng cho đèn.

Bước 1: Xác định chân LED

Đèn LED matrix có cách bố trí chân theo thứ tự khác lạ và không có đánh dấu, không như các loại IC hoặc linh kiện khác. Trong mô phỏng thì các chân lại bố trí có thứ tự tuần tự. Điều này dễ gây nhầm lẫn nên người dùng ban đầu cần chú ý.

Giả sử chúng ta có 1 đèn LED thì cần biết datasheet của nó. Ví dụ với sơ đồ đi kèm như sau

Có thể thấy rằng, chỉ cần xác định được chân 1 và 16 là sẽ suy ra được các chân còn lại theo quy tắc đọc chân IC thông thường. Theo sơ đồ trên, đưa điện vào chân 1 và chân 16 nối đất thì đèn tại hàng 5, cột 8 sẽ sáng. Từ đó dễ dàng xác định các chân còn lại.

Chú ý rằng sẽ có loại đèn matrix với Anode/Kathode đảo lại. Dòng điện sẽ đi theo chiều ngược lại. Do vậy, khi sử dụng cần nắm rõ loại đèn đang sử dụng. Nếu không cần kiểm tra bằng cách đo kiểm để xác định loại đèn và vị trí chân.

Bước 2: Thử đèn

Thêm 1 bước kiểm tra để xác định chân

Đèn D10 tại hàng 2, cột 2 sáng khi dòng điện tác động chân 14 sang chân 3

Có thể thấy rằng, tại mỗi thời điểm chúng ta chỉ có thể tác động tối đa 8 đèn trên cùng 1 hàng hoặc trên cùng 1 cột. Do vậy, để có thể hiển thị trên LED matrix chúng ta cần kỹ thuật quét chân.

Bước 3: Quét chân

Mỗi thời điểm chúng ta chỉ cho 1 hàng, 1 cột hoặc 1 điểm sáng. Do mắt người không thể phân biệt được tốc độ sáng tắt trên 30Hz nên chúng ta sẽ cho các LED sáng tuần tự theo từng hàng hoặc cột ở tốc độ cao. Đây chính là kỹ thuật quét chân.

Ví dụ hiển thị chữ A theo hàng

Chữ A

Đầu tiên, chỉ có chân 9 lên cao, điều khiển hàng thứ nhất. Các chân điều khiển hàng khác ở mức thấp. Các chân 3, 4 ,10, 6, 11, 15 xuống thấp giúp các đèn D2, D3, D4, D5, D6, D7 sáng. Và chân 13, 16 lên cao khiến đèn D1, D8 tắt.

Tiếp theo, chân 14 lên cao điều khiển hàng thứ hai. Các chân điều khiển hàng khác ở mức thấp. Các chân của hàng 2 xuống thấp toàn bộ giúp các đèn từ D9 đến D16 đều sáng.

Tuần tự như vậy cho đến hết 8 hàng. Khoảng thời gian chờ giữa từng hàng tùy theo chúng ta lựa chọn vào khoảng vài ms là đủ.

Điều khiển theo cột

Đầu tiên chỉ có chân 13 xuống thấp, các chân điều khiển cột khác lên cao. Các chân 5, 2, 7, 1, 12, 8, 14 lên cao và chân 9 xuống thấp. Như vậy đèn D1 tắt và D9, D17, D25, D33, D41, D49, D57 sáng.

Tiếp theo, chân 3 xuống thấp, các chân điều khiển cột khác lên cao. Các chân 5, 2, 7, 1, 12, 8, 14 và chân 9 lên cao. Do đó, các đèn ở cột thứ 2 đều sáng hết.

Tuần tự như vậy cho hết 8 cột.

Mô phỏng

Truớc khi tiến hành lắp ráp mạch thực tế thì mô phỏng là một kỹ thuật cho phép chúng ta kiểm tra thiết kế nhanh chóng và chính xác. Tuy nhiên, khi mô phỏng bằng Proteus thì vị trí chân đèn LED ma trận không giống như thực tế.

Led xanh có chân khác Led đỏ

Đôi khi ta phải xoay đèn để có thể nhìn thấy đúng hình cần hiển thị.

Led đỏ thường đuợc dùng mô phỏng

Do vậy ta phải kiểm tra lại thứ tự và chức năng chân Led trước khi mô phỏng.

Chú ý vị trí gán chân 2 Led là khác nhau

Chương trình minh họa

/*
 * matrix.c
 *
 * thanks to Circuit digest
 */ 

#include <avr/io.h>
#define F_CPU 1000000
#include <util/delay.h>
int main(void)
{

	DDRD = 0xFF;
	DDRB = 0xFF;
	DDRC = 0xFF;
	char PORT[8] = {1,2,4,8,16,32,64,128};
	//characters a,b,c,d,e,f,g,...
	static int ALPHA[26][8]={{0,0b01111111,0b11111111,0b11001100,0b11001100,0b11001100,0b11111111,0b01111111},
	{0,0b00111100,0b01111110,0b11011011,0b11011011,0b11011011,0b11111111,0b11111111},
	{0,0b11000011,0b11000011,0b11000011,0b11000011,0b11100111,0b01111110,0b00111100},

{0,0b01111110,0b10111101,0b11000011,0b11000011,0b11000011,0b11111111,0b11111111},

{0,0b11011011,0b11011011,0b11011011,0b11011011,0b11011011,0b11111111,0b11111111},

{0,0b11011000,0b11011000,0b11011000,0b11011000,0b11011000,0b11111111,0b11111111},

{0b00011111,0b11011111,0b11011000,0b11011011,0b11011011,0b11011011,0b11111111,0b11111111},

{0,0b11111111,0b11111111,0b00011000,0b00011000,0b00011000,0b11111111,0b11111111},

{0b11000011,0b11000011,0b11000011,0b11111111,0b11111111,0b11000011,0b11000011,0b11000011},

{0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b11000011,0b11001111,0b11001111},

{0,0b11000011,0b11100111,0b01111110,0b00111100,0b00011000,0b11111111,0b11111111},

{0b00000011,0b00000011,0b00000011,0b00000011,0b00000011,0b00000011,0b11111111,0b11111111},

{0b11111111,0b11111111,0b01100000,0b01110000,0b01110000,0b01100000,0b11111111,0b11111111},

{0b11111111,0b11111111,0b00011100,0b00111000,0b01110000,0b11100000,0b11111111,0b11111111},

{0b01111110,0b11111111,0b11000011,0b11000011,0b11000011,0b11000011,0b11111111,0b01111110},

{0,0b01110000,0b11111000,0b11001100,0b11001100,0b11001100,0b11111111,0b11111111},

{0b01111110,0b11111111,0b11001111,0b11011111,0b11011011,0b11000011,0b11111111,0b01111110},

{0b01111001,0b11111011,0b11011111,0b11011110,0b11011100,0b11011000,0b11111111,0b11111111},

{0b11001110,0b11011111,0b11011011,0b11011011,0b11011011,0b11011011,0b11111011,0b01110011},

{0b11000000,0b11000000,0b11000000,0b11111111,0b11111111,0b11000000,0b11000000,0b11000000},

{0b11111110,0b11111111,0b00000011,0b00000011,0b00000011,0b00000011,0b11111111,0b11111110},

{0b11100000,0b11111100,0b00011110,0b00000011,0b00000011,0b00011110,0b11111100,0b11100000},

{0b11111110,0b11111111,0b00000011,0b11111111,0b11111111,0b00000011,0b11111111,0b11111110},

{0b01000010,0b11100111,0b01111110,0b00111100,0b00111100,0b01111110,0b11100111,0b01000010},

{0b01000000,0b11100000,0b01110000,0b00111111,0b00111111,0b01110000,0b11100000,0b01000000},

{0b11000011,0b11100011,0b11110011,0b11111011,0b11011111,0b11001111,0b11000111,0b11000011}};

	char NAME[]={15,17,14,9,4,2,19};
	uint8_t c = 0;
	while(1)
	{
		for (int m=0; m<sizeof NAME; m++)
		{
			c = NAME[m];
			for (int n=0; n<200; n++)
			{
				for (int j=0; j<4; j++)
				{
					PORTB = PORT[j];
					PORTD = ~ALPHA[c][j];
					_delay_us(500);
				}

			        	PORTB=0x00;				

				for (int k=0; k<4; k++)
				{
					PORTC = PORT[k];
					PORTD = ~ALPHA[c][k+4]; 
					_delay_us(500);
					
				}

				PORTC=0x00;

			}
		}
		_delay_ms(1);
	}
}

Trên thực tế khi điều khiển nhiều Led ma trận, chúng ta cần bổ sung transistor kéo dòng hoặc IC tải dòng để tránh ảnh hưởng đến vi điều khiển và độ sáng của đèn. Ví dụ

Video minh họa

Leave a Reply

Your email address will not be published. Required fields are marked *