之前看了一下其他人的帖子,感觉遮遮掩掩不是太清楚,我这次来个教程手把手搭建,相关模块都会说清楚,真正做到知无不言,让国内技术板块的分享更加细致和友好,抛砖引玉,斗胆希望更多的大神可以将不涉及知识产权的代码和教程放上来。振镜介绍挺多,用在投影、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,图像边缘的分辨率又会有损失。但这的确是一种省事的办法。
转载请注明出处