Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Interesting PIC to PIC USART question

Status
Not open for further replies.

NJ Roadmap

New Member
This could have you guys dumbfounded like I am, or it could just be a simple answer!

Basically I have 2 PIC 18F4520s powered independently from two 12V-mains-sourced 5V regulators. I have the USART serial pins of the two PICs connected to each other along with a common ground line, so both the supplies have a common ground even though they are actually independent.

I basically have them talking to each other with PIC-1 waiting for PIC-2 to ask for data, and then PIC-1 transmitting data to PIC-2. This goes on in a loop just for testing purposes. I've got both PICs hooked up to LCDs so I know whats going on.

Now heres the peculiar part. I should theoretically be able to power up PIC-1 and then PIC-2 and immediately have PIC-2 asking PIC-1 for data, PIC-1 responding and the loop continuing. But I can't get that to happen. PIC-1 just waits for data even after PIC-2 has powered on and acknowledged that it has asked PIC-1 for data.

The ONLY way I can currently get around this is if I power on both PICs (in any order), reload the hex file for PIC-1 first while still having the 12V power connected, and then reload the hex file for PIC-2 using the same process. PIC-1 then correctly receives PIC-2's request and sends data back and the loop continues without a hitch.

I'm guessing this is something to do with either the fact that I've got common ground for 2 independent supplies, or something wrong with my code. I plan to eventually have wireless USART using Nigel's tutorials and inverting the signals as opposed to Manchester coding as the communication will be short-range, so the common ground issue will become irrelevant later. I have posted the important bits of my code below:

PIC-1 code (master):

while(1)
{
//approx 1 second delay before next sample and lcd update
for (n = 0; n <50; n++)
for( k= 0; k< twentyms; k++);
lcd_clr();
// initialise
TXSTA=0x26;
SPEN=1;
putch('?'); // Ask for data
LCDWrite('?', 1);
LCDWrite(' ', 1); //Acknowledge sent character to LCD
LCDWrite('s', 1);
LCDWrite('e', 1);
LCDWrite('n', 1);
LCDWrite('t', 1);

lcd_newline();
LCDWrite(getch(), 1); //Waiting...then write received character to LCD
LCDWrite(' ', 1); //Acknowledge receipt to LCD
LCDWrite('R', 1);
LCDWrite('c', 1);
LCDWrite('v', 1);
LCDWrite('d', 1);
}


PIC-2 code (slave):
while(1)
{
lcd_clr();
LCDWrite(getch(), 1); //Waiting...then write received character to LCD
LCDWrite(' ', 1);
LCDWrite('R', 1); //Acknowledge receipt to LCD
LCDWrite('c', 1);
LCDWrite('v', 1);
LCDWrite('d', 1);

//approx 1 second delay before sending character back
for (n = 0; n <50; n++)
for( k= 0; k< twentyms; k++);
// initialise
TXSTA=0x26;
SPEN=1;
putch('F');// transmit the character

lcd_newline();
LCDWrite('F', 1);
LCDWrite(' ', 1); //Acknowledge sent character to LCD
LCDWrite('s', 1);
LCDWrite('e', 1);
LCDWrite('n', 1);
LCDWrite('t', 1);
for (n = 0; n <50; n++)
for( k= 0; k< twentyms; k++);

}

Both PICs have the following serial initialisation:
/* Serial initialization */
void
init_comms(void)
{
SPBRG = DIVIDER;
TXSTA = (SPEED|NINE_BITS|0x20);
RCSTA = (NINE_BITS|0x90);
TRISC6=OUTPUT;
TRISC7=INPUT;
}

Another question: I can currently send one character reliably, what if I want to send a string? I'm planning to send int's and float's from the slave to the master with the master periodically polling the slave, so I was thinking of using sprintf() to append them to a string and then send the string.

Any insights would be appreciated!

p.s. I'm using the Hi-Tech PICC18 compiler and PICKit2 to load HEX files.
 
