Nghiên cứu Khoa học
Thiết kế cánh tay Robot dùng Arduino
Cánh tay Robot bao gồm các servo, kết nối các servo lại với nhau như sau:
- Servo 1 : quay cho cánh tay.
- Servo 2 : di chuyển lên xuống cho cánh tay.
- Servo 3 : di chuyển lên xuống cho phần đầu gắp của cánh tay.
- Servo 4 : điều khiển phần gắp của cánh tay.
Cấu tạo của cánh tay Robot như hình sau:
Hình 1: Cánh tay Robot dùng Arduino
Kết nối tương tự với các biến trở t như hình 1
Điều khiển cánh tay biến trở đến vị trí A và thực hiện một hành động, cánh tay robot sẽ di chuyển giống như cánh tay biến trở. Nhấn nút record để lưu lại vị trí đó. Sau đó tiếp tục thực hiện hành động và nhấn record để lưu.
Chú ý : Số hành động phải nhỏ hơn hoặc bằng với số hành động có thể nhớ của arduino.
Sau đó nhấn play_pause để cho cánh tay tự làm lại các động tác vừa lưu.
Tiếp đến nhấn play_pause để dừng hành động lại.
Tiếp đến nhấn Enable eeprom để lưu các động tác vào rom của arduino. Sau đó nhấn reset arduino và nhấn play_pause để kiểm tra xem cánh tay có hoạt động giống như các động tác ban đầu hay không.
Code chương trình trên Arduino:
byte pin_analog[servo_max] = { A0, A1, A2, A3 };
byte pin_servo[servo_max] = { 3, 5, 6, 9 };
unsigned int A0_value, A1_value, A2_value, A3_value;
// tính toán lấy giá trị góc của biến trở i
A0_value = constrain(analogRead(A0), 200, 823);
return map(A0_value, 200, 823, 4, 175);
A1_value = constrain(analogRead(A1), 200, 823);
return map(A1_value, 200, 823, 4, 175);
A2_value = constrain(analogRead(A2), 200, 823);
return map(A2_value, 200, 823, 175, 4);
A3_value = constrain(analogRead(A3), 200, 823);
return map(A3_value, 200, 823, 175, 4);
const unsigned int SIZE_MEMORY_EEPROM = 1024;
/* mảng lưu góc cho 5 servo */
byte goc_servo[servo_max][step_max];
// mảng 2 chiều quản lý (servo_max) servo
byte goc_tam_thoi[servo_max] = { 90 };
// lưu góc tạm thời tại thời điểm cần tính
pinMode(start_pause_pin, INPUT_PULLUP);
pinMode(ENABLE_EEPROM_PIN, INPUT_PULLUP);
pinMode(record_pin, INPUT_PULLUP);
for (byte i = 0; i < servo_max; i++) {
pinMode(pin_analog[i], INPUT);
servo[i].attach(pin_servo[i]);
void move_servo(byte i, byte goc_i)
void nhap_nhay(unsigned int time_delay, byte count)
for (byte i = 0; i < count; i++) {
void record(unsigned int step_x)
for (byte i = 0; i < servo_max; i++) {
goc_servo[i][step_x] = get_goc(i);
for (byte i = 0; i < servo_max; i++) {
move_servo(i, goc_tam_thoi[i]);
for (byte i = 0; i < servo_max; i++) {
hieu = abs(goc_tam_thoi[i] - get_goc(i));
if ((hieu >= 1) && (hieu < 170)) { // bạn cũng không được di chuyển arm điều khiển quá nhanh
step_move = EEPROM.read(SIZE_MEMORY_EEPROM - 1); // lấy lại step_move từ rom
for (byte i = 0; i < servo_max; i++) {
for (int step_j = 0; step_j < step_max; step_j++) {
goc_servo[i][step_j] = EEPROM.read(step_j + i * step_max);
// bước 1: lưu dữ liệu vào rom
EEPROM.write(SIZE_MEMORY_EEPROM - 1, step_move); // ghi step_move vào rom
delay(15); // đợi 15ms để hoàn thành ghi 1 ô nhớ
digitalWrite(led_pin, HIGH); // giữ nguyên đèn
for (byte i = 0; i < servo_max; i++) {
for (int step_j = 0; step_j < step_move; step_j++) {
EEPROM.write(step_j + i * step_max, goc_servo[i][step_j]);
delay(15); // đợi 15ms để hoàn thành ghi 1 ô nhớ
digitalWrite(led_pin, LOW); // tắt đèn
// chỉ được lưu dữ liệu vào eeprom khi đã có dữ liệu
// nhấn pause trước, sau đó mới nhấn nút ENABLE_EEPROM_PIN để bắt đầu ghi vào eeprom
if (digitalRead(start_pause_pin) == 0) {
if (digitalRead(ENABLE_EEPROM_PIN) == 0) {
if (digitalRead(start_pause_pin) == 0)
unsigned int step = 0, step_next;
//lấy hiệu góc hiện tại và góc sau
step_next = step + 1; // không viết : step++
/*step = step_mov :thì step tiếp theo của step cuối cùng là step đầu tiên*/
for (byte i = 0; i < servo_max; i++) {
hieu_f[i] = (float(goc_servo[i][step]) - float(goc_servo[i][step_next]));
for (float loading = 1.0; loading <= 100.0; loading++) {
//denta=30+((sq(loading-150))/1000);
// loading là phần trăm %, đánh giá kết thúc 1 động tác là 100%
for (byte i = 0; i < servo_max; i++) {
goc_tam_thoi[i] = byte(float(goc_servo[i][step]) - (((hieu_f[i]) * loading) / 100.0));
// gia tốc từ chậm->nhanh->chậm
if ((loading >= 0.0) && (loading < 20.0)) {
while ((millis() % delay_toc_do) != 0) { // làm trễ
/* cứ sau denta_ms, vòng lặp mới được thoát, */
step++; // tăng cho lần kế tiếp
while (digitalRead(start_pause_pin) != 0) {
//b1: điều khiển servo bằng biến trở
while (digitalRead(record_pin) != 0) {
if ((digitalRead(start_pause_pin) == 0) && (step_move == 0)) {
// nếu chưa có cài đặt náo mà vô thẳng phần chạy thì hiểu : lấy cài đặt từ eeprom
if ((digitalRead(start_pause_pin) == 0) && (step_move != 0)) {
// nút record đươcj nhấn, thoát lặp
step_move++; // tăng step cho bước sau
// nút start_pause được nhấn, thoát lặp
step_move--; //không có bước sau, giảm step_move xuống 1 đơn vị