PDA

View Full Version : Communications Example : PC to PIC bi-directional dialogue



Melanie
- 17th July 2004, 12:41
Judging by the emails I'm getting, folks have missed this hidden away at the end of another thread... so it's been repeated with a thread all of it's own.

Here's a sample program, thrown together for fun this lunchtime, to demonstrate bi-directional dialogue with a PC running something like Hyperterminal. It runs at 300 baud so almost any PIC will run it without an Xtal or Resonator (but best with!!!!).

The object of the program is to demostrate how commands can be passed from the PC User and acted upon by the PIC.

Yes, whatever you type on your PC is echoed back to you as feedback. The program is reasonably interactive... it tells you when you're Bad!, and tells you when you're OK. UPPERCASE and lowercase and cOmBINatIOns are handled with reasonably idiot-proof command interpretation... this is done by parsing the received command line (in a simplified manner for this example) rather than the usual way of having SERIN (or whatever) WAITing for a valid command.

You can even use the BACKSPACE Key and have the PIC perform rudimentary line editing.

PIC has five LED's which can be remote controlled in a variety of ways with commands like ON, OFF, BLINK, SWEEP and BEER. The major commands have sub-parameters which can be added to make control more interesting. Plenty of expansion for you to do your own thing.

Example:

ON Switch ON all LEDs
ON 2 Switch ON LED number 2

you can even have abnormally large gaps between the Command (eg ON) and the sub-parameters (eg 2)

ON 4 7 Switch ON LED number 4 for 7 seconds
BLINK 1 15 Blink LED number 1 15 times
OFF 1 Switch OFF LED number 1
SWEEP 25 Sequentially Sweep all LEDs 25 times

Try to break it (if you can) by typing combinations of garbage or having line lengths bigger than 10 bytes (my preset communications buffer maximum)....

Full instructions in the program comments.

Melanie

Melanie
- 18th July 2004, 13:01
Some of you may not have PBP, but might like to try the program to play with... so I've appended the HEX ready to burn into a 16F628.

LED1 is on RA0, kathode to PIC, anode to Vdd via Resistor (eg 330R). LED2 is on RA1 similarly. LED3 is on RA2. LED4 is on RA3 and finally LED5 is on RA4.

Connect RB1 (RX) via 1K5 Resistor to PC pin 3 on 9-Pin D Connector. Connect (TX) RB2 via 1K5 Resistor to PC pin 2 on 9-Pin D Connector. Connect your PICs Vss (0v) to PC pin 5 on 9-pin D Connector.

You don't need an xtal or Resonator, and you don't need to worry about connecting the MCLR pin either. Those pins should be left unconnected. Just the LED's and the connections to your PC.

The appended file is a HEX file. Unfortunately this forum does not allow the uploading of files with HEX extensions, therefore rename comms1.txt as comms1.HEX before programming.

Melanie

PaulB
- 10th November 2004, 15:44
Hi Melanie,

I assume that this will only work with a program compiled with PicBasic Pro and not PicBasic?

I have just purchased PicBasic and I planned to use this program for testing my programmer ( Velleman P8048), but I see that you use the DEBUG/DEBUGIN commands for communicating with the PC.

My Compiler manual says that DEBUG is not supported although it is syntax checked!

Can I not use the SERIN and SEROUT commands instead?

I haven't worked out how to address PortA pins yet/ Seems that all I/O points to PortB?

Regards

PaulB

Melanie
- 10th November 2004, 21:26
You should be able to reassign the I/O to whatever pins you fancy. I put the LEDs on PortA from memory, so it was obvious to put the other stuff on PortB.

Sure, you can use SERIN/OUT.

I do check examples like this before posting them... It should port to PBC... however, not having it I'm reluctant to post examples and code that I haven't tried and tested. somebody will always come back and say this or that didn't work and I'd have no way of checking it.

PaulB
- 11th November 2004, 13:05
Hi Melanie,

Thanks for the reply.

I thought that the SERIN and SEROUT were OK, but wanted to check.

