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/

40 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
    Replies
    1. Posting for anyone reading this in 2014!

      I was trying this in Windows 8 - apparently you can't create a txt file in C: Root. The solution is to create a folder and modify the folder path in your code. I changed line 8 to read:

      Set objFile = objFSO.OpenTextFile("C:\Users\M\Documents\Arduino\results\results.txt", ForWriting, True)

      Delete
  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
    Replies
    1. hi
      can you please share the code you have burnt on arduino before running above scripts so that arduino can receive the content of text file.
      thank you

      Delete
  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
    3. file is created but still get no data. Any help?

      Delete
    4. Baud rate is correct.
      Com port is also correct.
      Still the file is zero bytes. Help needed.

      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
  22. This comment has been removed by the author.

    ReplyDelete
  23. I have my Arduino connected to COM4 but when your .vbs is started it results a Line 12 permission denied error. If I change the script it works for COM3 but of course it not sending anything to my Arduino then. How is it that my Arduino is not receiving on its COM port. Everything is closed including serial monitor and computer was restarted just to be sure.

    Thanks for the advice.

    ReplyDelete
    Replies
    1. "Permission denied" means that the COM port is already in use. If Arduino IDE is running and/or the serial monitor is on, close them before running the VB script.

      Delete
    2. Thanks so much for the reply. Strange things indeed. I changed to different COM ports, then tried on another machine, with everything closed on a freshly booted machine and still get this permission denied error. I changed your script to point to the correct port ("COM7:9600,N,8,1", ForWriting) and still no luck. There is something am missing. I have simple code on Arduino to echo what comes in. Which works when I input manually but .vbs won't get past the permissions. The search continues.

      Delete
    3. Primary machine is Windows 7. 2nd machine is Windows 8.1.

      Delete
    4. I never tried the VB script on any windows higher than XP. Windows 7 and above have stricter security on everything, hardware and software components. Maybe you somehow need to have right for a VB script to access a COMP port? (It could just be a setting somewhere, I am just guessing). In any case, please let me know (post your conclusion here) if you find out. It will definitely help others too. Thanks in advance.

      Delete
    5. simply close arduino serial console or any other blocking serial communication windows.
      after that even win7 x64 is happy to let you use serials

      Delete
  24. very usefull
    and my extra bit of help

    1 use free-serial-analyzer to sniff serial packets and communication

    2 check simple cmd communication
    mode com7 Baud=9600 PARITY=n Data=8 Stop=1 dtr=off rts=off>null

    echo %1>//./com7
    ---------
    by default it adds CR+LF at the end
    3 try twice as first time serial port sets or initialized and nothing is received( its a big problem to overcome, thoughts are welcome)
    4 the above example does not send vbCR vbLF so add it manually if required by you arduino sketch
    com.Write("f"& vbCr&vbLF)

    so just sending data to serial cmd is enough,
    mode set is needed everytime

    ReplyDelete
  25. Dave cox can u tell me how to take data from arduino and save it to ms excel or word, I mean to save it in file?

    ReplyDelete
  26. If anyone knows how to save dat from arduini to a file.. Kindly tell me. Maddy.khan315@gmail.com

    ReplyDelete