CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Debuggin an RS232 transmission between PICC and Aruduino C
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Debuggin an RS232 transmission between PICC and Aruduino C
PostPosted: Sun Nov 11, 2018 7:31 am     Reply with quote

Hello! I am trying to create a working communication between "nodeMCU" v1.0, rev 2 and PIC16F690. I am using the CCS PIC C compiler and the arduino IDE with built in compiler. I have debugged the code and reached that during the RS232 transmission, the code never passes to the next command. I am guessing some setting is missing, like the end bit or something thats different between the 2 compilers. Can someone help me set the transmission right, so I can send strings. I have successfully sent integers with the "getc ()" function of PIC C.

"PIC16F690" code:
Code:

/************************************************************************
*                                                                       *
*   Filename:      main.c                      *
*   Date:          01-11-2018                                 *
*   File Version:  1.0                                         *
*                                                                       *
*   Author:        Arakel Horov                                        *
*   Company:                                                *
*                                                                       *
*************************************************************************
*                                                                       *
*   Architecture:  mid-range PIC                                         *
*   Processor:      PIC16F690                                   *
*   Compiler:      CCS PIC C                                 *
*                                                                       *
*************************************************************************
*                                                                       *
*   Files required: none                                                *
*                                                                       *
*************************************************************************
*                                                                       *
*   Description:                                          *
*                                                      *
*                     
*                                                      *
*************************************************************************
*                                                                       *
*   Pin assignments:                                                    *
*                                                                       *
************************************************************************/

//LCD module connections
#define LCD_RS_PIN PIN_C0
#define LCD_RW_PIN PIN_C1
#define LCD_ENABLE_PIN PIN_C2
#define LCD_DATA4 PIN_C3
#define LCD_DATA5 PIN_C4
#define LCD_DATA6 PIN_C5
#define LCD_DATA7 PIN_C6
//End LCD module connections

                                                /*** INCLUDE MACRO LIBRARIES, OTHER LIBRARIES *****/
#include <16F690.h>
#use delay(clock=4M)                             /* specifies the clock frequency in order to use the "delay_()"                                         /* function, must always be right after "#include <Processor>" */
#include <lcd.c>            /* Driver for the LCD display */

                                                /***** CONFIGURATION *****/
#fuses NOPROTECT, NOWDT, INTRC                         /* int. reset, no code protect, no watchdog, int. RC clock with clock pins as digital, int. oscilator/4 */
#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B5, bits=8, errors)                                                                           

                                                /*** Pin assignments ***/
                                             
                                                /***** CONSTANTS *****/
                                   
                                                /***** PROTOTYPES *****/
void Initialization ();                    /* The function Initialized the ports to the states and the */
                                    /* internal modules (timer, ADC, comparator, etc.) as we want them */
                                    /* By default the pins are set to their analog state on power-on or */
                                    /* reset, they can not be used as digital, so we need to disable the */
                                    /* analog modules and use the pins */
void Receive_RS232 ();
void Send_RS232 (int8 Send_data);
void Display ();
void Keypad ();
void Timer ();

                                                /***** MACROS *****/
                                               
                                                /****** GLOBAL VARIABLES*****/
unsigned int8 Flags; /* Bit coded. */                                   
                                                /***** MAIN PROGRAM *****/