Off topic, I'm really looking for a started guide to the use of PBC. The manual with it gives the syntax of the language tokens etc, but is not clear on use of directives etc and how to change the type of PIUC.

I thought that I should have simply been able to run your demo throug the compiler and get a HEX file at the end, but it barfs at the first @ directive!

I'll have a look through the forum again and post a note if I dont find anything.

Regards

Paulb

Melanie
- 13th June 2005, 10:37
Hi Melanie...

I am having a little problem with your program.

I loaded it into the 16f628a, and it appears the characters are getting to the rx port, but no echo's or messages....


Hi...

Sorry it's taken me so long to verify this... just so much work and so little time.

Worked straight away witha 16F628A out of the box... but... then I tried it on a normal 16F628 (just a random selection from stock)... and I had comms errors!... not all the keys on the keyboard would echo, and those that did were wrong.

So I recompiled for a 4MHz xtal (Resonator actually using XT_OSC), added the bits... and tried the chip that was giving me problems... whoo-hoo... away it ran without errors.

This just proves that Async comms even at 300 Baud are not always reliable on internal oscillator. The variances between individual chips are just too great.

I shall post this on the forum.

Melanie

D-Work
- 23rd October 2005, 21:49
Hello,

I have a problem with this sample. When a open PICBASIC Terminal and type ON nothing happens but when a type ON 1 the PIC return Bad!.

Whats seems the problem, i think the PIC works fine because in the terminal i get the Bad! answer from the PIC

Thanks,
David

Melanie
- 24th October 2005, 02:21
Please see the previous posts on this thread. You either have the wrong baudrate, or your PICs internal oscillator is out of spec and you need to recompile using an xtal or resonator.

D-Work
- 24th October 2005, 04:49
I use the baudrate provided in the source code "300 baud, 8 Data Bits, No Parity, 1 stop Bit, No Flow Control".
The problem is i get errors while compiling your code, i use version 2.1.3 of Proton+.



Error at Line [112] In file [COLOK.BAS] *** Value Expected! ***
Error at Line [165] In file [COLOK.BAS] *** Variable or Value is Missing! ***
Error at Line [170] In file [COLOK.BAS] *** Square opening bracket '[' missing! ***
Error at Line [183] In file [COLOK.BAS] *** Square opening bracket '[' missing! ***
Error at Line [211] In file [COLOK.BAS] *** Syntax error! ***
Error at Line [247] In file [COLOK.BAS] *** Syntax error! ***
Error at Line [250] In file [COLOK.BAS] *** Misplaced or Incorrect 'ENDIF'. Also check its corresponding IF Command! ***




Regards,
David

mister_e
- 24th October 2005, 09:32
Weird error message if you'd copy/paste the Melanie's code...Be sure you use MELABS compiler.

Melanie
- 24th October 2005, 09:35
My examples are NOT written for Proton but for MeLabs PBP and are posted on this forum and on MeLabs website. The code works perfectly when used with compiler it was intended for.

Jerson
- 15th May 2006, 08:14
Hello Melanie

I have seen the code you posted. I have a couple of queries and would like to know your opinion on them.

You use a step wise approach of building the command in the buffer by reading characters one by one. Can I use a construct like this and get away with it? If not, what could be the catch?


' wait for a command terminated by CR
hserin [STR CmdBuf\16\13]


You compare commands with templates in EEPROM. Is there a way to avoid this and compare directly with templates in program space? I plan to have a strcmp function for each template I want checked. So, I might invoke it like this

gosub CheckCmd1
if Result then Command1
gosub CheckCmd2
if Result then Command2

Each CheckCmd function will check the Command Buffer against the template it has.

I am trying to do this
Command1 - TS ddmmyy hhnn <CR> Time Set
Command2 - GL <CR> Get Log
Command3 - CL <CR> Clear Log

I'd like to know what you think of this approach

Thanks
Jerson

