基于DAC8563模块的低速模拟振镜驱动,实现直线插补,点到点划线

        之前看了一下其他人的帖子,感觉遮遮掩掩不是太清楚,我这次来个教程手把手搭建,相关模块都会说清楚,真正做到知无不言,让国内技术板块的分享更加细致和友好,抛砖引玉,斗胆希望更多的大神可以将不涉及知识产权的代码和教程放上来。振镜介绍挺多,用在投影、SLA3D打印、光刻、激光雕刻、医学美容仪器中,这里给个图意思一下。

       

需要材料:

(1)可以开发stm32的arduino开发环境(需要这个环境配置好stm32 arduino core,具体在github上,https://github.com/stm32duino/Arduino_Core_STM32)arduino开发环境,支持C++

(2)STM32 f407 vet6开发板(其实C8t6也可以的,但是c8t6供电不行,带不动DAC模块,如果不嫌慢,arduino uno也能用,库我修改了,直接兼容)原库地址(https://github.com/k164v/DAC8562)【注意】这个库只能兼容arduino uno等8位单片机,代码习惯有问题stm32的编译器报错,我修改了下,完美兼容了uno和stm(https://github.com/bignest/dac8563-for-stm32-on-arduino-IDE)里面包括了改好的库,以及扫描例程,扫描例子下面也会讲到,欢迎疯狂star,增加一下本人声誉。谢谢

(3)某宝购入的15kHz低速振镜套装,188元一套,带有【振镜】【±12电源】【驱动板】

(4)405nm激光器,500mw,200块左右【警告,这个功率其实会伤害眼睛实际测试可以烧穿a4纸】

(5)简单的光学平台,搭建稳定的光路,这个我用的是很小的光学平台+配套支架,价格不菲,各位同学可以用铝板和万能怪手代替。

(6)最重要的放最后,DAC8563模块,可以输出±5信号,16bit精度,spi接口,带有隔离

连线

代码



#include <DAC8562.h> //把我改好的库用上
#define REF_POWER 5
#define SS_PIN 10    //这里的10会自动被识别为PD5
#define printimpact 0.5  //这个参数影响图像大小
#define compensaimpact 100  // 这个参数影响图像细分,直接影响振镜运行速度
float x1,r1,x,y,k,b,distance;
//Initialize the DAC object
DAC8562 dac=DAC8562(SS_PIN,REF_POWER);

void setup() {
pinMode(SS_PIN, OUTPUT);  
dac.begin();


}

void loop() {

scan(0*printimpact,3*printimpact); //这个里面的值代表五角星的各个点
scan(1*printimpact,1*printimpact);
scan(3*printimpact,1*printimpact);
scan(1*printimpact,-1*printimpact);
scan(2*printimpact,-3*printimpact);
scan(0*printimpact,-1*printimpact);
scan(-2*printimpact,-3*printimpact);
scan(-1*printimpact,-1*printimpact);
scan(-3*printimpact,1*printimpact);
scan(-1*printimpact,1*printimpact);
}

void scan(float x2, float y2)  //最核心的直线插补,用就完了,自己手敲的
{ 
distance=sqrt((float)(x1-x2)*(x1-x2)+(float)(r1-y2)*(r1-y2));
k=(y2-r1)/(x2-x1);
b=y2-k*x2;


if(x1<x2)
{ 
for (x=x1; x<x2; x=x+(abs(x1-x2))/(distance*compensaimpact)) 
  {
  y=k*x+b;
 
  dac.writeA(x);

  dac.writeB(y);

  }
  x1=x2;
  r1=y2;
}


if(x1>x2)
{ 
for (x=x1; x >x2; x=x-(abs(x1-x2))/(distance*compensaimpact)) 
  {
  y=k*x+b;
 
  dac.writeA(x);

  dac.writeB(y);

  }
  x1=x2;
  r1=y2;
}

if(x1==x2)
{ 
  if(y2>r1)
  {
for (y=r1; y<y2; y=y+0.005) 
  {
  dac.writeA(x);
  dac.writeB(y);
  }
  x1=x2;
  r1=y2;
}
  if(y2<r1)
 {
  for (y=r1; y>y2; y=y-0.005) 
    {
      dac.writeA(x);
     dac.writeB(y);
    }
  x1=x2;
  r1=y2;
 }
}
  
}

演示

快门比较慢,可以看到轨迹是五角星。设想一下,把现在的代码加上通讯协议,就可以解析G代码了,这也是我之后要做的。

一些解释

(1)图像尺寸其实并不是真实的,角度关系和光斑位移关系需要三角函数计算,这不难,但我想直接测量实际光斑和输入值的对应数据,用matlab拟合。这样更暴力。

(2)计算过程中使用了很多浮点数,这可能导致速度慢,其实可以不用的,但是要改下库。或者使用带有浮点运算优化功能的单片机

(3)自己敲的代码中,之所以要把点对点长距离分解成很多分来走,是因为如果不这样,振镜电机很容易过冲。【在这里我姑且把这一方式叫做直线插补,其实这样叫不规范】事实上,调低细分参数compensaimpact到1,arduino uno也能运行的很快,但是边角都变圆了。如果用于3D打印机或者激光切割机,基于F407的话500就可以。到1000,就太慢了。总之,只要运算能力够,这个值越大越好.

(4)为什么不用F407自带的12bit DAC输出?其实可以用的,也能用,粗略的算下,100mm的长度,分配4096份是0.02441mm(16bit为0.001526),用于3D打印和雕刻应该够了,fdm打印出的成品也就0.1mm左右。。不过这样的话要松开振镜螺丝从新校对零点,stm32DAC 0-3.3v的,上电初始化要到1.65V,图像边缘的分辨率又会有损失。但这的确是一种省事的办法。

转载请注明出处

猜你喜欢

转载自blog.csdn.net/GEEKKER/article/details/107642739