Shop OBEX P1 Docs P2 Docs Learn Events
Access Windows CSV files from a Prop — Parallax Forums

Access Windows CSV files from a Prop

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
edited 2013-04-04 08:11 in Propeller 1
Attached is a project I've been working on for the past week. It's a Propeller object and a companion Windows PC program that allows Propeller programs to read and write CSV files on the PC. The PC program acts as a server for the Propeller program, running as a client via a serial connection (using FullDuplexSerial). With this facility, a Propeller program can create, append to, and read from CSV files on the PC, using strings, integer, fixed-point, and floating-point data. For safety, the files must all be rooted in a named subdirectory of any file device's root directory and not the root directory itself, but the Propeller program can create any number of subdirectories of that directory. (If you happen to choose "c:/Windows/system32" or somesuch, the consequences are your own fault. I bear no responsibility for stupidity. :) )

Here's a screen capture of the server program in action:
attachment.php?attachmentid=84976&d=1315715623

There are only two things to specify: the active directory and the serial port. Once these are specified, the enable button can be pressed and file transfers can begin. Pressing the Enable button will reset the Propeller, so you will need to have your program saved in EEPROM to use this system.

Documentation for the Propeller client object is embedded in the source code and is AutoDoc (Gold Standard) compatible. See this link for access to the AutoDoc facility:

The demo program exercises most of the client's features, and you should read over it, run it, and understand what's going on before writing your own programs.

Questions and comments, as always, are welcome!

