Ứng dụng thư viện bất đồng bộ để điều khiển bất đồng bộ nhiều (hàng chục) servo - Hư cấu chăng?

Mô tả dự án: 

Cũng đã khá lâu kể từ lúc mình xuất bản thư viện xử lý bất đồng bộ với Arduino. Tuy nhiên, mình vẫn chưa có nhiều ví dụ để thực sự kêu gọi các bạn sử dụng thư viện này trong dự án, hôm nay, sau khi được trao đổi với nhiều bạn, mình thấy vấn đề điều khiển nhiều servo có thể ứng dụng thư viện của mình vào một cách dễ dàng. Nên mình sẽ viết một bài ví dụ để hướng dẫn các bạn điều khiển rất nhiều Servo với thư viện của mình.

Đặt vấn đề

Bài toán đặt ra

Bạn có 3 servo (ở đây có thể mở rộng lên rất nhiều, phụ thuộc vào số chân tín hiệu), bạn muốn điều khiển 3 servo này đến 3 vị trí khác nhau, sao cho cả 3 cùng đến đích cùng một lúc!

Hướng giải quyết

Để di chuyển đến đích, mỗi servo sẽ cần một thời gian nhất định. Thời gian tổng để cả 3 cùng về tới tích đó là thời gian chậm nhất để đưa cái servo có quảng đường di chuyển xa nhất về đến đích.

Mở rộng vấn đề, trong một khoảng thời gian t (mili giây), chúng ta phải đưa 3 servo về đến đích, sao cho chúng về đích cùng một lúc.

Ta chia khoảng thời gian t này thì nhiều đoạn (period) liên tục, mỗi đoạn, servo sẽ di chuyển một số delta bước.

Để làm được điều này, ta cần tính delta của từng servo trong mỗi đoạn (period), từ đó, ở mỗi period sẽ cho servo[i] di chuyển một bước là delta[i].

Vấn đề nảy sinh đó là, làm thế nào tính toán delta trong thời thực để servo di chuyển đúng vị trí của nó và tạo được hiệu ứng "mượt"?

Liên tưởng đến thư viện bất đồng bộ của mình

Đầu tiên, bạn cần phải hiểu, thư viện bất đồng bộ của mình hoạt động như thế nào?

Thư viện bất đồng bộ của mình, hướng đến việc tiếp cận mọi thứ thông qua các tiến trình. Nghĩa là? toàn bộ chương trình trong Arduino được phân bổ thành từng tiến trình với chu trình lặp đi lặp lại. Ví dụ: led 1 blink với chu kỳ 1000ms, led 2 blink với chu kỳ 1234ms, led 3 blink với chu kỳ 4321ms. Lúc đó, ta sẽ chia hiệu ứng từng led trở thành những tiến trình. Ví dụ: tiến trình led_1_blink, chu kỳ 1000ms; tiến trình led_2_blink, chu kỳ 1234ms; tiến trình led_3_blink, chu kỳ 4321ms. Cao cấp hơn, thì chỉ có 1 tiến trình được gọi 3 lần, blink với 3 lần cài đặt tiến trình riêng!

Thư viện Bất đồng bộ

Quay về bài toán của chúng ta, chúng ta sẽ xem từng servo sẽ là một tiến trình riêng biệt với từng chu kỳ riêng HOẶC một tiến trình duy nhất với chu kỳ là thời gian cho từng đoạn period. Nghĩa là sau thời gian period, mỗi servo sẽ di chuyển theo từng bước delta của chúng!

Ví dụ

Servo 1, 2, 3 đang ở tọa độ 0;

Ra lệnh: Servo 1, 2, 3 lần lượt tiến đến vị trí 100, 100, 20 trong thời gian 1000ms.

Xử lý: Ta cho rằng mỗi period là 10ms, nghĩa là cứ 10ms ta sẽ phải cập nhập tọa độ của Servo 1, 2, 3. Ta sẽ tính delta cho từng servo như sau:

Số lượng period = Thời gian / thời gian mỗi period

delta[i] = (tọa độ mới của servo[i] - tọa độ cũ của servo[i]) / số lượng period

Như vậy, ta chỉ cần ứng dụng vào là chạy được ngay devil

Nối mạch

Arduino Uno Servo 1 Servo 2 Servo 3
5V 5V 5V 5V
GND GND GND GND
2 Tín hiệu    
3   Tín hiệu  
4     Tín hiệu

 

Lập trình

Cái này, bạn nào rành lập trình là hiểu ngay, còn các bạn mới nghiên cứu thì hơi nặng! Nhớ xem kỹ hướng mình dẫn dắt ở trên nhé :). Mình có kết hợp với thư viện SerialCommand để dễ test. Để kiểm thử, các bạn dùng dòng lệnh SERVO <thời gian muốn đến đích> <Đích của servo thứ 1> <Đích của servo thứ 2> ... <Đích của servo thứ n>. Với n được sét ở biến SERVO_COUNT. Cùng thưởng ngoạn bạn nhé!

Lưu ý

DEFAULT_PERIOD_SERVO: thời gian mỗi period là bao nhiêu

SERVO_COUNT  số lượng servo

servoPin: chân nào của Arduino sẽ kết nối với Servo!

Demo

Mình sẽ cập nhập demo trong thời gian tới.

Youtube: 
Demo 3 servo
lên
21 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results

Các bài viết cùng tác giả

Lưu các biến CHỈ ĐỌC với PROGMEM

Trong bài Tiết kiệm RAM trong Arduino?, chúng ta đã biết cách lưu chuỗi hằng vào bộ nhớ FLASH thay cho việc lưu hết bọn chúng vào RAM. Như vậy, một hằng chuỗi có thể được lưu vào bộ nhớ FLASH thay vì lưu vào RAM. Vậy, câu hỏi đặt ra là, những biến hằng khác (hằng số, hẳng mảng, hẳng số thực) có thể được lưu vào FLASH thay vì vào RAM hay không?

Trong thực tế, các biến hằng (trừ hằng chuỗi) hầu hết chỉ tốn vài chục byte để lưu trữ nên RAM, nên chúng ta cũng chưa gặp vấn đề gì trong việc lưu trữ hằng số hay hằng mảng cả. Nhưng thỉnh thoảng, có những lúc, ta phải tìm cách lưu trữ chúng ở một nơi khác, ví dụ Bài 12: Phát nhạc bằng Arduino với một cái loa hoặc buzzer.

Chần chừ gì nữa, biết muốn phám khá khả năng của Arduino - hay không?

lên
8 thành viên đã đánh giá bài viết này hữu ích.

Bài 10: Đếm số lần nhấn một button - ButtonStateChange

Nếu bạn đã đọc qua Bài 3: Xác định trạng thái của một nút nhấn (button) thì chắc hẳn bạn đã biết cách sử dụng một button. Nhưng đôi khi bạn muốn button của bạn đặc biệt hơn một tí, chẳng hạn như là nhấn vài ba lần thì mới thực hiện chức năng của nó. Để làm được điều này, bạn cần biết được lúc nào button được nhấn và lúc nào button được thả ra, và đếm số lần. Hôm nay, tôi sẽ hướng dẫn bạn giải quyết vấn đề này.

lên
27 thành viên đã đánh giá bài viết này hữu ích.