Clay Printing |
Stratasys F170 Printer |
A kitten based on TPMS |
给定确定体积的陶泥(打印长度确定),学员自行设计打印路径,使得打印出的陶泥模型满足约束条件;设计的路径保存为G-code文件。
1.全部打印路径为空间中一条连续的路径
2.模型需要自支撑
3.打印路径不能发生自交
CERAMBOT Plus打印机最大打印尺寸为:180*190*200mm,大家需要按照该尺寸设置打印中心。此外,为了保证打印时间,我们推荐大家设计模型时将尺寸控制在120*120*120mm以内。
因为陶瓷打印的陶瓷浆料的挤出量通常大于其他增材制造方式,所以打印路径中每个移动步骤的挤出量计算是一个关键问题。挤出量不足会导致相邻层的支撑较少,从而导致模型坍塌,如图1所示。另一方面,过多的挤出量导致粗糙的表面质量和更多的打印制造时间,从而导致陶瓷制品的不确定性。因此,需保证挤出量自适应,防止模型坍塌。
图1 自适应挤出量对比效果 |
图2 自适应挤出计算原理 |
如图2所示,两个相邻点的水平距离用s表示,两个相邻层的重叠宽度用∆a表示,w是直写线条宽度。θ是点的切线与打印方向之间的角度,θ最好不要超过30°,极限45°,否则,模型需要支撑才能避免坍塌。因此,根据角度限制,我们可以将比例阈值设置为2/3,即满足如下公式:
G-code是控制陶瓷打印成型过程的一系列命令,控制陶瓷打印设备的运动,例如移动的位置,使用的速度等等,每一行的打印指令在打印G代码中占据一行。
如上图所示的示例命令,参数X、Y、Z分别表示打印喷头的目标位置的坐标值,当运行到该指令时,打印喷头将从当前的位置移动到目标位置。参数E代表陶瓷浆料的挤出量,为从开始到当前层的陶泥累积挤出量。 某一行G-code的E值相较于上一行E值的增量表示为该步的陶泥挤出量e。
特别地,仅在G1时才会出现E值,若执行命令开始为G0,则将不进行陶瓷挤出,只进行打印喷头的移动。参数F表示打印的直线段XYZ的运动速度,单位是mm/min,在此处我们推荐为F=1800。同时,如果某条执行指令中不包含F参数时,则该直线段内的打印速度和上一步打印速度相同。
在生成G-code的工作中,要计算每个步骤的路径以及挤出量。如图3所示。这里,V0和V1表示路径上的两个相邻打印点,两点间距离L即为喷头移动步长。V0和V1的平均直写线条宽度用w表示,平均层高为∆z。V0到V1的最终挤出量e近似于黄色长方体的体积,即:
其中为打印机内参系数,此处为一常数。
为了计算挤出量e,需要确定层高∆z0,直写线条宽度w的数值。这些参数主要由挤出机喷头的内径确定。在本研究的设置中,我们建议设置参数如下:∆z0 =1.2mm,w = 3mm,F=1800,α=0.4。 在相同速度F和层厚下,挤出量越大,线宽w越大。
需要在生成的G-code前添加:
G28 ;Home
G1 Z15.0 F1800 ;Move the platform down 15mm
;Prime the extruder
M302
G1 F1800 E3
G92 E0
需要在生成的G-code末尾添加:
M104 S0
M140 S0
;Retract the filament
G92 E1
G1 E-1 F300
G28 X0 Y0
M84
教程最后为示例模型和其对应的标准G-code。“;”后为注释代码。
可以安装repetier或者Cura进行G-code预览:
repetier: https://www.repetier.com/download-now/
Cura: https://ultimaker.com/software/ultimaker-cura
学员们可以从以下多个角度来设计G-code路径:
对于一些简单柱体,学员们可以直接生成对应的G-code:
生成圆柱坐标点的示例代码:main.cpp
#include#include #include "tool.h" using namespace std; class Point3f { public: Point3f(){}; Point3f(float num1, float num2, float num3) { x = num1; y = num2; z = num3; } Point3f operator + (const Point3f &a) { return Point3f((a.x + this->x), (a.y + this->y), (a.z + this->z)); } float x, y, z; }; int main() { vector<vector<Point3f>> a; Point3f shift(100, 100, 0); //将模型中心移动到打印托盘中心 //cylinder double radius = 40;//半径40mm int layer_num = 30; int interval = 40; double angle_add = 360 / interval; double zz = delt_z / interval; for (int i = 0; i < layer_num ; i++) { vector<Point3f> b; for (int j = 0; j < interval; j++) { double angle = angle_add * j; b.push_back(Point3f(radius*cos(angle*PI / 180), radius*sin(angle*PI / 180), i * delt_z + j * zz) + shift); } a.push_back(b); } string file = "D://example1.gcode"; vector_to_gcode(a, file); return 0; }
根据坐标点生成G-code的代码:tool.h
#ifndef TOOL_H #define TOOL_H #include <iostream> #include <fstream> #include <string> #include <vector> using namespace std; static double Wmin = 3; //measurement: mm static double delt_z = 1.2; static double lamda = 0.4; #ifndef PI #define PI 3.1415926535897932384626433832795 #endif templatevoid vector_to_gcode(vector > contours, string filepath) { double E = 0; ofstream out(filepath); if (out.is_open()) { out << "G28 ;Home \nG1 Z15.0 F1800 ; Move the platform down 15mm \n;Prime the extruder \nM302 \nG1 F1800 E3 \nG92 E0 " << endl;//contours[0].size() } out << "G0 X" << contours[0][0].x << " Y" << contours[0][0].y << " Z" << contours[0][0].z << endl; int sizev = contours.size(); T last_one; for (int i = 0; i < sizev; i++) { int size_one = contours[i].size(); if (i == 0) { for (int j = 1; j < size_one; j++) { double length = length_P(contours[i][j - 1], contours[i][j]); double e = lamda * length * Wmin * delt_z; E += e; out << "G1 X" << contours[i][j].x << " Y" << contours[i][j].y << " Z" << contours[i][j].z<< " E" << E << endl; } last_one = contours[0][size_one - 1]; } else { for (int j = 0; j < size_one; j++) { double length = length_P(last_one, contours[i][j]); double e = lamda * length * Wmin * delt_z; E += e; out << "G1 X" << contours[i][j].x << " Y" << contours[i][j].y << " Z" << contours[i][j].z << " E" << E << endl; last_one = contours[i][j]; } } } out << "M104 S0 \nM140 S0 \n;Retract the filament \nG92 E1 \nG1 E-1 F300 \nG28 X0 Y0 \nM84" << endl; cout << "Write done!" << endl; } template double length_P(T a, T b) { return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y) + (a.z - b.z)*(a.z - b.z)); } #endif
学员们可以选择任意一条曲线Cs, 将Cs沿着路径曲线ψ进行扫掠,计算每一层点的位置,然后根据坐标点生成G-code文件(同01: tool.h)。
学员在扫掠过程中可以对Cs进行调整,包括长度和形状。也可以通过控制挤出量来控制层厚,进而获得不同的打印效果。
学员们可以使用建模软件设计模型,通过切片得到对应的G-code。由该方法生成路径时,需要保证路径满足前文提到的三条要求。
本课题不限制生成G-code的方法,学员们可以使用上述方法或者其他任何方法生成你们想要的G-code。
学员首先学习了解TPMS的相关基础知识,在一个基于libigl的基础框架上,进行TPMS结构的设计,利于相关软件(如maya,magics等)生成基于该TPMS结构的多孔模型,并利用提供的3D打印机进行制造。
下载libigl: https://github.com/libigl/libigl
或使用git: git clone https://github.com/libigl/libigl.git
使用cmake进行编译
在编译时会下载libigl所需的外部依赖项,github传输不稳定时,可将./cmake/LibiglDownloadExternal.cmake内GIT_REPOSITORY替换为国内源。 可用教程内LibiglDownloadExternal.cmake进行替换
学员也可参考以下博客进行libigl的安装配置: https://blog.csdn.net/u014354193/article/details/73380249
TPMS(Triply periodic minimal surface),是极小曲面中的一种,可参考论文 [Computer-aided porous scaffold design for tissue engineering using triply periodic minimal surfaces](https://link.springer.com/article/10.1007/s12541-011-0008-9),了解TPMS生成原理。
以下是一些关于如何生成TPMS的介绍: https://wewanttolearn.wordpress.com/2019/02/03/triply-periodic-minimal-surfaces/
Marching cube是经典的重建算法,可以用来生成隐式方程所表达的surface,算法流程可参考论文:[Marching cubes: A high resolution 3D surface construction algorithm] ( https://dl.acm.org/doi/10.1145/37401.37422)
本次实验中可以使用libigl中提供的marching_cubes 函数: https://libigl.github.io/tutorial/#marching-cubes
1.选定一种TPMS表达函数(隐式方程)进行编码;
2.使用libigl提供的marching cube算法,设定设置合适的函数周期和重建坐标范围;
3.计算对应voxel的坐标及TPMS在此位置的函数值,生成scalar field 'S' 和 vertex locations 'GV'
4.利用对应函数生成TPMS网格模型并绘制查看效果,将结果保存为obj格式。
关键代码:
计算TPMS在某位置的函数值: double TpmsValue(Vector3d coord, TpmsType tpms_type_) { double x = coord[0], y = coord[1], z = coord[2]; double tpms_value = 0; double tpms_constant_ = 0; if (tpms_type_ == kP) tpms_value = cos(x) + cos(y) + cos(z) + tpms_constant_; …… …… return tpms_value; } 划分voxel: int count_num = x_voxel_num*y_voxel_num*z_voxel_num; MatrixXd GV(count_num, 3); for (int zi = 0; zi < z_voxel_num; zi++) { const double z = (double)zi/(z_voxel_num-1) * model_size; for (int yi = 0; yi < y_voxel_num; yi++) { const double y = (double)yi / (y_voxel_num - 1) * model_size; for (int xi = 0; xi < x_voxel_num; xi++) { const double x = (double)xi / (x_voxel_num - 1) * model_size; GV.row(xi + x_voxel_num*(yi + y_voxel_num*zi)) = Vector3d(x, y, z); } } } 计算scalar field 'S': VectorXd S(count_num, 1); for (int n = 0; n < count_num; n++) S(n) = TpmsValue(GV.row(n), kTubularG); 用Marching Cube算法计算结果: MatrixXd SV; MatrixXi SF; igl::copyleft::marching_cubes(S, GV, x_voxel_num, y_voxel_num, z_voxel_num, SV, SF);
将TPMS模型与其他模型求交,可使用magics,maya等软件。得到TPMS多孔模型。
i. 导入模型(maya只接受obj格式文件)
ii. 移动模型至相交位置(maya快捷键w-平移,e-旋转,r-缩放,alt+鼠标控制视图),同时选中两个模型,选择“网格—布尔—交集”,点击后面方框进行设置,选择“正常”。
iii. 得到多孔模型
bunny多孔模型
iv. 利用Autodesk Meshmixer为模型挤出厚度,首先导入模型
v. Ctrl+A,全选模型,选择“Edit—>Extrude”功能,设置“Direction”和“Offset”等参数
vi. 将模型用F170打印机打印出来。
3D打印DIY介绍 (22M) | DIY成果展示 (53M) | 陶泥打印教程 (4M) | TPMS生成教程 (14M) | Photos (1M) |
玻璃钢生产厂家哈尔滨仿铜玻璃钢雕塑定做宁夏抽象人物玻璃钢雕塑定制伊春卡通玻璃钢雕塑定制扬州商场商业美陈解决方案北京玻璃钢家具雕塑主题玻璃钢雕塑销售方法工艺玻璃钢雕塑出厂价格湘潭玻璃钢果蔬雕塑漯河玻璃钢卡通雕塑定制多少钱泸水市玻璃钢雕塑生产商江门玻璃钢透光雕塑厂家上海玻璃钢牧童雨露雕塑玻璃钢艳后雕塑定制金华玻璃钢雕塑公司大连公园主题玻璃钢卡通雕塑品牌涟源玻璃钢卡通雕塑永康玻璃钢雕塑厂家玻璃钢花盆改造房间赤峰玻璃钢吉祥卡通雕塑出口商场美陈雕塑厂家四川玻璃钢雕塑制作厂家玻璃钢雕塑特性港式商场美陈商场美陈树广东商业商场美陈哪家好玻璃钢雕塑水果座椅钢包造型玻璃钢景观雕塑甘肃玻璃钢卡通雕塑摆件新华玻璃钢雕塑厂家太原大型玻璃钢雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万