项目设计是西电通院的特色课程,自从16级首次开始做这个,到我们18级现在已经是第三代了。
这个项目是以小组为单位的,一般是5-6人小组,全院打乱随机分组(据说是会按成绩区间分配)。由于工作量特别大,所以是要给每个人分配工作,然后最后再完成成品(今年是交的报告和视频成果)。
刚开始看这个项目:wdnmd,这也太难了吧,爷要挂科了。
之后赶紧联系了学长,学长大概和我解释了下这个项目是如何云云,我稍微对项目该如何完成稍微有一点了解了。然后又仔细看了项目设计的设计指南好几遍,总结出了一下几个工作:
1.电子:STM32以及传感器编程
2.数字电路设计:verilog,主要是驱动伺服电机
3.软件设计:java语言,做程序的主界面以及里面的操作内容
4.文案:最终报告整合、专利申请书等文案工作
5.网页设计:做一个静态web介绍你的公司和产品
6.组装:应该是所有人一起做,但是今年没有
7.机械设计:画机械图,一共三个,工作大不大
总的来说,前三项任务是比较重的,其他的相对压力较轻。在第一次会议时,我主动承担了电子设计以及经理的任务。接下来组里其他同学也确认了自己的任务。
作为经理,我当时构思的产品,如下:
1.模块化功能:即触摸界面显示几个按键,表示不同的功能。
2.具体功能:(中英双语)
2.1学科:语数外物化等,分为网课学习,教材查看,习题练习等
2.1.1网课学习:视频(缓存到本地,点开可以放)
2.1.2教材查看:内容意思一下
2.1.3习题练习(重点):全是选择题,通过不同色块代表选项,用RGB颜色检测器探测,与真实答案比较。成功了发语音(交互),失败了机械臂挥动
2.2外语:可添加口语功能(如果可实现):用户可跟读单词
2.3学习监督:设置开启和关闭,自主设定学习时长,若在规定时长内离开(激光测距仪检测),则机器人挥手,发出警告
2.4智能护眼:设置开启和关闭,超过限定学习时间,亮灯,发出休息提醒
3.维护模式:
3.1验证管理员账号
3.2验证机器人的各部分是否可以正常工作
3.2.1指定部位机械臂转动
3.2.2指定部位亮灯
3.2.3读取激光测距仪数据
3.2.4读取颜色传感器数据
网页设计相关:
1.总体框架按xxx的想法,基本是把内容都填充进去就好
2.需要美工,设计logo,海报,视频剪辑
FPGA:
主要是舵机控制,即机械臂挥动
FPGA (XC7A35T-1CSG324C)
关于非接触验证:
使用多个光敏传感器和卡插,卡插带缺口,嵌到传感器上,缺口可以将光遮挡住,从而输出0,反之输出1。由0,1的组合可以确定不同玩家或管理员,0000~1111
这个东西套件里没有,但是必要,去年不少组都采用此种方式
(我已购买)
关于答题:
选项ABC对应RGB三种色块,我不太清楚具体如何操作啊。选某个选项肯定是在上位机的屏幕上操作,那么直接在上位机上进行结果判定并反馈不就可了么?(最后压根没用这个)
关于交互:
1.stm32给fpga “go”指令,控制电机运行的模式(IO口电平控制)
相当于fpga作用是驱动电机做任意角度转动(自定),在vivado中封装好固定的运行状态,通过stm32电平的组合控制选择电机运行状态
DigitalOut(选电机,选模式)
2.stm32给上位机反馈传感器结果
上位机给stm32输入指令(COM串口通讯)
3.颜色、距离传感器都接I2C(I2C通讯)
4.光敏传感器接AO(数字信号)
DigitalIn(判断身份)
5.串口助手(USART)
而我技术部分负责的是电子设计,下面我来详细说明这部分
电子设计分为两部分,一个是STM32,另一个是传感器设计
本次项目中使用的是STM32L476单片机,是一款低功耗型的单片机
其中接口如下
1.有两类接口,一类是arduino配套的,一类是一般的,到时候需要哪个管脚就直接用杜邦线连接
2.所有管脚都有其相对应的功能,例如串口收发/AO/DO/电源等,按照要求连接即可
接着给出微控制器总体运行流程
主函数编写规范:
int main(){1
中断
while(1){2
while(1){3
插卡检测
if 失败:返回检测
if 成功:继续执行
while(1){4
if 学习模式 :
while(1){5
switch(各种功能)
5}
else if 维护模式:
while(1){6
switch(各种功能)
6}
else
4}
3}
2}
1}
调用函数:
颜色判断函数
颜色返回函数
距离返回函数
选项判断函数
插卡识别函数
电机控制函数
传感器分为三种,分别为:光敏、距离、颜色传感器
光敏电阻是用硫化隔或硒化隔等半导体材料制成的电阻器,其工作原理是基于内光电效应。随着光照强度的升高,电阻值迅速降低,由于光照产生的载流子都参与导电,在外加电场的作用下作漂移运动,电子奔向电源的正极,空穴奔向电源的负极,从而使光敏电阻器的阻值迅速下降。其在无光照时,几乎呈高阻状态,暗电阻很大。
用这个传感器,主要是把它作为插卡来进行身份识别的
测试结果如下:
注意:光敏传感器输出的是光强度数值,所以接支持模拟输出的AO口
VL6180是飞行时间测距传感器。传感器包含一个非常小的激光源和一个匹配的传感器。VL6180X可以检测飞行时间,或激光恢复传感器所需的时间从而计算出距离。因此VL6180X的准确度高。由于传感器模块体积小,易于在任何机器人或交互式项目中使用。可以将它与任何3-5V电源或逻辑微控制器一起使用。
用它来检测用户距离机器人的距离,若距离适当且超过一定时间,则开启身份识别界面
TCS34725芯片提供红、绿、蓝(RGB)以及明光感应的数字返回值。TCS34725彩色传感器有着广泛的应用,包括RGB LED背光控制、固态照明、健康产品、工业过程控制和医疗诊断设备等。
传感器返回四个参数值,分别为颜色参数中的 R, G, B 以及 C 值,根据说明以及我们的测试,由于距离,环境光线,测量物体的放反光程度等细微差异,输出的数据会产生一定量的误差或者偏差,因此在使用本传感器的过程中,需要对使用环境和处理数据的过程进行一定的调整及优化,以保证最后识别的结果有较高的精度保证。
测试结果如下:
需要使用VL6180x距离传感器、一个TCS34725颜色传感器以及四个光敏传感器组合完成。
我们使用专用的卡插和颜色挡板,光敏传感器检测到遮挡物时返回为0,未检测到时为1,从而不同卡插可以代表不同身份的用户。为了验证管理员身份,我们使用红色挡板遮盖颜色传感器,否则其余时刻用蓝色遮挡。
进行身份验证时,用户首先将代表身份的卡插和颜色挡板插入机器人指定位置,然后等待距离传感器判断用户是否在机器人面前,等待3s后,微控制器根据传感器读取的数据进行身份验证,从而进入应用界面(学习界面/维护界面)。
下面给出微控制器布线结果:
距离传感器和颜色传感器连线图
光敏传感器连线图
当成功验证管理员身份后,用户可以进入维护模式,检验各传感器、led灯、伺服电机的运转情况。对于fpga,是由微控制提供指令驱动的,故我们给出fpga不同功能对应的电平组合。
对应指令如下:
a:颜色传感器读取
b:距离传感器读取
c:光敏传感器读取
d:led闪烁
e:fpga“00”控制电平
f:fpga“01”控制电平
g:fpga“10”控制电平
h:fpga“11”控制电平
该部分代码如下:
#include "mbed.h"
#include "stdint.h"
#include <VL6180x.h>
#define VL6180X_ADDRESS 0x29
VL6180xIdentification identification;
// mbed uses 8bit addresses shift address by 1 bit left
VL6180x sensor(A4, A5, VL6180X_ADDRESS<<1);//距离传感器
Serial pc(SERIAL_TX, SERIAL_RX);
AnalogIn switch1(PA_0); //光敏传感器
I2C i2c(I2C_SDA, I2C_SCL); //颜色传感器
int sensor_addr = 41 << 1;
DigitalOut green(LED1);
void ret_rgb(int r,int g,int b) //该函数用于返回颜色值
{
if (r > g*1.3 && r > b*1.3)
{
pc.printf("red\n");
}
else if (g > r*1.3 && g > b*1.3)
{
pc.printf("green\n");
}
else if (b > r*1.3 && b > g*1.3)
{
pc.printf("blue\n");
}
else
pc.printf("no\n");
wait(0.1);
}
void color_read()
{
//打开颜色传感器
int r,g,b;
green = 1; // off
pc.baud(9600);
// Connect to the Color sensor and verify whether we connected to the correct sensor.
i2c.frequency(100000);
char id_regval[1] = {
146};
char data[1] = {
0};
i2c.write(sensor_addr,id_regval,1, true);
i2c.read(sensor_addr,data,1,false);
if (data[0]==68) {
green = 0;
wait (2);
green = 1;
} else {
green = 1;
}
// Initialize color sensor
char timing_register[2] = {
129,0};
i2c.write(sensor_addr,timing_register,2,false);
char control_register[2] = {
143,0};
i2c.write(sensor_addr,control_register,2,false);
char enable_register[2] = {
128,3};
i2c.write(sensor_addr,enable_register,2,false);
// Read data from color sensor (Clear/Red/Green/Blue)
while (true) {
char clear_reg[1] = {
148};
char clear_data[2] = {
0,0};
i2c.write(sensor_addr,clear_reg,1, true);
i2c.read(sensor_addr,clear_data,2, false);
int clear_value = ((int)clear_data[1] << 8) | clear_data[0];
char red_reg[1] = {
150};
char red_data[2] = {
0,0};
i2c.write(sensor_addr,red_reg,1, true);
i2c.read(sensor_addr,red_data,2, false);
int red_value = ((int)red_data[1] << 8) | red_data[0];
char green_reg[1] = {
152};
char green_data[2] = {
0,0};
i2c.write(sensor_addr,green_reg,1, true);
i2c.read(sensor_addr,green_data,2, false);
int green_value = ((int)green_data[1] << 8) | green_data[0];
char blue_reg[1] = {
154};
char blue_data[2] = {
0,0};
i2c.write(sensor_addr,blue_reg,1, true);
i2c.read(sensor_addr,blue_data,2, false);
int blue_value = ((int)blue_data[1] << 8) | blue_data[0];
// print sensor readings
//pc.printf("Clear (%d), Red (%d), Green (%d), Blue (%d)\n", clear_value, red_value, green_value, blue_value);
wait(0.5);
//颜色传感器显示数据
r = red_value;
g = green_value;
b = blue_value;
pc.printf("R %d G %d B %d\n ",r,g,b);
//ret_rgb(r,g,b);
}
}
void light_read(){
float s1;
pc.baud(9600);
while(1)
{
s1 = switch1.read();
s1 = s1*5000;
pc.printf("measure = %.0f\n",s1);
wait(0.3);
}
}
void distance_read(){
uint8_t retaddr;
pc.baud(9600);
wait_ms(100); // delay .1s
sensor.getIdentification(&identification); // Retrieve manufacture info from device memory
if(sensor.VL6180xInit() != 0) {
printf("FAILED TO INITALIZE\n"); //Initialize device and check for errors
};
sensor.VL6180xDefautSettings(); //Load default settings to get started.
wait(1);
retaddr=sensor.changeAddress(0x29,0x27);
sensor.getIdentification(&identification); // Retrieve manufacture info from device memory
wait(1);
retaddr=sensor.changeAddress(0x27,0x29);
sensor.getIdentification(&identification); // Retrieve manufacture info from device memory
while(1) {
//Get Distance and report in mm
printf("Distance measured (mm) = ");
printf("%d\n", sensor.getDistance() );
wait_ms(500);
}
}
int main(){
char order = pc.getc();
printf("welcome to the matainance system :\n");
switch(order){
case 'a'://颜色传感器
color_read();
break;
case 'b'://距离传感器
distance_read();
break;
case 'c'://光敏传感器
light_read();
break;
case 'd'://led闪烁
for(int p=0;p<10;p++){
green = ~green;
}
break;
case 'e':
pc.printf("00\n");
break;
case 'f':
pc.printf("01\n");
break;
case 'g':
pc.printf("10\n");
break;
case 'h':
pc.printf("11\n");
break;
}
}
代码思路比较简单,主要是定义几个传感器如何读取,并将数据显示(print)出来,然后主函数用case调用即可。FPGA与的stm32交互是用电平控制的,而我们是线上完成,所以无法与FPGA连接,用输出电平代替给的指令。
当然驱动传感器这方面有一些麻烦的驱动函数,不过网上都有库,如看懂函数输入输出,直接调用即可,自己写应该不太可能。。。