PDA

View Full Version : Wait for a string on a serial port



RuudNL
- 13th May 2017, 19:44
I am having a problem receiving data from a serial port.
In fact, the serial port receives MIDI information, it is no problem to set the baud rate to the midi standard of 31,25 KHz.

What I need is the following.

The sequence of CHR(176) + CHR(44) + CHR(69) should turn a port pin 'on'
The sequence of CHR(176) + CHR(44) + CHR(5) should turn a port pin 'off'

While this is running, a random combination of characters may appear on the input, but this should not influence the status of the output pin used.
The output should only react on 176+44+69 AND 176+44+5
I have made something already, but it seems this is not reliable.
Any ideas? Suggestions are highly appreciated!

aerostar
- 13th May 2017, 22:28
your code would be helpful but here is a pointer

pinon VAR portX.Y 'eg portb.7

Pollmidi:
HSERIN [WAIT(176,44),variable]
if variable = 69 then pinon=1 'alias to port
if variable = 5 then pinon =0
goto Pollmidi


Note there is no get out of this loop but this should give you an idea.

SERIN should also work if you do not have hardware UART

RuudNL
- 14th May 2017, 07:58
Thanks! That may be useful. I didn't know that you could combine a fixed string and a variable when using WAIT.
(I always thought you only could use a fixed string here.)

RuudNL
- 14th May 2017, 09:30
I just tested it, and it works.
At first I got the impression that is was unreliable (to the same degree as what I had created), but after some experimentation it showed that I needed a pull-up resistor at the output of the MIDI port. (In fact you should use an optocoupler for this.)
But with a pull-up resistor it works now without any problems. So I think my code would work also, but this code is more compact, so I will keep using it.
Many thanks again!

Scampy
- 14th May 2017, 10:18
This is the code I use for my serial comms



RCIF VAR PIR1.5 ' USART receive flag
Char VAR BYTE ' USART byte received
GIE VAR INTCON.7
nTest var byte



and then in the main loop of the code



FOR TempWD = 0 TO 500
IF RCIF=1 THEN GOSUB coms ; Check to see if PC application connected
PAUSE 1
next TempWD


And then the Comms subroutine


HSERIN [nTest]
SELECT CASE nTest
CASE "Q" ; if Q then send data to PC
Goto Term_TX
CASE "S" ; if S then receive data from PC
goto Term_RX
return


The Term_RX / Term_TX subroutines are then used with HSERIN or HSEROUT to receive and send data. As can be seen from the code I use Q and S as the keys to communicate with a PC application which receives variable data and populates text boxes, or if the value are changes in those text boxes and the update button clicked, the PS sends the new values for the variables..

Hope that helps

Art
- 17th May 2017, 19:02
With just a 3 byte buffer the whole thing could be non blocking,
and the 1 timeout might even be able to be changed to zero for no delay at all.



buffer var byte[3]
inputbyte var byte

main:
'
HSERIN 1,nodat,[inputbyte] ‘ receive next byte
buffer[2] = buffer[1] ‘ rotate into buffer
buffer[1] = buffer[0]
buffer[0] = inputbute
if (buffer[2] = 176 && buffer[1] = 44) then
if buffer[0] = 69 then portb.0 = 1
if buffer[0] = 5 then portb.0 = 0
endif
nodat: ' timeout label for no byte received
'
// the rest of the program

goto main

flotulopex
- 13th August 2017, 18:41
Hi,

I'm trying to do almost the same as RuudNL but I'm having some trouble to make it work.

From the Serial Communicator (MECANIQUE), using a FTDI TTL232R serial cable, I send a command identifier and a value to the PIC.


' ====== FUSES ================================================== ==================================
' PIC 12F683
@ __CONFIG _FCMEN_OFF &_IESO_OFF &_BOD_OFF &_CPD_OFF &_CP_OFF &_MCLRE_OFF &_PWRTE_OFF &_WDT_OFF &_HS_OSC

' ====== REGISTERS ================================================== ==============================
' Registers 76543210
ANSEL = %00000000 'Disable analog inputs
ADCON0 = %00000000 'ADC is OFF
CMCON0 = %00000111 'Comparator is OFF
OPTION_REG = %10000000 'Pull-Ups disabled
TRISIO = %00000001 'Inputs/Outputs
GPIO = %00000000 'High/Low

' ====== DEFINES ================================================== ================================
DEFINE OSC 8

' ====== VARIABLES ================================================== ==============================
TX_ON var GPIO.2 'LED
DataIn var GPIO.0
Switch var byte
BdRate var WORD

' ====== INITIALIZE ================================================== =============================
TX_ON = 0
Switch = 0
BdRate = 49236 '9600 OIN

' ====== PROGRAM ================================================== ================================
MAIN:
SERIN2 DataIn,BdRate,[WAIT("Identifier"),Switch]
IF Switch = 1 THEN TX_ON = 1
IF Switch = 0 THEN TX_ON = 0
GOTO MAIN
END

Unfortunately, the PIC doesn't react to the incoming data.

I might not use the correct syntax in the Serial Communicator.

Do I have to type something different as this here:
8455

Thanks for any help.

Scampy
- 13th August 2017, 22:21
Roger, what have you configured the serial port to. Reading the manual the value for MODE if using 9600 baud rate, with the normal 8 bit, no parity, 1 stop bit the value is 84, but you have bdrate (same as mode in the manual) set to 49236....



from the manual - SERIN2