-Phil

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2011-09-10 21:53
    Phil,

    This is great!

    Several times a day I need to access files from my Prop data logger. Normally I move a SD card from the Prop to the PC. This should free me from the need of stopping data collecting in order to transfer information to the PC.

    I'll try it out (probably tomorrow) and let you know what I think.

    Thanks,

    Daune
  • idbruceidbruce Posts: 6,197
    edited 2011-09-10 22:26
    Phil

    I have not tested it, but I am sure it works :)

    Anyhow, good job, and I am sure a lot of people will find this useful!

    Bruce
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2011-09-10 23:01
    Really slick Phil! Thanks for this.

    OBC
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-09-11 16:39
    Thanks, guys! I've updated both the client and server to v.0.91. On the server side, I discovered that the four bytes representing negative integers and fixed-point numbers were being unpacked and written to the file as unsigned numbers. There was also an issue with round-off for the fixed-point data. These issues have now been fixed. I've also added a "halt" instruction to the server which is sent when the object's stop method is called. This will close all files, and put the server in the "disabled" state, which eliminates having to do this by hand to free the port for uploading new programs to the Propeller chip. It also provides a nice visual indication of when all file data transfers have been completed.

    -Phil
  • idbruceidbruce Posts: 6,197
    edited 2011-09-11 16:44
    Sounds like some nice updates.

    I will have to set aside some time to check it out.

    Bruce
  • ElectricAyeElectricAye Posts: 4,561
    edited 2011-09-11 16:55
    Interesting!

    For some data acquisition projects, this might eliminate the SD card altogether.

    Thanks, Phil!
  • SarielSariel Posts: 182
    edited 2011-11-09 07:44
    Interesting!

    For some data acquisition projects, this might eliminate the SD card altogether.

    Maybe send the data with a pair of XBees, and call it a day. Boy, this would be nice to have. Will have to archive this stuff, just in case the need arises.
  • RussMRussM Posts: 27
    edited 2013-03-21 09:11
    Attached is a project I've been working on for the past week. It's a Propeller object and a companion Windows PC program that allows Propeller programs to read and write CSV files on the PC. The PC program acts as a server for the Propeller program, running as a client via a serial connection (using FullDuplexSerial). With this facility, a Propeller program can create, append to, and read from CSV files on the PC, using strings, integer, fixed-point, and floating-point data. For safety, the files must all be rooted in a named subdirectory of any file device's root directory and not the root directory itself, but the Propeller program can create any number of subdirectories of that directory. (If you happen to choose "c:/Windows/system32" or somesuch, the consequences are your own fault. I bear no responsibility for stupidity. :) )

    Here's a screen capture of the server program in action:
    attachment.php?attachmentid=84976&d=1315715623

    There are only two things to specify: the active directory and the serial port. Once these are specified, the enable button can be pressed and file transfers can begin. Pressing the Enable button will reset the Propeller, so you will need to have your program saved in EEPROM to use this system.

    Documentation for the Propeller client object is embedded in the source code and is AutoDoc (Gold Standard) compatible. See this link for access to the AutoDoc facility:
    The demo program exercises most of the client's features, and you should read over it, run it, and understand what's going on before writing your own programs.

    Questions and comments, as always, are welcome!

    -Phil

    Hi Phil! I am trying to implement your program to modify CSV files on a windows pc and I am having some issues. I am using a propeller demo board connected to my PC using the serial port on the demo board. I have your server program running and when I try to run the client program I keep getting an error of "unable to acess com3", even though my demo board is on and connected to my pc. Would you know why this is happening? Thank you!
  • Duane DegnDuane Degn Posts: 10,588
    edited 2013-03-21 09:24
    RussM wrote: »
    when I try to run the client program I keep getting an error of "unable to acess com3"

    You need to make sure the com port setting matches the same port as the one used by the Prop Tool to communicate with your Demo Board.

    When you press F7 from the Prop Tool which com port does it use? You'll want to use this same port in Phil's program.
  • RussMRussM Posts: 27
    edited 2013-03-21 09:34
    Duane Degn wrote: »
    You need to make sure the com port setting matches the same port as the one used by the Prop Tool to communicate with your Demo Board.

    When you press F7 from the Prop Tool which com port does it use? You'll want to use this same port in Phil's program.

    I am using COM3. What I don't understand is that when Phil's server program is running I am unable to detect COM3 which is keeping me from compiling my client program.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-03-21 10:40
    Russ,

    Is the server program disabled when you try to compile and load the client? If not, you need to do so first. Two programs cannot claim the serial port at the same time.

    -Phil
  • RussMRussM Posts: 27
    edited 2013-03-21 12:13
    Phil,

    I should have known that you can't have two programs on the serial port at once. I have the whole thing figured out now. Excellent program. Thank you~

    Edit: I ran into an issue that maybe you could help me with Phil. I tried a simple example of just creating a file and everything works fine.
    CON
    
    
      _clkmode      = xtal1 + pll16x
      _xinfreq      = 5_000_000
    
    
      APIN          = 0
      BPIN          = 1
    
    
    OBJ
    
    
      csv   : "csv_file_client"
    
    
    VAR
    
    
      byte read, write[2]
      
    PUB  start | i, ltr
    
    
      csv.start
      write := csv.open_write(string("Something.csv"))
    

    However, when I try to implement it in my program it does not work. In my program everything after the csv.start command seems to not compile. I tried moving around the csv commands within my code to try and get it to work but to no avail. Am I missing something?
     
    
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      '_xinfreq = 6_250_000
      
      TX_PIN = 0
      BAUD = 19_200
      MS_001 = CLK_FREQ / 1_000
      CLK_FREQ = ((_clkmode-xtal1)>>6)*_xinfreq
      
      LCD_PIN       = 27
      LCD_BAUD      = 19_200                                    
      LCD_LINES     = 4
      LCD_COLS      = 20
    
    
      ''Size Encoder A Channel(blue) = 1
      ''Size Encoder B Channel(yellow) = 2
      ''Angle Encoder A Channel(blue) = 4
      ''Angle Encoder B Channel(yellow) = 5
      ENCODER_CHANNELA_SIZE   = 1
      ENCODER_CHANNELA_ANGLE   = 4
    
    
    OBJ
      quad_size  :       "QuadDecoder"
      quad_angle  :       "QuadDecoder"
      LCD    :       "FullDuplexSerial"
      sio    :        "FullDuplexSerial"
      f32           : "F32"
      f32_orig      : "Float32Full"
      fs            : "FloatString"
      csv   :"csv_file_client"
    
    
    VAR
    
    
      long offset_size                                          ' example variable that will be accumulated to
      long offset_angle
      long distance
      long temp
      long distance_tick
      long f1
      long fA
      long angle
      long angle_tick
      byte cog
      long stack[90]
      byte highs[200]
      byte lows[200]
      long future_size
      long current_size
      long previous_size
      long detecthighpoint
      long detectlowpoint
      long k
      long j
      long index
      long index2
      long float_highs[200]
      long float_lows[200]
      byte read, write[2] 
    PUB start | i, ltr
    
    
      LCD.start(TX_PIN, TX_PIN, 00, 19_200)    'Initialize FullDuplexSerial.spin
      f32.start
      f32_orig.start
       
      csv.start
      write := csv.open_write(string("Data.csv"))
    
    
      quad_size.start(ENCODER_CHANNELA_SIZE, @offset_size)                    ' start the size encoder
      quad_angle.start(ENCODER_CHANNELA_ANGLE, @offset_angle)   
    
    
      LCD.tx($0C)
      LCD.tx($11)
     
    
    
        LCD.str(string("Size ="))
        LCD.tx($0D)
        LCD.str(string("Angle ="))
        LCD.tx($0D)
    
    
        distance_tick := 0.000983
        distance := 0.0
        angle_tick := 0.144
        angle := 0.0
        current_size := 0.0
        previous_size := 0.0
        detecthighpoint := 0
        detectlowpoint := 1
        k := 0
        j := 0
        offset_size := 0.0                                         ' initialize the accumulator
        offset_angle := 0.0
        index := 0
        
        repeat index2 from 0 to 199
          float_highs[index2] := 0.0
    
    
       repeat while (offset_angle < 2500)
          current_size := f32_orig.FMul(f32_orig.FFloat(offset_size), distance_tick)
          angle := f32_orig.FMul(f32_orig.FFloat(offset_angle), angle_tick)
    
    
          LCD.tx($87)
          LCD.str(fs.FloatToFormat(current_size,13,6))
          LCD.tx($9D)
          LCD.str(fs.FloatToFormat(angle,10,4))
             
          if (current_size < previous_size) AND (detecthighpoint == 1) '(previous size was a high)
            float_highs[i] := previous_size
            k++
            detectlowpoint := 1
            detecthighpoint := 0
          if (current_size > previous_size) AND (detectlowpoint == 1) '(previous size was a low)
            float_lows[i] := previous_size
            j++
            detecthighpoint := 1
            detectlowpoint := 0
               
        previous_size := current_size               
        waitcnt(clkfreq/100 + cnt)
    
    
      
      repeat index from 0 to (k-1) 
        csv.write_float(write, float_highs[index])
        {{LCD.tx($94)                           
        LCD.str(fs.FloatToString(float_highs[index]))
        LCD.tx($BC)
        LCD.str(fs.FloatToString(float_highs[index+1]))
        pause(2000)}}
    
    
      LCD.str(string("Wrote file"))
      pause(2000)
      LCD.tx($0C)
    
    
      csv.close_all 
      LCD.stop
      f32.stop                                             
      f32_orig.stop
      quad_size.stop
      quad_angle.stop
                         
    PUB pause(ms) | t 
     t := cnt 
     repeat ms 
      waitcnt(t += MS_001)     
    
    
    
    
    
  • Cluso99Cluso99 Posts: 18,066
    edited 2013-03-21 15:39
    phil, missed thisbefore. what agreat program, a real gem.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2013-03-21 15:54
    Russ,

    The server has to be running and enabled for your program to get past the csv.start.

    -Phil
  • Cluso99Cluso99 Posts: 18,066
    edited 2013-03-21 19:56
    Phil,
    I was looking at AutoDoc website but could not find the AutoDoc Gold Standard specs. Perhaps you might like to place a link on your webpage for this?

    For others, here is the link
    http://forums.parallax.com/showthread.php/127233-Automatic-Spin-Program-Documenter-(Online-version-now-available)?highlight=autodoc
  • RussMRussM Posts: 27
    edited 2013-04-04 08:11
    Hi Phil,

    I have a quick question. Is there any way to insert a carriage return in a CSV file so two sets of data are printed in two separate rows? Something like the following:
      repeat index3 from 0 to i 
        csv.write_float(write, float_highs[index3])
    
    
     'Have next set of data write to next row
      
      repeat index5 from 0 to i
       csv.write_float(write, float_angles[index5])
    
Sign In or Register to comment.