Trong bài viết này, chúng ta sẽ thảo luận về việc sử dụng mô-đul đo khoảng cách siêu âm và Vi điều khiển 8051 để xây dựng một bộ điều khiển mức nước đơn giản. Nhiều dự án dựa trên mô-đul đo khoảng cách siêu âm và bộ điều khiển mức nước đã được thảo luận ở đây. Đây chỉ là một ứng dụng khác của mô-đul đo khoảng cách siêu âm. Bộ điều khiển mức nước này có thể giám sát và điều khiển bồn nước có độ sâu lên đến 2m và độ chính xác đo lường chỉ cần 1cm. Do không sử dụng bất kỳ công tắc nổi cơ học hoặc điện cực nào, nên không có sự mòn hoặc ăn mòn cơ học và điều này làm cho hệ thống trở nên rất đáng tin cậy. Tuy nhiên, cần chú ý đến việc cách nhiệt mô-đul đo khoảng cách siêu âm khỏi hiện tượng rung động vì nó chứa nhiều linh kiện điện tử.
Mô-đul đo khoảng cách siêu âm HC-SR04.
Mô-đul đo khoảng cách siêu âm được sử dụng ở đây là HC-SR04. HC-SR04 bao gồm một bộ phát siêu âm, một bộ thu và các linh kiện cần thiết để tạo nên một hệ thống độc lập. Nguyên tắc hoạt động rất đơn giản. Nó gửi 8 xung sóng âm thanh 40KHz và thu sóng phản chiếu. Thời gian trễ giữa thời gian phát và thời gian thu được đo và khoảng cách được tính từ phương trình D = TS/2. Ở đây, D là khoảng cách, T là thời gian trễ và S là vận tốc của âm thanh. Tín hiệu đầu ra của HC-SR04 sẽ là một xung có độ rộng tương tự với khoảng cách. Từ tài liệu kỹ thuật, độ rộng của tín hiệu đầu ra sẽ là 58uS cho một khoảng cách 1cm. Chúng ta chỉ cần gửi một tín hiệu kích hoạt có độ rộng 10uS đến chân kích hoạt của mô-đul và đợi tín hiệu đầu ra tại chân thu của mô-đul. Sơ đồ thời gian và pinout của mô-đul đo khoảng cách siêu âm được hiển thị dưới đây.
Đối với việc biết thêm về mô-đul siêu âm HC-SR04 và cách nó tương tác với Vi điều khiển 8051, hãy tham khảo bài viết này: Mô-đul đo khoảng cách siêu âm sử dụng Vi điều khiển 8051. Sơ đồ mạch đầy đủ của bộ điều khiển mức nước siêu âm được hiển thị dưới đây.
Sơ đồ mạch. Bộ điều khiển mức nước siêu âm
Chân kích hoạt của mô-đul đo khoảng cách siêu âm được kết nối với P3.0 của Vi điều khiển. Chân thu của mô-đul được kết nối với P3.1 của Vi điều khiển. Các dây dữ liệu của màn hình LCD được giao tiếp thông qua Port0 của Vi điều khiển. Các dây điều khiển RS, RW và E của mô-đul LCD được kết nối với các chân P2.7, P2.6 và P2.5 của Vi điều khiển tương ứng. Bơm được điều khiển bằng Port 2.0 của Vi điều khiển. Bơm được sử dụng ở đây là bơm rửa kính chắn gió ô tô 12V. Các bơm hoạt động từ lưới điện cũng sẽ tương thích với mạch này, nhưng công suất dòng điện của chúng phải phù hợp với relay bạn đang sử dụng. Dù sao thì cần phải cẩn thận để tránh nguy cơ giật điện khi làm việc với các thiết bị hoạt động từ lưới điện.
Ở đây, mô-đul đo khoảng cách siêu âm được đặt ở đầu bồn và hướng về mặt nước. Nước phản xạ các xung sóng siêu âm phát ra bởi mô-đul. Mô-đul thu sóng phản chiếu và đo thời trễ thời gian. Khoảng cách giữa bề mặt nước và cảm biến được tính toán từ dữ liệu thu thập và mô-đul sẽ tạo ra một xung có độ rộng tương tự với khoảng cách. Vi điều khiển đọc độ rộng của xung đầu ra này và thực hiện các phép toán cần thiết để lấy được khoảng cách. Ở đây, chúng ta có thể thấy rằng mức nước được đo từ trên xuống dưới, khác với hầu hết các cảm biến đo mức nước từ dưới lên trên. Điều này được thực hiện để làm cho thiết bị này phù hợp với một loạt các độ sâu khác nhau. Vì mô-đul đặt ở trên đỉnh bồn, chúng ta cần trừ đi khoảng cách từ cảm biến đến bề mặt nước khỏi tổng độ sâu của bồn để lấy được mức nước từ dưới lên trên. Vì mỗi bồn có độ sâu khác nhau, người sử dụng cần phải đo độ sâu của bồn thủ công và điều chỉnh chương trình với dữ liệu này.
Vấn đề này được giải quyết bằng cách đo mức nước từ trên xuống dưới. Ở đây, thiết bị bật BƠM khi mức nước giảm xuống dưới 20cm từ trên cùng và tắt BƠM khi mức nước tăng lên 5cm từ trên cùng. Mức nước hiển thị trên màn hình LCD thực tế là độ sâu của bề mặt nước từ trên xuống. Các bồn có độ sâu lên đến 1.5 mét sẽ phù hợp với dự án này.
RS EQU P2.7 ;equates RS to P2.7
RW EQU P2.6 ;equates RW to P2.6
E EQU P2.5 ;equates E to P2.5
ORG 00H ;origin
MOV DPTR,#LUT ;move starting address of LUT to DPTR
CLR P3.0 ;clears P3.0(output)
SETB P3.1 ;sets p3.1(input)
MOV TMOD,#00100001B ;sets Timer1 as Mode2 timer and Timer0 as Mode1 timer
MAIN:ACALL DINT ;calls DINT subroutine
ACALL TEXT1 ;calls TEXT1 subroutine
MOV TL1,#200D ;loads TL1 with start value
MOV TH1,#200D ;loads TH1 with reload value
MOV A,#00000000B ;loads A with all Zeros
SETB P3.0 ;sets P3.0(trigger pulse)
ACALL DELAY1 ;calls DELAY1 subroutine (1uS)
CLR P3.0 ;clears P3.0
HERE: JNB P3.1,HERE ;loops here until echo is received
BACK:SETB TR1 ;statrs Timer1
HERE1:JNB TF1,HERE1 ;loop here until Timer1 roll over occurs
CLR TR1 ;stops Timer1
CLR TF1 ;clears Timer Flag 1
INC A ;Increments accumulator
JB P3.1,BACK ;jumps to label BACK if echo is still present
MOV R7,A ;saves accumulator to R7
ACALL SPLIT ;calls SPLIT subroutine
ACALL LINE2 ;calls LINE2 subroutine
ACALL LEVEL ;calls LEVEL subroutine
ACALL TEXT2 ;calls TEXT2 subroutine
ACALL TEXT3 ;calls TEXT3 subroutine
ACALL CHECK ;calls CHECK subroutine
JB P2.0,JUMP ;jumps to label JUMP if P2.0 is set
ACALL TEXT4 ;calls TEXT4 subroutine
SJMP EXIT2 ;jumps to label EXIT2
JUMP:ACALL TEXT5 ;calls TEXT5 subroutine
EXIT2:ACALL DELAY2 ;calls DELAY2 subroutine(1S)
SJMP MAIN ;jumps to label MAIN
CHECK:MOV A,R7 ;loads value of R7 to accumulator
SUBB A,#20D ;subtracts 20D from A
JNC ON ;jumps to label ON if carry flag not set(A>20D)
ACALL OFF ;else calls OFF subrotine
SJMP EXIT ;jumps to label EXIT
ON:SETB P2.0 ;sets P2.0 (motor ON)
EXIT:CLR CY ;clears carry flag
RET ;return from subroutine
OFF: MOV A,R7 ;loads value of R7 to accumulator
SUBB A,#5D ;subtracts 5D from A
JNC EXIT1 ;jumps to label EXIT1 if carry flag not set(A>5D)
CLR P2.0 ;else clears P2.0(motor OFF)
EXIT1:CLR CY ;clears carry flag
RET ;return from subroutine
DELAY1: MOV R6,#2D ;loads R6 with 2D
LABEL1: DJNZ R6,LABEL1 ;loops here until R6 is 0
RET ;return from subroutine
DELAY2:MOV R0,#15D ;loads R0 with 15D
BACK1: MOV TH0,#00000000B ;loads TH0 with start value
MOV TL0,#00000000B ;loads TL0 with start value
SETB TR0 ;starts Timer0
HERE2: JNB TF0,HERE2 ;loops here until roll over occurs
CLR TR0 ;stops Timer0
CLR TF0 ;clear Timer Flag 0
DJNZ R0,BACK1 ;loops the timer session 15 times for 1S delay
RET ;return from subroutine
TEXT1: MOV A,#48H ;ascii of "H"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#32H ;ascii of "2"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#4FH ;ascii of "0"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#20H ;ascii of " "
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#4CH ;ascii of "L"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#45H ;ascii of "E"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#56H ;ascii of "V"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#45H ;ascii of "E"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#4CH ;ascii of "L"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#20H ;ascii of " "
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#43H ;ascii of "c"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#54H ;ascii of "T"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#52H ;ascii of "R"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#4CH ;ascii of "L"
ACALL DISPLAY ;calls DISPLAY subroutine
RET ;return from subroutine
TEXT2: MOV A,#63H ;ascii of "c"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#6DH ;ascii of "m"
ACALL DISPLAY ;calls DISPLAY subroutine
RET ;return from subroutine
TEXT3:MOV A,#20H ;ascii of " "
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#4DH ;ascii of "M"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#6FH ;ascii of "o"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#74H ;ascii of "t"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#6FH ;ascii of "o"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#72H ;ascii of "r"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#20H ;ascii of " "
ACALL DISPLAY ;calls DISPLAY subroutine
RET ;return from subroutine
TEXT5: MOV A,#4FH ;ascii of "O"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#4EH ;ascii of "N"
ACALL DISPLAY ;calls DISPLAY subroutine
RET ;return from subroutine
TEXT4:MOV A,#4FH ;ascii of "O"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#46H ;ascii of "F"
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,#46H ;ascii of "F"
ACALL DISPLAY ;calls DISPLAY subroutine
RET ;return from subroutine
SPLIT:MOV B,#10D ;loads 10D to B
DIV AB ;divides A with B
MOV R3,B ;saves the remainder to R3 (3rd digit)
MOV B,#10D ;loads 10D to B
DIV AB ;divides A with B
MOV R2,B ;saves the remainder to R2 (2nd digit)
MOV R1,A ;saves the quotient to R1 (1st digit)
RET ;return from subroutine
LEVEL:MOV A,R1 ;moves R1 to A (1st digit)
ACALL ASCII ;calls ASCII subroutine
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,R2 ;moves R2 to A (2nd digit)
ACALL ASCII ;calls ASCII subroutine
ACALL DISPLAY ;calls DISPLAY subroutine
MOV A,R3 ;moves R3 to A (3rd digit)
ACALL ASCII ;calls ASCII subroutine
ACALL DISPLAY ;calls DISPLAY subroutine
RET ;return from subroutine
DINT:MOV A,#0CH ;display ON cursor OFF
ACALL CMD ;calls CMD subroutine
MOV A,#01H ;clear display screen
ACALL CMD ;calls CMD subroutine
MOV A,#06H ;increment cursor
ACALL CMD ;calls CMD subroutine
MOV A,#80H ;force cursor to the begining of 1st line
ACALL CMD ;calls CMD subroutine
MOV A,#3CH ;activate 2nd line
ACALL CMD ;calls CMD subroutine
RET ;return from subroutine
LINE2:MOV A,#0C0H ;jump to 2nd line position 0
ACALL CMD ;calls CMD subroutine
RET ;return from subroutine
CMD: MOV P0,A ;moves A to P0
CLR RS ;clears RS pin of LCD
CLR RW ;clears RW pin of LCD
SETB E ;sets E pin of LCD
CLR E ;clears E pin of LCD
ACALL DELAY ;calls DELAY subroutine
RET ;return from subroutine
DISPLAY:MOV P0,A ;moves A to P0
SETB RS ;sets RS pin of LCD
CLR RW ;clears RW pin of LCD
SETB E ;sets E pin of LCD
CLR E ;clears E pin of LCD
ACALL DELAY ;calls DELAY subroutine
RET ;return from subroutine
DELAY: CLR E ;clears E pin of LCD
CLR RS ;clears RS pin of LCD
SETB RW ;sets RW pin of LCD
MOV P0,#0FFH ;sets P0 as input
SETB E ;sets E pin of LCD
MOV A,P0 ;moves P0 to A
JB ACC.7,DELAY ;jumps back to label DELAY if ACC.7 is set
CLR E ;clears E pin of LCD
CLR RW ;clears RW pin of LCD
RET ;return from subroutine
ASCII: MOVC A,@A+DPTR ;over-writes A with ascii code of data in A
RET ;return from subroutine
LUT: DB 48D ;ascii of "0"
DB 49D ;ascii of "1"
DB 50D ;ascii of "2"
DB 51D ;ascii of "3"
DB 52D ;ascii of "4"
DB 53D ;ascii of "5"
DB 54D ;ascii of "6"
DB 55D ;ascii of "7"
DB 56D ;ascii of "8"
DB 57D ;ascii of "9"
END ;end statement
Về chương trình: Chân P3.0 của Vi điều khiển được sử dụng để kích hoạt mô-đul siêu âm HC-SR04 và chân P3.1 của Vi điều khiển được sử dụng để nhận tín hiệu phản xạ (echo). Cả hai bộ hẹn giờ của Vi điều khiển 8051 đều được sử dụng trong dự án này. Timer1 hoạt động ở MODE2 (8 bit tự động nạp lại) và Timer0 (16 bit) hoạt động ở MODE1. Một tín hiệu kích hoạt có độ rộng 1uS được gửi đến chân kích hoạt của mô-đul siêu âm và Vi điều khiển đợi tín hiệu echo tại chân echo của mô-đul. Chân echo của mô-đul được kết nối với chân P3.1 của Vi điều khiển. Trạng thái của chân này được kiểm tra bằng lệnh JNB. Mỗi khi có tín hiệu echo hợp lệ được nhận tại chân này, Timer1 sẽ được bắt đầu. Bộ hẹn giờ đếm từ 200D đến 255D (tức là 55 đếm) và sau đó nó quay vòng lại. Sau mỗi lần quay lại, chân echo lại được kiểm tra và bộ hẹn giờ được khởi động lại nếu có bất kỳ tín hiệu echo nào hiện diện. Sau mỗi lần quay lại, trình tự nhấn vào thanh ghi và chu kỳ này được lặp lại cho đến khi tín hiệu echo biến mất.
Từ tài liệu kỹ thuật của HC-SR04, rõ ràng rằng một xung xói echo có độ rộng 58uS tương đương với 1cm. Ở đây, chúng ta thực tế đang đếm số khối có độ rộng 58uS trong tín hiệu echo và số lần đếm trực tiếp cho biết khoảng cách tính bằng cm. Vì Vi điều khiển được đồng hồ bằng một tinh thể 12MHz, 55 lần đếm tương đương với 55uS. Các lệnh khác được thực hiện trong mỗi chu kỳ hẹn giờ tốn khoảng 3uS, do đó tổng cộng có 58uS trong mỗi chu kỳ hẹn giờ. Số lần chu kỳ hẹn giờ, tức là giá trị trong thanh ghi tích luỹ, cho biết khoảng cách tính bằng cm.
Sau đó, các phép toán cần thiết được thực hiện trên giá trị trong thanh ghi tích luỹ và giá trị này được hiển thị trên màn hình LCD. Ở đây, chương trình được thiết lập để bật BƠM khi mức nước giảm xuống dưới 20cm (mức thấp) từ trên cùng và tắt BƠM khi mức nước tăng lên 5cm (mức cao) từ trên cùng. Điều kiện bật BƠM được xác định bằng cách trừ 20D khỏi giá trị trong thanh ghi tích luỹ. Nếu cờ nhớ không được đặt, điều đó có nghĩa là mức nước nằm dưới 20cm từ trên cùng và motor được bật.
Nếu cờ nhớ không được đặt, chương trình gọi phụ chương trình TẮT. Trong phụ chương trình này, 5D được trừ từ giá trị lưu trữ trong thanh ghi tích luỹ và trạng thái của cờ nhớ được kiểm tra bằng lệnh JNC. Nếu cờ nhớ không được đặt, điều đó có nghĩa là mức nước nằm dưới 5cm từ trên cùng và BƠM vẫn hoạt động. Nếu cờ nhớ được đặt, điều đó có nghĩa là mức nước nằm trên 5cm từ trên cùng và BƠM được tắt.
Bơm được điều khiển thông qua chân P2.0 của Vi điều khiển. Trạng thái của chân này được kiểm tra bằng lệnh JB. Nếu chân P2.0 là cao, điều đó có nghĩa là BƠM đang hoạt động và trạng thái "Motor ON" được hiển thị trên màn hình LCD. Nếu chân P2.0 là thấp, điều đó có nghĩa là BƠM đã tắt và trạng thái "Motor OFF" được hiển thị trên màn hình LCD. Đọc bài viết này: Tương tác màn hình LCD với Vi điều khiển 8051 để hiểu thêm về phần tương tác với màn hình.
Hotline: 0979 466 469