Author Topic: PIC 16F1503 to Arduino nano UART communication  (Read 1054 times)

0 Members and 1 Guest are viewing this topic.

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
PIC 16F1503 to Arduino nano UART communication
« on: December 04, 2018, 12:21:44 pm »
I am not able to Send the Charactor '1' from PIC 16F1503 to Arduino nano receiver module. Its works fine between Arduino nano transmitter and receiver modules. But PIC to Arduino having problem. Please find below the transmitter PIC16F1503 code for your reference. Please put some light on my long way worry.  :--

************TRANSMITTER (PIC 16F1503) CODE************************
Code: [Select]

#include <xc.h>
#include <pic.h>

// by default frequency is 500KHz

#define Baudrate 1200 //bps
#define OneBitDelay (125000/Baudrate)
#define DataBitCount 8 // no parity, no flow control
#define UART_RX LATAbits.LATA1 //PORTAbits.RA1 // UART RX pin
#define UART_TX LATAbits.LATA0 //PORTAbits.RA0 // UART TX pin
#define UART_RX_DIR TRISA1 // UART RX pin direction register
#define UART_TX_DIR TRISA0 // UART TX pin direction register

//Function Declarations
void InitSoftUART(void);
void UART_Transmit(unsigned char);

// CONFIG1
 #pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
 #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
 #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
 #pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
 #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
 #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
 #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
 
 // CONFIG2
 #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
 #pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
 #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
 #pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
 #pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)



void main()
{

 ANSELA = 0x00; // Set ports as digital I/O, not analog input
 PORTA = 0x00;
 TRISA = 0x00; // Make all pins 0

         
 

 InitSoftUART(); // Intialize Soft UART

 while(1)
 {

  UART_Transmit('1'); //

 }
}


void InitSoftUART(void) // Initialize UART pins to proper values
{
 UART_TX = 1; // TX pin is high in idle state
 
 UART_TX_DIR = 0; // Output
}


void UART_Transmit(unsigned char DataValue)
{
 /* Basic Logic
   
    TX pin is usually high. A high to low bit is the starting bit and
    a low to high bit is the ending bit. No parity bit. No flow control.
    BitCount is the number of bits to transmit. Data is transmitted LSB first.

 */

 // Send Start Bit
 UART_TX = 0;
 __delay_us(OneBitDelay);
  UART_TX = 1;
 __delay_us(OneBitDelay*2);
  UART_TX = 0;
 __delay_us(OneBitDelay);

 for ( unsigned char i = 1; i /* 8bits*/; i <<= 1 )
 {

 //Set Data pin according to the DataValue

    if(DataValue & i) //if Bit is high
        {
            UART_TX = 1;
        }
    else //if Bit is low
        {
            UART_TX = 0;
        }

     __delay_us(OneBitDelay);
 }

 //Send Stop Bit
 UART_TX = 1;
 __delay_us(OneBitDelay*10);
}


**************************************ARDUINO_NANO_RECEIVER**************************
Code: [Select]

#include <VirtualWire.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
//LiquidCrystal lcd(7,6, 5, 4, 3, 2); //lcd (rs, enable, d4, d5, d6, d7)


#define ledPin 10
#define relay 9

char buf[100];

int pos = 0;

void setup()

{

lcd.begin();
Serial.begin(9600);

pinMode(ledPin, OUTPUT);
pinMode(relay, OUTPUT);

digitalWrite(ledPin, LOW);
digitalWrite(relay, LOW);

vw_set_ptt_inverted(true);

// Required for DR3100

vw_set_rx_pin(11);

vw_setup(1200); // Bits per sec

vw_rx_start(); // Start the receiver PLL running

}

void loop()

{
 
Serial.print(Serial.read());

uint8_t buf[VW_MAX_MESSAGE_LEN];

uint8_t buflen = VW_MAX_MESSAGE_LEN;

if (vw_get_message(buf, &buflen))

// Non-blocking

{

if(buf[0] == '1')

{

     digitalWrite(ledPin, HIGH);
     digitalWrite(relay, HIGH);
     
     lcd.setCursor(0,1);
     lcd.clear(); // clear display
     lcd.print("WATER LOW");
     delay(1000);
     lcd.clear(); // clear display

     lcd.setCursor(0,1);
     lcd.print("PUMP ON");

}

if(buf[0] == '0')

{

     digitalWrite(ledPin, LOW);
     digitalWrite(relay, LOW);
     
     lcd.setCursor(0,1);
     lcd.clear(); // clear display
     lcd.print("WATER ENOUGH");

   

}

if(buf[0] == 'x')

{

     digitalWrite(ledPin, LOW);
     digitalWrite(relay, LOW);
     
     lcd.setCursor(0,1);
     lcd.clear(); // clear display
     lcd.print("Float Error");

}

if(buf[0] == 'S')

{

     digitalWrite(ledPin, LOW);
     
     
     lcd.setCursor(0,1);
     lcd.clear(); // clear display
     lcd.print("TX Sleeping");

}

}
}
« Last Edit: December 05, 2018, 05:01:12 am by sumithcmohan »
 

