1. 功能说明
本文示例将实现R287样机6自由度并联拉线写字机器人写字(机器时代)的功能。

该机器人有两部分:绘图机构、走纸机构。绘图机构由6个舵机模块近似正六边形位置分布,共同控制位于中心的画笔;还具备一个走纸机构,走纸机构是由一个大圆周舵机驱动的。
2. 6自由度并联拉线写字机器人逆解算法
该6自由度并联拉线写字机器人的运动控制采用逆运动更容易一些,下面我们将对其逆运动算法进行介绍。我们先确定该6自由度并联拉线写字机器人的位置,通过建立坐标系的方法确定位置。这里我们选择在6自由度并联拉线写字机器人外一点建立一个直角坐标系,Z轴范围——笔架上下接线间距60,坐标系Z轴0点为7X11平板平面,这里面我们需要求解出每个舵机转动角度与画笔位置的关系:

各舵机坐标(注意这里面的Z轴坐标是以实际作用到舵机上的为准)
1(97,55,-10)
2(25,200,50)
3(97,345,-10)
4(302,345,50)
5(375,200,-10)
6(302,55,50)
中心点(x,y,z);目标点(xt,yt,zt);舵机半径 radius——24.0
中心点到每个舵机的距离:
目标点到每个舵机的距离 :
中心点到目标点舵机需要转动的角度(弧长公式):
其中90.0为笔在中心时舵机初始角度(这个很重要,舵机角度安装一定要注意),M_PI=3.1415926,0.5用于五入(为了补充运动过程中无法避免的损耗产生的运动误差)。
3. 电子硬件
本实验中采用了以下硬件:
| 主控板 | Basra主控板(兼容Arduino Uno) | 
| 扩展板 | Bigfish2.1扩展板 | 
| 电池 | 7.4V锂电池 | 
| 其它 | 画笔、画笔套管、连线、纸张等 | 
电路连接说明: 舵机连接:按圆盘顺时针方向,舵机位置依次对应Bigfish扩展板的D4, D7, D11,D3, D8, D12
4. 功能实现
编程环境:Arduino 1.8.19
下面提供一个6自由度并联拉线写字机器人写字(机器时代)的参考例程(servo_writing.ino):
/*------------------------------------------------------------------------------------
  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.
           Distributed under MIT license.See file LICENSE for detail or copy at
           https://opensource.org/licenses/MIT
           by 机器谱 2023-04-20 https://www.robotway.com/
  ------------------------------*/
