Comparing UART received text with a pre-defined string

General discussion on mikroC PRO for PIC.
Post Reply
Author
Message
MSWR
Posts: 14
Joined: 02 Feb 2019 16:15

Comparing UART received text with a pre-defined string

#1 Post by MSWR » 06 May 2023 17:27

:?:
Hi MikroE,
I'm new to MikroC and learning/working with UART now. Successfully initiated, send and receive some text via UART using following code:

Code: Select all

char uart_rd;
char Command[] = "M1_ON"; //Represents Motor1 ON
//
//TRISE, ANSEL etc. configuration here
//
UART1_Init(9600);        
Delay_ms(100);

UART1_Write_Text("M1_ON");

  while (1) {                    
    if (UART1_Data_Ready()) {    
      uart_rd = UART1_Read();     // read the received data,
      UART1_Write(uart_rd);       // and send data via UART
    }
  }
  
Simulating it through Proteus and virtual Terminal says Tx/RX is successful.
Now I want to execute the following pseudo-code:

Code: Select all

if uart_rd == "M1_ON" then RA1_bit=1; //Turn ON Motor1
//And same other commands here . . . . .
In other words I want to compare received text with a predefined string. In this way I want to create a number of commands that can be used to control different devices like Motor1, Relay1 etc. How can I do it?
I've tried

Code: Select all

 if(strcmp(uart_rd, Command))==0;{
 RA_bit=1;
 } 
to compare both string variables but it never returned a zero. Probably I'm missing some fundamental concept regarding strings.
Any kind help is highly appreciated; please keep it easy and simple as possible.
Humble regards.

frank.malik
Posts: 96
Joined: 09 Apr 2021 20:37

Re: Comparing UART received text with a pre-defined string

#2 Post by frank.malik » 08 May 2023 10:13

Hi,

the semicolon after the "==0" is a little bit suspicious.

Can you check the length of both strings first?
Upper/lower case issue?
What is the actual result of strcmp() if it isn't 0 ?

Instead of setting the constant string value, you may use strcpy. It might be safer.
Kind regards
Frank

Fusion for STM32 v8, STM32F407ZG@168MHz, 4" TFT capacitive
mikromedia 3, PIC32MZ2048EFH100@200MHz, 3" TFT capacitive
NECTO Studio 3.0.0, mikroC AI for ARM/PIC32, mikroSDK v.2.7.2

MSWR
Posts: 14
Joined: 02 Feb 2019 16:15

Re: Comparing UART received text with a pre-defined string

#3 Post by MSWR » 08 May 2023 20:37

Hi Frank,Thanks for reply.
The semicolon after the "==0" is a typo. No UPER/lower case issue for both strings. I write both strings for matching.
I could not check the string length. How to check it?
I could not observe the actual strcmp() result. However if I use this code

Code: Select all

 if(strcmp(uart_rd, Command)) !=0 {
 RA_bit=1;
 }
 
then RA1 become High which means both strings are not the same. Meanwhile I also tried to pass uart_rd variable to LCD in search of what actually is it? but it is simply ignored by compiler. I use following is test code for LCD.

Code: Select all

 
    LCD_OUT(1,1,"Hello"); //This is displayed correctly indicating the LCD connections are OK.
    LCD_OUT(2,2,Result); //This is simply ignored without any error or warning, I Don't know why?
    
My basic goal, for now, is to match both strings and get RA_bit=1 if both are same.
Regards.

jumper
Posts: 466
Joined: 07 Mar 2007 14:36

Re: Comparing UART received text with a pre-defined string

#4 Post by jumper » 09 May 2023 03:22

Hi,

I think you have several problems with your code.

1:

Code: Select all

char uart_rd;

This is a byte variable and can not be used to store an entire string consisting of several characters. 


2:

Code: Select all


if (UART1_Data_Ready()) {    
      uart_rd = UART1_Read();     // read the received data,
      UART1_Write(uart_rd);       // and send data via UART
    }

The above code will read ONE byte and put in the uart_rd variable overwriting the previous data
3:

Code: Select all

 if(strcmp(uart_rd, Command))==0{
 RA_bit=1;
 }
 
 What do you think is the return value from STRCMP if uart_rd='A'  and Command = "ABCD" .. probably anything except 0. 
 You can not compare a single BYTE with a STRING and expect to get 0 since it will fail comparison on byte 2 in the string and therefore return 2.
4:

Code: Select all

If you run this code on real HW then we aware that PORTA can be tricky so make sure you can toggle the LED on and OFF using your code before trying to use it as a debugging indicator. RA_bit must be defined and the pin setup correctly.

What to do?
Study the difference between BYTE and STRING variables and then if you still want to use the compiler library for reading the command then use UART_READ_TEXT() to get an entire command string read into the UARD_RD variable and declare that variable as a string with suitable length or if this is a program you plan to make bigger then start learning how to use interrupts to collect the received data into STRING variable. Then the software can do more things than just sit and wait for a command.

