这次主要是回复Merlin-1D文章:939753
这次试车是我和Merlin同步设计的发动机,并进行试车,本次的采集卡主要是由我设计的,下面先看几张图片
这会儿嘉立创打不开了,就暂时不展示原理图了
这次的采集卡主控是nano上面同种328p的芯片,并采用了nrf作为数据传输,传感器的采集芯片是hx711芯片,采集版在发送数据的同时并将数据同步采集到SD卡中,但是我的发动机在点火之后,后期处理数据的时候发现数据波动太小了,连着把试车台都推动了,结果采集的数据只有21牛左右,具体的试车视频且看我朋友的那篇文章,推力是明显很大的,工作时间1~2s
下面是本次基于arduino ide编写的程序代码:
C++#include <SD.h>
#include <HX711_ADC.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#if defined(ESP8266)|| defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif
RF24 radio(6, 7); // CE, CSN引脚
File file;
const byte address[6] = "0000";
const byte address2[6] = "Space.ST";
const int HX711_dout = 5; //接HX711 dout
const int HX711_sck = 4; //接 HX711 sck
HX711_ADC LoadCell(HX711_dout, HX711_sck);
const int calVal_calVal_eepromAdress = 0;
float a = 0;
float i;
int time = 0;
int period = 1000;
unsigned long timenow = 1000;
unsigned long time2 = 0;
void setup() {
Serial.begin(115200);
pinMode(3, INPUT_PULLUP); //设置复位按键
pinMode(8, OUTPUT); //设置蜂鸣器输出
pinMode(2, INPUT_PULLUP);
if (!radio.begin()) {
Serial.println("NRF初始化失败");
while (1) {
digitalWrite(8, 1);
delay(500);
digitalWrite(8, 0);
delay(500);
}
}
if (!SD.begin()) {
Serial.println("SD初始化失败");
while (1) {
digitalWrite(8, 1);
delay(500);
digitalWrite(8, 0);
delay(500);
}
}
radio.setPALevel(RF24_PA_MIN); // 设置为最大发射功率
Serial.println("准备...");
float calibrationValue;
calibrationValue = 30.61; //校准值根据实际情况进行修改
#if defined(ESP8266) || defined(ESP32)
//EEPROM.begin(512); // uncomment this if you use ESP8266 and want to fetch this value from eeprom
#endif
//EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch this value from eeprom
LoadCell.begin();
//LoadCell.setReverseOutput();
unsigned long stabilizingtime = 2000; // tare preciscion can be improved by adding a few seconds of stabilizing time
boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag()) {
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
}
else {
LoadCell.setCalFactor(calibrationValue); // set calibration factor (float)
Serial.println("Startup is complete");
}
while (!LoadCell.update());
Serial.print("Calibration value: ");
Serial.println(LoadCell.getCalFactor());
Serial.print("HX711 measured conversion time ms: ");
Serial.println(LoadCell.getConversionTime());
Serial.print("HX711 measured sampling rate HZ: ");
Serial.println(LoadCell.getSPS());
Serial.print("HX711 measured settlingtime ms: ");
Serial.println(LoadCell.getSettlingTime());
Serial.println("Note that the settling time may increase significantly if you use delay() in your sketch!");
if (LoadCell.getSPS() < 7) {
Serial.println("!!Sampling rate is lower than specification, check MCU>HX711 wiring and pin designations");
}
else if (LoadCell.getSPS() > 100) {
Serial.println("!!Sampling rate is higher than specification, check MCU>HX711 wiring and pin designations");
}
file = SD.open("test.txt", FILE_WRITE);
if (file) {
file.println(" ");
file.println(" ");
file.println("以上数据作废 ");
file.println("开始记录新数据:");
file.close();
}
}
void loop() {
unsigned long timenow2 = millis();
static boolean newDataReady = 0;
const int serialPrintInterval = 500; //increase value to slow down serial print activity
// check for new data/start next conversion:
if (LoadCell.update()) newDataReady = true;
if (newDataReady) {
i = LoadCell.getData();
}
if (digitalRead(2) == 1) {
if (timenow2 - time2 >= timenow) {
time2 = timenow2;
time++;
}
file = SD.open("test.txt", FILE_WRITE);
file.print(i / 1000 * 9.8); //单位转换N
file.print(" ");
file.print(time);
file.println("s");
file.close();
Serial.print(i);
radio.openWritingPipe(address);
radio.write(&i, sizeof(i));
Serial.print("g");
Serial.print(" ");
Serial.print(i / 1000 * 9.8);
Serial.print("N");
radio.openWritingPipe(address2);
radio.write(&time, sizeof(time));
Serial.print(" ");
Serial.print(time);
Serial.println("s");
} else {
time = 0;
LoadCell.tareNoDelay();
}
if (digitalRead(3) == 0) {
LoadCell.tareNoDelay();
digitalWrite(8, 1);
delay(500);
digitalWrite(8, 0);
time = 0;
file = SD.open("test.txt", FILE_WRITE);
if (file) {
file.println(" ");
file.println(" ");
file.println("以上数据作废 ");
file.println("开始记录新数据:");
file.close();
}
}
}
以上是发送端的代码
C++#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
static const unsigned char PROGMEM sh[]{
0x04, 0x00, 0xFF, 0xE0, 0x80, 0x20, 0x12, 0x00, 0x0A, 0x00, 0x22, 0x00, 0x12, 0x00, 0xFF, 0xE0,
0x04, 0x00, 0x09, 0x80, 0x30, 0x40, 0xC0, 0x20, /*"实",0*/
};
static const unsigned char PROGMEM shi[]{
0x00, 0x40, 0xF0, 0x40, 0x90, 0x40, 0x97, 0xE0, 0x90, 0x40, 0xF0, 0x40, 0x92, 0x40, 0x91, 0x40,
0x91, 0x40, 0xF0, 0x40, 0x90, 0x40, 0x01, 0xC0, /*"时",1*/
};
static const unsigned char PROGMEM zui[]{
0x3F, 0x80, 0x20, 0x80, 0x3F, 0x80, 0x20, 0x80, 0xFF, 0xE0, 0x48, 0x00, 0x7B, 0xC0, 0x49, 0x40,
0x79, 0x40, 0x4C, 0x80, 0xF9, 0x40, 0x0A, 0x20, /*"最",0*/
};
static const unsigned char PROGMEM da[]{
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0xFF, 0xE0, 0x04, 0x00, 0x0A, 0x00, 0x0A, 0x00,
0x11, 0x00, 0x11, 0x00, 0x20, 0x80, 0xC0, 0x60, /*"大",1*/
};
static const unsigned char PROGMEM shi2[]{
0x00, 0x40, 0xF0, 0x40, 0x90, 0x40, 0x97, 0xE0, 0x90, 0x40, 0xF0, 0x40, 0x92, 0x40, 0x91, 0x40,
0x91, 0x40, 0xF0, 0x40, 0x90, 0x40, 0x01, 0xC0, /*"时",0*/
};
static const unsigned char PROGMEM jian[]{
0x4F, 0xE0, 0x20, 0x20, 0x00, 0x20, 0x5F, 0xA0, 0x50, 0xA0, 0x50, 0xA0, 0x5F, 0xA0, 0x50, 0xA0,
0x50, 0xA0, 0x5F, 0xA0, 0x40, 0x20, 0x40, 0xE0, /*"间",0*/
};
static const unsigned char PROGMEM tong[]{
0x9F, 0x80, 0x44, 0x80, 0x03, 0x00, 0x1F, 0xC0, 0xD2, 0x40, 0x5F, 0xC0, 0x52, 0x40, 0x5F, 0xC0,
0x52, 0x40, 0x52, 0xC0, 0x40, 0x00, 0xBF, 0xE0, /*"通",0*/
};
static const unsigned char PROGMEM xin[]{
0x40, 0x00, 0x2F, 0x80, 0x04, 0x80, 0x04, 0x80, 0xE4, 0x80, 0x2F, 0x80, 0x24, 0x80, 0x24, 0x80,
0x24, 0x80, 0x34, 0xA0, 0x24, 0x60, 0x04, 0x20, /*"讯",1*/
};
static const unsigned char PROGMEM zhong[]{
0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x7F, 0xC0, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x7F, 0xC0,
0x44, 0x40, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, /*"中",2*/
};
static const unsigned char PROGMEM duan[]{
0x10, 0x20, 0x55, 0xC0, 0xB9, 0x00, 0x91, 0x00, 0xFD, 0xE0, 0x91, 0x40, 0xB9, 0x40, 0xD5, 0x40,
0x91, 0x40, 0x91, 0x40, 0xFD, 0x40, 0x02, 0x40, /*"断",3*/
};
static const unsigned char PROGMEM guo[]{
0xFF, 0xE0, 0x80, 0x20, 0xBF, 0xA0, 0x84, 0x20, 0x84, 0x20, 0xBF, 0xA0, 0x85, 0x20, 0x84, 0xA0,
0xFF, 0xE0, 0x80, 0x20, 0xFF, 0xE0, 0x80, 0x20, /*"国",1*/
};
static const unsigned char PROGMEM zhi[]{
0x10, 0x20, 0x50, 0x20, 0x7D, 0x20, 0x91, 0x20, 0xFF, 0x20, 0x11, 0x20, 0x7D, 0x20, 0x55, 0x20,
0x55, 0x20, 0x54, 0x20, 0x5C, 0x20, 0x10, 0xE0, /*"制",2*/
};
static const unsigned char PROGMEM zao[]{
0x82, 0x00, 0x52, 0x00, 0x1F, 0xC0, 0x22, 0x00, 0xC2, 0x00, 0x7F, 0xE0, 0x40, 0x00, 0x5F, 0xC0,
0x50, 0x40, 0x5F, 0xC0, 0x40, 0x00, 0xBF, 0xE0, /*"造",3*/
};
static const unsigned char PROGMEM zan[]{
0x20, 0xC0, 0xFB, 0x00, 0x52, 0x00, 0x7B, 0xE0, 0x12, 0x40, 0xFA, 0x40, 0x14, 0x40, 0x3F, 0x80,
0x20, 0x80, 0x3F, 0x80, 0x20, 0x80, 0x3F, 0x80, /*"暂",0*/
};
static const unsigned char PROGMEM ting[]{
0x11, 0x00, 0x1F, 0xE0, 0x20, 0x00, 0x27, 0xC0, 0x64, 0x40, 0xA7, 0xC0, 0x20, 0x00, 0x2F, 0xE0,
0x28, 0x20, 0x27, 0xC0, 0x21, 0x00, 0x23, 0x00, /*"停",1*/
};
static const unsigned char PROGMEM deng[]{
0x42, 0x00, 0x7B, 0xE0, 0x94, 0x80, 0x04, 0x00, 0x7F, 0xC0, 0x04, 0x00, 0xFF, 0xE0, 0x01, 0x00,
0xFF, 0xE0, 0x21, 0x00, 0x11, 0x00, 0x07, 0x00, /*"等",0*/
};
static const unsigned char PROGMEM dai[]{
0x11, 0x00, 0x21, 0x00, 0x47, 0xC0, 0x91, 0x00, 0x2F, 0xE0, 0x60, 0x80, 0xAF, 0xE0, 0x20, 0x80,
0x24, 0x80, 0x22, 0x80, 0x20, 0x80, 0x23, 0x80, /*"待",1*/
};
static const unsigned char PROGMEM jie[]{
0x22, 0x00, 0x21, 0x00, 0x2F, 0xE0, 0xF4, 0x40, 0x22, 0x80, 0x2F, 0xE0, 0x31, 0x00, 0xEF, 0xE0,
0x22, 0x40, 0x26, 0x40, 0x21, 0x80, 0x6E, 0x60, /*"接",2*/
};
static const unsigned char PROGMEM shou[]{
0x12, 0x00, 0x92, 0x00, 0x92, 0x00, 0x93, 0xE0, 0x94, 0x40, 0x9A, 0x40, 0x92, 0x40, 0xB2, 0x80,
0xD1, 0x00, 0x92, 0x80, 0x14, 0x40, 0x18, 0x20, /*"收",3*/
};
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
RF24 radio(6, 7); // CE, CSN
const byte address[6] = "0000";
const byte address2[6] = "Space.ST";
int size = 12; //中文字体大小
float a = 0; // 初始化a
int time = 0; // 初始化time
float b;
float c;
void setup() {
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
Serial.begin(115200);
if (!radio.begin()) {
Serial.println("初始化失败");
return;
}
Serial.println("初始化成功");
radio.setPALevel(RF24_PA_MIN);
radio.openReadingPipe(0, address);
radio.openReadingPipe(1, address2);
radio.startListening(); // 开启接收模式
oled.begin(SSD1306_SWITCHCAPVCC, 0x3c);
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(1);
for (int progress = 0; progress <= 100; progress++) {
oled.clearDisplay();
oled.setCursor(20, 0);
oled.print("@Space-Traveler");
oled.drawBitmap(39, 17, zhong, size, size, 1);
oled.drawBitmap(52, 17, guo, size, size, 1);
oled.drawBitmap(65, 17, zhi, size, size, 1);
oled.drawBitmap(78, 17, zao, size, size, 1);
oled.fillRect(10, 55, progress + 10, 10, 1); // Draw progress bar
oled.setCursor(25, 39);
oled.print("Progress: ");
oled.print(progress);
oled.print("%");
oled.display();
}
delay(1000); // Wait for a second at the end
}
void loop() {
b = a / 1000 * 9.8;
if (c < b) { c = b; }
uint8_t pipe;
if (radio.available(&pipe)) { // 使用whatPipe函数检查哪个管道有数据
if (pipe == 0) {
radio.read(&a, sizeof(a));
} else if (pipe == 1) {
// 读取数字数据
radio.read(&time, sizeof(time));
}
oled.clearDisplay();
oled.drawBitmap(0, 0, sh, size, size, 1);
oled.drawBitmap(13, 0, shi, size, size, 1);
oled.setCursor(25, 5);
oled.print(":");
oled.setCursor(30, 5);
oled.print(b);
oled.println("N");
oled.drawBitmap(0, 20, zui, size, size, 1);
oled.drawBitmap(13, 20, da, size, size, 1);
oled.setCursor(25, 25);
oled.print(":");
oled.setCursor(30, 25);
oled.print(c);
oled.println("N");
oled.drawBitmap(0, 40, shi2, size, size, 1);
oled.drawBitmap(13, 40, jian, size, size, 1);
oled.setCursor(25, 45);
oled.print(":");
oled.setCursor(30, 45);
oled.print(time);
oled.println("s");
oled.display(); // 确保在显示新数据之前调用oled.display()
Serial.print(b);
Serial.print("N");
Serial.print(" ");
Serial.print(time);
Serial.println("s");
if (digitalRead(2) == 0) { c = 0; }
if (digitalRead(3) == 0) {
while (1) {
oled.drawBitmap(100, 15, zan, size, size, 1);
oled.drawBitmap(100, 28, ting, size, size, 1);
oled.display();
if (digitalRead(2) == 0) {
digitalWrite(2, 1);
delay(200);
return;
}
}
}
} else {
oled.clearDisplay();
oled.drawBitmap(38, 25, tong, size, size, 1);
oled.drawBitmap(51, 25, xin, size, size, 1);
oled.drawBitmap(64, 25, zhong, size, size, 1);
oled.drawBitmap(77, 25, duan, size, size, 1);
oled.display();
}
}
以上为本次试车Mcu使用的所有代码
从我朋友那篇文章里原视频中,他的数据是采集到了的,120N左右(与理论推理偏差过大)
在试车之前已经调过校准了,目前不能断定也不能否决,是采集率的问题,虽然接收端的采集率只有20赫兹,但只是数据接收的速度过慢,但发送版的那部分数据采集是完全按照80赫兹进行工作,接收也可能是因为我额外加了oled作为显示,结果导致速率过慢了,这个是先前测试过的,但是为了方便观看就画蛇添足的加了一个
但这不能说明发送板采集有问题
目前暂时没有找到具体原因,测试之前,发送端的采集率达到80赫兹(不排除硬件问题),至于目前原因暂未找到,我们会进一步的进行查找和排除问题,另外如果我们的代码逻辑问题,希望大佬们能够指出