Menu

HSerPrint in a subroutine has a strange behaviour

2017-10-26
2017-10-26
  • Giuseppe D'Elia

    Giuseppe D'Elia - 2017-10-26

    I have a strange problem when using HSerPrint within a sub.
    The code is reported in the following.
    The first HSerPrint in the sub prints the expected characters: 13,10,"prova",13,10
    The second call prints the expected characters: received=
    The third call prints the unexpected characters: received=
    It seems that the instruction HSerPrint "received=" destroy the content of the local variable Strin_in and substitute the previous content with received=
    It is this a normal behaviour of the compiler?
    Sorry for the question, I'm new to GCBASIC.
    Thanks

    #chip 18F886, 16
    #option explicit
    
    ; ----- Define Hardware settings
      Dir PORTC.6 Out   'Tx = Pin 17
      Dir PORTC.7 In    'Rx = Pin 18
      'Config UART
      #define USART_BLOCKING
      #define USART_BAUD_RATE 9600
      #config OSC=HS
      sckp=1
    
      printing("13,10,""prova"",13,10")
    
      sub printing(Strin_in as String)
    
      Dim Strin_in as String *30
    
      HSerPrint strin_in
      HSerPrintCRLF
      HSerPrint "received="
      HSerPrintCRLF
      HSerPrint strin_in
    
      end sub
    
     
  • mmotte

    mmotte - 2017-10-26

    Guiseppe,

    I have repeated the unexpected results.

    It is like the HSerPrint's string input is overwriting Your "printing" sub's input string.

    Actually any string use of HSerPrint is over writing the Sub's input string.

    #chip 16F886, 8
    #option explicit
    
    ; ----- Define Hardware settings
      Dir PORTC.6 Out   'Tx = Pin 17
      Dir PORTC.7 In    'Rx = Pin 18
      'Config UART
      #define USART_BLOCKING
      #define USART_BAUD_RATE 9600
      '#config OSC=HS
      'sckp=1
      'Dim Strin_in as String *30
      Dim myString as string
      wait 5 sec
      HSerPrint "testing"
      HSerPrintCRLF
      Do
      printing("13,10,""prova"",13,10")
      wait 5 s
      loop
    
      sub printing(In Strin_in as String)
        mystring = strin_in
      HSerPrint "begin"
      HSerPrintCRLF
    
      HSerPrint Strin_in
      HSerPrintCRLF
      HSerPrint "received="
      HSerPrintCRLF
      HSerPrint Strin_in
    
      HSerPrintCRLF
      HSerPrint myString
      HSerPrint "end"
      HSerPrintCRLF
      HSerPrintCRLF
      end sub
    

    gives the output below , where the " HSerPrint "begin"" overwrites even the first use of "Srin_in" variable in the next "HSerPrint Strin_in" command
    Strin_in can be store in another string variable and used later.

    begin
    begin
    received=
    received=
    13,10,"prova",13,10end
    

    I don't know the solution.

    BR
    Mike

     
  • William Roth

    William Roth - 2017-10-26

    Same results here.

    It looks like the input string is getting overwritten.

    We need to know what version of Great Cow Basic you are using.

     
  • William Roth

    William Roth - 2017-10-26

    In the mean time the code below shows a workaround that tests ok here.

    #chip 18F886, 16
    #config OSC=HS
    
    #option explicit
    
    ; ----- Define Hardware settings
    Dir PORTC.6 Out   'Tx = Pin 17
    Dir PORTC.7 In    'Rx = Pin 18
    'Config UART
    
    #define USART_BLOCKING
    #define USART_BAUD_RATE 9600
    
    sckp=1 'invert serial
    
    MAIN_LOOP:
    DO
       printing("13,10,""prova"",13,10")
       wait 1 s
    Loop
    
    Sub printing(IN Tmp_Str as String)
    
         Dim Strin_in as string
         Strin_in = tmp_str
    
         HSerPrint strin_in
         HSerPrintCRLF
         HSerPrint "received="
         HSerPrintCRLF
         HSerPrint strin_in
         HSerPrintCRLF 2
    end sub
    
     
  • Giuseppe D'Elia

    Giuseppe D'Elia - 2017-10-27

    Hi all,
    ok with the workaround.
    Another one is to first define a String variable in the main, say String_var,
    assign String_var="13,10,""prova"",13,10" and call the subroutine as printing(String_var).
    Anyway, as I told, I'm new to GCBASIC so I downloaded it very recently and, till now, I believed to have the last version.
    I dont know how to read the version.

    In the hystory file, the first raws of concern are:
    2015-11-22
    - Renaming all '@' signs with '+' in G+Stools filenames.....

    in the about of the GCBASIC Help I read
    SynWrite
    6.22.2290
    It is possible to understand if my GCBASIC version is actually the last one?
    Many thanks

     
  • Giuseppe D'Elia

    Giuseppe D'Elia - 2017-10-27

    I apologize for the inconvenience.
    In the version file of GreatCowBasic directory is reported
    27/09/2017:v0.98.00
    Accordingly, I should have the last version.

     
  • Anobium

    Anobium - 2017-10-27

    @Giuseppe D'Elia

    Hello,

    Regarding your first post. My review.
    1. Does not compile. So, I guess the chip was meant to be a 16f886
    2. #config OSC=HS is not needed. As the compiler should handle this for you.
    3. This is not the string you need. "13,10,""prova"",13,10". This is processed as follows:

      retlw 49  ;1
      retlw 51  ;3
      retlw 44  ;,
      retlw 49  ;1
      retlw 48  ;0
      retlw 44  ;,
      retlw 34  ;"
      retlw 112 ;p
      retlw 114 ;r
      retlw 111 ;o
      retlw 118 ;v
      retlw 97  ;a
      retlw 34  ;"
      retlw 44  ;,
      retlw 49  ;1
      retlw 51  ;3
      retlw 44  ;,
      retlw 49  ;1
      retlw 48  ;0 
    

    A string tha this 19 chars long with the CR and LF handles as 4 chars.

    You need to use string concatentation and adapt you code as shown below.

    chr(13)+chr(10)+"prova"+chr(13)+chr(10) but you will need to complete the string concatentation before the call to the method.

    As follows:

       dim mystring as string
       dim myCRLF as string * 2
       myCRLF = CHR(13)
       myCRLF = myCRLF + CHR(10)
       mystring =  myCRLF + "prova"
       mystring =  mystring + myCRLF
    
       printing( mystring )
    
      sub printing(Strin_in as string)
    
      HSerPrint strin_in
      HSerPrintCRLF
      HSerPrint "received="
      HSerPrintCRLF
      HSerPrint strin_in
    
      end sub
    

    String concatentation of a function, such as CHR() is handled one per line of code. A better error message would help in the future but the compiler is doing what i would expect.

    Hope this helps.

     
  • William Roth

    William Roth - 2017-10-27

    Evan,

    I think your analysis/conclusion (#3) is based upon the asumption that the OP intends to execute the CR's and LF's included within the input string ("13,10,""prova"",13,10"). I did not make that assumption. I assumed that he actually intended to print/display ==> 13,10,"prova".13,10.

    We need for Giuseppe to clarify and explain what he expected to see at the serial terminal.

    Regardless, the bigger issue is that the string passed into the sub routine is being clobbered by "received="

    The code below better shows the problem:

    'Chip Settings.
    #chip 18f25k42, 16
    #option Explicit
    #config mclr=on, LVP=on
    
    #startup InitPPS, 85
    
    'Setup Serial port
    #define USART_BAUD_RATE 9600
    #define USART_BLOCKING
    #define USART_TX_BLOCKING
    
    Wait 500 ms
    
    Do
        String_Print_Test("Hello World")
        wait 1 s
    Loop
    
    sub String_Print_Test(IN In_String as String)
    
        HSerPrint In_String    ' should show Hello World at terminal
        HSerPrintCRLF          ' should move to start of next line
        HSerPrint "Great Cow"  ' should show Great Cow at terminal
        HserprintCRLF          ' should move to next line
        HSerPrint In_String    '  should print Hello World
        HSerPrintCRLF 2        ' Skip 2 lines
    
       '********** expected at terminal **********
       'Hello World
       'Great Cow
       'Hello World
    
       '**** actually seen at terminal ****
       'Hello World
       'Great Cow
       'Great Cow
    End sub
    
    Sub InitPPS
    
        'Module: UART1
         RC6PPS = 0x0013     'TX1 > RC6
         U1RXPPS = 0x0017    'RC7 > RX1
    
    End Sub
    

    The question is what happened to In_String?.

    How did In_String change from being "Hello World" to being "Great Cow" ?

    Bill

     

    Last edit: William Roth 2017-10-27
  • Hugh Considine

    Hugh Considine - 2017-10-27

    Hello all,

    I think this one may be due to the way string constants are passed to subroutines. On most chips, the string is copied into a temporary variable and then that temporary variable is passed to the subroutine. Here, it looks like the temporary variable is being reused where it shouldn't be.

    The workaround William posted would work because the temporary variable is copied into the new variable Strin_in before it is overwritten, and that is the best option for now. I will have to fix this in the compiler so that it stops trying to reuse the temporary variable while it is still in use.

    (The exception to "most chips" is the 16F1xxx series, where the string constant stored in the program memory can be directly accessed by the string functions in the compiler).

     
  • Giuseppe D'Elia

    Giuseppe D'Elia - 2017-10-27

    Hi all,
    I apologize for the mistake. In fact the PIC is The 16F886 as Anobium said, not the 18F886 as written in my first post.
    Really, my final goal is to use 13 and 10 to obtain a CR and a LF, respectively. However this does not concerns the code I submitted in my first post. I used the string "13,10,""prova"",13,10" just because it was quicly available in another code wherein the strange HSerPrint behaviour occurred. Accordingly, in my first post I was interested to just print "13,10,""prova"",13,10".
    However, thanks to you, I understund the compiler behaviour now.
    As a matter of fact I'm trying to develop a sub for printing an impredictable mixing of strings and numerical variables to speed up the printing effort and avoid a dense repetition of HSerPrint, HSerPrintCRLF, HSer Send and so on.
    Unfortunately I should be able to use a subroutine with a non fixed number of arguments and types (it is possible with GCBASIC? I think it is not) or, alternatively, to suitably manipulate a string.
    In particular, given the string vel_str="vel_var" and a byte variable named vel_var, the question is:
    it is possible, in some way, to use the string vel_str to print the value of the variable vel_var?
    Really I don't know. I have never written a compiler and maybe a compiler coding is required.
    Still thank you all for your attention

     
    • Anobium

      Anobium - 2017-10-28

      No problem.

      I am not sure how to advise. Serial printing will have some use of HserPrint but I am sure some of the clever folks reading this have good ideas. I use a TABLE sometimes - the TABLE has my string and I call the serial routine with pointers to the TABLE - this may work for you.

      :-)

       
  • kent_twt4

    kent_twt4 - 2017-10-28

    I would say once the GCB syntax is understood that it will give the user the tools to slice and dice the data whichever way one wants.

    To get further help more context is needed. The problem is not fully defined. Indeed parsing unknown number of ascii characters is possible "within limits". The limits are the devices amount of RAM available within the program.

    The big question is this is an investigation of unkown data stream from a particular device? If so then there is bound to be some sort of protocol. If the data stream is under control of the user then there should be no problem whatsoever.

     
  • Giuseppe D'Elia

    Giuseppe D'Elia - 2017-10-28

    Hi Anobium and Kent,
    as you will see in the following, the context to which I refer is really a non essential one, at the moment, although it could be of interest in more important problems.
    I will describe my case now.

    Because I'm learning GCBASIC and PIC programming, allowed by GCBASIC without the use of more "technical" languages (and I'm enjoing doing it), I would like to build a subroutine to print a sequence of strings and variables in an arbitrary order.
    This is to simplify the printing process that is usually unpredictable and frequently needed when code debugging. Sometimes is also annoying.

    A possible way could be to collect (in the required order) in a single String container, say STRING_in, the strings and names of the variables to be printed and then ito nvoke a subroutine with the single argument STRING_in.
    Strings and variable names could be separated by commas in STRING_in. The variables could be distinguished from the strings to be printed by pre-appending a standard, conventionally chosen character. Different characters could be used for byte, word and long variables, respectively.

    However, to follow this way I should be able to get the value of a variable, say VAR, from the string containing its name, say STRING="VAR".

    This need driven me to the second question in my last post.

    The table suggested by Anobium could be a good workaround, particularly when the code has been completed and you know all the prints you need, i.e., the variables, the CRLFs, the tabs, the strings (often used to refer to the printed variables) and so on.
    I can build the table and build a printing subroutine with the appropriate arguments. However if I want to use always the same subroutine I need a subroutine with a non fixed number of arguments and types. And this driven me to the first question in the previous post.

    This is a problem close to the one described by Kent and, furthermore, the "data stream" is under my control. However, I have not yet found the way to solve it with my (not full) knowledge of GCBASIC.

    Thenk you

     
  • kent_twt4

    kent_twt4 - 2017-10-28

    I think I had a similar problem when trying to parse .bmp data for the SD card? The method used was hinted at in my previous post. Different communication used as the SD card uses SPI communication. It involves parsing large amounts of data with similar but varying amounts of data. It is your data so you can sort data by prepending a flag if necessary like a 'b' for byte data, 'w' for word

    The solution to the problem was to read in blocks of data into a large buffer (512 in my case). There need not be parameters, although I needed a starting long address for my purposes. The buffer is now full of ascii chars that are then post processed into another large buffer that assembles all the variables while disregarding the comma's of the comma delimited values, line feed, carriage return etc., Then I printed that data out using HSerPrint, HSerPrintCRLF into a nice table.

    The use of strings can be used as flags in how the data is processed or formatted, like:

    'input stream
    t75,p3012,h55
    'output format
    Temp. 75f Press. 30.12in. Humidity 55%
    

    Again, not exactly what is asked for? but could be the way forward. In the end, a good amount of conditional testing is required, and possibly yet more subs to assemble the variables.

     
  • Giuseppe D'Elia

    Giuseppe D'Elia - 2017-10-29

    Hi Kent,
    yes, the problems are very symilar, altough not exactly the same. However, I think your answer helped me.

    Let we see if I understund.

    Let your first buffer of Ascii chars (the one to be post processed) be someting like:
    "temp,#75,Press.,##3012,in., Humidity ,#55,%"

    Then, post processing can understand that
    - temp is to be handled as a string,
    - #75 as a byte,
    - Press. as a string,
    -##3012 as a number with two decimals,
    -in. as a string,
    -Humidity as a string,
    -#55 as a byte,
    -% as a string.

    I agree, everyting is OK and you can print a nice table.

    Correspondingly, according to my question, my "buffer" of Ascii characters to be post processed (i.e., analysed by the printing subroutine) would be:

    " ""temp"",#temperature,""Press."",##Pression,""in."","" Humidity"",#Hum "

    wherein temperature, Pression and Hum are the names of the three variables containing the values of the temperature, Pression and Humidity to be printed.

    Here is the very difference between our problems:

    while your buffer (say string) contains the actual numerical values of temperature, pression and humidity, my string (say buffer) would contains the names of the variables containing the values of the temperature, pression and humidity.

    At the beginning of my question, I supposed that (and I asked if) it could be possible to recover the value of a (global) variable starting from the Ascii value of the NAME of the variable.

    However, you also suggested a possible answer to my question:
    my string must contain the (ascii) values of the variables I want to print, not the names of the variable itself. To this end I should use the STR GCBASIC command.

    And so, my string should be:

    " ""temp"",""#"" + STR(temperature),""Press."",""##"" + STR(Pression),""in."","" Humidity"",""#"" + STR(Hum) "

    I this will allow me to get a nice printing to.

    A final comment:
    obviously, one would ask if the effort to manage the printing in the way I want to follows is really justified, mainly from the MPU resource consuming point of view. I would agree it is not really justified, expecially on PIC with a small program memory.
    However, as I said, I'm learning and plaiyng and aiming to learn something new every days.
    I really thank you again.

     
  • kent_twt4

    kent_twt4 - 2017-10-29

    Giuseppe,

    Yes I believe you are well on your way to mastering GCB. Have fun, and check back in with the forum if you hit another speed bump.

     
  • Anobium

    Anobium - 2017-11-06

    The original issue of the string corruption in a subroutine should be fixed in all builds of the compiler after 5th Nov 2017. The following test program now works.

    #chip 16F886, 16
    #option explicit
    'Setup Serial port
    #define USART_BAUD_RATE 9600
    #define USART_BLOCKING
    #define USART_TX_BLOCKING
    
    Wait 500 ms
    
    Do
        String_Print_Test("Hello World")
        wait 1 s
    Loop
    
    sub String_Print_Test( In_String as String)
    
        HSerPrint In_String    ' should show Hello World at terminal
        HSerPrintCRLF          ' should move to start of next line
        HSerPrint "Great Cow"  ' should show Great Cow at terminal
        HserprintCRLF          ' should move to next line
        HSerPrint In_String    '  should print Hello World
        HSerPrintCRLF 2        ' Skip 2 lines
    
       '********** expected at terminal **********
       'Hello World
       'Great Cow
       'Hello World
    
       '**** actually seen at terminal ****
       'Hello World
       'Great Cow
       'Great Cow
    End sub
    
     

Log in to post a comment.