【项目】基于arduino的验光头盔
我的参赛项目编号01,喜欢就支持下这个项目吧:http://www.kenrobot.com/arduinocn/vote,参与投票还有机会获得Arduino开发板和套件的奖励哦!目测我第一个发项目的样子。上一张完成图吊吊胃口模型地址,求点赞哦!hackaday的项目地址https://hackaday.io/project/22001-servo-liquid-lens
most3d地址(模型地址):http://www.most3d.cn/model/13566/演示视频:http://player.youku.com/embed/XMzExMzAwNjAwMA
需要以下这些材料工具。1.3D打印机+数控雕刻机
2.arduino nano或promini+msp430 2553
3.oled1306iic接口的+编码器+l298n电机驱动+蓝牙模块+电位器
4.直流减速电机
5.arduinoIDE+Energia+SolidWorks+MATLAB
先感谢下mostfun的各种工作和支持。希望多多赞助创客比赛和活动,得广厦千万间,大批天下寒士俱欢颜。
然后开始正题,这次要做个机器,可以验光的机器。达到以下几个目标
1、双眼同时验光,不用拿个勺子遮住。
2、全程电控遥控。
3、老子就是要EVA配色。
备注:原型验证机器,用arduino开发再合适不过了,精度一般就可以。没有上升到工业级别的操作。不制板,用开发板搞。一块arduino nano。另一块我一会介绍。
先来看看整体框架。
总之就是,用单片机控制抽液使液体透镜度数发生变化,什么时候看清楚什么时候停下。
为此,先有液体透镜再说。液体透镜,就是两片薄膜之间有液体,液体减小,因为压力变化,所以薄膜会有形变。
用雕刻机切,然后拿透明薄膜做液体塑型的薄膜,再用光敏胶水按照只有我才知道的牛逼方式粘起来(过程艰辛不表,以免逼死强迫症)。
这样肯定不行后来换方案。
以上是在切。这个步骤3D打印机完成不了,因为需要完全密封和很平的平面。
再后来就是这个。使用m3螺丝固定,3+2的结构很稳定。
侧面钻孔装管子。用来抽液。现在还没有粘薄膜。使用SolidWorks里面的受力分析下曲面的变形情况,发现这个不是纯正的球面。所以,折射率什么的计算公式没有了。意思是我们不能用减少体积来算出透镜度数。【这个液体透镜的性能很简陋,暂时无法和一般的玻璃透镜对比,折射率,曲率厚度等光学参数都没有测,阿贝系数就更不用谈了,最致命的是这是个单双凸透镜,如果要成像的话需要单负透镜一凸一凹(这里就不展开了,我也不懂)】
所以说,这个的到时候用机器慢慢测啦。
以上先不管,先把头盔建好。头盔要放两个镜片,开发板,两个小型丝杆滑台,两个活塞,还有电池什么的。
为了和头贴合好一些。我找了一颗人头的SolidWorks模型,放大1.3倍后做布尔运算。
囧了
下面开始做遥控器。用arduino nano(后来换成promini了都是328p)+两个编码器+oled+蓝牙模块。
简陋的原理图
用编码器要用到中断,arduino默认两个中断,但是有库可以调用所有引脚都变成中断。
搜索PinChangeInt,有真相。
oled就用最牛逼的U8g库不解释。
外壳3D打印+数控雕刻。
一开始他是这样的。
太蠢萌了。
后来我怒改
感觉不是太炫,改
中间种种艰辛再次不表。反正换了5个壳子我才满意的。
转动编码器,左右眼度数会发送的同时显示。
这里产生的值和发送的值之间的关系使用MATLAB拟合。两者之间的关系给了nano让他自己算去吧。
找了家眼科医院,吧头盔电位器——度数之间做了拟合。
过程蛋疼艰辛,不表。
最后喜感测试
开机除了瞳距就是度数
疯狂的旋转
小师妹在控制着一切
同步控制,蓝牙一直亮着
患者情绪稳定,表示自己即将起飞
透过液体透镜可以观察到目标渐渐清晰了。
谢谢大家捧场!
之中有很多不足,交流的同时不要忘记投票哦。
本帖最后由 巨窝 于 2017-11-20 15:37 编辑
经过一系列冗长乏味的修改,做了一个贴合头部的模型。然而小了。继续修改。
带有机玻璃边框的是成品。左边这个是废品。太大了,留的孔本来要装电池,然而太大了。擦下图是楼主的打印机,200mm300mm的。太简陋了。
上个效果图。这个东西只能一边建模一边做,要不然肯带不上。效果图其实最后也没有用上。
绿色部分是丝杆滑台,使用两个直流电机+L298n驱动,电位器做闭环。和普通舵机一个原理,之前我想用普通舵机的驱动板来搞的,但是功率太小作罢只能上大功率的。L289n12V+5V输出。12V输入,可以给单片机供电,现在,正式进入编程。
头盔使用MSP 430 2553。德州仪器的板子。牛逼的是,出来IAR,CCS外,德州仪器出来一个开发平台,energia。开发方式和arduino IDE一模一样。唯一不爽就是驱动难安装,最后我装在xp电脑上可以用了。2553可以低功耗使用。
装在头盔上,接收蓝牙模块的字符串,然后和丝杠滑台的电位器做对比,差大于0就正转,小于零反转。用L298n驱动电机旋转。
(蓝牙模块是TI的cc2541.买的成品,其实这个成品里面集成了一个51的核,还有12位ADC采样,然而我不会51,只是将他当成天线用)
用着还好,涉及底层的库和arduino不兼容。
逻辑框图
哇 我觉得液体透镜好牛逼 Zoologist 发表于 2017-3-31 20:47
哇 我觉得液体透镜好牛逼
做这个好费事儿。心累,而且因为材料原因,度数不能超800.要不然就塑性形变了。 请参赛选手需将原创设计模型上传到most3d(http://www.most3d.cn/)社区,并将链接附在本文中,方便其他用户点赞投票。可以加下比赛交流群:511210578,相关信息会在群里公布
1.感谢对社区比赛的支持,请补充下项目演示视频,具体要求请参考:
http://www.arduino.cn/thread-47517-1-1.html
2.开发者积分和贡献值已发放,请点击以下链接领取纪念衫并参与抽奖~
http://www.arduino.cn/thread-48132-1-1.html
3.比赛结果会在11.15号前公布,请耐心等待。
本帖最后由 巨窝 于 2017-11-6 10:33 编辑
遥控器代码。
接收头盔的代码我改天再找找,很简单其实。
解释一下几个比较黑暗的牛逼库。
第一个就是scoop,任务多开,比如使用scoop让两个led各自按照自己的频率闪烁,那么在各自的线程里面使用sleep();这个函数就可以了,比起protothread要简单很多。
第二个是PinChangeInt,可以多开中断,arduino的中断默认只有2,3脚,用了这个库所有IO全部可以变成中断使用,适合多编码器。。。u8g库不解释
#include "SCoop.h"
#include <PinChangeInt.h>
#include <U8glib.h>
#define PinA 10//中断10
#define PinB 11 //中断11
#define PinC 8
#define PinD 9
unsigned long time = 0;
long count = 0; //计数值
int num = 240;
// int sensorValue ;
long count1 = 0; //计数值
int numa= 240;
volatile int oleda;
volatile int oledb;
volatile int oledc;
//int A;
//int B;
int R;
int p;
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);//启用
static unsigned char u8g_zuo_bits[] U8G_PROGMEM =
{0x40,0x00,0x40,0x00,0x40,0x00,0xFF,0x7F,0x20,0x00,0x20,0x00,0x20,0x00,0x10,0x00,
0xF0,0x1F,0x08,0x01,0x08,0x01,0x04,0x01,0x02,0x01,0x01,0x01,0xFC,0x7F,0x00,0x00,};
//左,阴码,逐行,逆向
static unsigned char u8g_you_bits[] U8G_PROGMEM =
{0x40,0x00,0x40,0x00,0x40,0x00,0xFF,0x7F,0x20,0x00,0x20,0x00,0x10,0x00,0x10,0x00,
0xF8,0x1F,0x14,0x10,0x12,0x10,0x11,0x10,0x10,0x10,0x10,0x10,0xF0,0x1F,0x10,0x10,};
//右
static unsigned char u8g_maohao_bits[] U8G_PROGMEM =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,};
//冒号
static unsigned char u8g_tong_bits[] U8G_PROGMEM =
{0x00,0x04,0x80,0x3F,0x1E,0x11,0x12,0x0A,0xD2,0x7F,0x1E,0x00,0x92,0x3F,0x92,0x24,
0x9E,0x3F,0x92,0x24,0x92,0x3F,0x12,0x04,0x9E,0x3F,0x12,0x04,0xC0,0x7F,0x00,0x00,};
//瞳
static unsigned char u8g_ju_bits[] U8G_PROGMEM =
{0x00,0x00,0xBE,0x7F,0xA2,0x00,0xA2,0x00,0xA2,0x00,0xBE,0x3F,0x88,0x20,0x88,0x20,
0xBA,0x20,0x8A,0x20,0x8A,0x3F,0x8A,0x00,0xBA,0x00,0x87,0x00,0x80,0x7F,0x00,0x00,};
//距
static unsigned char u8g_CSU_bits[] U8G_PROGMEM =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x07,0xF0,0xFF,0x03,0x7F,0x00,
0xFC,0x01,0x00,0x00,0x00,0xF8,0xFF,0x07,0xFC,0xFF,0x03,0x7F,0x00,0xFC,0x01,0x00,
0x00,0x00,0xFC,0xFF,0x07,0xFE,0xFF,0x03,0x7F,0x00,0xFC,0x01,0x00,0x00,0x00,0xFE,
0xFF,0x07,0xFE,0xFF,0x03,0x7F,0x00,0xFC,0x01,0x00,0x00,0x00,0xFF,0xFF,0x07,0xFF,
0xFF,0x03,0x7F,0x00,0xFC,0x01,0x00,0x00,0x80,0xFF,0x81,0x87,0xFF,0x80,0x03,0x7F,
0x00,0xFC,0x01,0x00,0x00,0xC0,0x7F,0x00,0x86,0x3F,0x00,0x02,0x7F,0x00,0xFC,0x01,
0x00,0x00,0xC0,0x7F,0x00,0x80,0x3F,0x00,0x00,0x7F,0x00,0xFC,0x01,0x00,0x00,0xE0,
0x1F,0x00,0x80,0x3F,0x00,0x00,0x7F,0x00,0xFC,0x01,0x00,0x00,0xE0,0x0F,0x00,0x80,
0x3F,0x00,0x00,0x7F,0x00,0xFC,0x01,0x00,0x00,0xF0,0x07,0x00,0x80,0xFF,0x00,0x00,
0x7F,0x00,0xFC,0x01,0x00,0x00,0xF0,0x07,0x00,0x80,0xFF,0x01,0x00,0x7F,0x00,0xFC,
0x01,0x00,0x00,0xF0,0x07,0x00,0x80,0xFF,0x0F,0x00,0x7F,0x00,0xFC,0x01,0x00,0x00,
0xF8,0x07,0x00,0x00,0xFE,0x3F,0x00,0x7F,0x00,0xFC,0x01,0x00,0x00,0xF8,0x07,0x00,
0x00,0xFE,0x7F,0x00,0x7F,0x00,0xFC,0x01,0x00,0x00,0xF8,0x07,0x00,0x00,0xFC,0xFF,
0x01,0x7F,0x00,0xFC,0x01,0x00,0x00,0xF8,0x07,0x00,0x00,0xF8,0xFF,0x03,0x7F,0x00,
0xFC,0x01,0x00,0x00,0xF8,0x07,0x00,0x00,0xC0,0xFF,0x07,0x7F,0x00,0xFC,0x01,0x00,
0x00,0xF8,0x07,0x00,0x00,0x00,0xFE,0x07,0x7F,0x00,0xFC,0x01,0x00,0x00,0xF8,0x07,
0x00,0x00,0x00,0xFE,0x0F,0x7F,0x00,0xFC,0x01,0x00,0x00,0xF0,0x0F,0x00,0x00,0x00,
0xF0,0x0F,0x7F,0x00,0xFC,0x01,0x00,0x00,0xF0,0x0F,0x00,0x00,0x00,0xE0,0x0F,0x7F,
0x00,0xFC,0x01,0x00,0x00,0xF0,0x1F,0x00,0x00,0x00,0xE0,0x0F,0xFF,0x00,0xFE,0x01,
0x00,0x00,0xE0,0x7F,0x00,0x86,0x01,0xE0,0x0F,0xFF,0x01,0xFF,0x01,0x00,0x00,0xC0,
0xFF,0x00,0x87,0x07,0xF8,0x0F,0xFF,0x83,0xFF,0x01,0x00,0x00,0x80,0xFF,0xFF,0x87,
0x1F,0xFE,0x07,0xFE,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0x87,0xFF,0xFF,0x07,
0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0xFE,0xFF,0x87,0xFF,0xFF,0x03,0xF8,0xFF,0x3F,
0x00,0x00,0x00,0x00,0xFC,0xFF,0x87,0xFF,0xFF,0x01,0xF0,0xFF,0x1F,0x00,0x00,0x00,
0x00,0xF8,0xFF,0x87,0xFF,0xFF,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x00,0xF0,0xFF,
0x01,0xFE,0x3F,0x00,0x80,0xFF,0x03,0x00,0x00,0x00,0x00,0x80,0x3F,0x00,0xF0,0x07,
0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,};
/*"C:\Users\zjz\Desktop\无标题.bmp",0*/
void setup() //真正主程不能删除修改
{
mySCoop.start();
}
void loop()
{
yield();
}
defineTask(TaskTest);
void TaskTest::setup()
{
Serial.begin(9600);
pinMode(PinA,INPUT_PULLUP); //D10脚为输入
pinMode(PinB,INPUT_PULLUP); //D11脚为输入
attachPinChangeInterrupt(PinA,blinkA,FALLING);
attachPinChangeInterrupt(PinB,blinkB,FALLING);
pinMode(PinC,INPUT_PULLUP); //D8脚为输入
pinMode(PinD,INPUT_PULLUP); //D9脚为输入
attachPinChangeInterrupt(PinC,blinkC,FALLING);
attachPinChangeInterrupt(PinD,blinkD,FALLING);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
pinMode(4, INPUT);
u8g.firstPage();
do {
u8g.drawXBMP( 0, 0, 102, 63, u8g_CSU_bits);//欢迎界面。
} while ( u8g.nextPage() );
sleep(1000);
time = millis(); //初值
}
void TaskTest::loop()
{
int buttonState = digitalRead(4);
if (buttonState == HIGH) {
Serial.print(30000);
Serial.print("X");
delay(100);
if (Serial.available() > 0) // 串口收到字符数,否则返回0.
{
p = Serial.parseInt(); // 在串口数据流中查找一个有效整数。
while (Serial.read() == 'X')
{ oledc=map(p,0,1023,0,65);
digitalWrite(7,HIGH);
}
}
}
else {
while (num != count)
{
num = count;
}
oleda=num;
while (numa != count1)
{
numa = count1;
}
oledb=numa;
u8g.firstPage();
do {
u8g.drawXBMP( 0, 0, 16, 16, u8g_zuo_bits);
u8g.drawXBMP( 20, 0, 16, 16, u8g_maohao_bits);
u8g.setFont(u8g_font_unifont);
u8g.setFont(u8g_font_timB12);//字体设置
u8g.setPrintPos(37, 16);
u8g.print(-oleda*oleda*oleda*oleda*0.000000001185+oleda*oleda*oleda*0.0000005392+oleda*oleda*0.002042-2.515*oleda+465.8);
u8g.print(" D");
u8g.drawXBMP( 0, 20, 16, 16, u8g_you_bits);
u8g.drawXBMP(20,20, 16, 16, u8g_maohao_bits);
u8g.setFont(u8g_font_timB12);//字体设置
u8g.setPrintPos(37, 35);
u8g.print(-oledb*oledb*oledb*oledb*0.000000001185+oledb*oledb*oledb*0.0000005392+oledb*oledb*0.002042-2.515*oledb+465.8);
u8g.print(" D");
u8g.drawXBMP( 0, 43, 16, 16, u8g_tong_bits);
u8g.drawXBMP( 20, 43, 16, 16, u8g_ju_bits);
u8g.drawXBMP( 36, 40, 16, 16, u8g_maohao_bits);
u8g.setPrintPos(56,58);
u8g.print(oledc);
u8g.print("mm");
} while ( u8g.nextPage() );
digitalWrite(7, LOW);
int A=oleda;
int B=oledb+10000;
Serial.print(A);
Serial.print("X");
Serial.print(B);
Serial.print("X");
}
}
void blinkA()
{
if ((millis() - time) > 15) //防抖动处理
count=count+3;
time = millis();
analogWrite(5,255);
}
void blinkB()
{
if ((millis() - time) > 15) //防抖动处理
count=count-2;
time = millis();
analogWrite(5,0);
}
void blinkC()
{
if ((millis() - time) > 15) //防抖动处理
count1=count1-3;
time = millis();
analogWrite(6,255);
}
void blinkD()
{
if ((millis() - time) > 15)//防抖动处理
count1=count1+2;
time = millis();
analogWrite(6,0);
}
图片有妹纸表示点赞 这个厉害了!
页:
[1]
2