Shop OBEX P1 Docs P2 Docs Learn Events
Unable to Extract Data from a String and Save to Variables — Parallax Forums

Unable to Extract Data from a String and Save to Variables

jmmb392jmmb392 Posts: 22
edited 2016-08-23 23:46 in Propeller 1
Dear forum,

I am having problems extracting data from a string. For example, I have the following string:
input := string"486,21,786,45561,.....,5444,12,7666"

Where every value between a comma "," is a reading from a sensor and I have to store it in variables so it would be like

sensor1 := 486
Temp1 := 21
sensor2 := 786
.
.
sensorn := 7666

Now, any suggestions in how to extract the values from the string and save them into variables?


This is the code that I have so far:
CON                          
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
 
VAR
  byte  databuffer[100]  
  
OBJ
  
  pst     :   "Parallax Serial Terminal"
  nums    :   "Simple_Numbers"
  str     :   "STRINGS2"
PUB Start | index, index2, input, length, packet_length


pst.start(9600)

''Example string
input := string("1254,23,7854,2111,112,")

length := strsize(input)
packet_length := length

pst.Str(String("Input string format = "))
pst.str(input)
pst.newline

databuffer[length] := ","
repeat index from length to 0
   databuffer[index - 1] := get_char(input, index - 1)

repeat while (index2 < packet_length)
   pst.char(databuffer[index2++])
   waitcnt(clkfreq / 10 + cnt)
pst.newline


pub get_char(p_str, n)

'' Returns nth character from str at p_str

  if (n < strsize(p_str))
    return byte[p_str][n]
  else
    return "?"                                                                

I am attaching the entire project as a zip file.

Thank you for your collaboration guys!!

