Ứ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ả

Các phép cộng, trừ, nhân, chia trong Arduino

Những phép toán trên có nhiệm vụ thực hiện việc tính toán trong Arduino. Tùy thuộc vào kiểu dữ liệu của các biến hoặc hằng số mà kết quả trả về của nó có kiểu dữ liệu như thế nào. Nếu là kiểu số nguyên thì nó cũng sẽ overflow [lên thiên đàn, xuống đất] (ví dụ, bạn xem tại int). Và nếu các giá trị đưa vào là số thực thì bạn được phép sử dụng các dấu chấm "." để ngăn cách phần nguyên và phần thực.

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