Some examples of Mode are: Mode = 84 (9600 baud, no parity, true)

flotulopex
- 14th August 2017, 06:12
Scampy,

I have connected the FTDI cable directly to the PIC this is why I use this particular mode ;)

To make sure the serial communication really "happens", for testing purpose, I have configured the PIC to send data to the Serial Communicator software.

So I think I may have a syntax issue here.

richard
- 14th August 2017, 06:29
MAIN:
SERIN2 DataIn,BdRate,[WAIT("Identifier"),Switch]
IF Switch = $31 THEN TX_ON = 1
IF Switch = $30 THEN TX_ON = 0
GOTO MAIN
END

or

in serialtool send

Identifier#1

sayzer
- 14th August 2017, 17:56
You have DEFINCE OSC 8 in your code with HS option in fuse.



OSCCON.0 = 0 ' Clock source defined by FOSC<2:0> of the Configuration Word register


This way, chip knows the clk source.

Default OSC value is for Internal 4Mhz clock.

Hope this will solve your issue.

flotulopex
- 14th August 2017, 19:20
Sayzer,

Sorry, i don't understand what I have done wrong with the OSC settings. I'm using an external 8MHz crystal; maybe I should have mentioned it.

I'll give Richard's suggestion (post #10) a try in a little moment and see what it does ;)

HenrikOlsson
- 15th August 2017, 07:25
Richard is on it (as usual). Remember that when you're using the serial terminal you're sending ASCII characters. In your original code you're checking if the variable contains the value 1 while you should check if it contains the ASCII character "1".

IF SWITCH = 1
IF SWITCH = "1"
IF SWITCH = $31
IF SWITCH = 49

Do you see (and understand) the difference between the four lines above?

/Henrik.

sayzer
- 15th August 2017, 08:03
Sayzer,

Sorry, i don't understand what I have done wrong with the OSC settings. I'm using an external 8MHz crystal; maybe I should have mentioned it.

I'll give Richard's suggestion (post #10) a try in a little moment and see what it does ;)

Hi Roger,


I know you are using external 8Mhz crystal, that is why you need to tell the chip about it.
In your code, there is no OSC setting. You have it in fuse.
Default OSC setting is internal 4Mhz.

You need to manually choose the OSC value for external source by OSCCON.0 = 0
Otherwise, chip will not know you have selected external HS.

To make sure you are running on the correct speed, have a flip flop on a pin for say 5000ms.




FlipFlop:

TX_ON = TX_ON ^ 1
PAUSE 5000

Goto FlipFLop


Then, you can see the speed.

AvionicsMaster1
- 15th August 2017, 13:43
Henrik, for my edification is this the correct answer? Please don't roll your eyes too far if this is too much of a NOOB question.

IF SWITCH = 1
IF SWITCH = "1"
IF SWITCH = $31
IF SWITCH = 49

IF SWITCH = 1 checks to see if SWITCH is set to ON
IF SWITCH = "1" checks to see if SWITCH is equal to an string value of 1
IF SWITCH = $31 checks to see if SWITCH is an ASCII 1
IF SWITCH = 49 checks to see if SWITCH is an ASCII 1

For the life of me I cannot discern the difference between the last two. $31 = 49 on the ASCII table. How are they different?

Thanks for your patience.

flotulopex
- 15th August 2017, 17:07
Default OSC value is for Internal 4Mhz clock.

Right, thanks for pointing this to me ;)

flotulopex
- 15th August 2017, 18:04
MAIN:
SERIN2 DataIn,BdRate,[WAIT("Identifier"),Switch]
IF Switch = $31 THEN TX_ON = 1
IF Switch = $30 THEN TX_ON = 0
GOTO MAIN
END

...or in serialtool send Identifier#1...

Thanks Richard, it works well expecting HEX values ($30 and $31) but it will not work with Identifier#1.

HenrikOlsson
- 15th August 2017, 18:18
Henrik, for my edification is this the correct answer? Please don't roll your eyes too far if this is too much of a NOOB question.
Don't worry about any eyes rolling, this type of thing comes up quite often and hopefully we all learn from it.

All four lines obviously compares the value stored in the variable SWITCH with whatever value is on the right side of the equal sign. But out of the four lines, only the first one would make any difference compared to other ones when put into a program. The other Three would execute exactly the same because they all compare SWTICH to the a value of 49 (while the first line compares SWITCH to a value of 1).

1 is simply the value of 1
"1" however is the ASCII character 1 (which happens to correspond to the value 49 expressed in decimal notation).
49 is the ASCII code, expressed in decimal notation, for ASCII character "1"
$30 is the hexadecimal representation of the decimal value 30 which is the ASCII code for character we know as "1"
%00110001 is the binary representation of the decimal value 30 which is the ASCII code for the character we know as "1"

If, instead of camparing SWITCH to something you'd assign values to it:

SWITCH = 1
SWITCH = "1"
SWITCH = 49
SWITCH = $30
SWITCH = %00110001

Only the first line is different, the other four lines all does exactly the same thing - it's just different ways of expressing, or interpreting, the same thing.

/Henrik.

richard
- 15th August 2017, 23:32
Thanks Richard, it works well expecting HEX values ($30 and $31) but it will not work with Identifier#1.

command parsing needs to be enabled in your transmit window

[right click in tx window] to see menu

flotulopex
- 16th August 2017, 20:01
Thanks Richard. I should have tried this... :o