Friday, May 22, 2009

Arduino writes to file

One of the frequently asked question on the Arduino forum is "how can Arduino save data to a file?" (see this thread for example). The quick answer is this: Arduino sends data over the serial port to the PC, which, in turn, is running an executable that reads the serial port. Every byte of data (or ASCII character) received is then saved to a file. So, this mechanism has two parts:
1. a piece of the sketch, running on Arduino, will send data using the function Serial.print();
2. a piece of code (executable, script etc) running on PC, will receive data from the serial port.

An example of VBscript that does just that is shown below. The characters read from COM6 (baud rate 9600, 8 bits, no parity, 1 stop bit) are saved to file "C:\results.txt".

Const ForReading = 1
Const ForWriting = 2

Set fso = CreateObject("Scripting.FileSystemObject")
Set com = fso.OpenTextFile("COM6:9600,N,8,1", ForReading)

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\results.txt", ForWriting, True)

MsgBox("Start to read data from COM")

Do While com.AtEndOfStream <> True
s = com.ReadLine
objFile.WriteLine(s)
WScript.Sleep(200)
Loop

objFile.Close
com.Close()

A similar approach can be used for reading characters from a file.

The following is an example VBscript that reads the characters from a text file ("C:\docs\quotes.txt") and sends them on port COM7(9600,N,8,1) to Arduino. I use it to load text messages (quotations) to an external EEPROM (24LC256).


Const ForReading = 1
Const ForWriting = 2

'------------------------------------------------------------------------------------------------
' open USB serial port (COMx);
'
' If the serial monitor in Arduino IDE is open, you will get an "access denied" error.
' Just make sure that the serial monitor is closed (so bytes are not sent by the arduino board).
'------------------------------------------------------------------------------------------------

Set fso = CreateObject("Scripting.FileSystemObject")
Set com = fso.OpenTextFile("COM7:9600,N,8,1", ForWriting)


'---------------------------------------------
' read content of text file line by line;
' write line to COMx;
'---------------------------------------------

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\docs\quotes.txt", ForReading)

MsgBox("Ready to write file content to COM")

Do While objFile.AtEndOfStream <> True
'---------------------------------------------------------------------------------------------------------
' read 10 characters at a time; arduino serial buffer cannot take more than 32 characters;
' writing a character to eeprom takes about 11 ms (assuming that there is no serial.prints in the loop);
' therefore, after each batch of 10 chars sent to COM, we should wait no less than 110 ms;
' we use 200 to have a margin of safety;
'---------------------------------------------------------------------------------------------------------
strChars = objFile.Read(10)
com.Write(strChars)
WScript.Sleep(200)
Loop

objFile.Close
com.Close()

MsgBox("Finished writing to COM")
In order to use the above scripts, copy the code, paste it into a text file and name it with the extension "vbs". Just by double clicking on the file, Windows will invoke wscript.exe, which will then execute the VBscript code.
NB: The above code was formatted by http://formatmysourcecode.blogspot.com/

