很好的帖子,赞一个
这是一个大部分新手爱好者遇到的一个问题
如何制作火箭发动机?
如何测量火箭发动机的推力?
制作推力采集卡的话需要哪些硬件?
相信大部分爱好者对于发动机的数据采集都尤为的重视,可是有的爱好者没有用于收集数据的采集器,有的把发动机插到土里,有的用砖垒到一起压在发动机上面,发动机测试完之后,除了看他工作正不正常,以及会不会炸,然后基本都白白浪费了一次试车。
更有甚者不惜花费高价购买成品的采集卡,我认为这是不好的现象,遇到问题就用钱来解决,根本没有自主动手的能力和独立解觉问题的能力。(个人观点,请谨慎对待)
看了一些科创上面一些推理采集卡的代码,有一部分的代码写的很好,但缺乏注释,要么就全都是英文的,看起来比较费劲,最主要使用的话没办法按照自己的需求进行修改,大部分爱好者都反映代码要么上传后数据不正常,要么就是上传完之后找不到调节校准值的地方,更有的甚至连代码都没上传成功,这部分原因都源于文章当中的解释不全面,大部分甚至都没有给硬件的连接,导致大部分新手在这上面花费大量时间后无功而返。
在此之前我其实还发布过一篇有关于采集卡的代码,但是代码当中的问题比较多,所以就删掉了
当然也不能说没有一个代码写的好的,这里分享一篇我遇到了一个比较好的文章(https://www.kechuang.org/t/70215) 这是作者 novakon 编写的推力采集卡,文章内容比较全面,硬件连接也给的比较详细,但问题的关键是我看他的代码的时候,根本找不到用来调节传感器校准值的地方,文章内也没有提到,甚至注释都是英文,看起来还极为费劲,不过最后我还是找到他调校准的地方。但是如果对于广大第一次接触的爱好者来说,这根本找不到,也就何谈制作采集卡了
另外我觉得在硬件上可以进行优化,然后可以外接一个蜂鸣器来反映工作状态,这样可以用来判断SD卡插入的时候是否正常
当然,看发布时间已经是十年前的帖子了!
所以这里,我重新自主编写了一个采集卡代码,我在上面写满了中文注释,可供大家进行参考和修改,另外,这里会向大家提供一些提高HX711采集率的方法,使其采样率高达144HZ,并且也会提供一些我自己画的PCB板,以及一些使用过程中的注意事项。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
首先需要一块arduino nano主控必须是mega328p的,如果你错买成168p的话,会导致内存不够,无法上传程序
接着就是一个SD卡模块,这里我推荐这个
接着就是最重要的模块,也是用来解析传感器数据的模块Hx711
这里有两款hX711模块,如果你不想有过多麻烦的话,请买第二个右上角带有一个80赫兹短接口的模块,然后到家之后把那个短接口给它连到一起,但如果你已经买了第一个的话,就接着往下看,我后面会提到如何修改他的采集率。
这里有人可能要问了,为什么第一个模块没有短接口还要额外修改,其实这是因为这款模块设计的缺陷,他是直接将芯片集成在电路板上,并且默认是10hz的,没有额外留可供选择采集率的接口。
这个问题待会儿说,现在就先说下接线
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
arduino nano板子上面有接口D1~D13我们主要来看这部分的
SD -- Nano
GND -- GND
3V3/5V -- VCC
MISO -- D12
CLK -- D13
MOSI -- D11
CS -- D10
Hx711 -- Nano
dout -- D5
sck -- D4
按键 -- Nano
GND--按键--D3
无源蜂鸣器 -- Nano
GND--无源蜂鸣器--D8
Hx711 -- 压力传感器
值得注意的是,这里传感器的接法有时候大于十千克的传感器的接法与第一种也相同,就按我的40kg传感器来说,他的接法与第一种一模一样,所以如果大量程的按第二种接法没有反应,请再尝试一下按第一种接法
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
硬件部分大概连接就完事了
现在先不着急看代码,先把Hx711模块的那个问题解决了
现在先来看一张图片
这是一张Hx711芯片的引脚定义图,可以看到第15号引脚也就是RATE,他旁边的定义是输出数据速率控制输入,这部分就是用来控制Hx711芯片采集率的引脚,当他的输入电平为低电平或悬空的时候,默认是十赫兹的采集率,而我们需要提高它的采集率就要把他拉高,你可以认为把它接到电源正极上面,这样我们就选择了他80赫兹的采样率。
第一款的Hx711模块就属于把这个引脚拉低了,也就是接到电源负极上了,而我们需要做的就是把它接回电源正极上,同时也要把他原先的那根线给切断,不然电源正负极就短路了
这里我提供一张几年前我修改的电路
图中的断接其实是短接,只是之前把这个字写错了,这张图切断的PCB线路可能看着不太清楚,你可以认为把第15号引脚给他抬起来,直接跟第16号引脚接在一起,也正如刚才芯片引脚定义图上的位置,把RATE和第一个数字电源接在了一起,同时要断开他与电源负极的连接。
到这里基本上就完事了,那么接下来就是大家最期待的代码部分了。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
接下来将展示硬件部分所需的代码
#include <SD.h>
#include <HX711_ADC.h>
#include <SPI.h>
File file;
#define BUFFER_SIZE 100
char buffer[BUFFER_SIZE];
/*
创建数据缓冲区,经验证100左右的数据
大小是刚好的,请不要随意修改,因为芯
片内存不够,过大的缓冲区会占用内部资源
在实测中发现单片机会无限制的重启
*/
const int HX711_dout = 5; //接HX711 dout
const int HX711_sck = 4; //接 HX711 sck
int Reset_button = 3; //设置复位按键
int Buzzer = 8; //设置蜂鸣器输出
/*此处可以根据硬件需求来进行修改*/
HX711_ADC LoadCell(HX711_dout, HX711_sck);
const int calVal_calVal_eepromAdress = 0;
float i; //存储推力数据的变量
/*校准值*/
//////////////////////////////////////////
float calibrationValue = 7971.5; //155.8
/////////////////////////////////////////
/*
此处的校准值默认是40Kg(单位是N)量程的传感器
调节的时候遵循“偏大调大,偏小调小”的原则
具体意思是:当校准值的数据比实际的物体
重量偏大 ,将校准值调大 ,当校准值的数据比
实际物体的重量偏小时,将校准值调小
*/
/*数据写入标志*/
/////////////////////////////////////////
float Lnitial_value = 0.5;
/////////////////////////////////////////
/*
当推力大于该数值数据将写入SD卡
*/
int bufferIndex = 0;
unsigned long startTime = 0; // 秒表开始时间(毫秒)
float elapsedTime = 0.0; // 经过的时间(秒)
bool startStop = false; //定义bool变量用于作为计时器启动标志
int period = 1000;
unsigned long timenow = 1000;
unsigned long time2 = 0;
void timting() //计时器
{
if (!startStop) {
startTime = millis(); // 记录秒表开始时间
}
if (startStop) {
elapsedTime = (millis() - startTime) / 1000.0; // 更新经过的时间(秒)
}
}
void zeroing() //复位传感器
{
tone(Buzzer,2300,500);
startStop = false;
file = SD.open("/data.csv", FILE_WRITE);
if (file) {
file.println(" ");
file.println(" ");
file.println(" ");
file.println(" ");
file.close();
} //存储空格与新数据进行区分
LoadCell.tareNoDelay();
Serial.println("置零");
delay(1000);
}
void writeFile() { //写入数据
if (bufferIndex > 0) {
file = SD.open("data.csv", FILE_WRITE | O_APPEND);
if (file) {
file.write(buffer, bufferIndex);
file.close();
bufferIndex = 0; // 重置缓冲区索引
} else {
Serial.println("SD卡丢失!");
}
}
}
void HX711_begin() {
Serial.println("准备...");
LoadCell.begin();
unsigned long stabilizingtime = 2000;
boolean _tare = true;
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag()) {
Serial.println("超时,请检查微控制器(MCU)与HX711之间的接线和引脚指定是否正确!!!");
} else {
LoadCell.setCalFactor(calibrationValue); // set calibration factor (float)
Serial.println("启动完成");
}
while (!LoadCell.update())
;
Serial.print("校准值:");
Serial.println(LoadCell.getCalFactor());
Serial.print("HX711测量转换时间ms:");
Serial.println(LoadCell.getConversionTime());
Serial.print("HX711测量采样率Hz:");
Serial.println(LoadCell.getSPS());
Serial.print(" HX711测量稳定时间ms:");
Serial.println(LoadCell.getSettlingTime());
Serial.println(" 注意,如果在您的草图中使用delay(),稳定时间可能会显著增加!");
if (LoadCell.getSPS() < 7) {
Serial.println("警告:采样率低于规格要求,请检查微控制器(MCU)与HX711之间的接线和引脚分配是否正确");
} else if (LoadCell.getSPS() > 100) {
Serial.println("!!采样率高于规格,检查MCU>HX711的接线和引脚指定");
}
}
void setup() {
Serial.begin(115200);
pinMode(Reset_button, INPUT_PULLUP);
HX711_begin();
if (!SD.begin()) {
Serial.println("SD初始化失败");
while (1) {
tone(Buzzer,2500,500);
delay(500);
tone(Buzzer,1800,500);
delay(500);
}
}
file = SD.open("/data.csv", FILE_WRITE);
if (file) {
file.println(" ");
file.println(" ");
file.println(" ");
file.println(" ");
file.close();
}
}
void loop() {
timting(); //调用计时器
static boolean newDataReady = 0;
if (LoadCell.update()) newDataReady = true;
if (newDataReady) {
i = LoadCell.getData();
}
// 将浮点数转换为字符串,并用逗号隔开
char num1Str[10];
char num2Str[10];
dtostrf(i, 6, 3, num1Str); // 6表示总宽度,3表示小数点后位数
dtostrf(elapsedTime, 6, 3, num2Str);
String data = String(num2Str) + "," + String(num1Str) + "\n";
if (i > Lnitial_value) {
startStop = true; //开始计时
if (bufferIndex + data.length() < BUFFER_SIZE) {
data.toCharArray(buffer + bufferIndex, data.length() + 1);
bufferIndex += data.length();
} else {
// 缓冲区满了,写入文件
writeFile();
}
Serial.print(num1Str);//打印推力
Serial.print(" ");
Serial.println(num2Str);//打印时间
} else {
startStop = false; //停止计时
}
if (digitalRead(Reset_button) == 0) {
zeroing();
}
}
首先是开头部分包含的库文件,要把他先进行安装才能进行上传代码
直接把包含的库文件放进库管理器里面搜索就能安装,如果你安装成功之后,就会显示移除,证明你安装成功,至于其他两个库文件是IDE自带的这里只用安装这一个就可以了,记住,如果还报错,证明你库文件安装错了,需要卸载重新安装
接下来还要选一下开发板的型号以及芯片的型号
开发板是arduino nano,详细要看一下芯片型号,这个一般来说是中间的那个,如果你购买的是新版的nano则需要选择第一个芯片型号,如果你的芯片型号是第三个的话,那你就买错了,这个芯片的型号内存较小,无法载入程序
接下来就是上传程序,点击左上角的那个向右的箭头即为上传程序
接下来给大家具体讲解一下代码中一些参数的修改,以及校准值的调整
首先代码当中
const int HX711_dout = 5; //接HX711 dout
const int HX711_sck = 4; //接 HX711 sck
int Reset_button = 3; //设置复位按键
int Buzzer = 8; //设置蜂鸣器输出
/*此处可以根据硬件需求来进行修改*/
这部分是可以用来修改的,我在下方有注释,可以按照自己的硬件需求进行修改
当然,还有一些参数是绝对不能修改,这些对于新手来说就不用管了,新手的话,暂时只用修改这部分代码,当然默认此代码的话,就与上述接线一致。
在说调节校准值之前,先说一下代码逻辑
板子在上电之后,需要先检测SD卡是否插入,如果没有插入的话会有蜂鸣器报警并终止程序,所以必须要插卡使用,其次,所有硬件初始化成功之后,推力需要大于0.5牛才能写入SD卡,此时串口才会有数据,所以串口没有数据的时候先不要着急,先尝试摁压一下压力传感器,这里可以在代码里面修改
/*数据写入标志*/
/////////////////////////////////////////
float Lnitial_value = 0.5;
/////////////////////////////////////////
/*
当推力大于该数值数据将写入SD卡
*/
如果你的串口成功的收到了数据的话,那么接下来就可以下一步了-------调节校准
调节校准值的代码在这一行
/*校准值*/
//////////////////////////////////////////
float calibrationValue = 7971.5; //155.8
/////////////////////////////////////////
/*
此处的校准值默认是40Kg(单位是N)量程的传感器
调节的时候遵循“偏大调大,偏小调小”的原则
具体意思是:当校准值的数据比实际的物体
重量偏大 ,将校准值调大 ,当校准值的数据比
实际物体的重量偏小时,将校准值调小
*/
调节校准值的方法我也在代码中注释了,这部分内容如果不好理解的话,举个例子,当前你放了一个1N的砝码在压力传感器上,而串口收到的数据是1.2N,此时校准的数据大于物体的实际重量,你就需要把校准值重新调大,如果收到的数据是0.8N,此时校准的数据明显低于实际物体的重量,那么此时就要把校准值进行调小,而具体调节多少就是你们自己试了
如果你收到的数据已经准确无误之后,那么恭喜你,你的这个采集卡基本成功,接下来就要说一下怎么再提高Hx711模块的采集率了,毕竟我们奔着的采集率是144hz。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
那么现在让我们把目光返回到这张图上,我们现在来看一下14和13号引脚,这上面的定义是外部晶振输入和输出,也就是说,我们要在这个地方外接一个晶振,而对于新手来说其实就不用再往下看了,因为这个地方按理说需要自己设计PCB板来进行连接,而普通的模块的话并没有提供晶振的接口,但是我后面提供了我自己设计的PCB板,你们可以直接拿过来到嘉立创的下单助手里面白嫖,他一个月有两张优惠券,并且零元包邮到家
言归正传,这个地方我们需要外接一个晶振,那具体是接多少好呢?因为如果外部晶振太大,会导致采样时间变短,从而还会导致数据的漂移和不稳定,经过大量查询,20Mhz的晶振是外部可接入最大的范围,并且实测并没有什么问题
那么接下来,是我设计的PCB板电路图,大家可以参照着电路图进行设计和使用
右上角的那个电路图就是Hx711的外围电路,旁边接了一个20Mhz的晶振,然后经过实测,板子基本上是正常工作的,并没有其他异常
下面是我和@YKCYKC一同试车的发动机
28a659f5edcf4b87de6c9787af2bc7e9.mp4 点击下载
然后这个是试车后导出的数据量
可以看到,两秒钟的时间,竟存入了将近600个数据,这个采集率远远高于了单片机内部读取的采样率,然后看一下试车的曲线图
可以看到确实没有什么问题,最大发动机的推力是128.14N,工作也挺正常
最后给大家提供我设计的PCB板,大家可以仿照设计和参考使用
上面是一些PCB板的图片,然后还要注意一下传感器的接线,我上面标识的激励线是E+,E-,与Hx711模块上的基本对应,而另外两个是S+,S-,分别对应模块上的A+,A-,接线的时候记得注意
而传感器接线的下面那一排是我预留的芯片烧录引导程序用的,这个具体的可以上网查查,我在此就不再详细说了
另外,我也导出了本次所需原件物料清单,并且在上面修改并备注好了部分的元件名称,以及需要注意的地方
好了到这里基本结束了,最后再说一些注意事项:
硬件和代码连接完成后,必须插卡使用,否则程序不会运行,要注意SD卡的系统文件格式,如果不是FAT32,请把它格式成这个系统文件,否则单片机是无法识别的,每次试车前尽量先清卡,因为所有的数据都是存储到一个文件里面,代码当中的一些重要参数请勿随意修改,否则可能会导致单片机无法正常运行(内存快到极限了),PCB板制版文件,无法在嘉立创中打开,直接上传到下单平台即可,物料清单当中备注的一些注意事项一定要仔细阅读!
这篇文章制作不易,主要是为了帮助大家为发动机做数据采集工作,同时,也希望大家能够奉行创新精神,创造出更好的采集卡。
另外代码中如有错误的地方,帮忙及时指出,在次感激不尽!
如果要讲究速度指标,用HX711不合适。
普通应变片搭配加工水平,精度能达到千分之二都算不错了,所以用12bit的SAR类型ADC是速度+精度的最佳选择。即使过采样滤波提高分辨率到14bit,降速后的刷新率也远超HX711。这种项目不是量产型消费品,提高的一点成本相对于人工和项目来说不值一提。
引用WEIZHANGLI发表于3楼的内容请教各位大佬,有谁知道这个文件为什么打不开啊?
我文章咋说的,仔细阅读
Hx711 -- Nano SD -- Nano,这里的nano指的是哪些接口啊?
这种情况怎么修复?
没事了,我又搞了很长时间,突然想到他是有几行初始代码的,我把他删了然后就没事了
在串口里又报错超时,请检查微控制器(MCU)与HX711之间的接线和引脚指定是否正确!!
怎么搞啊
请问lz我做了三个,我自己用一个,剩下的可以咸鱼出掉回本吗
200字以内,仅用于支线交流,主线讨论请采用回复功能。