I am trying to build a program for transferring files to an arduino project with an attached sd card. I have some code, it does some interesting stuff, but it's not quite what I want it to do. What I need it to do is to be able to transfer binary files to the arduino where I will save them to the sd. There are going to be several parts of this project. One part will probably be a shell script or C# script (windows) where I will transfer the files via COM. Another part will be the arduino code which will have to be able to distinguish between individual files, and will need to be able to recognize when seperate files are sent. Ultimately the shell script/C# whatever part will be sending file after file to the arduino, perhaps in a loop in a specific folder.

The arduino part will proably be coded in the "Processing" language, the default language for arduino development. At some point I will probably migrate to teensy if I can get the logic down right. Arduino is easier for the time being.

Some of the things that are hanging me up are that I have to figure out a way how to switch between the files, and transmit file names, etc. I will be delving into a sockets book I have laying around, perhaps that can shed some light on the subject. The binary transmission and reception is also a problem, as well as thinking more in terms of socket communication.

At some point I could add some VID/PID changing code possibly if I can get the project working, as well as some code to inject the script (which will at that point be batch or something) onto the computer.

This is just something I think would be cool to make, I will be making more code etc, I just was wondering if any of you had any useful observations on the 'Socket' like aspect of the serial communication?

Here is some starter code, but it is probably not executing correctly, it is operating on text files, not binary, and it has no concept of the file name, and the file switching is not in place yet.

#include <SD.h>
#include <SPI.h>

//Set by default for the SD card library
//MOSI = Pin 11
//MISO = Pin 12
//SCLK = PIN 13
//We always need to set the CS Pin
const int CS_PIN  = 10;
const int ERR_PIN = 1;
const int WRITE_PIN = 4;
bool closed = false;

//We set this high to provide power
const int POW_PIN = 8;


const int BUFF_SIZE = 32;
const bool debug = true;//switch to false for in the wild functionality
File myFile;

void setup()
{
  Serial.begin(9600);

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  if (!SD.begin(CS_PIN)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  myFile = SD.open("test.txt", FILE_WRITE);
}//end func

void loop()
{
  if(closed == false){
    if(myFile){
      char ch = Serial.read();

      if(ch == 0){//close file when eof encountered
        closed = true;
        myFile.close();
      }
      else if(ch != -1){
        myFile.print(ch);
        Serial.print(ch);
      }

    }else{
      //if the file didn't open, print an error:
      Serial.println("error opening test.txt");
    }
  }

}//end func


using System;
using System.IO.Ports;


namespace SerialPortWrite
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort port = new SerialPort();
            port.PortName = "COM6";
            port.BaudRate = 9600;
            port.DataBits = 8;
            port.Handshake = Handshake.None;
            port.StopBits = StopBits.One;

            port.Open();

            Console.WriteLine("Input text to send to COM device: ");
            String str = Console.ReadLine() + (char)(0);

            for (int i = 0; i < str.Length; i++) {
                port.Write(str[i] + "");

                byte[] buff = new byte[1];
                port.Read(buff, 0, 1);
                Console.Write((char)buff[0]);
            }

            Console.WriteLine();

            port.Close();

            //if debugger is attached, want to pause the output at the very end
            if (System.Diagnostics.Debugger.IsAttached) {
                Console.Write("Press any key to continue... ");
                Console.ReadLine();
            }
        }//end main

    }//end class

}//end namespace




#WINDOWS POWER SHELL
>#WRITE TO PORT
>[System.IO.Ports.SerialPort]::getportnames()
COM1
COM5
>$port = new-Object System.IO.Ports.SerialPort COM5, 9600, None, 8 one
>$port.open()
>$port.WriteLine("Hello World")
>$port.Close()

>#READ FROM PORT
>$port = new-Object System.IO.Ports.SerialPort COM5, 9600, None, 8, one
>$port.Open()
>$port.ReadLine()

>REM BATCH
>TYPE COM5
>REM WRITE TO COM PORT
>ECHO "some text" > COM5
>MODE COM22 BAUD=9600 PAIRITY = n DATA = 8

Dani AI

Generated

A compact, robust approach is to treat the serial link like a byte stream and implement simple framing, acknowledgements, and integrity checks instead of using a single sentinel byte or text APIs. Send a small per-file header (magic + filename + file-size), wait for an ACK, stream the exact number of raw bytes in fixed-size chunks, then send a checksum and wait for a final OK. This avoids problems with embedded NULs, newline translation, and resets during port open.

Example header (ASCII, easy to parse on AVR):

FILE\n
<filename>\n
<filesize>\n
<binary payload of exactly filesize bytes>

PC: send header, wait for "OK". Arduino: parse header, open SD file, read and write chunks, compute checksum, send ACK/NACK.

Arduino-side notes (addresses gaps in code)

  • Use binary-safe I/O: write file data with File.write(buffer, len) (not text print) and read serial with buffered reads (e.g., readBytes or a small ring buffer).
  • Use small chunks (32-256 bytes) to match AVR serial and SD write buffering.
  • Signal readiness explicitly because opening the host serial port often resets AVR boards; wait for an explicit "READY" from the board before sending a header.
  • Compute a checksum (CRC32 or a simpler CRC16) while writing and return it for verification.

PC-side tips

  • Read files in binary and use SerialPort.Write(byte[],0,len) (do not send char-by-char or use WriteLine).
  • Disable or manage DTR (or wait for READY) to avoid accidental resets when opening the port.
  • For multiple files, loop: send header, wait OK, stream file, wait completion ACK, then continue.

About protocols: 's Zmodem suggestion is valid—ZMODEM (or YMODEM for batch/filenames) gives features like resume and built-in filenames, but they are heavier to implement on AVR. Start with a tiny custom header+ACK protocol for simplicity, then migrate to a full protocol or to a more capable board (Teensy) if you need performance or resume features.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.