Last edited:
Why do you have two seperate sets of code for a serial echo routine? The code for both PIC's should be identical you just wire the TX of one to the RX of the other and vice versa. Send char, wait for char with a random timeout delay. If a char isn't received by the time out delay send another char. If you don't have a time out ability in the getch routine all that needs to happen is a single bit transmit or receive error and it will wait forever. There's likley a timeing glitch on the TX/RX line when the PIC's powering on that's keeping the loop from starting when you come up from a cold start. The line could be floating high or load when the PIC starts up in it's natural High Z state. Causing a single bit to be transmitting which starts the getch routine and it just sits there waiting for the next bits which never come.
 
So this is a 3-wire system? Do you have a quickie schematic so that I can take a look at the entire scheme?
 
Its literally 2 PIC18F4520's on independently-powered boards with each RX pin terminating at the other end at a TX pin (so that makes 2 wires) and the third wire is a ground wire, which is explained below.

The ground's of the two independently-powered boards are linked since the RX and TX levels on each board need to have the same reference, or atleast that's what I think.

I haven't actually tried it without the ground pins connected, but will do that tomorrow.

update: I have got the PIC sending strings via the USART to the other PIC by sending a character at a time. I am just wondering how I can implement error correction on a hardware USART if I'm just putting an ASCII char in the TXREG and getting an ASCII character out of the RXREG at the other end?

update 2: I have just had an idea: what if i convert each character in my string into binary, then add parity to it and then send this character as a 9-bit binary string? Or is there a way to do this more easily?
 
NJ Roadmap said:
Its literally 2 PIC18F4520's on independently-powered boards with each RX pin terminating at the other end at a TX pin (so that makes 2 wires) and the third wire is a ground wire, which is explained below.

The ground's of the two independently-powered boards are linked since the RX and TX levels on each board need to have the same reference, or atleast that's what I think.

I haven't actually tried it without the ground pins connected, but will do that tomorrow.

It needs the ground connection, unless you already have one elsewhere?.

update: I have got the PIC sending strings via the USART to the other PIC by sending a character at a time. I am just wondering how I can implement error correction on a hardware USART if I'm just putting an ASCII char in the TXREG and getting an ASCII character out of the RXREG at the other end?

For a simple wired connection there should really be no need?, but if you want to you should look at packet schemes.

update 2: I have just had an idea: what if i convert each character in my string into binary, then add parity to it and then send this character as a 9-bit binary string? Or is there a way to do this more easily?

You can add parity to it anyway, I believe there's even a parity bit setting in the hardware?, but I've never had occasion to use it - a simple parity bit isn't a very good check though!.

How fast are you trying to send?, there really shouldn't be any problems doing this!.
 
It sounds very much to me like a software issue. I can't tell too much from your code, partly because you describe the two PICs as "PIC-1" and "PIC-2" in the text, and then label both code samples as "PIC-2", though I assume that "master" is PIC-2... And, I don't know the specifics of the getch() routine.

But, if the getch() routine is blocking (ie - it doesn't return until something is received), then all it would take is for the slave PIC to miss the "request" character a single time, and then both PICs would sit there in the 'getch()' routine waiting for data, stuck. This is a very poor setup - although if you're powering them up in the order you describe, in theory the slave shouldn't be missing that request, it would be significantly more robust to implement a better scheme where some kind of a timeout is used so that things don't get kicked into an infinite loop. And, if you're planning to actually have the slave DO anything other than constantly sit waiting for the master to request data, you're probably going to want to make use of the USART interrupt so it just jumps to an ISR any time data comes in, handles it, and jumps back to the main program. This could also work well on the master, allowing it to send a request, and go do other things until the response arrives.
 
Nigel Goodwin said:
It needs the ground connection, unless you already have one elsewhere?.
I'm going to add RF capabilities tomorrow with a 433MHz AM module tomorrow, and obviously the 2 grounds will be isolated then. I'm guessing this isn't a problem as you have tried a similar mechanism in your tutorials?


Nigel Goodwin said:
For a simple wired connection there should really be no need?, but if you want to you should look at packet schemes
With USART over RF with simple signal inversion, it would be better if I have some form of error correction wouldn't it? I'd atleast like the receiving PIC to echo what it received to confirm that the data wasn't corrupted, and if it was, get the originally transmitting PIC to resend it? I'd rather not use this method though as even the echo-ed data may be corrupted.

Nigel Goodwin said:
You can add parity to it anyway, I believe there's even a parity bit setting in the hardware?, but I've never had occasion to use it - a simple parity bit isn't a very good check though!.
I know the USART has a ninth-bit setting but from what I read in the data sheet I'd have to manually load it, so I'm guessing this means I write the character into TXREG after writing the parity bit for that character into TX9D
(the 9th bit of transmit data). I know simple parity error-checking isn't very useful as theres still a chance that 2 bits may be wrong and hence parity would not be able to detect it, but is there a better solution?

Nigel Goodwin said:
How fast are you trying to send?, there really shouldn't be any problems doing this!.
Currently over wires at 9600bps, but I'm willing to take this down to as low as necessary when sending over RF in order to reduce error rates, considering I'm using the crude solution of signal inversion as opposed to Manchester Coding.
 
NJ Roadmap said:
I'm going to add RF capabilities tomorrow with a 433MHz AM module tomorrow, and obviously the 2 grounds will be isolated then. I'm guessing this isn't a problem as you have tried a similar mechanism in your tutorials?

you need a GND connection if there is no RF link between them. wire needs ground. if you make it wireless then no ground is needed. it's basic electronics. every thing must have a GND.


good luck with it ;)
 
