Problem with serial comms in FDS
Don M
Posts: 1,652
I am communicating with a coin hopper. Seems rather simple- you send it a serial command, it responds with a message and dispenses coins.
In my routine I reset the communication message counter, pause then issue a coin dispense command for 1 coin, pause then issue a second coin dispense command for 4 coins.
For some reason my code won't receive the response from the hopper the second time through the dispense routine. I can see it on the logic analyzer and it looks exactly as expected. I've tried putting rxflush in several different spots and using rxtime or just rx but to no avail. It dispenses the coins fine and as I said the analyzer shows the response every time.
Here's the screen shot of PST:
Here's my code:
Any suggestions?
In my routine I reset the communication message counter, pause then issue a coin dispense command for 1 coin, pause then issue a second coin dispense command for 4 coins.
For some reason my code won't receive the response from the hopper the second time through the dispense routine. I can see it on the logic analyzer and it looks exactly as expected. I've tried putting rxflush in several different spots and using rxtime or just rx but to no avail. It dispenses the coins fine and as I said the analyzer shows the response every time.
Here's the screen shot of PST:
Here's my code:
con _clkmode = xtal1 + pll16x ' Feedback and PLL multiplier _xinfreq = 5_000_000 ' External oscillator = 5 MHz MS_001 = 80_000_000 / 1_000 ' ticks in 1ms HOPRX = 0 ' to pin 6 on Hopper HOPTX = 1 ' to pin 5 on Hopper HOPADD = $00 ' Hopper address number 0 - 7 for daisy chaining additional hoppers obj term : "fullduplexserialplus" hopper: "fullduplexserialplus" var byte Ser_Num ' used to keep track of each dispense command so as not to repeat byte ACK_Message[12] ' buffer for the ACK messages word Num ' Number of coins pub main | d term.start(31, 30, %0000, 115_200) ' start terminal (use PST) hopper.start(HOPRX, HOPTX, %0000, 9600) ' start hopper serial port pause(600) term.str(@ver) pause(1000) Reset_Dispenser pause(1000) 'Ser_Num := 1 ' set serial number Num := 1 Dispense pause(1000) Num := 4 Dispense pub Dispense | chk1, chk2, d, idx idx := 0 hopper.rxflush hopper.tx($ED) ' Header hopper.tx($08) ' Number of bytes in message. Always 8 hopper.tx(Ser_Num) ' Command serial number. Should increment after each successful command hopper.tx($50) ' Dispense command hopper.tx(HOPADD) hopper.tx(Num & $FF) ' Lower byte of quantity to dispense hopper.tx(Num >> 8) ' Higher byte of quantity to dispense chk1 := $ED ^ $08 ^ Ser_Num ^ $50 ^ HOPADD ^ (Num & $FF) ^ (Num >> 8) hopper.tx(chk1) hopper.rxflush d := hopper.rxtime(200) if d == $FD byte[ACK_Message][idx] := d chk1 := d idx++ repeat 4 d := hopper.rx byte[ACK_Message][idx] := d chk1 := chk1 ^ d idx++ chk2 := hopper.rx byte[ACK_Message][idx] := chk2 if chk1 == chk2 Ser_Num++ repeat idx from 0 to 5 term.hex(byte[ACK_Message][idx], 2) term.tx(32) term.str(string("Hopper Dispense ACK OK", 13)) else term.str(string("Bad Checksum for Hopper Dispense...", 13)) else term.hex(d, 2) term.tx(32) term.str(string("No comms for Hopper Dispense...", 13)) pub Reset_Dispenser | chk1, chk2, d, idx hopper.rxflush hopper.tx($ED) ' Header hopper.tx($08) ' Number of bytes in message. Always 8 hopper.tx($00) ' Command serial number. Sending a "0" will reset the counter in hopper hopper.tx($50) ' Dispense command hopper.tx(HOPADD) hopper.tx($00) ' Lower byte of quantity to dispense hopper.tx($00) ' Higher byte of quantity to dispense chk1 := $ED ^ $08 ^ Ser_Num ^ $50 ^ HOPADD ^ (Num & $FF) ^ (Num >> 8) hopper.tx(chk1) idx := 0 chk1 := 0 chk2 := 0 d := hopper.rxtime(200) if d == $FD byte[ACK_Message][idx] := d chk1 := d idx++ repeat 4 d := hopper.rx byte[ACK_Message][idx] := d chk1 := chk1 ^ d idx++ chk2 := hopper.rx byte[ACK_Message][idx] := chk2 if chk1 == chk2 Ser_Num++ repeat idx from 0 to 5 term.hex(byte[ACK_Message][idx], 2) term.tx(32) term.str(string("Reset Hopper ACK OK", 13)) else term.str(string("Bad Checksum for Hopper Reset...", 13)) else term.str(string("No comms for Hopper Reset...", 13)) pub pause(ms) | t '' Delays program for ms milliseconds t := cnt repeat ms waitcnt(t += MS_001)
Any suggestions?
Comments
did you try some debugging by sending all the raw bytes to the terminal that come in from the device?
or did you try to send debug-info after each received byte?
best regards
Stefan
I even tried changing the pause time between dispenses to 5 seconds which is way more time than needed to wait for dispensing coins and no difference.
Yes. See the screen shot of PST. It shows the message buffer from the hopper. The last line shows an FF for some reason. That is what I'm trying to solve.
Yes.
Here are the screen shots from the Logic Analyzer. The first one shows the command from the Prop to reset the hopper and the hoppers immediate response:
The second one shows the command to dispense 1 coin and the immediate response back from hopper:
The third shows the command to dispense 4 coins then the immediate response back from the hopper:
And btw.. I am NOT sharing the same power supply for the hopper with the prop board. It is a separate supply.
Do they share a common ground? If not they need to unless you're using something like RS-485.
I also think you're dumping the RX buffer too frequently. Dump it once before you start to send data but the way the code reads now you dump it again after the send which could easily throw away the first character.
I definitely think you should be checking to see what's getting dumped from the RX buffer as Dave suggested.
Edit: It looks like the two devices are communicating elsewhere in the code so I bet you're already using a common ground.
Here's my latest working code. I made quite a few changes from the original.
What's odd is that in the spec sheet it shows an INQUIRE command and one of the flags shows whether the hopper is busy or not. But the hopper won't reply at all while it's busy dispensing so I just continue to poll it till it responds. I'll need to add some sort of time out so that it doesn't hang there forever if there is a problem.
Here's a screen shot of PST showing it working:
Yes. Common ground.
???? Did you look at my latest code post? I flush the rx buffer once during initialization and only 1 other time before the dispense command is sent. You think that is too often? I figured I'd flush it right before the command was sent so the buffer is clean and waiting for the reply.
Anyway that seems to work fine. As I mentioned earlier I need to study the proper way to store the data received into an indexed buffer so that I may test certain bytes/bits for flags.
This is a Chinese made hopper and the command responses documented aren't the same that is experienced. Anyway I'll mark this as solved for now. Please continue to add any comments as you wish.
Thanks for everyone's help. :-)
Probably not. The code I saw before commenting had a rxFlush after the command was sent (or so I remember).
I'm glad it's working. Sounds like a fun project.