Shop OBEX P1 Docs P2 Docs Learn Events
I would like to see examples of formats as to how people update varaibles via serial? — Parallax Forums

I would like to see examples of formats as to how people update varaibles via serial?

turbosupraturbosupra Posts: 1,088
edited 2014-09-29 11:32 in Propeller 1
Is the most efficient way to have a case statement for every variable I would like to update and to hard code all of their names into the case statement expressions?

Same question for a "send all values" type of command. I'd like to see good form examples and learn from that.

Without knowing the most efficient way, that does not seem like it.

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-09-29 07:39
    turbosupra wrote: »
    Is the most efficient way to have a case statement for every variable I would like to update and to hard code all of their names into the case statement expressions?

    Same question for a "send all values" type of command. I'd like to see good form examples and learn from that.

    Without knowing the most efficient way, that does not seem like it.

    I have to state the obvious here, if it's written in Forth then you always have access to all the routines and variables etc etc by name etc etc.

    To change the variable "speed"
    25 speed !

    To read the variable "speed"
    speed @ .

    To increment the variable "speed" by 5
    5 speed +!

    To write a "macro" that takes an increment value and limits it to 100
    : SPEED+ ( n -- ) speed @ + 100 MIN speed ! ;

    To use the new "macro"
    5 SPEED+


    Oh sorry, if it's not in Forth you'll have to do it the hard way.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-29 07:50
    Assuming your application has a fixed number of variables, assign them numbers that your host and embedded applications understand. In your serial data you would include the register number and the new value. You probably want to have a protocol and methods that supports writing and reading values.
    pub write_reg(reg, value)
    
      case reg
        0 : return (red := value)
        1 : return (green := value)
        2 : return (blue := value)
    
      return BAD_REG 
    
    
    pub read_reg(reg)
    
      case reg
        0 : return red
        1 : return green
        2 : return blue
    
      return BAD_REG
    


    Using case like this allows you to create register numbers that have meanings. If you want to have a simple, contiguous block of values (starting at 0) and your variables are all the same type, you can do something like this -- though I don't recommend it because it's not easy to follow.
    firstVariable[idx] := value
    


    Again, this assumes a 0-based index, that your variables are all the same type (e.g., longs), and that they appear in the listing in numeric order.
    var
    
      long  red
      long  green
      long  blue
    


    You can set the blue value like this:
    red[2] := 255
    


    It works, but is not as easily followed (by others, or when you come back to it later) as the methods above.

    Your biggest challenge may be protocol. What are you using? Sounds like you want a variable-length protocol if you want the ability to set all values with one call.
  • Mike GreenMike Green Posts: 23,101
    edited 2014-09-29 08:21
    What's the application? What sort of variables do you want to update and under what circumstances? Is someone typing the changes? Is it another program that's communicating?

    Jon's scheme is good when another program is sending the data, but a person may have problems remembering the register numbers if there are more than a few. It's not hard to set up a name table and search that for a typed name to get an entry number that you can then handle like Jon's register numbers. The names can be easy to remember. FemtoBasic uses a scheme like this for the Basic keywords. It takes each name in a program line, searches a table of string constants, and substitutes the number of the table entry if one is found.
  • turbosupraturbosupra Posts: 1,088
    edited 2014-09-29 08:47
    I'm not sure what protocol I should be using.

    I would like to update longs and bytes, both numeric, string and boolean values. It will probably be by hand through the terminal and not through another program. I have a protocol that uses variablename=value, and splits the two based on the equals sign delimiter into a prefix and suffix. I would like to have it recognize the prefix and then set the prefix to the suffix. I posted for help in hopes of learning to do it the industry standard way, rather than whatever I could think of. I believe this is similar to what Jon is describing with the reg routines.

    I've ran into an issue now where I can't set something to True or False through my code and the terminal. I can set it to 0 or 1, and when I print a variable set to true or false it will print out through the terminal .dec(variablename) as a 0 or 1 to represent true or false, but I can't set variablename=false or variablename=true, through the terminal.

    Is it possible at different times, to set [long testEcho] to 0, to 739350, to true, to false and to "test" ?

    PUB variableUpdator(preAddr, sufAddr) | localIndex, pstVariableUpdator  
    
      ' Initialize variables here      
      localIndex := 0
      pstVariableUpdator := 0
      debug.str(preAddr)
      debug.tx(13)
      debug.str(sufAddr)
      debug.tx(13)
    
      case -1
        (strcomp(preAddr, string("testEcho"))) :
          if strcomp(sufAddr, string("echo"))
            debug.tx(13)
            debug.str(string(" ***** "))
            debug.str(preAddr)
            debug.str(string(" := "))
            debug.dec(testEcho)
            debug.str(string(" ***** "))
            debug.tx(13)
    
          else
            testEcho := sufAddr
            debug.str(string(" ***** "))
            debug.str(preAddr)
            debug.str(string(" is now set to "))
            debug.dec(testEcho)
            debug.str(string(" ***** "))    
    
        other :
            debug.str(string("Default failed"))
            debug.tx(13)
    
    
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-29 09:20
    I've attached a very simple demo of sending values to the Propeller using a serial connection. The demo is through a terminal (PST), but it could have been from an application. This demo uses a string that starts with ">" when then host is sending a command to the Propeller, and ends in [CR]. When the Propeller responds to the host, the header is "<". In either case, fields are separated with commas (like GPS), and are decimal values. Again, this is meant to be simple to get you started.

    Mike has a valid point: you have to remember the register number. I'm out of time today, but tomorrow will update the demo that lets you provide register names -- if that would be valuable. If you don't have a lot of registers, it's really not worth the effort.


    Edit: It looks like you posted while I was creating a demo graphic to show you the interaction of my code
    I can't set something to True or False through my code and the terminal.

    Remember that Spin treats any non-zero value as true. If you want to promote any value to true (-1), you can do it like this:
    myvalue := (myvalue <> 0)
    


    The demo I attached only deals with values, though the type doesn't matter because due to the use of write_reg(). You could modify this for booleans (which should be stored as longs). Strings are another matter. It's possible, but is quite a bit more involved. I would suggest an "S" command that included a string index.
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-29 09:22
    You would need to interpret the right side of the expression to determine whether it is a number or a symbol, such as true or false. For a number you would just convert it to a value and store it in your variable. For a symbol you would need to determine if the symbol matches "true" or "false", and then set it to a value of 1 or 0. This assumes you are using a value of 1 for true, and not -1, which is what Spin uses for true.
  • turbosupraturbosupra Posts: 1,088
    edited 2014-09-29 10:35
    Actually this was very useful, so thank you for taking the time to post it.

    With this
    myvalue := (myvalue <> 0)
    
    I wasn't sure if that was a syntactical spin trick that I didn't know about or a shorthand way of saying you can set it to anything other than 0. I tried it in a small demo program and the value still printed out as 0. Can I set it to a 1, or is that bad form? From what you and Dave explained, it sounds like spin says if ( x == 0 ) and if ( x <> 0 ) are the ways it evaluates for true and false?

    I tried setting a variable := false to variable := 1 (with a wait so it could report on both states) and it did not work, it stayed false. I then tried setting a variable := false to variable := -1 (with a wait so it could report on both states) and it worked.


    JonnyMac wrote: »
    I've attached a very simple demo of sending values to the Propeller using a serial connection. The demo is through a terminal (PST), but it could have been from an application. This demo uses a string that starts with ">" when then host is sending a command to the Propeller, and ends in [CR]. When the Propeller responds to the host, the header is "<". In either case, fields are separated with commas (like GPS), and are decimal values. Again, this is meant to be simple to get you started.

    Mike has a valid point: you have to remember the register number. I'm out of time today, but tomorrow will update the demo that lets you provide register names -- if that would be valuable. If you don't have a lot of registers, it's really not worth the effort.


    Edit: It looks like you posted while I was creating a demo graphic to show you the interaction of my code



    Remember that Spin treats any non-zero value as true. If you want to promote any value to true (-1), you can do it like this:
    myvalue := (myvalue <> 0)
    


    The demo I attached only deals with values, though the type doesn't matter because due to the use of write_reg(). You could modify this for booleans (which should be stored as longs). Strings are another matter. It's possible, but is quite a bit more involved. I would suggest an "S" command that included a string index.
  • JonnyMacJonnyMac Posts: 9,105
    edited 2014-09-29 11:07
    I tried setting a variable := false to variable := 1 (with a wait so it could report on both states) and it did not work, it stayed false.


    I can only assume you made a mistake in your test code. I verified (though I've used this syntax many times):
    myvalue := (myvalue <> 0)
    


    before posting -- it works as intended (promotes any non-zero value to true [-1]). It's a cleaner way of doing this:
    if (myvalue <> false)
        myvalue := true
    


    Remember that Spin evaluates Boolean expressions as true (-1) or false (0)
  • Dave HeinDave Hein Posts: 6,347
    edited 2014-09-29 11:23
    turbo,

    I've attached the setup utility that I use in spinix to change variable values in the EEPROM. This is similar to the type of thing you are trying to do. Maybe it will help to see how I did it for my application.

    Dave
  • turbosupraturbosupra Posts: 1,088
    edited 2014-09-29 11:30
    I had to have made a mistake, I will try again.

    Thanks Jon. I wrote this a few minutes ago as an idea from your previous post and now reading your most recent post, it looks like I was close?
        (strcomp(preAddr, string("testEcho"))) :
          if strcomp(sufAddr, string("echo"))
            debug.tx(13)
            debug.str(string(" ***** "))
            debug.str(preAddr)
            debug.str(string(" := "))
            debug.dec(testEcho)
            debug.str(string(" ***** "))
            debug.tx(13)
    
          elseif strcomp(sufAddr, string("toggle"))  
            if (testEcho == true)
              testEcho := false   
            elseif (testEcho == false)
              testEcho := true
              
            debug.str(string(" ***** "))
            debug.str(preAddr)
            debug.str(string(" is now set to "))
            debug.dec(testEcho)
            debug.str(string(" ***** "))
            debug.tx(13)  
    
          else
            testEcho := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010)    
              
            debug.str(string(" ***** "))
            debug.str(preAddr)
            debug.str(string(" is now set to "))
            debug.dec(testEcho)
            debug.str(string(" ***** "))
            debug.tx(13)   
    
    
  • turbosupraturbosupra Posts: 1,088
    edited 2014-09-29 11:32
    Yeah this is cool, thank you. It covers things I would like to do in the future. :)
    Dave Hein wrote: »
    turbo,

    I've attached the setup utility that I use in spinix to change variable values in the EEPROM. This is similar to the type of thing you are trying to do. Maybe it will help to see how I did it for my application.

    Dave
Sign In or Register to comment.