Posted on  Updated on 

3D打印耗材直径的检测方案

本文主要讨论3D打印耗材直径的检测,前期所有的数据将由单片机呈现,后期将考虑加入klipper固件。
目前主流的方案有两种,一种是线性CCD检测,一种是基于霍尔检测。

霍尔检测

采用俩个49E

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void setup() {
// 初始化引脚和串口
pinMode(A0, INPUT);
pinMode(A1, INPUT);
Serial.begin(115200); // 设置波特率为115200
}

int mi15 = 118; // 对应1.5mm的数值
int mi20 = 138; // 对应2.0mm的数值

void loop() {
int sum = 0;
int count = 8; // 需要的循环次数

for (int i = 0; i < count; i++) {
int a = analogRead(A0);
int b = analogRead(A1);
sum += (a - b); // 累加差值
delay(5); // 每次读取之间的延时,防止数据过于密集
}

int average = sum / count; // 计算平均值

if (average < 90) {
// 如果平均值小于90,打印"none"
Serial.println("none");
} else if (average > 160) {
// 如果平均值大于160,打印"out"
Serial.println("out");
} else {
// 当平均值在90到160之间,线性插值计算毫米值
float mmValue = 0;

if (average >= mi15 && average <= mi20) {
// 如果平均值小于或等于 mi15,则按1.5mm处理
mmValue = 1.5 + (float(average - mi15) / (mi20 - mi15)) * (2.0 - 1.5);

}
Serial.print("毫米值: ");
Serial.println(mmValue); // 打印毫米值
}
}

目前存在问题,变化幅度小,分辨率低

霍尔检测修正

增加差分放大,放大4.7倍,OUT引脚读取

测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#define READ_COUNT 5 // 连续读取次数

// 接线:A0接OUT,A2接IN-,A3接IN+

// 定义模拟值对应的毫米数
const float VALUE_0_0MM = 222.0; // 0.0mm 对应的模拟值
const float VALUE_1_5MM = 382.0; // 1.5mm 对应的模拟值
const float VALUE_2_0MM = 440.0; // 2.0mm 对应的模拟值

void setup() {
Serial.begin(9600); // 初始化串口通讯
}

void loop() {
// 读取模拟值
float analogValueA0 = readAverage(A0);
float mmValueA0 = calculateMM(analogValueA0);

float analogValueA1 = readAverage(A2);
float mmValueA1 = calculateMM(analogValueA1);

float analogValueA2 = readAverage(A3);
float mmValueA2 = calculateMM(analogValueA2);

// 打印结果
Serial.print("A0 - Analog: ");
Serial.print(analogValueA0);
Serial.print(" mm: ");
Serial.println(mmValueA0);

Serial.print("A2 - Analog: ");
Serial.print(analogValueA1);
Serial.print(" mm: ");
Serial.println(mmValueA1);

Serial.print("A3 - Analog: ");
Serial.print(analogValueA2);
Serial.print(" mm: ");
Serial.println(mmValueA2);

delay(100); // 延迟100毫秒
}

// 读取指定模拟引脚的平均值
float readAverage(int pin) {
long sum = 0; // 用于累加读取值
for (int i = 0; i < READ_COUNT; i++) {
sum += analogRead(pin);
delay(10); // 读取间隔,避免读取过快
}
return sum / (float)READ_COUNT; // 返回平均值
}

// 根据模拟值计算毫米数(线性变化公式)
float calculateMM(float analogValue) {
// 检查模拟值范围,确保线性插值正常工作
if (analogValue <= VALUE_0_0MM) return 0.0; // 小于等于 0.0mm
if (analogValue >= VALUE_2_0MM) return 2.0; // 大于等于 2.0mm

// 使用分段线性插值计算
if (analogValue <= VALUE_1_5MM) {
// 范围 [0.0mm, 1.5mm]
return (analogValue - VALUE_0_0MM) * (1.5 - 0.0) / (VALUE_1_5MM - VALUE_0_0MM);
} else {
// 范围 [1.5mm, 2.0mm]
return 1.5 + (analogValue - VALUE_1_5MM) * (2.0 - 1.5) / (VALUE_2_0MM - VALUE_1_5MM);
}
}

线性CCD检测

CCD的基本原理