我正在与Arduino和Lora合作。Arduino A有一个相机,收音机和SD卡。Arduino B有相同的设置,除了相机。
目标是从A向B发送一张图片。下面的代码应该从SD卡A读取32个字节(多亏了mmixLinus,它做得很好),并通过LoRa发送到Arduino B,后者将这32个字节保存到自己的SD卡中。文件将一次发送32个字节,直到所有的53 k到达。
经过一些故障排除,并认为我正在丢失数据包,我决定计数发送的数量与接收的数量。他们匹配。
我还把每个数据包的字节数发送到控制台。它们匹配。
但是,保存在接收SD卡中的结果文件比发送SD卡上的原始文件小。它无法使用。
我注意到,除了最后一个数据包可以更小之外,我希望每个数据包都是32字节。但是,即使发送和接收的字节匹配,我也不确定为什么我的代码在读取每个文件时不使用完整的32字节。
这些是我的主要问题。
1.你能帮我找出我做错了什么吗?
1.什么是一种 * 理想 * 的简单方法来实现错误检查,确保每个发送的数据包在接收时都经过检查和验证,并让发送方知道它可以发送下一个数据包?
这是发件人的代码。
oFile = SD.open("ring.jpg", FILE_READ); //open source file for read.
long cByteTotal = oFile.size(); //get total bytes
Serial.print("Original size: ");
Serial.println(cByteTotal);
while (cByteTotal > 0) {
int length = cByteTotal < 32 ? cByteTotal : 32;
if (length < 32) {
Serial.println("Sending last packet."); //info
}
oFile.read(cArray, length); //read 32 bytes from file
cArray[length] = '\0'; // terminate the char array
sendMessage(String(cArray)); //send the file via Lora after casting to string
delay(250); // just in case to give time to receiver to process
cByteTotal -= length;
}
oFile.close();
Serial.println("Done Sending.");
void sendMessage(String cArray) {
LoRa.beginPacket();
LoRa.write(cArray.length());
LoRa.write(cArray);
LoRa.endPacket();
}
这是接收器的代码。
void loop() {
onReceive(LoRa.parsePacket());
}
void onReceive(int packetSize) {
if (packetSize == 0) {
return;
}
packageTotal++;
byte incomingLength = LoRa.read();
String incoming = "";
while (LoRa.available()) {
incoming += (char)LoRa.read();
}
if (incomingLength != incoming.length()) {
// check length for error
Serial.println("LENGHT [ERROR]"); // this does not get triggered, which is good.
return; // skip rest of function
} else {
cFile = SD.open("wimage.jpg", FILE_WRITE);
cFile.print(incoming);
cFile.close();
}
}
我正在使用以下Lora library
谢谢你的帮助!
1条答案
按热度按时间o2rvlv0m1#
这里你犯的主要错误是你把文件内容当作一个字符串,这是绝对不应该的。一个二进制文件可以有
0x00
,字符串终止符,这肯定会毁了你的午餐。首先,我们需要将32字节的块作为二进制blob来处理,并使用
write(const uint8_t *buffer, size_t size);
。另外,我们使用的是LoRa.write(cArray.length());
,它没有做什么:它不会告诉LoRa库你发送了多少字节,接收方知道你收到了多少字节。你的函数应该是这样的:接下来,传输本身。你正在
while
循环中传输,延迟非常小,太小了,至少有两个原因,和,没有检查接收方是否确实收到了块#x,并且正确地接收了它。这将导致很多问题...你已经有了一个循环,命名为
loop()
,所以你不需要另一个循环。相反,在loop
中,从卡中读取32个字节,将它们发送到一个包中,包中包含块号、数据和基本CRC。例如,将包中的每个字节相加,并将其作为16位数使用。作为数据包的最后2个字节。您将拥有2 [计数器] +32 [数据] +2 [CRC]的结构。然后切换到“等待确认”模式。直到你听到你的接收器返回,发送给你4个字节,2个为索引,2个为CRC,你什么也不做。如果发送回来的CRC是错误的,你不增加计数器。如果CRC是正确的,增加。然后你切换到发送模式。冲洗和重复。
在接收端,你处于待机模式。当你接收到一个数据包时,你计算CRC并比较--如果不正确,你把它发送回去,然后回到接收模式。如果正确,你把32个字节保存在缓冲区的正确位置。然后发送回索引+CRC。最后你保存。
哦,还有,是接收,不是接收...