Bài viết trình bày kỹ thuật sử dụng Shift Register và Feedback Node trong các vòng lặp (For hoặc While loop). Đây là kỹ thuật dùng để truyền dữ liệu từ một lần thực thi trước sang lần thực thi vòng lặp tiếp theo.
Shift Registers
Biểu tượng Shift Registers xuất hiện thành từng cặp mũi tên trên bờ biên đứng của các vòng lặp như hình dưới đây. Đầu terminal bên phải (mũi tên hướng lên) của vòng lặp (là đầu out put) chứa đựng giá trị của một lần thực thi vòng lặp. LabVIEW truyền dữ liệu lưu trữ ở terminal bên phải sang terminal bên trái (Mũi tên hướng xuống). Vòng lặp sau đó sử dụng dữ liệu của terminal bên trái như là giá trị ban đầu cho lần thực thi tiếp theo của vòng lặp. Quá trình này cứ tiếp diễn cho đến khi vòng lặp được thực thi hết. Sau khi thực thi xong cả vòng lặp, terminal bên phải trả về và lưu trữ giá trị cuối cùng của vòng lặp. Để đặt một Shift Register lên một vòng lặp, ta click phải lên bờ biên của vòng lặp và chọn Add Shift Register từ menu pop up của nó. Một Shift Register có thể lưu trữ và truyền bất cứ loại dữ liệu nào và các terminal (Trái và phải) của một Shift Register phải nối cùng một loại dữ liệu. Chúng ta có thể đặt nhiều Shift Register lên một vòng lặp. Mỗi Shift Register sẽ làm việc độc lập với một hoạt động nào đó trong vòng lặp.
Chúng ta hãy cùng phân tích hoạt động của Block Diagram trên đây với hai Shift Register được đặt trên biên của vòng lặp. Với Shift Register phía trên, ngay sau lần lặp đầu tiên thì terminal bên phải sẽ nhận và lưu trữ giá trị bằng 2 (là tổng của 0 và 2), sau đó giá trị 2 này sẽ được truyền sang terminal bên trái để trở thành giá trị ban đầu của lần lặp thứ hai. Đối với Shift Register phía dưới thì sau khi kết thúc vòng lặp đầu tiên, giá trị mà terminal bên phải nhận được là 2 (Tích của 1×2), giá trị 2 này cũng được truyền qua terminal bên trái của Shift Register phía dưới. Kết thúc lần lặp thứ 2, giá trị nhận được của terminal bên phải ở Shift Register phía trên là 4 (tổng của 2 cọng 2) và cũng truyền sang terminal bên trái để trở thành giá trị ban đầu cho vòng lặp thứ 3. Đối với Shift Register bên dưới thì kết thúc vòng lặp thứ hai thì giá trị nhận được ở terminal bên phải là 8 (tích của 2×4), giá trị này được truyền sang terminal bên trái và trở thành giá trị ban đầu cho lần lặp thứ 3. Quá trình cứ thế tiếp tục như thế và bạn có thể đoán được sau khi kết thúc 10 lần lặp, thì giá trị ở terminal bên phải của Shift Register trên và dưới sẽ bằng bao nhiêu?
Initializing Shift Registers
Vì terminal bên trái của một Shift Register chỉ nhận giá trị từ terminal bên phải sau khi kết thúc lần lặp thứ nhất. Vậy tại lần lặp đầu tiên thì giá trị của terminal bên trái sẽ nhận giá trị bao nhiêu và lấy từ đâu? Chính vì lí do đó, chúng ta cần thiết lập giá trị ban đầu cho terminal bên trái ngay tại lần lặp thứ nhất khi VI chạy ( Để làm việc này chúng ta chỉ cần nối dây từ một giá trị xác định (hằng số hoặc control) tới đầu terminal bên trái như hình dưới đây.
Vòng lặp For trong Block Diagram này sẽ thực thi tổng cộng 5 lần lặp, giá trị của các terminal tăng lên một đơn vị sau mỗi lần lặp. Kết thúc 5 lần lặp thì terminal bên phải nhận giá trị 5 và terminal bên trái nhận giá trị 4. Lưu ý rằng, cứ mỗi lần bạn chạy vòng lặp này thì giá trị của terminal bên trái sẽ bắt đầu là giá trị 0 (Cần phân biệt mỗi lần chạy vòng lặp khác với mỗi lần lặp). Nếu như chúng ta không nối giá trị ban đầu nào vào terminal bên trái thì vòng lặp sẽ sử dụng giá trị mặc địch của loại dữ liệu được nối vào Shift Register ở lần chạy đầu tiên, còn các lần chạy sau đó thì nó sẽ lấy giá trị sau cùng của lần chạy trước đó (Giá trị out put ở terminal bên phải).
Hãy kiểm tra điềunày bằng việc tạo ra một vòng lặp For mà không có giá trị ban đầu như Block Diagram dưới đây. Ở lần chạy đầu tiên, Shift Register bắt đầu với giá trị 0 (Là giá trị mặc định của kiểu dữ liệu 32-bit integer). Sau khi kết 5 lần lặp cho lần chạy đầu tiên của vòng lặp For này. Đầu ra output (terminal bên phải) sẽ nhận và lưu trữ giá trị là 5. Nếu bạn lại chạy vòng lặp một lần nữa, giá trị ban đầu của Shift Register lúc này không phải là 0 như lần chạy đầu tiên mà bắt đầu từ 5 (là giá trị cuối cùng của lần thực hiện vòng lặp trước đó). Nếu sau khi chạy lần 2 và tiếp tục chạy lần 3 thì giá trị ban đầu sẽ bắt đầu là 10 và cứ thế tăng lên nếu ta thực hiện chạy nhiều lần. Đây có thể là kết quả mà chúng ta không mong muốn và gọi là một “Uninitializes Shift Register “.
Một “Uninitialized Shift Registers” sẽ giữ nguyên giá trị của những lần chạy trước cho tới khi bạn đóng VI đó lại.
Stacked Shift Registers
Một vấn đề đặt ra là nếu bạn muốn sử dụng dữ liệu của những lần lặp trước đó nhưng không phải là ngay trước đó thì làm thế nào. Ví dụ tại lần lặp thứ n nhưng bạn có nhu cầu sử dụng dữ liệu, kết quả của terminal bên phải (out put) tại lần lặp thứ n-2, n-3 hay trước đó 4 năm lần thì sao? Lúc này bạn cần sử dụng “Stacked Shift Registers”. Để thiết lập một “Stacked Shift Register”, bạn click chuột phải lên đầu terminal bên trái của một Shift Register và chọn Add Element từ Shortcut menu pop-up. Để dễ hình dung hoạt động của các Stacked Shift Register, có thể so sánh rằng terminal bên trái là đời con của terminal bên phải, Stacked của terminal bên trái là đời cháu của Terminal bên phải, và cứ thế nếu bạn tạo ra một stacked của stacked nữa bằng việc click chuột phải và chọn add Element. Lưu ý là Stacked Shift Register chỉ được đặt ở cạnh trái của vòng lặp như hình dưới đây mà thôi.
Feedback Node
Giống như Shift Register, một Feedback Node được sử dụng trong vòng lặp cũng lưu trữ dữ liệu sau khi kết thúc một lần lặp, gửi dữ liệu đó tới lần lặp tiếp theo. Quá trình lặp sẽ tiếp diễn cho tới khi vòng lặp hoàn toàn kết thúc. Tuy nhiên không có khái niệm tương đương với Stacked Shift Register trong Feedback Node, nó chỉ lưu trữ và truyền dữ liệu ở hai vòng lặp kế tiếp nhau mà thôi. Chúng ta cũng có thể thiết lập giá trị ban đầu cho một Feedback Node với ý nghĩa như initialize của Shift Register.
Initializing the Feedback Node on Loop Execution
Để thiết lập giá trị ban đầu cho Feedback Node, chúng ta nối một giá trị xác định vào đầu terminal Initialize của Feedback Node. Hãy kiểm tra việc thực hiện Feedback Node của Block Diagram dưới đây.
First Execution |
Second Execution |
||
Iteration |
End Value |
Iteration |
End Value |
0 |
3 |
0 |
3 |
1 |
4 |
1 |
4 |
2 |
5 |
2 |
5 |
3 |
6 |
3 |
6 |
Để thiết lập giá trị ban đầu cho Feedback Node, chúng ta cũng có thể Righ Click vào initialize và chọn Move Initializer One Loop Out để một biểu tượng dấu chấm có màu tương ứng với kiểu dữ liệu bạn nối với Feedback Node hiện ra ở bờ biên trái của vòng lặp. Đó chính là terminal cho phép bạn nối giá trị ban đầu của Feedback Node để thiết lập giá trị ban đầu cho nó. Trong trường hợp vòng lặp có chứa Feedback Node của bạn lại nằm trong một vòng lặp khác thì bạn có thể click chuột phải vào initialize để di chuyển terminal initialize này ra bờ biên trái của vòng lặp ngoài (Thực hiện bằng việc click chuột phải vào initialize terminal và chọn Move Initializer One Loop In). Hãy tự mình kiểm tra sự thực hiện của hai thay đổi này như thế nào bằng việc tạo ra hai Block Diagram có các vị trí initialez terminal nằm ở vòng lặp ngoài và ngay trên vòng lặp chứa trực tiếp Feedback Node.
Nếu chúng ta không nối giá trị nào vào initialize terminal của Feedback Node, vòng lặp sẽ hoạt động tương tự như trường hợp Uninitialized Shift Registers. Hãy tạo ra một Block Diagram có chứa vòng lặp như hình dưới đây để kiểm tra việc thực thi của nó. Trường hợp này gọi là “unwired initializer terminal” của Feedback Node.
First Execution |
Second Execution |
||
Iteration |
End Value |
Iteration |
End Value |
0 |
1 |
0 |
5 |
1 |
2 |
1 |
6 |
2 |
3 |
2 |
7 |
3 |
4 |
3 |
8 |
Mặc dù bạn có thể tách Feedback Node và initialize terminal của nó rời ra nhau (như trường hợp đặt trên biên của vòng lặp For hay While ở trên, song bạn không thể tách riêng ra khỏi vòng lặp hay cấu trúc của Feedback Node (Bờ biên của các vòng lặp chứa Feedback Node là giới hạn cuối cùng của sự tách riêng). Bạn cũng không thể tách chúng riêng rẽ ra khi bạn tạo một SubVI chứa Feedback Node và initialize terminal của nó nằm ngoài SubVI đó. Nếu bạn làm thế thì trong cả hai trường hợp trên, LabVIEW đều báo lỗi.
Thay thế Shift Registers bằng một Feedback Node
Bạn hoàn toàn có thể thay thế một Shift Register bằng một Feedback Node bởi việc click chuột phải lên Shift Register và chọn Replace with Feedback Node từ Shortcut menu. Hay bạn cũng có thể làm ngược lại là thay thế một Feedback Node bằng Shift Register với việc lựa chọn Replace with Shift Register.