Melanie
- 15th May 2006, 09:14
Yes you can read in a string of characters the way you specify... but the problem is you are locked in the HSERIN or SERIN command until the number of characters that you specify in your string have arrived. If it's a keyboard input from a host for example, and they go off for a Coffee and a natter in the little-boys room half-way thru the string, then so does your PIC. The best way is to poll the Received Flag in the USART by background interrupt and continually feed a ring buffer. But that's a subject for another time.

No problem with comparing against what's in program-codespace rather than in EEPROM. My example was written that way so people can understand and play with it more easily.

Jerson
- 15th May 2006, 11:22
Melanie

Thanks very much. Your feedback has been helpful. Input will be through another PIC and so the human speed does not matter.

Jerson

InitialDriveGTR
- 8th July 2006, 03:53
Hi, I compile and get some errors. Sorry, but I had to attach it in a picture format.

Thanks.

Melanie
- 8th July 2006, 09:18
Works for me...

H:\Data-Reference\PIC\PBP246>pbp -p16f628 comms1 -v
PicBasic Pro Compiler 2.46, (c) 1998, 2005 microEngineering Labs, Inc.
All Rights Reserved.
Pass 1:
Pass 2:
Code Gen:
Macro Pass:
PM.EXE H:\DATA-R~1\PIC\PBP246\comms1.ASM
PM Assembler 4.07, Copyright (c) 1995, 2004 microEngineering Labs, Inc.
921 words used.

You didn't explain how you've compiled it, but if you follow the example in the PBP manual you will have no problems.

mister_e
- 8th July 2006, 09:37
If you're not using a MELABS compiler you'll have this error message, this error messge also apply on the low cost PBC compiler. It may also happen on PBP using MPASM as assembler.