25 comments:

  1. This is about one of the cleanest hacks I have found for getting data off the arduino to a file. Good work.

    ReplyDelete
  2. Is there a code out there to take the data output as above, from Arduino and place into a MS Excel spreadsheet. Using VBA ?

    Thks
    Charlie

    ReplyDelete
  3. Charlie,
    The easiest way to do this using VBS would be output the results as a comma separated value (CSV) file. This will then load into Excel automatically.

    If multiple values are included on a single line the code above will need to either read each line character by character or include a routine to parse the line into individual data items.

    ReplyDelete
  4. I did this and it worked for me the first time but then its just giving me " |D! HDR1D! HDR1D! @biB" 'R1D" continually.

    ReplyDelete
  5. After uploading the sketch onto an Uno I can see that the initial message is displayed and the file is created, but then it looks like the only way to stop the stream is to unplug the Uno. When I try to open the output file, not only is it empty, but it is locked for editing.

    How would I stop the stream other than unplugging the Arduino? Why would nothing be being saved to the file? The first question might answer the second.

    When I go to run the sketch again it says COM6 isn't found, so I need to restart the computer so it'll find the right COM for the sketch.

    Thank so much for this! I'm sure if I understand it better it will work as intended. This is very useful!

    ReplyDelete
  6. @General Blogger - you're probably using the wrong baud rate. Set both to 9600.

    ReplyDelete
  7. Hey team,

    Windows Script Host is returning a "Permission Denied" error whenever I try to run the first .vbs file listed above on the "set objFSO..." line. I am the administrator on this system, and I don't really know where to begin to correct this error. Any support would be appreciated.

    Thanks,
    W

    ReplyDelete
  8. Will,
    The "Permission denied" error you mention may be caused by the fact that the port is already opened by another app (such as Arduino IDE). Make sure that this is not the case and try again.

    ReplyDelete
  9. I'm getting Permission denied as well it's on line 8 which is when it's trying to write the file to the c:\ Any Idea's? Using Windows 7

    ReplyDelete
  10. I haven't used Windows 7 yet and I am not familiar with Windows 7 at all.
    There may be settings (through Control Panel) that allow user/admin to access the COM ports.

    ReplyDelete
  11. I got this working - you need to make sure you are not running the Serial Monitor and you may have to edit the file to point to the correct COM port you are using for the Uno USB port.
    I had trouble stopping it too - fire up Task Manager (Ctrl-Alt-Del) and kill wscript.exe.
    Excel should be able to read the file nicely if you format the Serial output with commas and edit file and change .TXT to .CSV file type.
    Maybe an Excel Macro.....??

    ReplyDelete
  12. my error is file not found at line 11 which is when create fso:
    Set fso = CreateObject("Scripting.FileSystemObject")

    why is that happen?sorry for my noob question...any1 help?

    ReplyDelete
  13. The error may be on the "...fso.OpenTextFile..." line. Check that by removing comments and empty lines.

    ReplyDelete
  14. Hi Florin. I was looking to do the exact same thing -- read bytes from a file and dump them to a 24LC class eeprom. While I see the VBS files, I was wondering if your arduino sketch was also available? I browsed your google code directory but didn't see it...

    ReplyDelete
  15. Max,
    Yes, the sketch (eeprom_quotes.pde) is part of the "original" WiseClock zip file:
    http://code.google.com/p/wiseclock2/downloads/detail?name=WiseClock_Mar21.zip&can=2&q=#makechanges
    Last time I tested it was with Arduino 23. You will need to adapt it for Arduino 1.0, you know, replace wprogram.h with Arduino.h and a few more changes. Let me know if this is a problem, I will help you with that.

    ReplyDelete
  16. Hi, I am using your code to save arduino (connected via USB) results in a text file but i get File not found exception at this code line com = fso.OpenTextFile("COM25:9600,N,8,0", ForReading)" any help ???

    ReplyDelete
    Replies
    1. In Windows, COM ports above a certain value (9?) are addressed differently, see this:
      http://support.microsoft.com/kb/115831

      Delete
  17. hi FlorinC, I'm trying your code but the txt file is not updated, it's always zero bytes. the file is being created though.

    ReplyDelete
    Replies
    1. What OS are you on? Do you get any error? Are you sure you send data over the serial port? Are you using the correct COM port in your script?

      Delete
    2. ok, i compiled and downloaded the code, started your script... woo hoo! it's working now... like magic, big thanks to you. :)

      Delete
  18. hi FlorinC, do you have any websites with code in VBS to capture data as they come? some kind of event handling? I found some info on Wscript but not making much headway

    ReplyDelete
    Replies
    1. Sorry man, I rarely wrote VBS, and this was the last one I wrote one.

      Delete
  19. It works fine but stops after just one line of data.

    How can it be made to run continually and how is data transmission stopped

    ReplyDelete
  20. Sorry, it actually saved two lines of data - this would be very helpful if it can save until manually stopped

    ReplyDelete
  21. Hello Everybody,

    I am saving the .csv file thru a Processing code.
    In the same line, I have the date, and then the Temperature value, something like:

    05-01-2014 25
    05-01-2014 26

    and so on.

    I am having a hard time to make excel read this spaced information in 2 different columns... I tried with a "," between the values, also with more spacing like " ", but excel is still reading the file in the single column.

    Any advice concerning my issue? Thanks much!

    ReplyDelete