evandude said:
It sounds very much to me like a software issue. I can't tell too much from your code, partly because you describe the two PICs as "PIC-1" and "PIC-2" in the text, and then label both code samples as "PIC-2", though I assume that "master" is PIC-2... And, I don't know the specifics of the getch() routine.
Yeah sorry about that, my bad!

void
putch(unsigned char byte)
{
/* output one byte */
while(!TRMT) /* set whilst TX in progress */
continue;
TXREG = byte;
}

unsigned char
getch() {
/* retrieve one byte */
while(!RCIF) /* set when register is not empty */
continue;
return RCREG;
}

evandude said:
But, if the getch() routine is blocking (ie - it doesn't return until something is received), then all it would take is for the slave PIC to miss the "request" character a single time, and then both PICs would sit there in the 'getch()' routine waiting for data, stuck. This is a very poor setup - although if you're powering them up in the order you describe, in theory the slave shouldn't be missing that request, it would be significantly more robust to implement a better scheme where some kind of a timeout is used so that things don't get kicked into an infinite loop. And, if you're planning to actually have the slave DO anything other than constantly sit waiting for the master to request data, you're probably going to want to make use of the USART interrupt so it just jumps to an ISR any time data comes in, handles it, and jumps back to the main program. This could also work well on the master, allowing it to send a request, and go do other things until the response arrives.

Yeah I realised that. The original code (which has now been expanded a lot) works pretty well but as you mention above it can go terribly wrong if a character has been missed. I am hence going use an ISR on the slave PIC to overcome this. My main issue now is how I can implement something better than just parity-checks (I haven't even found the need for this as the data received is pretty clean, but once I install RF capabilities tomorrow I probably will need it..)
 
Also with respect to RF, I am using a RX module and a TX module at each end but they will both be operating at 433MHZ so I am planning to use a half-duplex process as follows. Please let me know if you think this will work:

Note: Master PIC will idle in TX mode and Slave PIC in RX mode

1. Master polls slave for data (some sort of query character(s)) and then switches to RX mode
2. Slave receives polling query and switches to TX mode
3. Slave sends sensor data to Master (preset number of characters) and switches to RX mode
4. Master receives preset number of characters and then switches back to TX mode

I expect the polling interval (step 1) to be about 5 mins as none of the sensor data is critical to the master and all control is done on the slave. The master is literally a dumb-terminal for data display and some user inputs which need to be transmitted to the slave. If this data is to be transmitted to the slave I plan to implement the following process, very similar to the above process for sensor data polling:

Note: Master PIC will idle in TX mode and Slave PIC in RX mode

1. Master send slave heads-up that it is sending user inputs (some sort of 'heads-up' characters) and switches to RX mode, waiting for ACK data
2. Slave receives 'heads-up' data and switches to TX mode
3. Slave sends ACK data and switches to RX mode
4. Master receives ACK data and then switches back to TX mode
5. Master sends user inputs (preset number of characters) to slave and STAYS in TX mode
6. Slave receives user inputs and STAYS in RX mode

I guess I could implement some sort of ACK packet sending at every step of the process. Can anyone see any flaws in the above processes?
 
Major flaw is the RF link, as your UART is waiting for a start bit, then if the signal drops too weak it will generate false start bits, and false data. This is another advantage of the Manchester coding.

AM modules may not be as bad as FM though?, as with FM you get the white noise when the signal drops.

The modules I used have a signal strength output on an extra pin, you could monitor that, and only enable the UART if the signal is strong enough.
 
This module doesn't have a singal strength pin unfortunaltely. I chose AM because they were cheaper than the comparable FM module from the same company. It turns out that it may actually be better than FM for this application! The module outputs 3.6V for a high and 0.6V for a low. Will 3.6V be enough for the USART to detect a high?

Link to RF Solutions AM-HRR30-433 datasheet: https://www.electro-tech-online.com/custompdfs/2007/02/61126.pdf
 
NJ Roadmap said:
This module doesn't have a singal strength pin unfortunaltely. I chose AM because they were cheaper than the comparable FM module from the same company. It turns out that it may actually be better than FM for this application! The module outputs 3.6V for a high and 0.6V for a low. Will 3.6V be enough for the USART to detect a high?

Should be fine, logic levels are generally VERY compatible with each other.
 
Nigel Goodwin said:
Major flaw is the RF link, as your UART is waiting for a start bit, then if the signal drops too weak it will generate false start bits, and false data. This is another advantage of the Manchester coding.

AM modules may not be as bad as FM though?, as with FM you get the white noise when the signal drops.
I am confused about this, can you elaborate a bit about when a signal may drop too weak? (whats confusing me is that i am using inversion so surely a drop in signal should keep it high?)

I am planning to use ZTX653 NPNs for the signal inversion and planning to transmit and receive at 300bps to start off with to reduce chances of errors. Hopefully this will work tomorrow!
 
Heres a link where I'm getting my info for the transistor inverters:
http://www.kpsec.freeuk.com/trancirc.htm

Any general purpose low power NPN transistor can be used. For general use RB = 10k and RC = 1k, then the inverter output can be connected to a device with an input impedance (resistance) of at least 10k such as a logic chip or a 555 timer (trigger and reset inputs)

For TX, the transistor output side will be connected to the DATA-IN of the TX module. Im not sure whether the input impedance will be high enough...any thoughts?

p.s. Thanks for the help so far!
 
Last edited:
NJ Roadmap said:
I am confused about this, can you elaborate a bit about when a signal may drop too weak? (whats confusing me is that i am using inversion so surely a drop in signal should keep it high?)

Sorry, it's not the logic level going low, it's the signal level going low - this may (and WILL for FM) cause the logic level to randomly change.

I am planning to use ZTX653 NPNs for the signal inversion and planning to transmit and receive at 300bps to start off with to reduce chances of errors. Hopefully this will work tomorrow!

As in your other post, the simple NOT gate will be fine, there's no impedance problems to worry about, it's all just logic.
 
NJ Roadmap said:
Heres a link where I'm getting my info for the transistor inverters:
http://www.kpsec.freeuk.com/trancirc.htm

Thats a great site!!

Just one thing about RF data transfer with wireless modules, Is it better to transmitt in inverted mode rather than normal mode to reduce the error rate? (if so, why)
 
gramo said:
Thats a great site!!

Just one thing about RF data transfer with wireless modules, Is it better to transmitt in inverted mode rather than normal mode to reduce the error rate? (if so, why)

Check my PIC Wireless tutorial at which explains why!.
 
I've just soldered the RF modules and inverters on. Yet to test it, but was wondering whether inversion is necessary for AM modules too?

Also, probably a silly question but I'd rather ask it than not: can the the RX and the TX modules share the same antenna? This is assuming that only one module is on at a time.
 
NJ Roadmap said:
I've just soldered the RF modules and inverters on. Yet to test it, but was wondering whether inversion is necessary for AM modules too?

I would have thought so, it's the AC coupling which requires it.

Also, probably a silly question but I'd rather ask it than not: can the the RX and the TX modules share the same antenna? This is assuming that only one module is on at a time.

It's usually done via PIN diode switching, I wouldn't suggest just connecting them together.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top