Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

My PIC16F887 is sending AT Comands to my LCD instead of the UART PORT

Status
Not open for further replies.

ComputerAngel

Junior Member level 2
Joined
May 28, 2017
Messages
22
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
202
Hello, I am working on automatic irrigation system with gsm notification. I used a potentiometer to step down the voltge level to 2.9v for the gsm module. When I run the codes below however, the microcontroller(PIC16F887) outputs the "AT" commands on my LCD instead of pushing them to the UART PORT and as such the gsm module is unable to send sms. I need help

Code:
#include<stdio.h>
    // LCD module connections
    sbit LCD_RS at RB4_bit;
    sbit LCD_EN at RB5_bit;
    sbit LCD_D4 at RB0_bit;
    sbit LCD_D5 at RB1_bit;
    sbit LCD_D6 at RB2_bit;
    sbit LCD_D7 at RB3_bit;

    sbit LCD_RS_Direction at TRISB4_bit;
    sbit LCD_EN_Direction at TRISB5_bit;
    sbit LCD_D4_Direction at TRISB0_bit;
    sbit LCD_D5_Direction at TRISB1_bit;
    sbit LCD_D6_Direction at TRISB2_bit;
    sbit LCD_D7_Direction at TRISB3_bit;
    // End LCD module connections
   
                     unsigned int temp;
                     unsigned int humi;
                     float h;
                     float a;
                     float hs;
                     float r_per;
                     float attemp ;
                     char humidity [4];
                     char msg1[] = "System failure.";
                     char msg[] =  "Humidity level normalized";
                     char number[] = "AT+CMGS=\"+2348187848800\"";
                     char car[] = "AT+CSCS=\"GSM\"";
                     char start[] = "AT+CMGF=1";
              void write_lcd()
                  {
                    Lcd_Cmd(_LCD_CLEAR);
                    Delay_ms(300);
                    Lcd_Out(1,1, "Initializing....");
                    Delay_ms(5000);
                    Lcd_Cmd(_LCD_CLEAR);
                    Delay_ms(500);
                    Lcd_Out(1, 1, "Initialization");
                    Lcd_Out(2, 3, "Complete");
                    Delay_ms(5000);
                    Lcd_Cmd(_LCD_CLEAR);
                    Delay_ms(200);
                   }



void main(){
    ADC_Init();
    UART1_Init(9600);
    ANSEL  = 0;                      
    ANSELH = 0;
    Lcd_Init();
    Lcd_Cmd(_LCD_CURSOR_OFF);
    TRISA0_bit = 1;
    TRISD = 0;
    TRISC = 0;
    RD2_bit =0;
    RC3_bit = 0;
    RC2_bit = 0;
    RC1_bit = 0;
    RC0_bit = 0;
    Delay_ms(200);
    RC3_bit = 1; //This sets the blue LED on system boot.
    Delay_ms(100);
    write_lcd();
    RC3_bit = 0;  //after system boot it is then turned off.
    Delay_ms(500);


  while(1) {
                 humi = ADC_Get_Sample(1);
                 h = (humi*5000)/1023;
                 hs = h/1000;
                 r_per = hs*20; //
                 a = (100-r_per);
                 FloatToStr(a, humidity);
                 humidity[4] = 0;
                 Lcd_Cmd(_LCD_CLEAR);
                 Delay_ms(500);
                 Lcd_Out(1, 1, "Irrigation Init");
                 Lcd_Out(2,1, "Humidity:");
                 Lcd_Out(2,12, humidity);
                 Delay_ms(3000);
                 if(hs >= 2)
                   {
                    //RC3,RC2,RC1,RC0 ==red led, green led, blue led and water sensor
                    RC3_bit = 1; //Turn ON Blue LED
                    RD2_bit = 1; //Turn ON the water pump
                    Delay_ms(9000);
                     if(RC4_bit == 1) //after turning ON the water sensor, check if it's despencing
                       {
                   UART1_Write_Text("AT");
                   UART1_Write(0x0D);
                   Delay_ms(5000);
                   UART1_Write_Text("ATE0");
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(start);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(car);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(number);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(msg);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write(0x1A);
                   Delay_ms(100);
                        RC3_bit = 1;
                        Delay_ms(1500);
                        RC3_bit = 0;
                        Delay_ms(4000);

                       }
                       else
                       {

                   UART1_Write_Text("AT");
                   UART1_Write(0x0D);
                   Delay_ms(5000);
                   UART1_Write_Text("ATE0");
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(start);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(car);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(number);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write_Text(msg1);
                   UART1_Write(0x0D);
                   Delay_ms(100);
                   UART1_Write(0x1A);
                   Delay_ms(3000);
                         RC3_bit = 1;
                         Delay_ms(2000);
                         RC3_bit = 0;
                         RD2_bit = 0; //Shutdown the water pump
                         Delay_ms(2000);
                                              }
                   }
                   if(hs < 2)
                     {
                     RD1_bit = 0;
                     RC3_bit = 0;
                     RD2_bit = 0; //turn OFF  the water pump.
                     RC2_bit = 1; //Turn ON the green LED, system is normal
                     Lcd_Cmd(_LCD_CLEAR);
                       Delay_ms(500);
                     Lcd_Out(1, 1, "Irrigation Sys");
                     Lcd_Out(2,1, "Humidity: ");
                     Lcd_Out(2, 11, Humidity);
                     Delay_ms(5000);
                      Lcd_Cmd(_LCD_CLEAR);
                       Delay_ms(500);
                     Lcd_Out(1, 1, "Onas Irrigation ");
                     Lcd_Out(2,1, "Sys Stat: Good  ");
                     Delay_ms(5000);

                     }
         }
}
Screenshot (581).png
 