Offline Buriedcode

  • Super Contributor
  • ***
  • Posts: 1293
  • Country: gb
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #1 on: December 04, 2018, 12:58:24 pm »
Well.. a few things.

Firstly, please use code tags to post code.  Its the # symbol just below "font size" when posting. Alternatively, put your code between the html tags [ code] and [ /code]  (without the sapce between [ and c.

Secondly, please say what compiler you're using.  Many will assume XC8 with MPLAB X but the "InitSoftUART" looks like MikroC to me.  Which is it?

Your void UART_Transmit routine looks odd.  You send 0110 (a start bit, then 1 for two bit periods, then a 0) before sending your byte, and a stop bit. Why?  This makes no sense.  It jsut needs to be a start bit (a bit 0).  The for loop, whilst I understand you're shifting a 1 through a byte, doesn't look like it actually ends.  I'm unsure why you are making life so difficult for yourself when all you have to do is:

Code: [Select]
UART_TX = 0;
__delay_us(OneBitDelay);
for(i=0;i<8;i++) {
    if(DataValue & 0x80) // if MSBit is high
        {
            UART_TX = 1;
        }
    else //if Bit is low
        {
            UART_TX = 0;
        }
    DataValue <<= 1;
    __delay_us(OneBitDelay);
    }
UART_TX = 1;
__delay_us(OneBitDelay);


You may need to tweak the OneBitDelay value, although at such a low baud it shouldn't matter. 
 
The following users thanked this post: sumithcmohan

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #2 on: December 05, 2018, 04:55:31 am »
Thanks @Buriedcode  for your suggestions.



Well.. a few things.

Firstly, please use code tags to post code.  Its the # symbol just below "font size" when posting. Alternatively, put your code between the html tags [ code] and [ /code]  (without the sapce between [ and c.


Thanks for this information

Quote

Secondly, please say what compiler you're using.  Many will assume XC8 with MPLAB X but the "InitSoftUART" looks like MikroC to me.  Which is it?



I am using the compiler XC8 with MPLAB X.

Quote

Your void UART_Transmit routine looks odd.  You send 0110 (a start bit, then 1 for two bit periods, then a 0) before sending your byte, and a stop bit. Why?  This makes no sense.  It jsut needs to be a start bit (a bit 0).  The for loop, whilst I understand you're shifting a 1 through a byte, doesn't look like it actually ends.  I'm unsure why you are making life so difficult for yourself when all you have to do is:

Code: [Select]
UART_TX = 0;
__delay_us(OneBitDelay);
for(i=0;i<8;i++) {
    if(DataValue & 0x80) // if MSBit is high
        {
            UART_TX = 1;
        }
    else //if Bit is low
        {
            UART_TX = 0;
        }
    DataValue <<= 1;
    __delay_us(OneBitDelay);
    }
UART_TX = 1;
__delay_us(OneBitDelay);


You may need to tweak the OneBitDelay value, although at such a low baud it shouldn't matter. 

I tried this. Still my serial print at receiver module is like this, while tried to send '1' from PIC transmitter

Code: [Select]




Its blank. What is wrong here.

I have placed the Serial.print() function here.

Code: [Select]

if (vw_get_message(buf, &buflen))

// Non-blocking

{
 
Serial.println(buf[0]);

if(buf[0] == '1')

{

« Last Edit: December 05, 2018, 07:38:10 am by sumithcmohan »
 

Offline Buriedcode

  • Super Contributor
  • ***
  • Posts: 1293
  • Country: gb
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #3 on: December 05, 2018, 02:37:01 pm »
Ok, now that I can read the code better with the tags, I think I see the problem.

You're using the virtualwire library to receive, but you're sending plain old serial (with a start and stop bit?).  Please tell us what exactly you are trying to achieve here, are you planning on sending the data wirelessly and just trying to send it over wire as a test? is this for IR communication?  I believe the protocol (channel coding) of the virtualwire library is very different from standard UART.

When you said it works with Arduino transmitting, I assumed you had used the exact same code for the Arduino to transmit during the test.

So either you must use the virtual wire library from your PIC, which I don't think is possible since the library is written for Arduino, and written in C++ (XC8 is plain 'ol C). Or... you need to write your own library for XC8 to send the data in the same format as virtualwire.  The latter shouldn't be too hard, especially if you're just planning on sending a few bytes.

This is the danger of using libraries without knowing exactly what the library is doing :)
 