void main ()
{
                                    /****** local variables *****/
    unsigned int8 i;
    char RS232_Receive_byte;
                           /*** Initialisation ***/
Initialization ();
lcd_init();                         // Initialize LCD module                                   

                                                                       
                                             
                                                /*** Main loop ***/
 while (1)
 {
   lcd_putc ('\f');
   printf(lcd_putc,"Everything works");
   gets (RS232_Receive_byte);
   delay_ms (500);
   printf(lcd_putc,"%s", RS232_Receive_byte);
   printf(lcd_putc,"End of RS232");
   delay_ms (500);
   
 }
}
                                                /***** FUNCTIONS *****/
                                   
 void Initialization ()
 {
                                                   /*** Initialisation ***/
                                   
                                                                        /* configure ports */
                                                                        /* on default (reset, power-on) all analog inputs (ADC, comparators, CVref) are enabled */
                                             
                                                                        /* configure comparator */
   setup_comparator (NC_NC_NC_NC);                                                     
                                                                        /* configure programmable voltage reference */
   setup_vref (FALSE);                                                  /* the programmable voltage reference pin is disabled, RC2 is digital */
                                                     
                                                                        /* configure ADC */
   setup_adc (NO_ANALOGS);                                              /* OPTION1: ADC module is disabled to conserve power, ADC pins are available as digital */
   //setup_adc (ADC_CLOCK_INTERNAL);                                    /* OPTION2: Use the internal RC oscilator as the clock for the conversion, turn ADC module on */
                                                                        /* The minimum/maximum conversion time is from 500uS to 50mS, we can not set the internal RC clock to something else */
                                                                        /* Tconversion = 13xTad, Tad = instruction clock/4, instruction clock = RC clock = 4MHz */
                                                                        /* If the instruction clock is different, we will get not accurate results */
   //setup_adc (ADC_CLOCK_DIV_16);                                      /* OPTION3: Specifying ADC accuracy */
   //setup_adc_ports (sAN0);                                               /* Pins available for ADC input */
   //set_adc_channel (0);                                                 /* Active pin to sample at the moment, since we have                                                  only 1 ADC module and only 1 pin (channel) can sample */
                                                                        /*at one time, this can be used in the main cycle if we have more than 1 channel */
   
   //setup_dac (DAC_VSS_VDD);                                             /* Setup the DAC if present */
                                                      /* Use "dac_write (variable)", in order to write to the DAC */                                                   
                                                                        /* configure timer */
   setup_timer_0 (RTCC_INTERNAL | T0_DIV_256);                     /* No timer is userd */
                                                     
   delay_ms (100);                                          /* Delay in order to prevent any pin
                                                      problems, because the pins after a restart and power on are enabled on their default function (as output, input, analog input), and that might cause problems without a resistor to ground as they may accept a value which should not be accepted, this can
                                                      happen once in a 100 restarts, 10 restarts or some other number */                                                   
}

void Receive_RS232 ()
{
   Flags = getc ();
}

  void Send_RS232 (int8 Send_data)
{
   delay_ms (1);
   putc (Send_data);
}

void Display ()
{
   unsigned int8 i;
 for (i=120; i<255; i++)
 {
      /* Flags = getch (); */
      printf(lcd_putc,"i %u, Flags %d", i, getch ()); /* We need to use "%u" to print in unsigned format or on the display we will have +127 to - 128. */
      output_b (Flags << 6);
      delay_ms (500);
      lcd_putc ('\f');
      output_b (0);
      delay_ms (500);   /* When we put this delay, that breaks the communication with the nodeMCU module, thats why the total delay of the program must be the same
                        as the delay in the nodeMCU, meaning 500 + 500 = 1000mS */
 }
}


Arduino "nodeMCU" v1.0, rev2 code:
Code:

#include <ESP.h>
#include <ESP8266WiFi.h>

int Flags = 1; /* Bit coded. */

void setup()
{
  // start serial port at 9600 bps:
  Serial.begin(9600);
  Serial1.begin (9600);
}

void loop()
{
/*** First program ***/

    Serial.print ("ESP connected.");
    delay (1000);
 
/*** Second program ***/



}

_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Update
PostPosted: Sun Nov 11, 2018 7:58 am     Reply with quote

Update:

When I send "5" with nodeMCU, I receive "53" on the "PIC.

"nodeMCU" v1.0, rev2 code:
Code:

Serial.print (5);
delay (1000);


"PIC16F690" code:
Code:

 while (1)
 {
   lcd_putc ('\f');
   /*
   printf(lcd_putc,"Everything works");
   lcd_putc ('\n');
   */
   printf(lcd_putc,"%d",  getc ());
  /* printf(lcd_putc,"End of RS232"); */
   delay_ms (1000);
   
 }
}

_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Sun Nov 11, 2018 8:59 am     Reply with quote

You would....

You need to start to understand how ASCII works, and what is being sent.
The ASCII character for the letter '5', is 0x35. 53 decimal.

The code on your Arduino, sends the numbers as text. Just as if you typed
them in. Now the big problem you have is that this is all you are sending. You need to send some form of terminator character, or the receiving program cannot tell when a number ends. Currently, if you send:

Serial.print (5);
Serial.print (5);

55 gets sent. With nothing to separate the digits. How is the receiving code, to know the difference between these two separate numbers (5 & 5), and the code sending a larger number like:

Serial.print(55);

You need to be sending a terminator. Use the Arduino function Serial.println,
instead of serial.print. This then adds a linefeed after the number.

Then your receiving code can use gets, which will receive a string, until a
line feed is seen. This can then be turned into the correct number using
atol (look at the manual, since there are different 'ato' functions depending
on the size of the value you expect to receive.
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Reply to Ttelmah
PostPosted: Sun Nov 11, 2018 11:08 am     Reply with quote

Thanks Ttelmah! I understand the ASCII part.

I am guessing the "ln" function puts the last bit in the 10 bit RS232 packet, meaning its the end bit?

As for the "ato" function I have to look it up, but I do not know much about it.
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Sun Nov 11, 2018 11:26 am     Reply with quote

No. The println functin, prints the data as a _line_. So adds a line feed after the value printed.

Gets, gets a 'line' of text from the serial. So will generate a text array containing the number and automatically store a string 'null terminator' in place of the line feed.

Then atol converts a numeric string of text into a long integer. There are also atoi (converts only to a 8bit integer), and atof that read a float.
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Updated version
PostPosted: Sun Nov 11, 2018 12:44 pm     Reply with quote

Even the "atoi" function does not work. The PIC does not seem to receive the code, I do not know why. The terminal at arduino shows its sent.

"PIC16F690" code:
Code:

/************************************************************************
*                                                                       *
*   Filename:      .txt                      *
*   Date:          5-04-2017                                 *
*   File Version:  1.0                                         *
*                                                                       *
*   Author:        Yordan Itsov                                        *
*   Company:                                                *
*                                                                       *
*************************************************************************
*                                                                       *
*   Architecture:  Baseline PIC                                         *
*   Processor:      PIC16F506                                   *
*   Compiler:      CCS PIC C v5.061                                   *
*                                                                       *
*************************************************************************
*                                                                       *
*   Files required: none                                                *
*                                                                       *
*************************************************************************
*                                                                       *
*   Description:                                          *
*                                                      *
*                     
*                                                      *
*************************************************************************
*                                                                       *
*   Pin assignments:                                                    *
*                                                                       *
************************************************************************/

//LCD module connections
#define LCD_RS_PIN PIN_C0
#define LCD_RW_PIN PIN_C1
#define LCD_ENABLE_PIN PIN_C2
#define LCD_DATA4 PIN_C3
#define LCD_DATA5 PIN_C4
#define LCD_DATA6 PIN_C5
#define LCD_DATA7 PIN_C6
//End LCD module connections

                                                /*** INCLUDE MACRO LIBRARIES, OTHER LIBRARIES *****/
#include <16F690.h>
#use delay(clock=4M)/* specifies the clock frequency in order to use the "delay_()"                                         /* function, must always be right after "#include <Processor>" */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lcd.c>            /* Driver for the LCD display */

                                                /***** CONFIGURATION *****/
#fuses NOPROTECT, NOWDT, INTRC                         /* int. reset, no code protect, no watchdog, int. RC clock with clock pins as digital, int. oscilator/4 */
#use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)                                                                         

                                                /*** Pin assignments ***/
                                             
                                                /***** CONSTANTS *****/
                                   
                                                /***** PROTOTYPES *****/
void Initialization ();                    /* The function Initialized the ports to the states and the */
                                    /* internal modules (timer, ADC, comparator, etc.) as we want them */
                                    /* By default the pins are set to their analog state on power-on or */
                                    /* reset, they can not be used as digital, so we need to disable the */
                                    /* analog modules and use the pins */
void Receive_RS232 ();
void Send_RS232 (int8 Send_data);
void Display ();
void Keypad ();
void Timer ();

                                                /***** MACROS *****/
                                               
                                                /****** GLOBAL VARIABLES*****/
unsigned int8 Flags; /* Bit coded. */                                   
                                                /***** MAIN PROGRAM *****/

void main ()
{
                                    /****** local variables *****/
                                   
                           /*** Initialisation ***/
Initialization ();
lcd_init();                         // Initialize LCD module                                   

                                                                       
                                             
                                                /*** Main loop ***/
 while (1)
 {
   Receive_RS232 ();

 }
}
                                                /***** FUNCTIONS *****/
                                   
 void Initialization ()
 {
                                                   /*** Initialisation ***/
                                   
                                                                        /* configure ports */
                                                                        /* on default (reset, power-on) all analog inputs (ADC, comparators, CVref) are enabled */
                                             
                                                                        /* configure comparator */
   setup_comparator (NC_NC_NC_NC);                                                     
                                                                        /* configure programmable voltage reference */
   setup_vref (FALSE);                                                  /* the programmable voltage reference pin is disabled, RC2 is digital */
                                                     
                                                                        /* configure ADC */
   setup_adc (NO_ANALOGS);                                              /* OPTION1: ADC module is disabled to conserve power, ADC pins are available as digital */
   //setup_adc (ADC_CLOCK_INTERNAL);                                    /* OPTION2: Use the internal RC oscilator as the clock for the conversion, turn ADC module on */
                                                                        /* The minimum/maximum conversion time is from 500uS to 50mS, we can not set the internal RC clock to something else */
                                                                        /* Tconversion = 13xTad, Tad = instruction clock/4, instruction clock = RC clock = 4MHz */
                                                                        /* If the instruction clock is different, we will get not accurate results */
   //setup_adc (ADC_CLOCK_DIV_16);                                      /* OPTION3: Specifying ADC accuracy */
   //setup_adc_ports (sAN0);                                               /* Pins available for ADC input */
   //set_adc_channel (0);                                                 /* Active pin to sample at the moment, since we have                                                  only 1 ADC module and only 1 pin (channel) can sample */
                                                                        /*at one time, this can be used in the main cycle if we have more than 1 channel */
   
   //setup_dac (DAC_VSS_VDD);                                             /* Setup the DAC if present */
                                                      /* Use "dac_write (variable)", in order to write to the DAC */                                                   
                                                                        /* configure timer */
   setup_timer_0 (RTCC_INTERNAL | T0_DIV_256);                     /* No timer is userd */
                                                     
   delay_ms (100);                                          /* Delay in order to prevent any pin
                                                      problems, because the pins after a restart and power on are enabled on their default function (as output, input, analog input), and that might cause problems without a resistor to ground as they may accept a value which should not be accepted, this can
                                                      happen once in a 100 restarts, 10 restarts or some other number */                                                   
}

void Receive_RS232 ()
{
    unsigned int8 i;
    unsigned int8 Character = 5;
    char RS232_Receive_byte;
    char ch;
    char string[32];
    unsigned int8 val;
   
 /* ch = getc();                       /* receives a single character via RS232 */
 /* printf(lcd_putc,"Stuck 1"); */
 gets(string);
  val = atoi(string);
  delay_ms (1000);
  printf(lcd_putc,"%d\n",  val);
  /* printf(lcd_putc,"End of RS232"); */
}

  void Send_RS232 (int8 Send_data)
{
   delay_ms (1);
   putc (Send_data);
}

void Display ()
{
   unsigned int8 i;
 for (i=120; i<255; i++)
 {
      /* Flags = getch (); */
      printf(lcd_putc,"i %u, Flags %d", i, getc ()); /* We need to use "%u" to print in unsigned format or on the display we will have +127 to - 128. */
      output_b (Flags << 6);
      delay_ms (500);
      lcd_putc ('\f');
      output_b (0);
      delay_ms (500);   /* When we put this delay, that breaks the communication with the nodeMCU module, thats why the total delay of the program must be the same
                        as the delay in the nodeMCU, meaning 500 + 500 = 1000mS */
 }
}


"nodeMCU" v1.0, rev2 code:
Code:

#include <ESP.h>
#include <ESP8266WiFi.h>

String Name = "Text";
int Flags = 1; /* Bit coded. */

void setup()
{
 
  // start serial port at 9600 bps:
  Serial.begin(9600); /* On pins RS and TX, software serial interface RS232 variation. */
  Serial1.begin (9600); /* Hardware serial interface RS232 variation. */
}

void loop()
{
/*** First program ***/
    Serial.println (Name);
    delay (1000);  /* The delay is in "mS". */
 
/*** Second program ***/



}


Result: empty display or a "0".
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Sun Nov 11, 2018 12:58 pm     Reply with quote

Er. You are telling println, to send a text line, not a number.
On your original post you wanted to send a number.

atoi, converts an ASCII test _number_ to a numeric value. If you just want to display the received text, print the 'string', with %s.
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Additional requirements.
PostPosted: Sun Nov 11, 2018 1:00 pm     Reply with quote

With a number I get "0", with a text string I get nothing or only side "M". By the way I want to be able to send both. I need to dive deep into this interface and make it work every time from now on.
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
temtronic



Joined: 01 Jul 2010
Posts: 9255
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Nov 11, 2018 1:05 pm     Reply with quote

PIC serial is 57,600 baud
Ard serial is 9600 baud
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Result
PostPosted: Sun Nov 11, 2018 1:22 pm     Reply with quote

temtronic wrote:
PIC serial is 57,600 baud
Ard serial is 9600 baud


I see :D.
Code:
#use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

I copied the new line with the "parity=N" and it lead to a problem.

Thanks to the both of you!

Sending a number is displayed ok on the LCD 16x2 I2C display, even without the "atio ()" function.
Sending a text is displayed ok on the LCD 16x2 I2C display.
The only problem is that when a text is sent it gets displayed only once and stops. If you have any ideas, they are welcomed :D.

I want to ask how to make it so that only when something is sent from the nodeMCU v1.0 rev2 then the PIC16F690 receive function gets activated, now I need to use an equal delay on both nodeMCU and PIC16F690 in order to make it work. Should I start a new thread?

I guess the "atoi ()" will be needed if I need to process this information and set some port pin high or low.
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Sun Nov 11, 2018 1:25 pm     Reply with quote

and once you have the baud set right, string will contain the text, and you can then test if this contains a number or not.
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Mon Nov 12, 2018 12:56 am     Reply with quote

The receive has to be activated before data arrives.
What you can do is test if data has arrived with kbhit, and
(safer if you do not test very quickly), use an interrupt driven serial buffer.
You can do this by adding 'RECEIVE_BUFFER=32' (or some similar value) to
the #use RS232 declaration (and enabling the global interrupt).
Arakel



Joined: 06 Aug 2016
Posts: 107
Location: Moscow

View user's profile Send private message Visit poster's website AIM Address

Elaboration
PostPosted: Mon Nov 12, 2018 7:43 am     Reply with quote

If I understand correctly, the RS232 data will be recorded in the buffer and I will test the buffer to see if data has arrived?

Why is it needed to make it 32? Should 16 not be enough?
_________________
Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems!
temtronic



Joined: 01 Jul 2010
Posts: 9255
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Nov 12, 2018 8:22 am     Reply with quote

Typically the buffer should be 2X larger than the expected data stream coming in AND be a 'binary' number. Say you expect 20 bytes of data... 2 * 20=40, next binary is 64.
You also have to consider 'processing' time. PICs, like all computers, only do ONE thing at a time, so if it's busy elsewhere, you need to store (buffer) the incoming data until the PIC is free to read it. The larger the buffer the more data can be stored.
newguy



Joined: 24 Jun 2004
Posts: 1911

View user's profile Send private message

PostPosted: Mon Nov 12, 2018 9:04 am     Reply with quote

temtronic wrote:
Typically the buffer should be 2X larger than the expected data stream coming in AND be a 'binary' number. Say you expect 20 bytes of data... 2 * 20=40, next binary is 64.
You also have to consider 'processing' time. PICs, like all computers, only do ONE thing at a time, so if it's busy elsewhere, you need to store (buffer) the incoming data until the PIC is free to read it. The larger the buffer the more data can be stored.


I'd also suggest that a slow baud rate would allow you to use a smaller buffer. For example, at 9600 baud, one character takes 1/960 = 1.04ms to arrive. At 115,200 baud, one character takes just 1/11520 = 86.8us to arrive. All other things being equal, the slower rate allows more "breathing room", code-wise, to allow for parsing/processing of any incoming message.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group