Comments

  • So the "sensor" is sending you a comma delimited ascii string?

    You might consider running through the string replacing each comma as it is detected with a null ($00) to delimit it as the leftmost string at a "current string address" (see CLIB101 in the OBEX for a set of semi-standard C string manipulation functions), then decimalize it (see Simple Numbers also in the OBEX). Thereafter update the "current string address" by the length of the string last processed and repeat until out of data.

    Not sophisticated but it will work.

  • I do a lot of command parsing so I wrote my own strings library (based on work by others plus my own bits) to support it. I whipped up a demo based on your test string -- it works. The code should be pretty easy to follow.
    dat
    
      TestStr       byte    "486,21,786,45561,5444,12,7666", 0                                                          
                                                                     
                                                                     
    pub main | idx, p_field                                                        
                                                                     
      setup
    
      term.rx                                                       ' open PST, enable, press a key
      term.tx(term#CLS)
    
      fields := str.fields(@TestStr, ",")
      term.str(string("Fields = "))
      term.dec(fields)
      repeat 2
        term.tx(13)
    
      repeat idx from 0 to fields-1
        p_field := str.field_pntr(@TestStr, idx, ",")
        param0[idx] := str.asc2val(p_field)
        term.str(string("param"))
        term.tx("0" + idx)
        term.str(string(" = "))
        term.dec(param0[idx])
        term.tx(13)
    
  • JonnyMac wrote: »
    I do a lot of command parsing so I wrote my own strings library (based on work by others plus my own bits) to support it. I whipped up a demo based on your test string -- it works. The code should be pretty easy to follow.
    dat
    
      TestStr       byte    "486,21,786,45561,5444,12,7666", 0                                                          
                                                                     
                                                                     
    pub main | idx, p_field                                                        
                                                                     
      setup
    
      term.rx                                                       ' open PST, enable, press a key
      term.tx(term#CLS)
    
      fields := str.fields(@TestStr, ",")
      term.str(string("Fields = "))
      term.dec(fields)
      repeat 2
        term.tx(13)
    
      repeat idx from 0 to fields-1
        p_field := str.field_pntr(@TestStr, idx, ",")
        param0[idx] := str.asc2val(p_field)
        term.str(string("param"))
        term.tx("0" + idx)
        term.str(string(" = "))
        term.dec(param0[idx])
        term.tx(13)
    

    Dear JonnyMac,

    Thank you for your response, it was really helpful Let me show you my approach, I created a loop so that I can receive n amount of variables, as long as it is within 100 bytes. I am using two objects that contain methods for string manipulation, but when I save the values, I get the wrong results. Please check the code below, I am also attaching my entire project. Thank you for your help!
    CON                          
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    OBJ
    
    pst : "Parallax Serial Terminal"
    XB  : "Xbee_Object V2.0"
    str : "STRINGS2"
    nums : "Simple_Numbers"
    str2 : "ASCII0_STREngine_1"
    VAR
    byte  databuffer[100]
    PUB Main      | ptr, lsb, msb, og, length, index, index2, output[5], offset, lsb2
    pst.start(9600)
    og := string("123,4114,2,551,23,")
    length := strsize(og)
    pst.Str(String("Packet received = "))
    pst.Str(og)
    pst.newline
    pst.Str(String("Packet length = "))
    pst.dec(length)
    pst.newline
    pst.Str(String("Initial offset = "))
    pst.dec(offset)
    pst.newline
    pst.newline
    pst.newline
    
    '' Creating loops to manage any string packet size
    
    repeat index from length to 0
       databuffer[index - 1] := get_char(og, index - 1)
    
    
    repeat 5                    '' I should know in advance how many variables
                                '' to receive, in this case it is 5
    
        offset := str.charpos(og, ",", offset, length) 
        pst.Str(String("Comma location = "))
        pst.dec(offset)
        pst.newline
        lsb := offset - 1
        repeat index2 from msb to lsb
          output[ptr] := str2.buildstring(databuffer[index2])
          output[ptr] := str2.builtstring(output[ptr])
        msb :=  offset + 1
        
        pst.str(output[ptr])    '' This should print each reading in its variable'                   
        ptr++                   '' output[0]=123, output[1]=4114, and so on, but it does not
        pst.newline
        pst.str(og)             '' Printing packet again just to check if it did
        pst.newline             '' not change
        pst.newline
        waitcnt(clkfreq + cnt)
    ''''''''''''''''            '' Printing again to double check! 
    pst.newline
    pst.str(output[0])                    
    pst.newline
    pst.str(output[1])                    
    pst.newline
    pst.str(output[2])                    
    pst.newline
    pst.str(output[3])                    
    pst.newline
    pst.str(output[4])                    
    
    pub get_char(p_str, n)
    
    '' Returns nth character from str at p_str
    
      if (n < strsize(p_str))
        return byte[p_str][n]
      else
        return "?"  
                               
    
  • Wait. I'm confused. I gave you working code (using just ONE string library), and yet you want me to look at your broken code? Did you actually run the demo that I uploaded? I attached the project archive so you would have access to the actual code plus my strings library.

  • MikeDYurMikeDYur Posts: 2,176
    edited 2016-08-25 13:18
    Thanks for posting Jon, I know a prize when I get one.
  • JonnyMac wrote: »
    Wait. I'm confused. I gave you working code (using just ONE string library), and yet you want me to look at your broken code? Did you actually run the demo that I uploaded? I attached the project archive so you would have access to the actual code plus my strings library.

    Hi JonnyMac,

    I have been out because I was hospitalized due to a UTI, but I guess I am used to it since I am quadriplegic. I wanted to take the time to thank you for your code, I included it in my code and it worked perfectly, I have problems when I transfer float values, but it is ok. I shared my code with you not because I wanted you to correct it, but because I wanted to share my beginner's work. Now, I was finally capable of:

    - Reading the infrared pulses from a power meter.
    - Measure current, voltage, rms current, rms voltage and power factor of the 3 phases of the power meter (mcp3208 a2d converter for the sensors)
    - Time stamp the data with a ds1307.
    - Store values in a SD card.
    - Finally send the data wirelessly thru a Zigbee API mesh network, and receive it in the coordinator side.

    One again, thank you for your collaboration!!
  • I'm glad I could help, and -- more importantly -- that you're no longer in the hospital. Continued good health, and happy coding!
Sign In or Register to comment.