The following users thanked this post: sumithcmohan

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #4 on: December 06, 2018, 10:18:44 am »
Quote
You're using the virtualwire library to receive, but you're sending plain old serial (with a start and stop bit?).  Please tell us what exactly you are trying to achieve here, are you planning on sending the data wirelessly and just trying to send it over wire as a test? is this for IR communication?  I believe the protocol (channel coding) of the virtualwire library is very different from standard UART.

I am planning to send data wirelessly through a 433MHz RF transmitter.

Quote

When you said it works with Arduino transmitting, I assumed you had used the exact same code for the Arduino to transmit during the test.

yes, same code used in that case.

Quote
So either you must use the virtual wire library from your PIC, which I don't think is possible since the library is written for Arduino, and written in C++ (XC8 is plain 'ol C). Or... you need to write your own library for XC8 to send the data in the same format as virtualwire.  The latter shouldn't be too hard, especially if you're just planning on sending a few bytes.

I tried other way.


 

Offline Buriedcode

  • Super Contributor
  • ***
  • Posts: 1293
  • Country: gb
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #5 on: December 06, 2018, 11:22:41 am »
Ok, to transmit data over a 433MHz link, as you have found out you must use something other than standard UART formatting.  I believe "virtual wire" uses some other form of channel coding, possibly manchester coding, or sending specific symbols per bit.  This is so there are equal numbers of 0's and 1's, because any wireless link cannot transmit a DC component, so the data must be balanced.  It also provides plenty of transitions (no longer strings of 0's or 1's) so that the receiver can synchronize to the data - this is why manchester encoding is used, as it is "self clocking", there is a transition in the middle of every data bit, allowing the receiver to easily distinguish between bits.

You said you used the same code for both the Arduino transmitter, and the PIC transmitter.  In that case I don't see how the code you posted can work, as it just sends "0110" then 8 bits of data.  Where-as according to the virtual wire documentation, it requires a long preamble, and sends each "bit" as a 4 or 6-bit symbol.  Perhaps the "0110" is one of these symbols?

Apologies if I'm missing something, but it seems like the virtual wire library is more complicated than you realize. Sending data over RF isn't easy, and whilst prebuilt libraries can help a lot, it is often best to know what that library is doing. I'm sure it can be ported to a PIC micro, but it doesn't just send data via a UART, it appears to be much more involved.  This guy apparently ported it to a PIC32:

http://webedh.free.fr/?page_id=36

If you wish to use 433Mhz modules and PIC's, but don't want to use virtual wire, then Roman Black has an excellent write-up: https://www.romanblack.com/RF/cheapRFmodules.htm
Although I tend to hate "instructables" as they often leave out vital information: https://www.instructables.com/id/Wireless-Communication-Using-Cheap-433MHz-RF-Modul-1/
 
The following users thanked this post: sumithcmohan

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #6 on: December 07, 2018, 12:58:15 pm »
Thanks for the Romanblack code. I am trying on it. Will update the status tomorrow.
 

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #7 on: December 08, 2018, 05:35:58 pm »
Finally with your great support I have made a good communication between Pic 16F1503 and Arduino nano using the marvelous romanblack code. The final code will update here on Monday.

I am very thankful to buried code for getting  a unconditional support on my coding issues. Today I am very happy and get rid off the long one week coding meditation 🧘‍♂️. Now confidence leveled up.
 

Offline Buriedcode

  • Super Contributor
  • ***
  • Posts: 1293
  • Country: gb
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #8 on: December 08, 2018, 06:26:46 pm »
No problem, thats what the forum is for!

Also note that, there are many ways to communicate with these modules. Some good search terms would be "channel coding", "line coding", etc..  Also, there are many standards that are well documented, reading up on these shows the different kinds of synchronization, error detection/correction, and modulation used.  Stuff like Keeloq, used for remotes have at least two different standards..
 

Offline sumithcmohan

  • Contributor
  • Posts: 8
  • Country: in