/*
* 舵机连接,按圆盘顺时针舵机位置依次对应Bigfish:4, 7, 11, 3, 8, 12
* 书写范围:dx --> 50; dy --> 40
*/
#include <Arduino.h>
#include <avr/pgmspace.h>
#include "model.h"
#include "words.h"
#include <Servo.h>
#define SQU 0
#define JI 1
#define QI 2
#define SHI 3
#define DAI 4
Servo myServo[SERVO_NUM];     //笔筒控制舵机数组
Servo myServo1;               //走纸舵机
Servo myServo2;               //压纸舵机
int servo_port[SERVO_NUM] = {4,7,11,3,8,12};   //笔筒控制舵机引脚   
int words_num[10] = {};   
Point squ[] = {};              //字体
Point ji[] = {};
Point qi[] = {};
Point shi[] = {};
Point dai[] = {};   
int pos_x = 0, pos_y = 1, pos_z = 2;
boolean pos_test = false;      //位置测试, 真为测试
void setup() {
  Serial.begin(9600);
  myServo1.attach(16);         //走纸舵机引脚
  myServo2.attach(17);         //压纸舵机引脚
  myServo1.write(88);          //走纸停
  pressServoDown();            //压纸
 
  if(pos_test) posTest();      //坐标位置测试
  wordsArrayLength();          //计算flash中存储的字体数组长度
  delay(1000);
}
void loop() {                  //写字
//   writing(SQU);
  writing(JI);                 //机
  writing(QI);                 //器
  writing(SHI);                //时
  writing(DAI);                //代
  while(1){};
}
void setPos(Point pos) {                               
  static const float _basic_dists[kActuatorCount] = {
    distance(kInitialPoint, kActuatorOrigins[0]),
    distance(kInitialPoint, kActuatorOrigins[1]),
    distance(kInitialPoint, kActuatorOrigins[2]),
    distance(kInitialPoint, kActuatorOrigins[3]),
    distance(kInitialPoint, kActuatorOrigins[4]),
    distance(kInitialPoint, kActuatorOrigins[5])
  };
  int degree[kActuatorCount] = {};
  for (int i = 0; i < kActuatorCount; ++i)
  {
    float dist = distance(pos, kActuatorOrigins[i]);
    float deg = 90.0 + (dist - _basic_dists[i]) /
                   kActuatorRadius / M_PI * 180.0;
    degree[i] = floor(deg+0.5);
  }
  for (int i = 0; i < kActuatorCount; ++i)
  {
    ServoGo(i, map(degree[i], 0, 180, 700, 2100));
  }
}
void writeLine(Point a, Point b, unsigned long t) {
  static const int dt = 50;
  unsigned long k = t / dt;
  float dx = (b.x - a.x) / (float)k;
  float dy = (b.y - a.y) / (float)k;
  Point p = a;
  for (int i = 0; i < k; ++i)
  {
    setPos(p);
    delay(dt);
    p.x += dx;
    p.y += dy;
  }
}
void ServoStart(int which)
{
  if(!myServo[which].attached())myServo[which].attach(servo_port[which]);
  pinMode(servo_port[which], OUTPUT);
}
void ServoStop(int which)
{
  myServo[which].detach();
  digitalWrite(servo_port[which],LOW);
}
void ServoGo(int which , int where)
{
    ServoStart(which);
    myServo[which].writeMicroseconds(where);
}
void posTest(){
//    setPos({175, 185, 20});   //最小坐标
//    delay(1000);
    setPos({200, 200, 50});   //中间坐标,确定笔的位置时可将位置设置为中间坐标,打开开关然后机械调整舵机角度直到笔筒在中间位置即可
    delay(1000);
//    setPos({225, 225, 20});   //最大坐标
//    delay(1000);
    while(1){delay(10);};
}
void wordsArrayLength(){
   words_num[0] = sizeof(squArray) / sizeof(squArray[0]) / 3;
   words_num[1] = sizeof(jiArray) / sizeof(jiArray[0]) / 3;             //机
   words_num[2] = sizeof(qiArray) / sizeof(qiArray[0]) / 3;             //器
   words_num[3] = sizeof(shiArray) / sizeof(shiArray[0]) / 3;           //时
   words_num[4] = sizeof(daiArray) / sizeof(daiArray[0]) / 3;           //代
}
void readProgmem(int p, Point a, Point b, int ary[]){
    a.x = pgm_read_word_near( ary + p * 3 + pos_x) + 175;
    a.y = pgm_read_word_near( ary + p * 3 + pos_y) + 185;
    a.z = pgm_read_word_near( ary + p * 3 + pos_z);
   
    b.x = pgm_read_word_near( ary + (p + 1) * 3 + pos_x) + 175;
    b.y = pgm_read_word_near( ary + (p + 1) * 3 + pos_y) + 185;
    b.z = pgm_read_word_near( ary + (p + 1) * 3 + pos_z);
   
    writeLine(a, b, 500);
//    Serial.print(a.x);  
//    Serial.print("_");
//    Serial.print(a.y);
//    Serial.print(" ");
//    Serial.print(b.x);  
//    Serial.print("_");
//    Serial.println(b.y);
}
void writing(int which){
  for(int i=0;i<words_num[which] - 1;i++){
    switch(which){
        case 0:
          readProgmem(i, squ[i], squ[i+1], squArray);
        break;
        case 1:
          readProgmem(i, ji[i], ji[i+1], jiArray);
        break;
        case 2:
          readProgmem(i, qi[i], qi[i+1], qiArray);
        break;
        case 3:
          readProgmem(i, shi[i], shi[i+1], shiArray);
        break;
        case 4:
          readProgmem(i, dai[i], dai[i+1], daiArray);
        break;
    }
    pos_x = 0;
    pos_y = 1;
    pos_z = 2;
  }
  setPos({200, 200, 50});
  delay(1000);
  pressServoUp();
  delay(100);
  positionSwitch();
  pressServoDown();
}
void positionSwitch(){                //走纸函数
    myServo1.write(80);
    delay(500);
    myServo1.write(88);
    delay(100);
}
void pressServoDown(){                //压杆落
  myServo2.write(70);  
}
void pressServoUp(){                  //压杆抬
  myServo2.write(75);  
}5. 资料内容
①写字-例程源代码
②写字-样机3D文件
资料内容详见:6自由度并联拉线写字机器人-写字



