A couple of comments in general about your code:
- you set both ANSEL and ANSELH to 0 which will make all analog pins act as digital. However you then call some ADC_xxx function as though you expect the ADC to read one of the pins. This seems a little odd to me.
- you seem to make an assumption that your writes through the UART will always succeed and within however long you delay. It is always better to wait for the response and to check that it is "OK\r\n" (or whatever).

As to your problem, are you doing this in a simulator or on a real device? If it is a simulator then consider that it could be adding a later of bugs of its own. It is always better to use a real device where possible.
I note that you only allow 3 characters (and a trailing NULL) for the 'humidity' string. Does the function you are calling limit the output to 3 characters and the trailing NULL? If not then you could well be exceeding the buffer size and when you write the string to the LCD, it may not be stopping (on the trailing null) where you expect it to - this may mean that it will write random text to the LCD.
Are you getting the correct outputs on the LCD that you would expect (i.e. the initialisation messages etc.)? If not then strip out all of the code except the LCD initialisation code and send a string to make sure that this part of the code is working correctly.
I would comment out everything except the code to initialise the UART and send a message to it. Also,rather than using the GSM device, connect either a scope or a PC (through a UART-USB cable if necessary) and check that you are getting the signal that you expect.

Susan
 

Oh! I had no idea. I thought even after declaring all PORTS digital, PORTA will still function as analog since I did not disable the comparators. That explains why I was getting either 1023 or 0. The LCD was displaying the texts such as the "Initialization..." And the rest however it is also outputting the "AT" commands to LCD. As you suggested I will check via computer port is the PIC is transmitting anything. Please, how do i specify only a specific PORT as digital? I don't know how it's done in MikroC.

Thanks

- - - Updated - - -

A couple of comments in general about your code:
- you set both ANSEL and ANSELH to 0 which will make all analog pins act as digital. However you then call some ADC_xxx function as though you expect the ADC to read one of the pins. This seems a little odd to me.
- you seem to make an assumption that your writes through the UART will always succeed and within however long you delay. It is always better to wait for the response and to check that it is "OK\r\n" (or whatever).

