NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » 2 MCUs via USART not consistent

April 02, 2011
by Schrat
Schrat's Avatar

I am communicating from one MCU to another using USART. I started wirelessly with the GP-GC010 (GPs) and had sporadic results. Sometimes I would turn the system on and it communicated fine and other times it would not. Thinking it was the GPs, I took them out of the equation and replaced them with wireless doorbells (not giving me the flexibility that I want). Using the chime to trigger an interrupt and then transmitting from pin 3 -

uint32_t serial; 
int b  = 0;
printf_P(PSTR("%lu %d\n"), serial, b);

to pin 2 on the receiving MCU. Again sporadic results. Once it powers up and works, it continues to operate just fine. Since it works sometimes and not others with the only change being turn the system off and on, I am assuming it is not a software issue. The code is written that if serial does not match one of the two “serial” numbers it loops back up to the “scanf_P(PSTR("%lu %d"), &serial, &b);”. It seems to work consistently if I power up the transmitting MCU before the receiving MCU which does not help me if I go back to the GPs. Additionally it does not help with my desire to understand why. I have connected a resistor from pin 3 TXD to GND and this has increased the percentage of time it works from about 10% to about 90%. I am switching the GND to turn the system on and off and have attempted switching the POS, which did not seem to matter. The entire system is fairly complicated and I am hoping this is enough info to have someone see the error in my ways.

April 02, 2011
by Noter
Noter's Avatar

How long is the wire connecting them and what baud rate are you using?

April 02, 2011
by Schrat
Schrat's Avatar

When I was using the GPs it was in a PCB and the track traveled about an inch and past thru a single pole double throw switch that allows me to reroute to program the chip. When I removed the GP I added a 9 inch wire and then it travels the thru the same switch and track. Baud rate is 19200bps.

April 04, 2011
by Schrat
Schrat's Avatar

I have now removed all the code and components that do not affect the problem I am having.

When the tMCU is turn on first and then the rMCU everything works fine. If the tMCU is then turned off or the transmitting wire disconnected the value of p on the rMCU infinity increases. Turning the tMCU on again does nothing.

If the tMCu is turned on second or turned off before transmitting, the value of serial remains 88. Turning the tMCU on again does nothing.

tMCU code

#define F_CPU 14745600

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

// PIN DEFINITIONS:
// PC3 = 26 -- keyer input switch (pulled to ground when pressed)
// PC4 = 27 -- LED YELLOW

uint32_t serial; //serial number 655
int16_t b  ;//Varible that is transmitted  
int8_t push;// flag to tell if button push

int main() {

  serial = 0;
  b = 1;
  push = 0;

  PORTC |= (1<<PC3);// enable internal pullup on PC3 (the button)
  DDRC |= (1<<PC4);// enable LED on PC4

  // fire up the LCD
  lcd_init();
  lcd_home();

  // start up the serial port
  uart_init();
    UBRR0L = 47;    // for 19200bps with 14.7456MHz clock

  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

 lcd_write_int16(serial);
   lcd_write_string(PSTR(" B =   "));
  lcd_write_int16(b);

    while(1){

 while(PINC & (1<<PC3)) { //Waits for keypress = exit loop
    }

        serial = 655;
        PORTC |= (1<<PC4);// turn on LED yellow

 while((PINC & (1<<PC3))==0) {// stops and waits for button release

}
        printf_P(PSTR("%lu %d\n"), serial, b);// write message to serial port   
        PORTC &= ~(1<<PC4);// turn off LED

   push++;

    // Clear screen
  //             20 columns wide:
  //                     01234567890123456789
  lcd_line_one();
  lcd_write_string(PSTR("                    "));
  lcd_line_two();
  lcd_write_string(PSTR("                    "));
  lcd_line_three();
  lcd_write_string(PSTR("                    "));
  lcd_line_four();
  lcd_write_string(PSTR("                    "));

   lcd_line_one();
  lcd_write_int16(serial);
  lcd_write_string(PSTR(" B =   "));
  lcd_write_int16(b);
  lcd_line_two();  
  lcd_write_string(PSTR(" push "));
  lcd_write_int16(push);

  }
       return 0;
}

rMCU code

    #define F_CPU 14745600

    #include <stdio.h>
    #include <math.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    #include <util/delay.h>
    #include <inttypes.h>
#include <stdlib.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"