i suspect the MPASM as assembler, just rem the config fuses (somewhere at the top of the code, and use the correct syntax for MPASM. See FAQ to know how to.

sakthi
- 8th November 2006, 13:21
Hi
i m need of code for transmitting data from one PIC and another PIc receives the transmitted data,the communication is via SPI.i tried a lot bt i didnt get the o/p.i want to know what are the registers i have to configure.and i wantto know whether i have to dowload the transmitter prgm in one PIC and receiver program in another program.plz help me,i need it urgently.plzzzzzzzzzzzzzz.i m using pic16f877a

grounded
- 1st June 2008, 05:48
I converted this to run on a 16f676 it compiled but when I ran it I only get every other character back If I type Richard I get Rcad, if I type 123456789 I get 13579 and I guess because it's only "seeing" every other character I can not operate the LED
any ideals
thanks



' code by Melanie converted to be used with 16f676 by grounded
' added 4mhz external clock for this project to correct problems
' using microCode Studio and it's serial communicator
' -------------------------------------------------------------
'
' CPU Hardware Layout
' -------------------

' pin changed to use with 16f676
' PortA.0 - RX cable via 1K5 Resistor to PC pin 3 on 9-Pin D Connector
' PortA.1 - TX cable via 1K5 Resistor to PC pin 2 on 9-Pin D Connector
'
' PortC.0 - LED1 to VDD via Resistor
' PortC.1 - LED2 to VDD via Resistor
' PortC.2 - LED3 to VDD via Resistor
' PortC.3 - LED4 to VDD via Resistor
' PortC.4 - LED5 to VDD via Resistor

' Don't forget to connect Vss to PC pin 5 on 9-pin D Connector

pic16f676
' FUSES SET IN INC FILE
' _XL_OSC, WDT_ON, MCLR_OFF,
' CPD_OFF, BOD_OFF, PWRT_ON,PROTECT_OFF


DEFINE OSC 4 'EXTERNAL CLOCK SPEED 4MH.added for this project
pause 2000 'DELAY TO LET STABILIZE AFTER POWER UP
CMCON = 7 'COMPARATOR OFF
VRCON = 0 'VOLTAGE REF. DISABLE
ANSEL = 0 'DIGITAL
OPTION_REG=0 'DEFAULT
WPUA = 0 'NO WEAK PULLUPS
INTCON=0 'INTERUPPTS OFF


' Debug (Communication) Defines (Transmit)
' ----------------------------------------
DEFINE DEBUG_REG PORTA 'CHANGED FROM B FOR 16F676
DEFINE DEBUG_BIT 1
DEFINE DEBUG_BAUD 300
DEFINE DEBUG_MODE 1

'
' DEBUG (Communication) Defines (Receive)
' ----------------------------------------
DEFINE DEBUGIN_REG PORTA 'CHANGED FROM B
DEFINE DEBUGIN_BIT 0
DEFINE DEBUGIN_BAUD 300
DEFINE DEBUGIN_MODE 1



'
Data @0,2,"ON",0,0,0,0,0
Data 3,"OFF",0,0,0,0
Data 5,"BLINK",0,0
Data 5,"SWEEP",0,0
Data 4,"BEER",0,0,0
Data 0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0
Data 0,0,0,0,0,0,0,0

'
' RAM Assignments and Variables
' -----------------------------
BadFlag var BIT ' Flag for Bad Command
CounterA var BYTE ' Just a Counter
CounterB var BYTE ' Just a Counter
CounterC var BYTE ' Just a Counter
CounterW var WORD ' Word-sized Counter
Command var BYTE ' Holds the Command action to execute
CommsBuffer var BYTE [10] ' Max Comms Command Line size
CommsPointer var BYTE ' Pointer to data in Comms Buffer
LEDStatus var BYTE
DataA var BYTE ' Usage as Data Byte
Xvariable var BYTE ' 1st Numeric Variable
Yvariable var BYTE ' 2nd Numeric Variable

'
' Program Constants
' -----------------
BufMax con 10 ' Max size of data Buffer
CommandMax con 10 ' Max number of COMMANDS to be processed



'
' Start - Initialise Processor
' ============================
TRISA=%00000001
TRISC=%00000000 'changed from B to C for 16f676
Xvariable=0:Gosub LEDsOFF ' All LEDs OFF
'
' Clear Buffer ready for start of New Command Line
' ------------------------------------------------
RestartLine:
For CounterA=1 to BufMax
CommsBuffer[CounterA-1]=0
Next CounterA
CommsPointer=0 ' Set Pointer to Start of Buffer
'
' Communications (Closed) Loop
' ----------------------------
ReadLoop:
DEBUGIN [DataA]
If DataA<32 then
If DataA=8 then ' Process BACKSPACE Key
If CommsPointer>0 then ' ---------------------
CommsPointer=CommsPointer-1 ' Rewind one position
CommsBuffer(CommsPointer)=0 ' Erase character in Buffer
DEBUG $08,$20,$08 ' Echo Erase sequence to PC
Goto ReadLoop
endif
endif
If DataA=13 then goto ENTERKey
Goto ReadLoop
endif
If DataA>126 then goto ReadLoop
DEBUG DataA ' Only Echo Printable Characters
If DataA>96 then ' Convert all alphabetics to UPPERCASE
If DataA<123 then DataA=DataA-32
endif
CommsBuffer(CommsPointer)=DataA ' Save to Buffer
CommsPointer=CommsPointer+1 ' Bump Pointer
If CommsPointer<10 then goto ReadLoop
' Loop for next character
'
' Process [ENTER] Key
' -------------------
' also execute if Command Buffer exceeded
ENTERKey:
'
' This section Parses the Command Line
' ====================================
'
' Look for Command WORD
' (scan through available Command vocabulary)
' -------------------------------------------
Gosub LSpace ' Remove Leading Blanks
Gosub REnd ' Locate Command Word End
If CounterA=0 then goto EchoCRLF
' Nothing to Process
For Command=1 to CommandMax
BadFlag=0
CounterB=(Command-1)*8
Read CounterB,DataA ' Get Preset Command word Length
If DataA=CounterA then ' If Length correct, process entire word
For CounterC=1 to CounterA
CounterB=CounterB+1
Read CounterB,DataA
If CommsBuffer(CounterC-1)<>DataA then BadFlag=1
Next CounterC
If BadFlag=0 then goto GoodCommand
endif
Next Command
'
' Bad Command Word
' ----------------
BadMove:
DEBUG REP $00\8,13,10,"Bad!"
' Tell User No Cigar

EchoCRLF:
DEBUG 13,10 ' New Line
Goto RestartLine ' Loop Round and Do again

'
' Parse for First Numeric Variable (if any)
' -----------------------------------------
GoodCommand:
Gosub ShuffleData ' Advance Command Line to start of next Word (if any)
Gosub REnd ' Locate End of next word
Gosub GetNumericWord ' Get numeric value
If BadFlag=1 then goto BadMove ' Invalid Data
Xvariable=DataA ' Save 1st Numeric Variable
'
' Now check for 2nd Numeric Variable (if any) on the Command Line
' ---------------------------------------------------------------
Gosub ShuffleData ' Advance Command Line to start of next (last) Word (if any)
Gosub REnd ' Locate End of word
Gosub GetNumericWord
If BadFlag=1 then goto BadMove ' Invalid Data
Yvariable=DataA ' Save 2nd Numeric Variable
'
' Execute Command
' ---------------
If (Command<4 and Xvariable>5) then
DEBUG REP $00\8,13,10,"No such LED!"
goto EchoCRLF
endif
If Command<3 then
If Yvariable>9 then goto BadMove
If Yvariable>1 then gosub WaitMessage
endif
If Command=3 then
If Yvariable>60 then goto BadMove
If Yvariable>5 then gosub WaitMessage
endif
If Command=4 then
If Xvariable>5 then gosub WaitMessage
endif
'
' ON LED Command
' --------------
If Command=1 then
Gosub LEDsON
If Yvariable>0 then
CounterW=Yvariable*1000
Pause CounterW
Gosub LEDsOFF
endif
endif
'
' OFF LED Command
' ---------------
If Command=2 then
Gosub LEDsOFF
If Yvariable>0 then
CounterW=Yvariable*1000
Pause CounterW
Gosub LEDsON
endif
endif
'
' BLINK LED Command
' -----------------
If Command=3 then
For CounterA=1 to Yvariable
Gosub LEDsON
Pause 200
Gosub LEDsOFF
Pause 200
Next CounterA
endif
'
' SWEEP Command
' -------------
If Command=4 then
CounterB=Xvariable
If CounterB<1 then CounterB=1
For CounterA=1 to CounterB
For Xvariable=1 to 5
Gosub LEDsON
Pause 100
Gosub LEDsOFF
Next XVariable
Next CounterA
endif
'
' BEER Command
' ------------
If Command=5 then DEBUG REP $00\8,13,10,"Yes Please!"
'
' Tell User all executed OK
' -------------------------
DEBUG REP $00\8,13,10,"OK"
Goto EchoCRLF

'
' Subroutine Area
' ===============

'
' Subroutine extracts Numeric Value from Command Line
' ---------------------------------------------------
GetNumericWord:
DataA=0
BadFlag=0
If CounterA>2 then Goto BadWord
If CounterA>0 then
CounterB=CommsBuffer(0)
If CounterB<48 then goto BadWord
DataA=CounterB-48
If DataA>9 then goto BadWord
If CounterA=2 then
CounterB=CommsBuffer(1)
If CounterB<48 then goto BadWord
CounterB=CounterB-48
If CounterB>9 then goto BadWord
DataA=DataA*10+CounterB
endif
endif
Return
BadWord:
BadFlag=1
Return

'
' Shuffle Data to remove processed word
' -------------------------------------
ShuffleData:
For CounterB=0 to 9
CounterC=CounterA+CounterB
If CounterC<=9 then
CommsBuffer(CounterB)=CommsBuffer(CounterC)
else
CommsBuffer(CounterB)=0
endif
Next CounterB
'
' Subroutine removes leading SPACES (Blanks) from Buffer
' ------------------------------------------------------
LSpace:
If CommsBuffer(0)=32 then
For CounterA=1 to 9
CommsBuffer(CounterA-1)=CommsBuffer(CounterA)
Next CounterA
CommsBuffer(9)=0
Goto LSpace
endif
Return

'
' Subroutine Locates end of Dataword in Comms Buffer
' --------------------------------------------------
' CounterA on exit End Point
REnd:
For CounterA=0 to 9
If CommsBuffer(CounterA)=32 then goto REndExit
If CommsBuffer(CounterA)=0 then goto REndExit
Next CounterA
CounterA=10
REndExit:
Return

'
' Subroutine tells User to Wait
' -----------------------------
WaitMessage:
DEBUG REP $00\8,13,10,"Wait..."
Return

'
' Subroutine DISABLES LEDs
' ------------------------
LEDsOFF:
If Xvariable=0 then
LEDStatus=$1F
else
LEDStatus.0(Xvariable-1)=1
endif
PortC=LEDStatus '*****CHANGED TO C FROM A
Return

'
' Subroutine ENABLES LEDs
' -----------------------
LEDsON:
If Xvariable=0 then
LEDStatus=$0
else
LEDStatus.0(Xvariable-1)=0
endif
PortC=LEDStatus '******* CHANGED TO C FROM A
Return

End

Melanie
- 2nd June 2008, 09:28
I would query first that perhaps you are not receiving 100% good Data...

Replace ReadLoop with this code...



ReadLoop:
DEBUGIN [DataA]
DEBUG DataA," ",HEX2 DataA,10,13
Goto ReadLoop


This will echo the HEX representation of what has been received... so if you type Richard you should get...

R 52
i 69
c 63
h 68
a 61
r 72
d 64

where the character is what you typed along with its HEX as confirmation of good data...

If every 2nd character is not what you expected, then time to find out why...

grounded
- 2nd June 2008, 15:37
thanks
I will "play" some more
I thought I mite have missed something when I converted

grounded
- 4th June 2008, 06:28
up date
I tried using hyperterminal and everything works just as it should
I then tried MCS serial communicator (again) with readloop get hex and all I got was R 52
SOO the code is good , the hardware is good there is just something I'm missing using MCS comm. One big difference hyperterm. is real time key stroke to echo, MSC only after manual CR.
I also tried realterm. sometime the echo worked but never the LED (BLINK, SWEEP, ON OFF ETC.) ideals.
thanks

ibralfy
- 15th July 2008, 19:15
Dear Melanie

Please I need your help if , i try to construct project to control 8 devices by using pic16f84

one as transmitter and another pic as a receiver to control 8 relays and to read the status of relays which one is open and which one is closed , if the relay switch is on the led indicate that is on in transmitter (frist pic) in this case i can switched off.


would you please can you help me ?


thank you very much



Eng. ibrahim elalfy

my private E-mail is

[email protected]

ibralfy
- 15th July 2008, 20:05
Dear Melanie

Please I need your help if , i try to construct project to control 8 devices by using pic16f84

one as transmitter and another pic as a receiver to control 8 relays and to read the status of relays which one is open and which one is closed , if the relay switch is on the led indicate that is on in transmitter (frist pic) in this case i can switched off.


would you please can you help me ?


thank you very much



Eng. ibrahim elalfy

my private E-mail is

[email protected]

skimask
- 15th July 2008, 20:11
Please I need your help if , i try to construct project to control 8 devices by using pic16f84
one as transmitter and another pic as a receiver to control 8 relays and to read the status of relays which one is open and which one is closed , if the relay switch is on the led indicate that is on in transmitter (frist pic) in this case i can switched off.

Good plan posting your real email address!
See this thread:
http://www.picbasic.co.uk/forum/showthread.php?t=1742
You'll get help, just post your info...

Leonardo
- 25th November 2008, 18:50
Hello,

¿How can I change the baud rate to 2400?. ........ Solved

Thank you

Sean_Goddard
- 2nd October 2017, 12:35
I know not strictly to do with PIC Basic, but if anyone is interested, I rewrote this into ProtonBasic (Crownhill) :eek: and it works just fine. I'll post the code here when I'm on my own PC.