Menu

Serial port Receive troubles

G. C.
2023-10-29
2023-11-16
1 2 3 > >> (Page 1 of 3)
  • G. C.

    G. C. - 2023-10-29

    Hi,

    This time I am trying to play with LCDs and serial ports.. I connected two PIC18F1220 in such a way that one sends continuosly a couple of strings to the serial port, put a wire fm it's TX line and the RX of the second one that should receive and print on a 16x2 LCD module those two strings..

    The LCD module and all trials of prints etc works fine, but if I put the command HSerGetString to read fm uart I am not able to get anything.. The transmitter should be working fine, I see the stream of the two strings on the output pin with an oscilloscope. Can't understand why the receiver does not work.

    Any help it's appreciated, thx.

    Attache here the two short source files..
    Rgds,
    GC

     
  • Anobium

    Anobium - 2023-10-29

    The issue here is the you are checking the receive buffer without checking whether new data has been received.

    There is a missing piece of the puzzle with USART handling in the Help but you can find in the demo extensively. This needs to be sorted in the Help.

    If USARTHasData Then
    HSerReceive(InData)
    .....

    If USARTHasData ( or USARTnHasData where is a number greater than 1 ) will test the interrupt flag. If the USART has data then the IF statement would proceed to read the incoming buffer.

    That said... you have not setup USART to have USART_BLOCKING constant defined. This would block the program until you have recieved USART data... so, if you want a non-blocking operating you would need #define USART_BLOCKING and the 'if USARTDATA then as shown above.

    Hope this helps.

     
  • G. C.

    G. C. - 2023-10-29

    Ok, I added the #USART_BLOCKING and then put a check on the If USARTHasData Then as follows:

     If USARTHasData Then 
              HSerGetString usart_input
      end if
    

    But still get no input from the Usart... I would like to read a string at a time, not a single character. I used the same listing as the example in the help file (for the HSerGetString command), but it does'nt work. The problem is surely onto the HSerGetString command, as removing it the rest of the flow is correct...

    Regarding the demos, are you referring to those at this link:
    https://github.com/Anobium/Great-Cow-BASIC-Demonstration-Sources/tree/master/Serial_Communications_Solutions

    Or there is somewhere else more stuff to look at? In those above I could not find any example with HSerGetString...
    Thx,
    GC

     
  • mmotte

    mmotte - 2023-10-29

    GC

    The documentation is at https://gcbasic.sourceforge.io/help/_hsergetstring.html

    Looks like it wants USART_BLOCKING so it can wait for the chars of the string and the return char 13 to end the string

    The example is in the help
    GL
    73
    Mike

     
    • G. C.

      G. C. - 2023-10-30

      thanks Mike,

      But as I said above, after the suggestion fm Anobium, I already added the #USART_BLOCKING statement..
      and also added the "If USARTHasData Then" command, that is not documented anywhere (at least I was not able to find it).

      Apart fm the #USART_BLOCKING define, my receiving algoritm was essentially the one of the help file.. On the 2nd UC, transmitter side, I used the HSerPrintStringCRLF command, so in the received string there should be present also a Carriage Return / Line feed block that terminates the incoming string.

      In the help example the CR is sent out, and I guess is not influent on the received string.
      It really seems that the HSerGetString command does'nt work. I must have missed something else.. But if all the examples present in the help are tested and true, then I really do not understand why my implementation does'nt work.

      Rgds,
      GC

       
  • Anobium

    Anobium - 2023-10-30

    GC, I think there may be a better approach.

    Why? The Transmitter is send a data stream every 1s or 2s ( depends on where is it in the program). And, the receiver is meant to read the data stream and stay in-sync whilst printing to the LCD and doing delays. The chance of this working is low. You may get some data through but you need a 100% realisable solution.

    A bit of history. In the old days we used to use XON-XOFF communications as of serial comms, or, we could use RTS/DTR. Both methods synchronised the serial transmissions. These extra signals would ensure the datastream in terms of sender and receiver where prepared. We cannot do this with a microcontroller ? Yes, you could use extra communications ports/lines but this means more connections between the microcontrollers.

    The way I would do this.

    1. Get a single char working from one to the other. This ensure the connectivity is good. I would implement the Buffer Ring ( see the Help ) in the receiver. So, when this is working you will be able to see the datastream on the LCD with delays etc. The size of the buffer may have to large to handle the delays you have. as the transmitter will be pushing data out during your delays, but, the Ring Buffer will take care of the incoming datastream.
    2. Then, using the Ring Buffer expand the program to index the Ring Buffer ( consuming the incoming data) to find CHR(10) and the transfer the Ring Buffer to the variable usart_input byte by byte until you see a (CHR13). Then, display on the LCD.

    My thoughts

     
  • Chris Roper

    Chris Roper - 2023-10-30

    The first thing I do when debugging communications of any kind is a loopback test.
    In this case start by disconnecting the receiving device and shorting out the TX and RX pins on the transmitter.

    Then send some data to see if the device can receive data from itself.
    Start with single characters then build up to strings but all on one device.

    When that is working fine move the code to the receiver and have it echo back whatever it receives.

    Then, and only then, when you know the communications work you may start adding the interrupts, delays and display functions.

    That way you will know when something changes and breaks the code.

    Slowly but logically may cost development time but it saves hours of frustrating debugging in the long run.

    Cheers,
    Chris

     
    👍
    1
    • G. C.

      G. C. - 2023-10-30

      Hello Chris,

      I tried the simplest code I would think of, but still have not been able to make it work..
      I just have connected power supply, an led on pin 18 via a limiting resistor, and shorted pins 9(tx) with 10(rx).. Then sent a char, wait 10 msec and read the rx... If it was the same data trasmitted, I would have pulsed the LED.
      But I am unable to make it work, not even such simple stuff.. :(

      Can you direct me to a working example I could look at?
      Thx,
      GC

       
      • G. C.

        G. C. - 2023-10-30

        The listing

         
        • Anobium

          Anobium - 2023-10-30

          My pennies worth...

          Comment out #DEFINE USART_DELAY OFF You are not allowing the byte buffer to fill and you will get only some of the bits received. Using #DEFINE USART_DELAY OFF is great for when just sending. In my experience.

           
  • Anobium

    Anobium - 2023-10-30

    See https://github.com/GreatCowBASIC/Demonstration_Sources/blob/main/Serial_Communications_Solutions/Hardware_Serial_Buffer_Ring/mega328_pbhardwareseriaring.gcb for example. Do not get hung up that this is an AVR ...the Ring Buffercode is the same - ports are different.

    Adapted for to show some LCD commands, not tested and this assumes you have implemented the Ring Buffer with bkbhit and bgetc exposed.

    Evan

        Dim lastchar as byte
        'Get character(s) and send back
            Do
                ' Do we have data in the buffer?
                if bkbhit then
                      lastchar = bgetc
    
                      select case lastchar
                        case 13
                          cls
                          print usart_input
                          wait 3 sec
    
                        case 10
                          // clear string
                          usart_input = ""
    
                        case else 
                          // concat string
                          usart_input += chr(lastchar)
    
                      end select
    
                end if
            Loop
    
     

    Last edit: Anobium 2023-10-30
  • mmotte

    mmotte - 2023-10-30

    GC
    With USART_BLOCKING and using the the getstring routine you should be able to sync on the char 13 (return) of the getstring routine. Anobium is right that you will not get all the messages because you are sending them faster than you are processing them . sending at 3 sec per cycle and receiving at 4 sec per cycle ( yes the messages take small amount of time). Even with a receive buffer you will overflow and you will need to parse the buffer to find the beginning and ends of the messages.

    I am busy today but maybe I will try it this evening.

    GL
    Mike

     
    • G. C.

      G. C. - 2023-10-30

      Hi Mike,

      Seeing yr input I tried to delay more the transmissions (now 10 secs fm each other), either with HSerPrintStringCRLF and a whole string, or using HSerPrint with a single character followed by HSerPrint of a CR, but the result is the same... Does'nt work.

      Tried the same receiver code with HSerGetString, but despite the much slower transmission it does not work.

      Then I changed the receiver to get a single char with HSerReceive, and in this case I get one time only a zero printed (it should have been a "Z" the first time, then the transimtted chars "G" & "C") , and then nothing more gets printed on the LCD after the CLS command..

      But as it alters my variable that was initialized at a value of 122 (or the ascii Z), something into the UART is happening or it just sends back a zero for one time..

      I am sure I am doing something wrong but do not know what. I need to devote more time to testing deeper and with the simplest steps at a time, like Chris/Anobium suggested.

      Will see.. In the mean time, if you want to see the last sources, I am attaching them here.
      Thx and rgds,
      GC

       
  • G. C.

    G. C. - 2023-10-30

    Thanks Chris/Anobium..

    I'll try out the things both of you suggest..
    But let me clarify that I was just getting confident with GCB and trying some of the LCD's routines and it was quite simple to get characters on the display (the worst problem was to adjust the contrast).

    This is'nt a project, but only a way for me to learn to use GCB. In another attempt on another board with LED matrixes Anobium supported me as I understood the way to debug line by line the code I was used to with MPLAB/XC8/ICD3 in GCB is not possible, unless recurring to "relatively complex" ways. One of this is debug the assembler produced by GCB, the other use a Terminal with USB to ttl adapter connect to the board on development, wich sends on the uart some variables status/values to the PC Terminal.. Etc..
    I am quite a lazy guy and jumped on GCB once discovered it, as it promises very, very simple approaches to developing applications..
    So discarded the assembler debug, the look into the .H files to understand the GCB code etc., I watched a video of Anobium explaining how to use the terminal. Soon after, I ordered some USB/TTL adapters to try out. Will take a couple of weeks to get delivered.

    Meanwhile I experimented with an LCD 16x2.. And seen how simple it was to print something on the display I told myself: "wait a minute, I can avoid the PC and make myself a Poor Man's Terminal" with a Pic and LCD (the receiver).. If it turns to be so easy to get a string fm UART (HSerGetString, only one line of code!) and send it to an LCD, I'll have created a simple tool for debugging other boards.. Onto a board in development, it's just necessary to place a print to uart line with the variable to check that goes to Poor Man's Terminal as it was a sort of breakpoint in MPLAB to get a look to a variable value at that point of program.. Hope I have made clear the simple idea.

    The transmitter PIC is just connected to Vcc/Gnd and the TX out to print a couple of test strings to send to the RX input of the receiver under test. It seems working (I see the data on a scope, do not have a protocol analyzer to make sure it's correct, but I assume it is).

    Once tried and working , the idea was to share it on the Forum for others newbie's use. It's a simple way to reduce the stuff and cabling on workbench.. And simplify debug the phase.

    We'll, in my first couple of approaches, I understand that there are not many shortcuts in GCB too, there is some unavoidable pain to suffer... But still the level of firmware semplification makes it worth the time to learn it and make the most of it, I believe!
    Bye,
    GC

    PS: I am sure I'll come out soon with someting "naive" as that above mentioned, in order to get some help.. :) :)

     
  • G. C.

    G. C. - 2023-10-30

    This one attached here is the last of many trials I have made.. none working..
    Very frustrating..
    I tried all the RS232 HW commands, strings or single characters, but none is working.

    I can't believe the chip is faulty, I see the data transmitted oon the scope. There are problems with the receiving commands or I miss some header file or what ?!?

    Rgds,
    GC

     
    • Anobium

      Anobium - 2023-10-30

      Your program works fine here on a 18LF25K50. Flashes every 3s.

      Try the hex attached. This is from my build of the compiler but I have used MPASM to get the HEX. Load, test and report back.


      Comment out #DEFINE USART_DELAY OFF You are not allowing the byte buffer to fill and you will get only some of the bits received. Using #DEFINE USART_DELAY OFF is great for when just sending. In my experience.


      The ASM for the 18F1220 looks correct. There are no registers being created in error and all looks ok.

      I do have such an old chip to test. Anyone else got one?


      I hate to ask. You are connecting B.1 to B.4 the bottom most pins on the chip.

       
      • G. C.

        G. C. - 2023-10-30

        I tried yr HEX file, but it behaves exactly as mine... Does'nt work.

        I commented the DELAY OFF line and loaded yr HEX, recontrolling again the connection between pin 9 (b1, TX) and 10 (b4, RX). I checked with an ohmmeter if the jumper was internally open.. But it's ok. It's difficult to make HW errors with such small setup (see picture), but don't worry to ask - sometimes it's someting really simple that prevents the board to work regularly.

        So I start to believe that perhaps the 18F1220 has some "misterious" additional setting to be done, that the receiving commands not take care of. This because I saw the output pin pulses having a familiar serial port behaviour (even if I can't tell if the data it's correct, as I don have a protocol analyzer). Tomorrow I'll try the same SW on a newer model.

        Bye,
        GC

         
        • Anobium

          Anobium - 2023-10-30

          the jpg.

          draw on the picture the two pons you have connected. the TX and RX. I am verifing you have them connected.

           
          • G. C.

            G. C. - 2023-10-30

            As i said above, pin 9 and 10 are connected, verified with a tester..
            do not get wrong by perspective angle of the picture. count the holes
            on the breadboard and you will see the green jumper is connected correctly.
            tomorrow i will try another uc, i have another couple of them, and eventually
            rewire with a newer model

            bye, GC

             
            • Anobium

              Anobium - 2023-10-30

              Ok. Take the resistor off pin9

               
              • G. C.

                G. C. - 2023-10-30

                I will.. it's a 47k, ininfluent on sw. I tried to pull up a bit the pin to vcc (the stand by status is a logical one) for getting better edges on the output stream.. But it won't change anything.

                 
                • Anobium

                  Anobium - 2023-10-31

                  Please try it.

                   
  • Ccin E Crout

    Ccin E Crout - 2023-10-30

    You have had some advice so far, my advice may not be any more helpful than anyone else's, quite possibly less, but it is how I approached a similar task.

    I had the need to display serial data that was sent out at regular intervals, from one circuit board outwards, to many multiple receivers who (if addressed correctly) would then respond. All this was on a one wire bi-directional serial data line. My desire was to read the original 'outwards bound' data and also the 'inwards' reply. The data sent and received was then formatted and displayed on an LCD screen. I was trying to intercept the data as some of it was in a custom format and it was that unspecified data stream (isn't it always the case!} that I needed, in order to try to replicate one of the receivers that constantly fail in the field, so that I could build a replacement that would be a drop in exchange the original, with one that had vastly superior reliability.

    Using software serial, I managed to get it working mostly well enough. It would often lose entire packets or discard them as the start of a message would be lost. After I had managed to extract the required data - and having built the module I needed - I set to and tried to improve my packet sniffer. I tried a few approaches which worked a little better. Putting it into a faster device helped but it would still often lock up or skip messages. I then hit on the idea of using an interrupt. That made it near to 100% bulletproof reliable. No lockups, no dropped packets, just brilliant.

    1. Setup software serial on any pin (so long as it is covered by Interrupt On Change)
    2. Set an interrupt On Change on the same pin as the software serial, set so that when the serial data starts (transitions from High to Low or Low to High depending on the polarity of the data you are trying to capture) the IOC is triggered.
    3. Immediately the IOC is triggered, start the software serial to capture the data.
    4. Reset the interrupt.
    
     
    • G. C.

      G. C. - 2023-10-30

      Thanks for your suggestions, Ccin E Crout,
      However you are using a software serial transmission, wich does'nt apply here.. I am struggling with the USART peripheral, wich is expected to take care of most of the work by itself and not requiring a special SW.. You have to take care of start bit/ parity etc. This should be done entirely by the usart module.
      Thanks for your input anyway, I'll think about it if I have to make some serial transmission like IR remotes etc in a similar way, perhaps.
      Bye,
      GC

       
      • Ccin E Crout

        Ccin E Crout - 2023-10-30

        I try to always use the software serial. It gives me flexibility and as I've had close to zero success using the hardware serial I would rather take any potential hit on additional code space and get the serial working. Then again, I often don't plan my pin assignments terribly well in advance which ends up giving me little option other than to use software serial.

        It might be worth you giving the software serial a try. You never know, it could be the answer you're looking for?

        I hate serial communication. It almost never works too well for me, I'm always suffering and swearing at it. "It shouldn't be this $%$!$ hard!" I was frankly astounded that I actually got my design working. I only started it during lockdown as I got bored and wanted a challenge.

        Best of luck.

         
1 2 3 > >> (Page 1 of 3)

Log in to post a comment.