IF you want to try you can maybe make Command 1 byte long and see if you can get that to work first. If you do that then a simple "if (uart_rd==Command) " should be enough and no need to use string compare because you have 2 byte variables to compare.

Code: Select all


char uart_rd[10];
char Command[] = "M1_ON"; //Represents Motor1 ON    for EACH COMMAND SENT ON THE UART $ should be used as terminating character
//
//TRISE, ANSEL etc. configuration here
//


main(){
UART1_Init(9600);        
Delay_ms(100);

UART1_Write_Text("M1_ON");

  while (1) {                    
    if (UART1_Data_Ready() == 1) {          // if data is received 
    UART1_Read_Text(uart_rd, "$", 10);    // reads text until '$' is found
    UART1_Write_Text(uart_rd);             // sends back text 
    
     if(strcmp(uart_rd, Command))==0{
           RA_bit=1;
           }
           else RA_bit=0;
         }
     }
}  
CODE NOT TESTED!!

MSWR
Posts: 14
Joined: 02 Feb 2019 16:15

Re: Comparing UART received text with a pre-defined string

#5 Post by MSWR » 09 May 2023 11:00

Hi Jumper,
Thanks for reply. You made things a lot clear.
Toggling RA1_bit is verified and all TRISE configuration is OK. As I mentioned earlier that I'm missing something the most basic. And here it is; uart_rd variable is a char so it can't hold a string. I'll try with UART_READ_TEXT().
Command consisting only one character is a good idea except it would be difficult to recognize many commands like 1,2,3,.... or A,B,C,,,,, etc with associated function.. But still it's really good to start with. I'll try all the stuff and hope it'll be working some way.
Again thanks for help. :-)

jumper
Posts: 466
Joined: 07 Mar 2007 14:36

Re: Comparing UART received text with a pre-defined string

#6 Post by jumper » 09 May 2023 15:36

Code: Select all


LCD_OUT(1,1,"Hello"); //This is displayed correctly indicating the LCD connections are OK.
    LCD_OUT(2,2,Result); //This is simply ignored without any error or warning, I Don't know why?
    
The reason you think it is a compiler problem is because you did a mistake.

Result from strcmp is a numerical value. To be able to print it out you need to convert it to an acsii representation of that value. This can be done either using library functions or in this case just adding 48 to the result. For example if the result is zero then the ascii character for 0 is result +48

The compiler did not ignore your line but i suspect that lcd_out only works with printable characters from the acsii table.

Study some more and convert the result value to a string before passing it to the lcd_out function and see what happens.

MSWR
Posts: 14
Joined: 02 Feb 2019 16:15

Re: Comparing UART received text with a pre-defined string

#7 Post by MSWR » 10 May 2023 15:11

Hi Jumper, Thanks for further updates.
I understand that strcmp() is returning a numerical value so I've also tried with IntToStr((), ShortToStr(), but the result was same. Nothing was displayed on LCD.
As you suggested, I tried with a single character transmission and it was successful. :)
I also tried UART1_Write_Text() and UART1_Read_Text() but result is same as before. Probably I'm not properly getting around with mechanism. A practical example would be nice if possible.
Now here I've a straight question. If I use following code,

