|
|
View previous topic :: View next topic |
Author |
Message |
qleyo
Joined: 23 Aug 2005 Posts: 22
|
Please help! Modem <-> RS232 <-> 18F452 |
Posted: Tue Mar 21, 2006 11:30 am |
|
|
I've been trying to avoid opening a new topic, but have searched this forum high and low to no avail.
I am using a PIC millenium dev board, a pic18F452(with 4mhz crystal) and a round solutions GSM-GPRS modem. First things first, I have buzzed all rs232 cables to check cross over or not. And they aren't i.e. non cross over.
When I connect my modem to a PC using hyperterminal (setup is - baud: 9600, data bits: 8, parity: None, Stop bits: 1, Flow control: none), my AT commands work fine. I have used a port sniffer to get the exact hex values going out.
I then connected my PIC to the PC and got all my AT commands, once again with the port sniffer to get hex values. On comparison, the hex values were exactly the same. So I know I'm sending valid data.
I have grounded RTS, and sent an AT&K0 to disable hardware handshaking. My program is below. The GPRS modem does not respond. I included a function that waits for a khbit() rather than using delays, but RX is inactive High, so my function does not work well. I can't think of anything else, I've checked logics, voltages everything I can think of. And i'm running out of time :'(
Code: | #include <18F452.h>
#include <string.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232 (BAUD=9600,parity=N,XMIT=PIN_C6,RCV=PIN_C7,ERRORS,bits=8)
#define CR 0x0D
#define LF 10
void gprs_error()
{
char msg[20];
char response_ok[25];
char response_connect[25];
strcpy(response_ok,"OK");
strcpy(response_connect,"CONNECT");
//check if command returned an error
//program will not continue until gprs returns a string
gets(msg);
//check if error returned
delay_ms(100);
if (stricmp(msg, response_ok))
printf("\r\nok\r\n");
else if (stricmp(msg, response_connect))
printf("\r\nconnect\r\n");
}
void delay_sec (void)
{
delay_ms(200);
delay_ms(200);
delay_ms(200);
delay_ms(200);
delay_ms(200);
}
void flash()
{
delay_sec();
output_low(PIN_B2);
delay_sec();
output_high(PIN_B2);
}
void flash3()
{
delay_sec();
output_high(PIN_B3);
delay_sec();
output_low(PIN_B3);
}
//PROGRAM WILL HALT UNTIL RESPONSE FROM GPRS ON RX IS RECEIVED
void wait_for_response ()
{
while(!kbhit())
flash();
flash3();
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
/***start test sequence***/
while(TRUE)
{
delay_sec();
printf("AT&K0%c",CR); //turn off handshaking
flash();
printf("ATE1%c",CR); //enable echo
wait_for_response();
printf("ATD 07745691189;%c",CR); //make a phone call
wait_for_response();
flash();
}
}
|
|
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Tue Mar 21, 2006 11:40 am |
|
|
Note: open invitation for someone to correct me follows.
Your PIC development board and the modem are both (???) DTE's (???) or is it DCE's (???).
I can't remember the proper terminology at the moment. Basically the PC is wired to be "boss". The PIC development board and the modem are wired to be "slaves".
To get one slave to speak to the other (PIC board --> modem) you'll need a null modem serial cable. A null modem cable is not a straight pass-through. Among other things, the most important switch is pin 2 -> pin 3 and pin 3 -> pin 2. This allows one slave's TX to be routed to the other's RX and vice-versa.
Hope this helps. |
|
|
rberek
Joined: 10 Jan 2005 Posts: 207 Location: Ottawa, Canada
|
|
Posted: Tue Mar 21, 2006 11:55 am |
|
|
The board and modem are both DCE's. The PC is the DTE. And you are correct! |
|
|
qleyo
Joined: 23 Aug 2005 Posts: 22
|
|
Posted: Tue Mar 21, 2006 11:59 am |
|
|
newguy wrote: |
Your PIC development board and the modem are both (???) DTE's (???) or is it DCE's (???).
|
Nope controlling device is DTE so here PIC is DTE so is PC. Modem is DCE.
I tried a cross over connection, didn't work.
newguy wrote: | ]To get one slave to speak to the other (PIC board --> modem) you'll need a null modem serial cable. A null modem cable is not a straight pass-through. Among other things, the most important switch is pin 2 -> pin 3 and pin 3 -> pin 2. This allows one slave's TX to be routed to the other's RX and vice-versa. |
Do you understand what I was trying to say in my post? Eventually the PIC is to control the modem. However what I did was connect the PIC to PC to see I was getting the correct AT commands. I also connected the PC to modem to issue those commands and compared the hex output both ways. On connecting the PIC to modem I don't get anything.
Quote: | The board and modem are both DCE's. The PC is the DTE. And you are correct! |
:'( noo PC is DTE, PIC is DTE, modem is DCE. This is a sticky from the manufacturer of my modems forum. http://www.modem-gsm.de/forum/showthread.php?id=17 |
|
|
rberek
Joined: 10 Jan 2005 Posts: 207 Location: Ottawa, Canada
|
|
Posted: Tue Mar 21, 2006 12:19 pm |
|
|
Please help me understand this.
Leaving terminology aside for a moment, it would seem that both the modem and PIC board can talk to the PC. Assuming you are using a regular RS232 cable, that means that they are both using the same pin to transmit to the PC (pin 2 or 3, I can't remember). If that is so, then they won't be able to talk to each other without a null modem, since you would be connecting Tx to Tx and Rx to Rx.
What am I missing from your description? |
|
|
qleyo
Joined: 23 Aug 2005 Posts: 22
|
|
Posted: Tue Mar 21, 2006 5:14 pm |
|
|
So does the PC cross over on the inside? How come a straight connected cable works with PC. Also what I said was I did try a null connection and that did not work either, infact I had a null connection till my lecturer came and said to make it straight (not that that solved my problem) :( |
|
|
Eugeneo
Joined: 30 Aug 2005 Posts: 155 Location: Calgary, AB
|
Re: Please help! Modem <-> RS232 <-> 18F452 |
Posted: Tue Mar 21, 2006 6:05 pm |
|
|
If you say:
Modem = Male
Pic = Male
PC = Female
Modem to PC is straight
Pic to PC is straight
Pic to Modem, well that's not straight so you need a null modem
delay_ms(1000) works as long as you don't use a long register but you may loose some bytes since your not using the interrupts. |
|
|
rberek
Joined: 10 Jan 2005 Posts: 207 Location: Ottawa, Canada
|
|
Posted: Tue Mar 21, 2006 7:45 pm |
|
|
Nothing crosses over in the PC. It will always transmit on pin 3 of the cable and receive on pin 2. That means, with a straight-thru cable, the modem and the PIC board must always receive on pin3 and transmit on pin 2.
If they are connected together with a straight thru cable, they will both be transmitting to each other on pin 2 and receiving on pin 3. This is a collision and nothing will happen, |
|
|
qleyo
Joined: 23 Aug 2005 Posts: 22
|
|
Posted: Wed Mar 22, 2006 2:18 am |
|
|
Oh I see what you are saying. I was thinking about DTE and DCE in terms of who is "controlling". So you are saying that if my modem and PIC worked with my PC, they must be acting and configured as DCE devices.
I'm on the same page now, (hmm...but it didn't work with null connection :( ) ok I'm going to do a lot of probing today. And swap the PIC to modem connection again. I'll let you know if I get anything.
Quote: | Modem = Male
Pic = Male
PC = Female |
Yes that is how it is, because right now I have to use a female to female header to connect the PIC and modem. Right I'm clear on the connection issue, let me swap cables (and leave it that way), do alot of probing and update everyone before the end of today. Thank you. |
|
|
qleyo
Joined: 23 Aug 2005 Posts: 22
|
|
Posted: Wed Mar 22, 2006 5:17 am |
|
|
Ok i'm back, i've now done the cross over connection. RTS still grounded. I modified my code to check for khbit() from the mode. And i've stopped sending commands to the modem. All I do now is send it a text message and the modem sends data on RX stating it has received a message.
I've tested 3 text messages, and they all worked, so my connection is definitely fine now. However the modem still does not respond to AT commands. Here is the working program that waits for RX data from the modem.
Code: | #include <18F452.h>
#include <string.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOPUT
#use delay(clock=4000000)
#use rs232 (BAUD=9600,parity=N,XMIT=PIN_C6,RCV=PIN_C7,ERRORS,bits=8)
void delay_sec (void)
{
delay_ms(200);
delay_ms(200);
delay_ms(200);
delay_ms(200);
delay_ms(200);
}
void flash()
{
delay_sec();
output_low(PIN_B2);
delay_sec();
output_high(PIN_B2);
delay_sec();
output_low(PIN_B2);
}
void flash3()
{
delay_sec();
output_low(PIN_B3);
delay_sec();
output_high(PIN_B3);
delay_sec();
output_low(PIN_B3);
}
int main()
{
/***start GPRS connection sequence***/
char gprs_msg[25];
while(1)
{
while(!kbhit())
flash();
flash3();
delay_sec();
gets(gprs_msg);
flash3();
}
return 0;
}
|
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Mar 22, 2006 8:20 am |
|
|
Try this. I didn't test it but it compiles just fine.
Code: |
#include <18F452.h>
#include <string.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232 (BAUD=9600,parity=N,XMIT=PIN_C6,RCV=PIN_C7,ERRORS,bits=8)
#ifndef NULL
#define NULL 0
#endif
/* *************************************************************************
DESCRIPTION Waits for a string for the specified timeout
RETURN: none
ALGORITHM: none
NOTES: Passing a 0 for the timeout will wait forever
*************************************************************************** */
static int *WaitFor(
int *s, /* String that we are looking for */
int16 timeout) /* How long to wait in miliseconds */
{
int *p;
int index = 0;
int buf[15]; /* increase the size of the buffer to suit your needs */
while (TRUE)
{
if (kbhit())
{
buf[index] = getc();
index++;
if (index > sizeof(buf))
return(NULL);
p = strstr(buf, s);
if (p)
return (p);
}
delay_ms(1);
if (timeout)
{
timeout--;
if (!timeout)
return (NULL);
}
}
}
void main()
{
int buf[] = { "OK" };
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
/***start test sequence***/
/* reset the modem */
printf("ATZ\r");
(void)WaitFor(buf, 4000);
/* Configure the modem */
printf("AT&FE0&C0&D0S0=0\r");
(void)WaitFor(buf, 4000);
/* make a phone call */
printf("ATD 07745691189\r");
while(TRUE)
{
}
}
|
|
|
|
qleyo
Joined: 23 Aug 2005 Posts: 22
|
|
Posted: Wed Mar 22, 2006 10:00 am |
|
|
waheeeyyyy I got a phone call!!!! :D i'm skipping skipping and more skips :D <tears of joy in between>
I thought CCS couldn't take pointers, obviously wrong.
Thank you! |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Mar 22, 2006 11:54 am |
|
|
CCS cannot take pointers to constants but pointers are okay. However, you can pass a constant string to a function. CCS will just break the string up into individual bytes and do multiple calls to the function. |
|
|
qleyo
Joined: 23 Aug 2005 Posts: 22
|
|
Posted: Sat Mar 25, 2006 8:40 am |
|
|
Hi Mark, I'm stuck on something else. What i've done is connected another COM port to HyperTerminal to print messages. (Could not be asked with setting up LCD)
Now the modem always seems to get OK even after AT#SKTOP which should return CONNECT, would it be a smart move to clear the buffer before calling the function again (I would have thought it would simply overwrite), also I added a statement to print each character after adding it to the buffer.
Code: |
buf[index] = getc();
fprintf(PC,"%c",buf[index]);
|
But I don't seem to get anything (I wanted to be able to see the actual modem echo's and responses)
I also added a printf before issues each AT command to print the current AT command to hyperterminal which works fine (its not in this piece of code below as I didn't manage to e-mail myself the updated version before the labs shut, plus its trivial)
lastly would it be a smart move to terminate the current buffer with a NULL before doing strstr. e.g.
Code: |
buf[index] = getc();
buf[index+1] = '\0';
fprintf(PC,"%c",buf[index]);
|
Heres the modified code, Thanks again
Code: |
#include <18F452.h>
#include <string.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT
#use delay(clock=4000000)
#use rs232 (BAUD=9600,parity=N,XMIT=PIN_C6,RCV=PIN_C7,ERRORS,bits=8,stream=GPRS)
#use rs232 (BAUD=9600,parity=N,XMIT=PIN_C5,ERRORS,bits=8,stream=PC)
#ifndef NULL
#define NULL 0
#endif
void delay_sec (void)
{
delay_ms(200);
delay_ms(200);
delay_ms(200);
delay_ms(200);
delay_ms(200);
}
void flash()
{
delay_sec();
output_low(PIN_B2);
delay_sec();
output_high(PIN_B2);
delay_sec();
output_low(PIN_B2);
}
/* *************************************************************************
DESCRIPTION Waits for a string for the specified timeout
RETURN: none
ALGORITHM: none
NOTES: Passing a 0 for the timeout will wait forever
*************************************************************************** */
static int *gprs_response(int16 timeout) // How long to wait in miliseconds
{
int index = 0;
char buf[25]; // increase the size of the buffer to suit your needs
char character;
int ok[] = { "OK" };
int connect[] = { "CONNECT" };
while (TRUE) {
if (kbhit()) {
buf[index] = getc();
fprintf(PC,"%c",buf[index]);
index++;
if (index > sizeof(buf))
{
fprintf(PC,"\r\nError reading GPRS data");
return(NULL);
}
else if (strstr(buf, ok))
{
fprintf(PC,"\r\nGPRS response - OK");
return (TRUE); //drop out of function
}
else if (strstr(buf, connect))
{
fprintf(PC,"\r\nGPRS response - CONNECT");
return (TRUE); //drop out of function
}
}
delay_ms(1);
if (timeout) {
timeout--;
if (!timeout) {
fprintf(PC,"\r\nGPRS Timeout - no valid response");
return (NULL);
}
}
}
}
/***still buggy do not use yet***/
static int *server_response(int16 timeout) // How long to wait in miliseconds
{
int index = 0;
char *p;
char buf[15]; // increase the size of the buffer to suit your needs
char character;
while (TRUE)
{
if (kbhit())
{
buf[index] = getc();
fprintf(PC,"%c",buf[index]);
index++;
if (index > sizeof(buf))
{
fprintf(PC,"\r\nError reading GPRS data");
return(NULL);
}
}
delay_ms(1);
if (timeout)
{
timeout--;
if (!timeout)
{
fprintf(PC,"\r\nTime out error");
return (NULL);
}
}
}
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
/***start test sequence***/
while (1)
{
delay_sec();
fprintf(PC,"\r\n***Program started***\n");
/* reset the modem */
fprintf(GPRS,"ATZ\r");
(void)gprs_response(8000);
flash();
/* Configure the modem */
fprintf(GPRS,"AT&FE0&C0&D0S0=0\r");
(void)gprs_response(8000);
flash();
fprintf(GPRS,"AT&K0\r");
(void)gprs_response(8000);
flash();
/* set socket data */
fprintf(GPRS,"at#SKTSET= 0,80,\"www.someurl.co.uk\",0,0;\r");
(void)gprs_response(8000);
flash();
/* set user ID */
fprintf(GPRS,"at#userid=\"wap\"\r");
(void)gprs_response(4000);
flash();
/* set user password */
fprintf(GPRS,"at#passw=\"wap\"\r");
(void)gprs_response(8000);
flash();
/* activate GPRS context, modem should respond with IP address */
fprintf(GPRS,"at#gprs=1\r");
(void)gprs_response(8000);
flash();
/* save settings */
fprintf(GPRS,"at#sktsav\r");
(void)gprs_response(8000);
flash();
/* open socket connection, modem should respond with CONNECT */
fprintf(GPRS,"at#sktop\r");
(void)gprs_response(100000);
flash();
/* HTML instructions */
fprintf(GPRS,"GET /gprs.php?val=1 HTTP/1.0\r\n");
delay_ms(1);
fprintf(GPRS,"Connection: keep-alive\r\n\r\n");
(void)server_response(100000);
delay_sec();
delay_sec();
delay_sec();
delay_sec();
delay_sec();
/* close connection */
fprintf(GPRS,"+++");
(void)gprs_response(100000);
delay_sec();
delay_sec();
delay_sec();
delay_sec();
delay_sec();
}
}
|
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sat Mar 25, 2006 10:23 am |
|
|
Quote: |
Now the modem always seems to get OK even after AT#SKTOP which should return CONNECT, would it be a smart move to clear the buffer before calling the function again (I would have thought it would simply overwrite), also I added a statement to print each character after adding it to the buffer.
Code:
buf[index] = getc();
fprintf(PC,"%c",buf[index]);
|
You don't want to do any printing of chars while you are waiting. This might cause you to miss a char while you are sending one.
Quote: | lastly would it be a smart move to terminate the current buffer with a NULL before doing strstr. e.g.
Code:
buf[index] = getc();
buf[index+1] = '\0';
|
Most definitely! I converted this from some code that I use. My code used a global buffer where the data was received by an interrupt. I always terminated the string in the ISR.
Note that I added a /0 to the buffer at the start of the function. This would clear the buffer so to speak. The problem is most likely because nothing had been received and an old response was still in the buffer.
Code: | /* *************************************************************************
DESCRIPTION Waits for a string for the specified timeout
RETURN: none
ALGORITHM: none
NOTES: Passing a 0 for the timeout will wait forever
*************************************************************************** */
static int *gprs_response(int16 timeout) // How long to wait in miliseconds
{
int index = 0;
char buf[25]; // increase the size of the buffer to suit your needs
char character;
int ok[] = { "OK" };
int connect[] = { "CONNECT" };
// Clear any previous messages
buf[0] = 0;
while (TRUE) {
if (kbhit()) {
buf[index] = getc();
index++;
buf[index] = 0;
if (index >= sizeof(buf)-1)
{
fprintf(PC,"\r\nError reading GPRS data");
return(NULL);
}
else if (strstr(buf, ok))
{
fprintf(PC,"\r\nGPRS response - OK");
return (TRUE); //drop out of function
}
else if (strstr(buf, connect))
{
fprintf(PC,"\r\nGPRS response - CONNECT");
return (TRUE); //drop out of function
}
}
delay_ms(1);
if (timeout) {
timeout--;
if (!timeout) {
fprintf(PC,"\r\nGPRS Timeout - no valid response");
return (NULL);
}
}
}
}
|
|
|
|
|
|
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
|