int main() {
  uint32_t serialh;
  uint32_t serial;//Serial that is transmitted  
  int b;
  int8_t p;   //counts by value of b
  int8_t z; //only = 2 at beginning

    serialh  = 655;// input side 0
    serial  = 88;//Serial that is transmitted  
    b = 0;// int transmitted
    p = 0;   //counts by value of b
    z= 2; //only = 2 at beginning

  // fire up the LCD
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  lcd_home();

     // start up the serial port
  uart_init();
    UBRR0L = 47;    // for 19200bps with 14.7456MHz clock

  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

    lcd_line_one();
  lcd_write_int16(serialh);
  lcd_write_string(PSTR(" B =   "));
  lcd_write_int16(b);
   lcd_line_two();
  lcd_write_string(PSTR("Before scanf loop"));

  while(1) {

 while(z){
 scanf_P(PSTR("%lu %d"), &serial, &b);

 if((serial == serialh) && (b != 2)){
        p = p + b;
        z = 0;}//kicks out of scan loop

 lcd_home();

    // Clear screen 20 columns wide:
  //                     01234567890123456789
  lcd_line_one();
  lcd_write_string(PSTR("                    "));
  lcd_line_two();
  lcd_write_string(PSTR("                    "));
  lcd_line_three();
  lcd_write_string(PSTR("                    "));
  lcd_line_four();
  lcd_write_string(PSTR("                    "));

   lcd_line_one();
  lcd_write_int16(serial);
  lcd_write_string(PSTR(" B =   "));
  lcd_write_int16(b);
   lcd_line_two();
  lcd_write_string(PSTR("P     =  "));
  lcd_write_int16(p);
   lcd_line_four();
  lcd_write_string(PSTR("In the scan loop"));

}//end of scan loop

    z = 1;//resets flag for scan loop

 lcd_home();

    // Clear screen 20 columns wide:
  //                     01234567890123456789
  lcd_line_one();
  lcd_write_string(PSTR("                    "));
  lcd_line_two();
  lcd_write_string(PSTR("                    "));
  lcd_line_three();
  lcd_write_string(PSTR("                    "));
  lcd_line_four();
  lcd_write_string(PSTR("                    "));

   lcd_line_one();
  lcd_write_int16(serial);
  lcd_write_string(PSTR(" B =   "));
  lcd_write_int16(b);
   lcd_line_two();
  lcd_write_string(PSTR("P Bot = "));
  lcd_write_int16(p);
   lcd_line_three();
  lcd_write_string(PSTR("Kicked out of loop"));

}

  return 0;
}
April 04, 2011
by Noter
Noter's Avatar

I think if you change from using scanf over to just reading in a single character at a time to build your input string, you will discover your problem. Scanf may be ok for reading files but it's not so good for communication lines that can drop a character or sometimes get an extra one from noise. Especially when reading more than one variable at a time.

April 06, 2011
by Schrat
Schrat's Avatar

I finally have reliable communication between two MCUs. Inserting the following code just before the scanf_p.

if(UCSR0A = (1<<RXC0));{//if unread data clears USART
        UCSR0B &= ~(1<<RXEN0);//sets RXEN0 to 0 and disables Usart clearing all
        UCSR0B |= (1<<RXEN0);//sets RXEN0 to 1 = enables USART
}

Starting both MCUs simultaneously must have put some data in the receive buffer that corrupted the data I was attempting to transmit. Page 191 of the data sheet explains what is happening with the above code.

In problem solving, I found that “lcd_write_int16(UCSR0A);” actually shows the value of UCSRnA register and then I used an excel program to do the bit math.

I also notice that occasionally the rMCU receives a signal that would send it past the scanf_p without changing the values that were transmitted the time previously. To correct this, before the scanf_p I set the values being received to a value that would normally not be used and after the scanf_p I checked that the values actually had been changed. If they had not, I told the program to disregard these values and return to the scanf_p.

Hopefully transferring this from my wired prototyping board into the wireless application will go as easily as I am anticipating (as a saying goes, one cannot be a programmer without being an eternal optimist).

April 06, 2011
by Noter
Noter's Avatar

Glad you got it figured out. I always implement communcation functions binary byte oriented so I can send/receive variable length blocks of binary data. Additionally I crc the block to be sure all bytes made it thus an incorrect crc indicates junk and the whole block is discarded. Add in an ACK/NAK so the sender can retransmit failures and you have bullet proof communications for any serial/wireless connection.

Being an eternal optimist is good and you need a boat load of patience too.

April 06, 2011
by Schrat
Schrat's Avatar

I did attempt communicating via binary byte but I did not know where to start and after several attempts my boat load of patience sank.

Thanks

May 09, 2011
by kle8309
kle8309's Avatar

Hi, Just one question on the sure-electronics link the GP-GC010 no longer exist but there are two other choices:

2pcs Wireless RF Transceiver 431-470MHz GFSK Data Transfer

20dBm Wireless 2.4GHz Transceiver Module 600m 2pcs - NRF2401A

May 09, 2011
by kle8309
kle8309's Avatar

which one should I buy? and I have done some research on the Xbee module from sparkfun should I invest in that?

May 10, 2011
by Schrat
Schrat's Avatar

I have just received 4 of the RMB-CM12111s from Sure Electronics and they seem to communicate consistently. http://www.sureelectronics.net/goods.php?id=1053 I am having difficulty sending more than an 8-bit packet at a time. I do not believe this is because of the hardware but probably because I don’t what I am doing.

May 20, 2011
by kle8309
kle8309's Avatar

Hi Schrat, Were you able to get rf-maginc working. Don't you need a pc with rs-232 port? Because, ultimately I wanted to be able to change the RFID and stuff.

May 25, 2011
by Schrat
Schrat's Avatar

No, I was unable to get the RF Magic software to connect. I purchased the “CP2102 USB/TTL/RS232 Serial Port Converter”. I did notice someone posted on Sure Electronics the following:

Leave EN pin of a module unconnected! Then connect TxD and RxD and GND lines of a module to your USB<->COM converter. DO NOT connect Vcc pin of a module. Than connect converter to your PC. Start RF-Magic software. And only after all these manipulations connect Vcc pin of a module to 5v! Then press "Read" button of RF-Magic software. It must read the configuration of a module successfully. I am confused why manufacturer(seller) didn't provide such instructions list. Best regards from Lithuania

Have not had time or the need to try it.

Post a Reply

Please log in to post a reply.

Did you know that you can build a circuit to convert the "dit" and "dah" of Morse code back into letters automatically? Learn more...