Code: Select all

 char uart_rd[6]; // or [5] or [10] etc.
 UART1_Write_Text("Hello); //Tx the string Hello
 // And then receive it using
 uart_rd=UART1_Read_Text("Hello); //Rx the string
Does uart_rd, now, have the complete string "Hello" inside it ? Can uart_rd be used in place of "Hello" ?

Appreciating your great help and precious time.

jumper
Posts: 466
Joined: 07 Mar 2007 14:36

Re: Comparing UART received text with a pre-defined string

#8 Post by jumper » 10 May 2023 15:57

Short answer is no.

For uart_read_text to work you need these things
1: a string variable to store received data into

2: the message you want to receive MUST have a delimiter. That is a character or characters that will tell the function that the end of message has arrived.

In the below example i used $ as end of message character.

So the message you send from the PC should look like this:

M1_ON$
or
M1_OFF$

EACH COMMAND MUST END WITH THE DELIMITER CHARACTER.

It is also smart to make the uart_rd string longer than what is required just to make sure the entire command will fit plus the extra character null that the uartreadtext function adds to rhe string.

UART1_Read_Text(uart_rd, "$", 10);

That line will put up to 10 received characters into the uart_rd variable unless a $ character is found. As soon as the $ character is found then the function will exit and uart_rd should now have valid data. I am not sure if the $ sign is added to uart_rd or not but you can find out by sending the uart_rd string to the lcd to see what it contains.

There are plenty of good examples in the help file for the uart read text function that works.

Code: Select all



char uart_rd[10];
char Command[] = "M1_ON"; //Represents Motor1 ON    for EACH COMMAND SENT ON THE UART $ should be used as terminating character
//
//TRISE, ANSEL etc. configuration here
//


main(){
UART1_Init(9600);        
Delay_ms(100);

UART1_Write_Text("STARTED");

  while (1) {                    
    if (UART1_Data_Ready() == 1) {          // if data is received 
    UART1_Read_Text(uart_rd, "$", 10);    // reads text until '$' is found
     
     UART1_Write_Text("received:");             // sends back text 
     UART1_Write_Text(uart_rd);             // sends back text 
     UART1_Write(10);             // new line and carriage return
     UART1_Write(13);             // 
    
          }
    
}  
CODE NOT TESTED!!


MSWR
Posts: 14
Joined: 02 Feb 2019 16:15

Re: Comparing UART received text with a pre-defined string

#9 Post by MSWR » 11 May 2023 06:53

Hi Jumper, thanks for reply.
As far I know delimiter is included in the message because virtual terminal in proteus includes it along with text. So we can use the last two or three alphabets as delimiter. (i-e "ON").
"M1_ON$" will be displayed aling with $.
I searched and found tons of articles and videos to send and receive characters via UART (almost all the same wording and it was pretty simple) but unfortunately couldn't find any working example about receiving text (and doing something useful with it except displaying it on virtual terminal :D ). Probably because it is not as simple as I was expecting. Anyway, very thankful to you for great help. At least now I can communicate using single character commands. Based on this, now I can start with my PCB design too. I hope someday I would be able to manipulate uart strings. If you encounter any practical example please share it.
Thanks and humble regards :)

jumper
Posts: 466
Joined: 07 Mar 2007 14:36

Re: Comparing UART received text with a pre-defined string

#10 Post by jumper » 11 May 2023 12:33

No no nooooooo

If you use more than one character as delimiter then how to you send the OFF command?

Can you send M1_ON$ from the pc and get your firmware to send back the received string to the PC with only having $ as delimiter character?

If yes then we can move on with trying to compare strings. If no then we need to find out why you cant get the command received from the PC.

Please explain what is working and not working for you now and post the entire code you use.

If you can send back the received string using only $ as delimiter then comparing should be pretty easy.

paulfjujo
Posts: 1557
Joined: 24 Jun 2007 19:27
Location: 01800 St Maurice de Gourdans France
Contact:

Re: Comparing UART received text with a pre-defined string

#11 Post by paulfjujo » 20 May 2023 08:54

hello,


maybe the better way is to use a buffer and RX interrupt

2 cases : you have a terminator character at the end of your command (sended by PC terminal Keyboard)
like a <CR> ( code =13 = 0x0D)
or you don't have it ,but you know what is the maximum lenght of your command.

case 1 :

see details in firts part of example.c.txt

use string comparaison :
form of the commande like this : CONS1=xxxx<CR>
CR as terminator
then xxxx value is extract in the code.

Code: Select all

 if(DataReady1==1)
   {
     *(Buffer1+12)=0; // limite taille
     CPrint("\r\nRec=");
     Print(Buffer1);
     p0=strstr(Buffer1,"CONS");
     // test cdes  CONS1=xxxx<CR>   CONS2=xxxx<CR>
     if (p0>0)  // action to do
     { 
      ... etc ....
         .... etc ......
   


case 2 :


see second part in example.c.txt
The buffer is filled with incomming data
and you check individual character inside the buffer to recognize a command

Code: Select all

  if (Flag_Buffer1==1) // c'est donc une Interrupt UART
   {
      p1=Buffer1;
      if((*(p1)=='H') && (*(p1+3)=='p'))     //Help<CR>
     {
       UART1_Write_CText("\r\n Help : Help<CR>  \r\n");
       UART1_Write_CText(" RTC Update: U;14;05;18;15;36;02#<CR>\r\n");
       UART1_Write_CText(" exemple pour :14 Mai 2018 02(Lundi) 15H36\r\n");
       UART1_Write_CText(" Plage Luminosité Minimale PLM=18:06<CR>\r\n");
       UART1_Write_CText(" Aff=1=Affiche Trame en binaire sur terminal sinon,  Aff=0 sur Matrices <CR>\r\n");
       UART1_Write_CText(" Seepd=xx  vitesse de defilement xx de 01 à 99 <CR>\r\n");
       UART1_Write_CText(" Msg=x...x de 8 à 40 caracteres Affiche le message x...x pendant 1 mn <CR>\r\n");
       UART1_Write_CText(" et affichage Date reduit et pas de temperatures pendant le Msg Affiché <CR>\r\n");

    //   UART1_Write_CText(" Message à afficher <32 cars : Msg=blabla<CR>\r\n");
       CRLF1();
      p1=0;
     }
     if((*(p1)=='U') && (*(p1+20)=='#'))     //U;12;05;18;15;36;02;#<CR>
     {
       UART1_Write_CText(" Cde RTC Update : ");
       UART1_Write_Text(Buffer1);
       CRLF1();
       MAJ_RTC();
       .... etc ......
         .... etc ...... 
       
Case 3 :
NO CR at the end of command

just test individual caractere from the 1rst position in the Buffer1
by systematique pooling ... after RAZ buffer and a little delay to permit the receiving data
(a time window is necessary to detect interrupt and fill the buffer !)

example.c.zip
(6.38 KiB) Downloaded 31 times

Post Reply

Return to “mikroC PRO for PIC General”