As to your problem, are you doing this in a simulator or on a real device? If it is a simulator then consider that it could be adding a later of bugs of its own. It is always better to use a real device where possible.
I note that you only allow 3 characters (and a trailing NULL) for the 'humidity' string. Does the function you are calling limit the output to 3 characters and the trailing NULL? If not then you could well be exceeding the buffer size and when you write the string to the LCD, it may not be stopping (on the trailing null) where you expect it to - this may mean that it will write random text to the LCD.
Are you getting the correct outputs on the LCD that you would expect (i.e. the initialisation messages etc.)? If not then strip out all of the code except the LCD initialisation code and send a string to make sure that this part of the code is working correctly.
I would comment out everything except the code to initialise the UART and send a message to it. Also,rather than using the GSM device, connect either a scope or a PC (through a UART-USB cable if necessary) and check that you are getting the signal that you expect.

Susan

Please how do I wait for response and check if it is OK before I start sending the commands?
 

To set a port as digital or analog you need to use the ANSEL(H) registers. Look at the data sheet (e.g. Register 3-3 on page 41) and look at how the bits are defined. Above each bit definition is the text "R/W-1" - this means that the bit can be read (R) or written (W) and will be set to 1 on reset. (ANSELH has some bits that have "U-0" above then which mean they are unimplemented (U) and will always read as 0 .)
You will also note that the bits in ANSEL(H) refer to "ANx" rather than port bits. Therefore you need to look at the pin diagram for the MCU and see what pin you want to use to read the analog voltage. The pins have text next to then such as "RA5/AN4/SS/C2OUT" (where the SS actually has a bar over it). The way to read this is that the pin has a number of different functions it can perform and the ones on the right (in this case) take precedence over the ones to the left. If you use the comparator #2, then the pin will have the 'Comparator 2 output' signal on it.
On the other hand, if you want to use the MSSP interface, then you may want to have the 'Slave Select' (\SS\) input active. However even if you make the MSSP peripheral active, you *MUST* have the Comparator #2 inactive (as it would have precedence) - fortunately all peripherals are inactive by default on reset.
If both those peripherals are off, then the pin would be used for either PORT A bit 5 or as analog input #4. If you want AN4 active, then you need to look at the ANSEL register to see which bit corresponds to AN4 and set that accordingly. If you look at the description below the register bit diagram, you will see that setting a bit to 1 makes the pin analog and setting a bit to 0 makes it digital. So, if you want the pin to be an analog input, set the ANSEL register bit #4 to 1. (I don't use mikroC so I'm not sure of the correct syntax - for the free XC8 compiler it would be 'ANSELbits.ANS4 = 1'.)
If you want the pin to act as a digital input or output, then set the ANSEL bit to 0 and set the TRISA register bit #5 to 1 for input or 0 for output.
It is important that you learn how to read the data sheet as it contains all of the information you need.

As for how to wait for the response, I just about gave you the answer before. You need to look up various AT commands that you will be using, but most will respond with "OK" or "ERROR: xxxx". Some will also provide additional output but will generally end with the "OK" text on a line of its own. You are already using a UART to send text to the GSM module so you should also use the 'receive' side of the UART to pick up the characters it is sending back.
Getting the characters can be the easy bit - interpreting them is a bit harder. I suggest that you use a ring buffer to receive the characters (look these up on Google - they are fairly simple to implement but very useful) making it big enough for at least the largest response you expect. Each line is terminated by "\r\n" so when you add a "\n" to the buffer, trigger off the parsing process and see what the message is that you have received. In the first instance, there will be 3 cases you are interested in:
1) the text starts with "OK" in which case the last message was correctly received and processed
2) the text starts with "ERROR" in which case something went wrong. The rest of the message will give you some indication of what the problem is so you can sort it out
3) the text starts with something else in which case it is probably the response from the command you have just sent and you need to sort that out.
The bottom line is that, when you get the "OK" or "ERROR" message, you know the previous command has been processed either correctly or otherwise. Therefore you know that you can sent the next command.

Susan
 

Thanks a lot. The microcontroller wasn't transmitting anything, I noticed it after connecting the UART port to my PC via UART to USB module as you suggested. I had to change it. Thanks a lot for your help.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top