Frustrated Modbus


Closed Thread
Results 1 to 21 of 21
  1. #1
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79

    Default Frustrated Modbus

    Hey,
    I have been working on this too long and thought I had it working. The program below works fine when hooked up to rs 232 but when I hook it up to a rs 485 chip it does not work. It is not a hardware issue I know for a fact that the 485 hardware and hookup are wired properly. I am pretty sure I have a problem with a configuration or something in my program.

    I am using a pic 18F4585 at 20 MHz. I am using hardware rx tx and I have a RTS line for the 485 chip. I know its not called rts on the 485 chip but anyway. My rts line is PORTC.4 and I have a led attached to it to see if it flashes every time a response is made. When I have the tx and rx of the pic tied to 232 chip and the computer everything works fine, the rts led flashes whenever the chip is making a response.
    When I hook the tx and rx up to a 485 chip I get 1 response and 1 flash of the RTS LED and then its done. I had this problem before when I was using Portd.2 pin and thought that maybe it was interrupting off of the compatator and not exiting the interrupt routine. So I switched it to c.4 and it worked, then I lost my code and had to backtrack a little. Now I am stuck and frustrated I missing something simple and stupid but beating my head isn't helping anymore.
    When using the rs232 on the computer I don't actually use any handshaking
    Anyone want to take a look at my messy code and see what they think. Maybe it will pop right out to someone else.
    Thanks
    Shawn
    Attached Files Attached Files

  2. #2
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    947


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hi Shawn

    The only place I have some doubts is this
    Code:
     while (PIR1.5 = 1)                          'Write modbus frame to buffer
       buffer[Length] = RCREG
       Length = Length + 1
       if Length = 75 then 
        Length = 0
       EndIf
     wend
    I would rather let the ISR exit immediately after collecting and buffering the character. Keeping it in the while:wend means it will not exit the ISR and also will not be able to keep time in the timer ISR branch. Set length=1 only when you start collecting a newframe. Rest of the time, the ISR will collect a character, increment length, etc

    A strategy I use to check such types of communications

    Repeatedly Send a modbus message to the PC running brayTerm in Hex mode. this will obviate any Tx/Rx timing and baud rate issues

    Once you have this running easy, work on the Rx part where the PC sends a fixed modbus message. the PIC will indicate a proper packet received by a flash of led.

    Done that, now let it run in a command-response format. It's bound to work.

  3. #3
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    For starters, you'll need to put a DISABLE INTERRUPT before your readMB ISR.
    Otherwise the Interrupts will keep interrupting the ISR.

    And, the CREN bit (RCSTA.4) needs to be toggled (cleared then set) to clear a OERR or FERR condition.
    Your routine simply turns the receiver off (RCSTA.4 = 0), and no further data will be received.
    DT

  4. #4
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Ok
    Thanks for the help so far. I am breaking the code into different pieces and I am going to test them 1 piece at a time and post them here for you guys to laugh over. This piece is the transmit chunk of the routine. It is hooked to my pc via a rs485 to rs232 converter which uses rts. This code works but do you see anything fishy in it. Its sole purpose is to put out known characters using the rts pin to talk on the 485 network. If you guys don't mind I am going to do this with the whole project and then at the end attach the whole code to the post for anyone looking for modbus rtu code.


    Thanks
    Shawn
    Attached Files Attached Files

  5. #5
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    OK
    I just tried to reply and something freaked out. Anyways, I was just reading the posts again. Jerson I actually had been thinking the same thing about the while loop for receiving characters. I want to change it but am not sure how. I will probably have more questions when I get to that bit of the code. Thanks
    Darrel, it just dawned on me what you were saying. In order to clear the rx errors you basically just turn off the receiver. In my code I do that but I never turn it back on. So if there is a rx error I'm done until I reset the PIC. That would explain some goofy things that were happening before. Thanks
    Shawn

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hi Shawn,
    I looked at your TX-routine and the thing that caught my eye was:
    Code:
    Rts = 1
    For B0 = 1 To Length      ' Send the response to Master
      B1 = buffer[B0]
      Gosub charout
    Next B0
    Pause 5
    RTS = 0
    Pause 5000
    Now, you say that it all works and I can possibly see why in this particular example but in your real code do you always put the first byte of the frame at location 1 in the array? Arrays are zero-indexed so the first location of Buffer is Buffer[0] and the 6th location is Buffer[5].

    The reason it works in the example you posted is because PBP doesn't have any boundry checks on arrays so when you do Buffer[6]=6 it's actually writing to the memory location AFTER the last "slot" in the array. In this case there might not BE anything of importance there but in you're real program there's a risk you're actually overwriting another variable.

    Also, in this example you have the Buffer array declared as an array of words, is that what you want? It won't work properly when you try to stuff a 16 bit word into the 8bit TXReg - you'll loose the high byte which isn't a problem in this case but still....

    Finally, you could replace the Pause 5 with something like
    Code:
    While TXSTA.1=0 : WEND
    That should make it wait just long enough for the last bit to go out before turning off your transmitter.

    Well, that's my thoughs...

    /Henrik.

  7. #7
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Thanks Henrick,
    I knew better with the array numbering I just dropped the ball. As for the Word sized array I also realize that the Tx register is only 8 bits. It will be taken care of in the function routines.
    While TXSTA.1 = 0 : WEND that rocks thank you.
    Next question, I am switching this project over to 40Mhz and so I need to reconfigure timers. In the Modbus.txt file above, at the end it has a If Then statement that looks for a 10mS delay between Rx interrupts. This delay means that the modbus frame of characters is over. The comment says 10mS but for the life of me I cannot figure out where this comes from. It uses a 20Mhz OSC. It uses tmr2 with a 1:16 prescaler and then a variable that increments 1 time every time PIR1.1 is true. All I should have to do when switching from 20 to 40Mhz is take the 120 x 2 and use that value. But I would like to understand how it is getting 10mS.
    20000000/4=5000000 1/5000000=200nS 200nS*16= 3.2uS and 3.2uS*120=384uS
    Attached Files Attached Files

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hi Shawn,
    TMR2 interrupts when its value matches what's in PR2. I don't see anything being written to PR2 in the code you posted so I'm assuming that its 0 and therefor TMR2 interrupts when it rolls over from 255 to 0.

    You have calculated that the timer "ticks" at 3.2us which is correct but it needs 256 ticks before it interrupts so there's 3.2*256=819.2us between each interrupt. The ISR then counts 120 interrupts so 0.819ms*120=~100ms..... Hmm I must be doing something wrong...

    Anyway, you should know that according to the MODBUS specification the correct interframe delay or timout depends on the baudrate at which the network is run. For baudrates of 19200 and below the interframe delay should equal 3.5 characters and for baudrates over 19200 the delay should be fixed at 1750us.

    So to meet the specification the delay at 9600baud should be 1/9600*11bits*3.5 = 4ms.

    /Henrik.

  9. #9
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hey Henrik,
    I guess it doesn't really matter what the modbus code said because I am revamping it. I didn't actually write that code, or at least the communication part. I copied it from someone else's work. It only had a couple of modbus functions and it used an I2C chip to read and write to registers. So I modified it. As far as I can tell, the codes TMR interrupts every 98mS which is way to long and that might have been part of my problem.
    @20Mhz and a 1:16 pre-scaler TMR1 Variable counts to 120, this is my math for it.
    1/5000000=200nS 200nS*16=3.2uS 3.2uS*256=819.2uS
    819.2uS*120=98.304mS
    In post #7 I forgot to figure in the 8bit PR2 register.

    So, check my math if you would, what I need to do is.....
    @40Mhz-1:16 pre-Scaler-8bit TMR
    I need my TMR Counter Variable to count to 10.
    40Mhz/4=10Mhz 1/10Mhz=100nS 100nS*16=1.6uS 1.6uS*256=409.6uS
    409.6uS*10=4.096mS

    Thats way closer to 4mS then it was unless my math is wrong. I am going to try and scope it to see what I get

    Shawn

  10. #10
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hi Shawn,
    Math seems correct to me and ~4ms interframe timeout is what you want for 9600 baud. I can't really see why the 98ms timeout would cause you any trouble as long as the masters timeout setting is set long enough. Obviously it would take unnecessary time but again, as long the masters timeout setting allows it it should have worked.

    /Henrik.

  11. #11
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    ok,
    I wrote a short program to test the 4mS TMR2 routine. My math seems to be right I scoped it and all is good. Next part of the project will be he Rx code.

    Shawn

  12. #12
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Ok
    New puzzle for ya all. This may be too much code for you to go over. But I am going to attach it anyway. This program is only to interrupt receive a modbus frame and detect the end of the modbus frame, then echo it back out the tx line. It seems to be working kinda, however I am only receiving 4 bytes of information back no matter what size of modbus frame I send. I put this line of code in to display my length variable which is the variable that determines how many bytes are transmitted out of the pic.
    Serout2 LCD,16468,[12,dec length]
    Length is displaying as zero. I think somewhere I am having a problem incrementing my length variable. I am still sifting through the code but I thought I would post it for anyone that is bored.
    Oh ya, I realize that the Serout2 command is a time eater but I am manually sending the ModBus frames from my Pc using MBPoll. When I first wrote the program I did not have the Serout2 command in there and still had the same problem.
    Thanks
    Shawn
    Attached Files Attached Files

  13. #13
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    I'm Back
    Ok, I am making progress, maybe. I know what the problem is but I haven't narrowed down the cause yet. I broke up the receiver error routine into to parts to check RCSTA.1 and RCSTA.2 individually. If either one errors I turn on a corresponding LED. Now every time my ModBus Master sends a request I get an error on RCSTA.2. I get an error but my slave(pic) still sends out the proper message to the master. Now the goofy thing is, is that I do not have this problem when using rs232. Only have the problem using my 485 to 232 converter.
    When using the rs232 chip I can have the cpu scan at 5ms with no errors. Using the 485 to 232 if I scan ever 5 senconds my message gets through but my pic still has RCSTA.2 errors. It errors every time.

    At this point I am no longer sure if its a software problem or a hardware problem. I'm not real sure what a framing error is but I am going to investigate.
    Heres my code if anyone would like to through in their 2 cents.
    The readRegResponse: label is the subroutine where the RTS line is pulled and data sent out.

    Thanks
    Shawn
    Attached Files Attached Files

  14. #14
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    I got it, I'm still not sure what difference it made between using the rs 485 and the rs 232 bus, but I fixed the RCSTA.2 error problem. Turns out reading the RCREG clears the frame error. So I put the routine that checks for the error after the routine that reads out the RCREG when a character is detected. That seems to make sense in my mind.

    So this is how it tested out. I set the scan rate on my Modbus Master to 1mS. Obviously that is rediculous but I wanted to dump all I could at it. I sent a function 3 command from the Master to read 8 one word registers every 1ms. What I got was 1308 TX RX round trips in a minute with no errors on the master or the slave. That comes out to roughly 46mS per TX RX round trip which I thought was pretty good since every byte sent and received takes about 1mS. There was 31 bytes in every TX RX round trip, so theres about 30mS. Then there is a 4mS wait for end of frame delay. That puts me up to 34mS, so it looks like I am waisting 12mS a second which I would like to get down but I am not to worried about at this time.


    I am going to keep posting problems with this project on this post, and eventually I will post the final modbus code on here.
    Thank You
    Shawn

  15. #15
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,520


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hi Shawn,
    I'm glad you got it going. Reading RCREG clears the error but what causes the error in the first place? I guess if it works and you get the data you expects there's no problem really but why does it indicate framing error?

    Your function 3 request from the PC is 8 bytes (Adress(1), Function(1), StartingAdress(2), NumberOfRegs(2), CRC(2)) and the response is 21 bytes (Adress(1), Function(1), ByteCount(1), Data(16), CRC(2)) so there should be 30 bytes if I'm not mistaken. Why is there 31?

    Also, I think that the interframe delay is applied by the PC too which means that it too has to see the line idle for 4ms before it calls the frame complete - even though it knows how many bytes to expect. Then IT needs to process the frame before it's ready to send a new one. And I don't think the PC timing is very precise so it's hard to say exactly how long it's actually waiting. Obviously I don't know the exact details of how MBPoll works but I think your timings may be a bit better than you think.

    Turn on a LED when the RX interrupt fires the first time in a new frame and turn it off when you pull the "RTS"-line low, that will tell you exactly how long time the PIC is spending. Of course, there's not much to do to the time it takes receiving and transmitting so perhaps set the LED when the 4ms timer timesout and reset it when the first character is put in the TXReg, that will show you exactly how long it takes to actually process the frame. (Or use a timer to measure the execution time, put its value and in of the registers you're reading and you'll get the result in MBPoll).

    /Henrik.

  16. #16
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hello,
    How is everyone? I got a new question, it is related to this project but not to modbus. If no one minds I am just going to keep asking questions on this post. I am working with a MCP4209 DA Converter. I want to output 0 to 10V. So I want to run the output of the 4209 into a non inverting 741 op amp. My problem is, the lowest value out of the op amp I can get is 3.97V. Is that all the closer a 741 can get to the lower rail. I have 12V going to the positive rail and ground hooked to lower rail. I get my 10V out when my 4209 is putting out 5V.
    I have a 10K resistor hooked from ground to pin2 of the 741. And a 10K resistor from pin2 of the 741 to pin6 of the 741. Input from the 4209 is running to pin3 of the 741.
    If I run the 741 at + and - 12V all works good but I do not want to add a negative voltage supply to my project. Is there anyway around this?
    Thanks
    Shawn
    Last edited by shawn; - 1st May 2011 at 19:46. Reason: lacking info

  17. #17
    Join Date
    Aug 2008
    Location
    Portugal
    Posts
    240


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Quote Originally Posted by shawn View Post
    Hello,
    How is everyone? I got a new question, it is related to this project but not to modbus. If no one minds I am just going to keep asking questions on this post. I am working with a MCP4209 DA Converter. I want to output 0 to 10V. So I want to run the output of the 4209 into a non inverting 741 op amp. My problem is, the lowest value out of the op amp I can get is 3.97V. Is that all the closer a 741 can get to the lower rail. I have 12V going to the positive rail and ground hooked to lower rail. I get my 10V out when my 4209 is putting out 5V.
    I have a 10K resistor hooked from ground to pin2 of the 741. And a 10K resistor from pin2 of the 741 to pin6 of the 741. Input from the 4209 is running to pin3 of the 741.
    If I run the 741 at + and - 12V all works good but I do not want to add a negative voltage supply to my project. Is there anyway around this?
    Thanks
    Shawn
    Hi try to use a LM358 Insted of the 741. Power the LM at +12V and ground and post the results.
    Thanks and Regards;
    Gadelhas

  18. #18


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    I'm guessing you mean "MCP4902"? A couple of basic questions... you have compensation in your feedback loop? If you don't have a cap there you're asking for problems, especially with a 741. If you really only need single-ended output go with one of the devices from Microchip designed for rail-to-rail single-ended use (or whoever, the MC stuff is pretty inexpensive). Don't forget the offset voltage from the opamp itself; it also gets amplified (by two here).

    Are you decoupling as you should? Caps on the rails as described in the doc's for the DA?

  19. #19
    Join Date
    Dec 2004
    Location
    nebraska
    Posts
    79


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Hey
    thanks for the replies on the op amp. I tore a lm358 out of a board and tried it. It worked good. I have some mcp601 but they are only good for 5.5V which is not enough. Where does the cap go the example circuits I looked at don't show a cap.
    thanks
    shawn

  20. #20
    Join Date
    Aug 2008
    Location
    Portugal
    Posts
    240


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Quote Originally Posted by shawn View Post
    Hey
    ...I tore a lm358 out of a board and tried it. It worked good...
    Great!!!
    Thanks and Regards;
    Gadelhas

  21. #21


    Did you find this post helpful? Yes | No

    Default Re: Frustrated Modbus

    Look at the attached schematic. Whenever you design a circuit around an opamp you should use a compensation cap in the feedback loop as well as good power supply decoupling. In most documents this information is "left out" because it is a "given" (the schematic gets very crowded showing every decoupling cap).

    The formula for calculating the "Ccomp" cap is shown in the schematic with a very simple explanation (it really is beyond this forum to explain -3db break points etc.). The point is, you can design yourself a very nice oscillator if you ignore Ccomp and bypassing (another term for decoupling), especially when using breadboards and flying wire construction.

    In the example, figure out what the highest frequency is that you will be passing though the circuit and calculate the value needed and then use the closest common value available. If this is varying DC I wouldn't get too worried about it...

    There are often overlooked parameters using opamps (and other devices, even by "pro's") such as CMRR and PSRR (a little homework for you) that do not work properly without a bypass cap. A 0.01-0.1uF cap is mandatatory on every IC in a design. The additonal cap such as the 1uF Tantalum (notice one cap is ceramic, the other is tantalum, or could be electrolytic - another homework assignment ) shown is optional but you as the designer of the circuit are responsible for deciding that (ever looked at a circuit board and seen caps soldered across pins on parts; they "decided" incorrectly).

    Consider these things as "law" and you will find that your circuits behave correctly not only on the bench but in actual use, over time and temperature changes. Ignore them and one day your circuit may "flake" on you; by the time you get it back to the bench it'll work "correctly" again... until the next time...
    Attached Images Attached Images

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts