Upload using C#

This isn't a question, just figured I'd post this for anyone else that may need to do what I did. I have an Arduino Duemilanove board that interfaces to a C# application. That works well, but I always had to go back to the Arduino IDE to upload changes to the board.

I needed to be able to also upload new versions of the code from the C# application, so after poking around the forums I wrote something that seemed to me to be useful enough (not limited to C# apps, once you see what it does) to post back. The following snippet of code is called as a result of a button push in my C# application....

private void aVRUpdateButton_Click(object sender, EventArgs e)
{
    // These files must be part of the installation.
    // They come from the Arduino installation directory arduino/hardware/tools/avr/bin
    if (!File.Exists(installDir + "\\avr\\avrdude.exe"))
    {
        MessageBox.Show("avrdude tool not installed", "AVRUpdate error");
        return;
    }
    if (!File.Exists(installDir + "\\avr\\avrdude.conf"))
    {
        MessageBox.Show("avrdude config file not installed", "AVRUpdate error");
        return;
    }
    if (!File.Exists(installDir + "\\avr\\cygwin1.dll"))
    {
        MessageBox.Show("avrdude cygwin dll not installed", "AVRUpdate error");
        return;
    }
    if (!File.Exists(installDir + "\\avr\\libusb0.dll"))
    {
        MessageBox.Show("avrdude usb dll not installed", "AVRUpdate error");
        return;
    }

    // THis file is the new image to be uploaded to the Arduino board...
    if (!File.Exists(installDir + "\\avr\\AVRImage.hex"))
    {
        MessageBox.Show("AVR image not installed", "AVRUpdate error");
        return;
    }

    textBox_Trace.Text += "(DO NOT RESET OR TURN OFF TILL THIS COMPLETES)\r\n";
    MessageBox.Show("Click OK to Start", "AVR Update");
    string avrport = "COM" + numericUpDown_Port.Value.ToString();
    string dir = installDir;
    dir.Replace("\\", "/");
    Process avrprog = new Process();
    StreamReader avrstdout, avrstderr;
    StreamWriter avrstdin;
    ProcessStartInfo psI = new ProcessStartInfo("cmd");


    psI.UseShellExecute = false;
    psI.RedirectStandardInput = true;
    psI.RedirectStandardOutput = true;
    psI.RedirectStandardError = true;
    psI.CreateNoWindow = true;
    avrprog.StartInfo = psI;
    avrprog.Start();
    avrstdin = avrprog.StandardInput;
    avrstdout = avrprog.StandardOutput;
    avrstderr = avrprog.StandardError;
    avrstdin.AutoFlush = true;
    //avrstdin.WriteLine(installDir + "\\avr\\avrdude.exe -Cavr/avrdude.conf -patmega328p -cstk500v1 -P" + avrport + " -b57600 -D -Uflash:w:" + dir + "/avr/AVRImage.hex:i");
    avrstdin.WriteLine("avr\\avrdude.exe -Cavr/avrdude.conf -patmega328p -cstk500v1 -P" + avrport + " -b57600 -D -Uflash:w:avr/AVRImage.hex:i");
    avrstdin.Close();
    textBox_Trace.Text = avrstdout.ReadToEnd();
    textBox_Trace.Text += avrstderr.ReadToEnd();
}

The code assumes that a few files taken from the Arduino bin directory are found under the path whose string is contained within "installDir" (specifcally: avrdude.exe, avrdude.conf, cygwin1.dll & libusb0.dll). The function simply opens a process running CMD and then issues the avrdude command line that will pump a new image to the arduino board on the comport taken from a numeric-up-down tool within the GUI. The output of the process is copied back into a textbox (textbox_Trace) for viewing by the user.

Obviously the arguments passed to avrdude depend on your configuration, but I think (please correct me if I'm wrong) this is a fairly generic approach.

Enjoy! If you happen to use it and find any bugs, please post back.

Cool.

This is interesting, thanks for sharing.

Couple of changes for the above code...
First, if the COM port number is greater than 9, then you have to
use this microsoft hocus pocus...

string avrport;
if (numericUpDown_Port.Value <= 9)
    avrport = "COM" + numericUpDown_Port.Value.ToString();
else
    avrport = "\\\\.\\COM" + numericUpDown_Port.Value.ToString();

and second, I wasn't properly using the Replace method...

 string dir = installDir.Replace("\\", "/");

Hi,

This is exactly what I want to do. But is there no way to do this serially? I would like to do what this program is doing within my own program. I would like to precompile a sketch and then programmatically upload it on the fly in my C# or whatever Windows based program over the serial. I've looked at the Ardunio IDE open source JAVA code and am struggling to identify the code that does this. Although I believe the stk500 protocol has something to do with this. Can anybody shed some light on serially uploading a new HEX sketch to the ardunio over USB on windows using software?

Many Thanks

NozFx

I assume when you say you want to do this "serially", you mean you'd like to do this by opening a serial port and pushing the image directly onto the board without using avrdude?
That may seem cleaner, but then you have to maintain it if things change. Simply using avrdude.exe to do this from an application allows me to just abstact that whole protocol out and assume avrdude.exe knows what its doing...
Anyway, if you decide to look into this, you probably want to look at the avrdude code, not the JAVA code for the GUI. I'm pretty sure the Arduino GUI does the same thing as I'm doing (if I remember correctly, that's how I figured out how to do it, by turning on trace in the gui and then doing the download).
Hope this helps.

Hi,

Thanks for the prompt response. I take your point but realistically this isn't going to change very frequently. I guess I'll end up using this but I did find this:

Although not exactly what I want to achieve in principle its exactly what needs to be achieved. This is a sketch which via serial updates another Arduino with a sketch via an master ardunino. Although code is in sketch, essentially it could be ported to PC based app right? of course, you still have first point, I just want the most seemless solution for my application.

Kind Regards

NozFx

yea, if you have C code that talks directly to the Arduino, then it should easily port over to C# using SerialPort.