Nút nhấn, công tắc hành trình để làm gì? Nút nhấn, công tắc hành trình là những thứ tưởng chừng đơn giản nhưng lại rất quan trong trong lập trình robot. Ví dụ với những robot tự động, người điều khiển cần ra lệnh cho robot thông qua nút nhấn để từ đó có thể tự thực hiện nhiệm vụ, hoặc trong một cơ cấu chuyển động chạy từ A đến B, nếu không có công tắc hành trình nhận về tín hiệu kết thúc thì có lẽ cơ cấu chuyển động sẽ chạy cho đến lúc cháy.
Tại sao cần có kĩ thuật và chú ý trong lập trình nút nhấn? Bản chất của nút nhấn và công tắc hành trình đều là gửi về một tín hiệu 0 hoặc 1 về chân vi điều khiển. Nếu trong trường hợp chúng ta không nhấn nút mà vi điều khiển vẫn nhận tín hiệu có đóng/ngắt? Đó chính là nhiễu. Hiểu đơn giản là trong quá trình hoạt động, các trạng thái chuyển mạch của Role, nhiễu từ những vật thể xung quanh, tác động qua trường điện từ lên chân của vi điều khiển, vô tình làm cho VĐK hiểu nhầm là chúng ta có tác động. Chính vì vậy chúng ta cần có kĩ thuật để chống nhiễu. Có 2 cách để chống nhiễu nhưng lại thường được dùng kết hợp cả 2. Đó là xử lý nhiễu bằng lập trình và xử lý nhiễu bằng phần cứng. Tôi sẽ trình bày 2 cách này ở phần dưới.
Có bao nhiêu cách lập trình cho nút nhấn? Chúng ta thường sử dụng 2 cách cho lập trình nút nhấn. Một là tạo ra vòng lặp kiểm tra trạng thái, hai là sử dụng ngắt.
– Vòng lặp kiểm tra:
Ví dụ về 1 chương trình cho nút nhất dùng vòng lặp kiểm tra
1 2 3 4 5 6 7 8 9 |
while(1) { if(read_pin(PINB,0)==0) { cbi(PORTB,2); _delay_ms(500); } sbi(PORTB,2); } |
Trong ví dụ trên, chúng ta thấy điều kiện để thực hiện lệnh cbi(PORTB,2) đó là PINB=0; tuy nhiên như đã nói ở trên, nếu chúng ta gặp các xung nhiễu 0 đúng vào thời điểm thực hiện lệnh if, lúc này chương trình của chúng ta sẽ tự động thực hiện khối lệnh bên trong.
Để xử lý vấn đề này, chúng ta hoàn toàn có thể dùng lập trình để khử nhiễu. Các bạn theo dõi đoạn chương trình sau đã được thêm thành phần loại nhiễu. Đó là chúng ta sẽ dùng delay trong một khoảng thời gian đủ dài vượt qua xung nhiễu, và chúng ta kiểm tra trạng thái của chân PINB một lần nữa, nếu nó là giá trị khác 0 thì kết luận tín hiệu mới nhận trên chân là nhiễu, vì tay người chúng ta nhấn bình thường thì ít nhất cũng phải vài trăm ms cho lần nhấn nhả, và chúng ta bỏ qua khối lệnh trong if. Nếu PINB=0, có nghĩa là tín hiệu đó là tín hiệu do ta kích hoạt và chúng ta sẽ thực thi khối lệnh bên trong if.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
while(1) { if(read_pin(PINB,0)==0) { _delay_ms(10); if(read_pin(PINB,0)==1) goto out; _delay_ms(10); if(read_pin(PINB,0)==1) goto out; _delay_ms(10); if(read_pin(PINB,0)==1) goto out; cbi(PORTB,2); _delay_ms(500); out: ; } sbi(PORTB,2); } |
Một tính huống tiếp theo, cũng phát sinh từ việc chung ta dùng vòng lặp như trên. Ví dụ: chúng ta cần thực hiện khối lệnh trong if 1 lần duy nhất mỗi khi chúng ta nhấn nút. Nhưng do chúng ta thực hiện vòng lặp hỏi liên tục, nên trong khi chúng ta nhấn nút, thời gian sẽ đủ để chúng ta thực hiện khối lệnh này vài lần, dẫn đến kết quả của việc nhấn nút sẽ sai đi. Dưới đây là cách khắc phục bằng chương trình.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
while(1) { if(read_pin(PINB,0)==0) { _delay_ms(10); // Dùng delay để khử nhiễu if(read_pin(PINB,0)==1) goto out; _delay_ms(10); // Dùng delay để khử nhiễu if(read_pin(PINB,0)==1) goto out; _delay_ms(10); // Dùng delay để khử nhiễu if(read_pin(PINB,0)==1) goto out; while(read_pin(PINB,0)==0); // chỉ thực hiện câu lệnh 1 lần sau khi nhấn và nhả nút. cbi(PORTB,2); out: } sbi(PORTB,2); } |
– Sử dụng ngắt:
Khi sử dụng ngắt thì chúng ta có thể được vi điều khiển ngắt chương trình đang thực thi để nhảy đến chương trình con phục vụ ngắt, sau khi thực hiện xong VĐK sẽ quay về thực hiện tiếp công việc của mình.
Ví dụ về trình phục vụ ngắt với chân ngắt INT6:
1 2 3 4 |
ISR(INT6_vect) // ngắt công tắc hành trình { Dong_co_canh_tay=0 ; // gửi giá trị PWM=0 ngắt động cơ } |
-Cách khử nhiễu cuối cùng đó là thực hiện trên phần cứng, chúng ta có thể dùng các tụ mica104 để hàn giữa GND và chân vi điều khiển cần chống nhiễu, cũng có thể hàn trực tiếp lên các đầu ra của công tắc hành trình hoặc nút nhấn.