Re: PIC 16F1503 to Arduino nano UART communication
« Reply #9 on: December 13, 2018, 06:42:18 am »
I have successfully made wireless communication between PIC and Arduino. See the codes below.

PIC16F1503 Code for Transmission to arduino nano

Code: [Select]

void send_rf_byte(unsigned char txdat)
{


  //-------------------------------------------------------
  // This is a pulse period encoded system to send a byte to RF module.
  // Bits are sent MSB first. Each byte sends 9 pulses (makes 8 periods).
  // Timing;
  //   HI pulse width; always 80uS
  //   0 bit, LO width; 20uS (total 0 bit pulse period 100uS)
  //   1 bit, LO width; 70uS (total 1 bit pulse period 150uS)
  //   space between bytes, LO width; 170uS (total space period 250uS)
  // (timings tested with 20MHz xtal PIC 18F, no pll)
  //-------------------------------------------------------
  unsigned char tbit;

  // make 250uS start bit first
  __delay_us(PAUSE_LO);      // 170uS LO
  UART_TX= 1;
  __delay_us(PAUSE_HI);     // 80uS HI
  UART_TX = 0;
 
    for(tbit=0; tbit<8; tbit++)
     {
       __delay_us(DEFULT_LO);             // default 0 bit LO period is 20uS
       if(txdat&(1<<7))__delay_us(INCREASE_LO);  // increase the LO period if is a 1 bit!
       UART_TX = 1;
       __delay_us(HI_PULSE);             // 80uS HI pulse
       UART_TX = 0;
       txdat <<= 1;                // roll data byte left to get next bit
     }
 
    __delay_ms(150);


    SLEEP();
       
       }

Arduino nano Receiver code

Code: [Select]

void loop()
{
  //-------------------------------------------------------
  // This function receives an RF packet of bytes in my pulse period
  // encoded format. The packet must have 10 valid contiguous bytes
  // or the function will not exit. There is no timeout feature, but could be added.
  // global variable; unsigned char rxdat[10] holds the 10 byte result.
  // Note! TMR0 is running at 500kHz, so 200uS = 100 TMR0 ticks
  //-------------------------------------------------------
  unsigned char rrp_data;
  //unsigned char rrp_period;
  float rrp_period;
  unsigned char rrp_period2;
  unsigned char rrp_bits;
  unsigned char rrp_bytes;
 
signa = digitalRead(receiver);

  rrp_bytes = 0;
  while(rrp_bytes < 5)   // loop until it has received 10 contiguous RF bytes
  {
    //-----------------------------------------
    // wait for a start pulse >200uS
    while(1)
    {
     
      rrp_period = pulseIn(receiver,LOW)/multipier;         // grab the pulse period!
      //rrp_period2 = pulseIn(receiver,HIGH);         // grab the pulse period!
      //rrp_period = rrp_period1 + rrp_period2;
      //Serial.println(rrp_period);
                     // and ready to record next period
      if(rrp_period < 250) rrp_bytes = 0;   // clear bytecount if still receiving noise
      else break;                   // exit if pulse was >200uS
    }

    //-----------------------------------------
    // now we had a start pulse, record 8 bits
    rrp_bits = 8;
    while(rrp_bits)
    {
     
      rrp_period = pulseIn(receiver,LOW)/multipier;         // grab the pulse period!
     
      //Serial.println(rrp_period);
      if(rrp_period >= 250) break;  // if >=200uS, is unexpected start pulse!

      if(rrp_period < 80) bitWrite(rrp_data, 0, 0);    // 61 = 122uS
      else               bitWrite(rrp_data,0,1);
      //Serial.println(rrp_data);
      if (rrp_bits!=1) rrp_data = (rrp_data << 1);   // save the good bit into rrp_data
      rrp_bits--;                   // and record 1 more good bit done
    }
      //Serial.println(rrp_data);
    //-----------------------------------------
    // gets to here after 8 good bits OR after an error (unexpected start pulse)
    if(rrp_bits)      // if error
    {
      rrp_bytes = 0;  // reset bytes, must run from start of a new packet again!
    }
    else              // else 8 good bits were received
    {
      rxdat[rrp_bytes] = rrp_data;  // so save the received byte into array
      rrp_bytes++;                  // record another good byte was saved

      //Serial.print("LOW float instruction = ");
      //Serial.println(rxdat[0]);
      //Serial.print("HIGH float instruction = ");
      //Serial.println(rxdat[1]);

    }
      Serial.print("instruction = ");
      Serial.println(rxdat[0]);
      task(rxdat[0]);


  }

         

}

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf