使用批处理脚本在PC和Arduino之间传输文本文件
我有一个基于Arduino欠款和我的PC之间的文件传输的个人项目。 这些文件的文件为文本格式,可以超过10MB。
我首先购买了SD SPI模块,将外部SD卡连接到我的Arduino和兼容的Micro-SD卡。
SD卡方面,一切正常,检测到卡,并且数据存储也可以正常工作。
要从我的PC传输数据,我正在使用批处理脚本,这些脚本通过Arduino使用的串行端口发送文本文件内容。
问题出现了: 我无法一次通过串行端口传输超过65535的长度文件。
如果文件包含超过65535个字符,则转移卡住了,直到重置Arduino卡,我将无法做任何事情。 我尝试了更多的字符,但它只写了文件中的第一个字符。
因此,如果我的文件执行65635个字符,则只有前100个字符将写在新文件中。
但是正如我所说,我的目标是传输大量文件。
为了说明我的问题,我为您提供了一些关于Arduino和批处理脚本的代码。
arduino part
我启动了使用按钮的不同状态。
- 第一个运行一个“ send_file”批次脚本,该脚本将将数据发送到串行端口并写入SD卡上的新文件。
- 第二个将运行一个“ read_serial”批处理脚本,该脚本将读取Arduino通过串行端口发送的文件内容。
- 第三个用于删除之前创建的文件。
请注意,我将RGB LED用于不同的状态,还使用键盘库在我的计算机上执行操作。
这是完整的代码:
#include <Wire.h>
#include <Keyboard.h>
#include <SPI.h>
#include <SD.h>
File myFile;
const int chipSelect = 53;
String AltGrazerty = "~#{[|`\\^@#]}";
String shiftazerty = "QBCDEFGHIJKL?NOPARSTUVZXYW1234567890 Q+QQQQM%Q./Q>";
String azerty = "qbcdefghijkl,noparstuvzxyw&q\"'(-q_qq )=q$q*mqq;:!<";
const byte scancode[] = { 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, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 100 };
int BP1 = 28, BP2 = 29, BP3 = 31, BP4 = 30, BP5 = 33, BP6 = 32;
int red_light_pin= 9;
int green_light_pin = 11;
int blue_light_pin = 10;
int ledstate = 0;
int val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0, flag = 0;
void setup() {
Serial.begin(115200);
Keyboard.begin();
if (!SD.begin(chipSelect)) {
while (1);
}
myFile = SD.open("test.txt");
while (myFile.available()) {
Serial.write(myFile.read());
}
myFile.close();
Serial.flush();
pinMode(BP1, INPUT_PULLUP);
pinMode(BP2, INPUT_PULLUP);
pinMode(BP3, INPUT_PULLUP);
pinMode(BP4, INPUT_PULLUP);
pinMode(BP5, INPUT_PULLUP);
pinMode(BP6, INPUT_PULLUP);
pinMode(red_light_pin, OUTPUT);
pinMode(green_light_pin, OUTPUT);
pinMode(blue_light_pin, OUTPUT);
}
void loop() {
val1 = digitalRead(BP1);
val2 = digitalRead(BP2);
val3 = digitalRead(BP3);
val4 = digitalRead(BP4);
val5 = digitalRead(BP5);
val6 = digitalRead(BP6);
switch (ledstate){
case 0 : RGB_color(255, 239, 0);
break;
case 1 : RGB_color(255, 0, 0);
break;
case 2 : RGB_color(0, 255, 0);
break;
case 3 : RGB_color(0, 0, 255);
break;
}
if (val1 == 0)
{
if (flag == 0)
{
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(250);
Keyfr("C:/Users/***/Desktop/send_data.bat");
delay(500);
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();
String text = Serial.readString();
myFile = SD.open("test.txt",FILE_WRITE);
if(myFile){
myFile.println(text);
myFile.close();
} else {}
ledstate = 1;
flag = 1;
}
} else if (val2 == 0) {
if (flag == 0) {
Serial.flush();
delay(500);
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(250);
Keyfr("C:/Users/***/Desktop/read_data.bat");
delay(500);
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();
ledstate = 2;
flag = 1;
}
} else if (val3 == 0) {
if (flag == 0) {
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(250);
Keyfr("C:/Users/***/Desktop/del.bat");
delay(500);
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();
myFile = SD.open("test.txt");
if (myFile) {
SD.remove("test.txt");
myFile.close();
} else {}
ledstate = 3;
flag = 1;
}
} else if (val4 == 0) {
if (flag == 0) {
flag = 1;
}
} else if (val5 == 0)
{
if (flag == 0) {
flag = 1;
}
} else if (val6 == 0) {
if (flag == 0) {
flag = 1;
}
} else if (val1 == 1 && val2 == 1 && val3 == 1 && val4 == 1 && val5 == 1 && val6 == 1)
{
flag = 0;
}
delay(50);
}
void Keyfr(const String &Texte) {
int j = -1;
for (unsigned int i = 0; i < Texte.length(); i++) {
char c = Texte.charAt(i);
if (c == '\t') {
Keyboard.write(KEY_TAB);
}
int index = azerty.indexOf(c);
if (index > -1) {
j = scancode[index] + 136;
Keyboard.write(j);
} else {
index = shiftazerty.indexOf(c);
if (index > -1) {
j = scancode[index] + 136;
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(j);
Keyboard.releaseAll();
} else {
index = AltGrazerty.indexOf(c);
if (index > -1) {
j = scancode[index + 27] + 136;
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.write(j);
Keyboard.releaseAll();
if (index == 0 || index == 7) {
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.write(j);
Keyboard.releaseAll();
Keyboard.write(KEY_BACKSPACE);
}
}
}
}
}
}
void RGB_color(int red_light_value, int green_light_value, int blue_light_value)
{
analogWrite(red_light_pin, red_light_value);
analogWrite(green_light_pin, green_light_value);
analogWrite(blue_light_pin, blue_light_value);
}
批处理部分
我只在这部分中给您发送和读取脚本,即使我认为脚本不是问题。
发送脚本:
@echo off
setlocal EnableDelayedExpansion
@echo mode COM5 BAUD=115200 PARITY=n DATA=8
set "cmd=findstr /R /N "^^" file.txt | find C/ ":""
@type file.txt > COM5
阅读脚本:
@echo off
setlocal EnableDelayedExpansion
@mode COM5 BAUD=115200 PARITY=n DATA=8 DTR=ON
set "cmd=findstr /R /N "^^" file.txt | find /C ":""
@type COM5>file2.txt
希望我的问题是可以理解的,我的英语是正确的(不是我的主要语言)。
提前致谢。
罗曼。
I have a personal project based on file transfer between an Arduino Due and my PC.
Theses files are in text format and can go over 10Mb.
I firstly bought an SD SPI module to connect an external SD card to my Arduino and a compatible micro-SD card.
SD card sided, everything works well, the card is detected and data storage is also working.
To transfer data from my PC, I am using Batch scripts that send text file content over Serial port used by Arduino.
The problem comes:
I am unable to transfer over 65535 length file over Serial port at once.
If the file contains more than 65535 characters, the transfer stuck and I am unable to do anything until I reset the Arduino card.
I tried with a bit more characters, but it only writes firsts characters in the file.
So, if my file does 65635 characters, only the first 100 characters will be written in the new file.
But as I said, my goal is to transfer huge files.
To illustrate my problem I give you some codes on Arduino and Batch scripts.
Arduino part
I launch different states with buttons.
- First one run a "send_file" batch script that will send data to serial port and write into a new file on SD card.
- A second one will run a "read_serial" batch script that will read file content sent over Serial port by Arduino.
- The third one is used to delete the file created before.
Note that I use RGB led for different states, and also Keyboard library to do actions on my computer.
Here is the complete code:
#include <Wire.h>
#include <Keyboard.h>
#include <SPI.h>
#include <SD.h>
File myFile;
const int chipSelect = 53;
String AltGrazerty = "~#{[|`\\^@#]}";
String shiftazerty = "QBCDEFGHIJKL?NOPARSTUVZXYW1234567890 Q+QQQQM%Q./Q>";
String azerty = "qbcdefghijkl,noparstuvzxyw&q\"'(-q_qq )=q$q*mqq;:!<";
const byte scancode[] = { 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, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 100 };
int BP1 = 28, BP2 = 29, BP3 = 31, BP4 = 30, BP5 = 33, BP6 = 32;
int red_light_pin= 9;
int green_light_pin = 11;
int blue_light_pin = 10;
int ledstate = 0;
int val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0, val6 = 0, flag = 0;
void setup() {
Serial.begin(115200);
Keyboard.begin();
if (!SD.begin(chipSelect)) {
while (1);
}
myFile = SD.open("test.txt");
while (myFile.available()) {
Serial.write(myFile.read());
}
myFile.close();
Serial.flush();
pinMode(BP1, INPUT_PULLUP);
pinMode(BP2, INPUT_PULLUP);
pinMode(BP3, INPUT_PULLUP);
pinMode(BP4, INPUT_PULLUP);
pinMode(BP5, INPUT_PULLUP);
pinMode(BP6, INPUT_PULLUP);
pinMode(red_light_pin, OUTPUT);
pinMode(green_light_pin, OUTPUT);
pinMode(blue_light_pin, OUTPUT);
}
void loop() {
val1 = digitalRead(BP1);
val2 = digitalRead(BP2);
val3 = digitalRead(BP3);
val4 = digitalRead(BP4);
val5 = digitalRead(BP5);
val6 = digitalRead(BP6);
switch (ledstate){
case 0 : RGB_color(255, 239, 0);
break;
case 1 : RGB_color(255, 0, 0);
break;
case 2 : RGB_color(0, 255, 0);
break;
case 3 : RGB_color(0, 0, 255);
break;
}
if (val1 == 0)
{
if (flag == 0)
{
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(250);
Keyfr("C:/Users/***/Desktop/send_data.bat");
delay(500);
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();
String text = Serial.readString();
myFile = SD.open("test.txt",FILE_WRITE);
if(myFile){
myFile.println(text);
myFile.close();
} else {}
ledstate = 1;
flag = 1;
}
} else if (val2 == 0) {
if (flag == 0) {
Serial.flush();
delay(500);
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(250);
Keyfr("C:/Users/***/Desktop/read_data.bat");
delay(500);
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();
ledstate = 2;
flag = 1;
}
} else if (val3 == 0) {
if (flag == 0) {
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
delay(250);
Keyfr("C:/Users/***/Desktop/del.bat");
delay(500);
Keyboard.press(KEY_RETURN);
Keyboard.releaseAll();
myFile = SD.open("test.txt");
if (myFile) {
SD.remove("test.txt");
myFile.close();
} else {}
ledstate = 3;
flag = 1;
}
} else if (val4 == 0) {
if (flag == 0) {
flag = 1;
}
} else if (val5 == 0)
{
if (flag == 0) {
flag = 1;
}
} else if (val6 == 0) {
if (flag == 0) {
flag = 1;
}
} else if (val1 == 1 && val2 == 1 && val3 == 1 && val4 == 1 && val5 == 1 && val6 == 1)
{
flag = 0;
}
delay(50);
}
void Keyfr(const String &Texte) {
int j = -1;
for (unsigned int i = 0; i < Texte.length(); i++) {
char c = Texte.charAt(i);
if (c == '\t') {
Keyboard.write(KEY_TAB);
}
int index = azerty.indexOf(c);
if (index > -1) {
j = scancode[index] + 136;
Keyboard.write(j);
} else {
index = shiftazerty.indexOf(c);
if (index > -1) {
j = scancode[index] + 136;
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(j);
Keyboard.releaseAll();
} else {
index = AltGrazerty.indexOf(c);
if (index > -1) {
j = scancode[index + 27] + 136;
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.write(j);
Keyboard.releaseAll();
if (index == 0 || index == 7) {
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.write(j);
Keyboard.releaseAll();
Keyboard.write(KEY_BACKSPACE);
}
}
}
}
}
}
void RGB_color(int red_light_value, int green_light_value, int blue_light_value)
{
analogWrite(red_light_pin, red_light_value);
analogWrite(green_light_pin, green_light_value);
analogWrite(blue_light_pin, blue_light_value);
}
Batch part
I give you in this part only send and read scripts, even if I think theses scripts are not a problem.
Send script :
@echo off
setlocal EnableDelayedExpansion
@echo mode COM5 BAUD=115200 PARITY=n DATA=8
set "cmd=findstr /R /N "^^" file.txt | find C/ ":""
@type file.txt > COM5
Read script :
@echo off
setlocal EnableDelayedExpansion
@mode COM5 BAUD=115200 PARITY=n DATA=8 DTR=ON
set "cmd=findstr /R /N "^^" file.txt | find /C ":""
@type COM5>file2.txt
I hope my problem is understandable and my English is correct (not my primary language).
Thanks in advance.
Romain.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
就像您为Arduino-&gt; PC所做的那样,在接收文件时(pc-&gt; arduino)时,您必须循环并在SD卡上循环并写入SD卡,直到您获得协议结束(可以是任何内容:BRK,EOF,eof,timeout,,,,超时,, ETC。)。您无法在单个字符串中收到整个文件,除非它比UART缓冲区容量要短……因此,您获得64 kb的限制也就不足为奇了 - 实际上,它对UART来说甚至很大:我工作了。对于某些仅具有 16字节的UART 的内部缓冲区...这意味着在115,200波特时,您需要每毫秒毫秒刷新此缓冲液,以避免缓冲区过度!
当前,您的
loop()
函数过于复杂,最坏的是delay> delay
指令和分支...可以完成带有轮询循环的UART的阅读,但是这种情况,别无其他。或通过中断处理程序设置接收器。通过UART传输与通过TCP/IP发送的情况不同。没有自动重传,没有ACK,什么也没有。您甚至都不知道您当前收到的内容的大小 - 这就是为什么通过自定义协议,您通常将大小作为传输的第一个元素发送,////或您使用ack的UDP之类的东西 - 发送固定尺寸块,从接收器等待ACK发送另一个块,最后一个块通过其标头标记为“部分”(您也需要制作这样的标题)。
Like what you did for Arduino->PC, when receiving the file (PC->Arduino), you must loop and write on SD card continuously, until you get a protocoled END (can be anything: BRK, EOF, timeout, etc.). You can't receive the whole file within a single string, unless it is shorter than the UART buffer capacity... So it's not surprising that you get a 64 kB limit - it's even quite huge for an UART, in fact: I worked with some UARTs that had only 16 BYTES of internal buffer... Meaning that at 115,200 bauds, you need to flush this buffer EVERY MILLISECOND to avoid a buffer overrun!
Currently, your
loop()
function is excessively complex, and worst, containsdelay
instructions and branches... Reading from an UART with a polling loop can be done, but in this case, don't do anything else. Or setup a reception through an interruption handler.Transferring through an UART isn't the same as sending through TCP/IP. There is no automatic retransmission, no ACK, NOTHING. You don't even know the size of what you are currently receiving - that's why, through a custom protocol, you usually send the size as FIRST element of a transmission, and/or you use something like UDP with ACK - sending fixed-size chunk, waiting ACK from receiver to send another chunk, the last chunk being marked as "partial" through its header (you'll need to make such a header, too).