Detectar la llegada de un sms.

Buenos dias, antes de nada gracias por su atención. Estaba intentando con un 16f877 y un sim800L de detectar cuando me llega un sms para luego poder tratarlo pero no logro conseguirlo. El código lo escribo en Pbp y les agradecería si me podrían ayudar en lo que estoy haciendo mal. Les adjunto lo que tengo escrito, en un principio solo esta lo de recibir la palabra +CMTI y que el micro pueda procesarlo, luego ya adelantare con el resto. Les adjunto el código y gracias.


Código:
Define OSC 20                    



DEFINE LCD_DREG PORTB          

DEFINE LCD_DBIT 4

DEFINE LCD_RSREG PORTB

DEFINE LCD_RSBIT 0

DEFINE LCD_EREG PORTB

DEFINE LCD_EBIT 3



A1 VAR BYTE              'creo estas variables para que almacenen la informacion

A2 VAR BYTE              'del texto +CMTI

A3 VAR BYTE

A4 VAR BYTE

A5 VAR BYTE

A6 VAR BYTE

A7 VAR BYTE

A8 VAR BYTE

A9 VAR BYTE

A0 VAR BYTE



Baud  con 32 '19200,8,N,1



TX   var PORTA.5

RX   var PORTA.4





TRISA = %011111



PORTA = 0 : PORTA.5 = 1



                     ;****************************



LCDOut $fe,1,"< RECIBIR SMS  >"

Pause 5000

    GOTO COMANDO1

 

  COMANDO1:



    serout2 tx,baud,["AT",13]            

    SerIn2 RX,Baud,500,Error1,[wait("OK")]

    LCDOut $fe,1,"   AT OK     "

    pause 4000



    COMANDO2:

    serout2 tx,baud,["AT+CMGF=1",13]            

    SerIn2 RX,Baud,500,Error2,[wait("OK")]

    LCDOut $fe,1,"  Modo texto   "

    pause 4000



    COMANDO3:

    SerOut2 TX,Baud,["AT+CNMI=1,1,0,0,0",13]

    SerIn2 RX,Baud,1500,ERROR3,[wait("OK")]

    LCDOut $fe,1,"  CNMI OK   "

    PAUSE 4000





    AGUARDA:

serIN2 RX,BAUD,[A1]  '+      

serIN2 RX,BAUD,[A2]  'C      

serIN2 RX,BAUD,[A3]  'M    

serIN2 RX,BAUD,[A4]  'T

serIN2 RX,BAUD,[A5]  'I

serIN2 RX,BAUD,[A6]            ; VARIABLES QUE ALMACENAN LA INFORMACION DEL

serIN2 RX,BAUD,[A7]            ;MISSATGE. CADA CARACTER SE  GUARDA EN UNA VARIABLE

serIN2 RX,BAUD,[A8]

serIN2 RX,BAUD,[A9]

serIN2 RX,BAUD,[A0]

pause 100

;*************COMPROVAR SI LLEGA LA PALABRA +CMTI **********************

IF A1= "C" THEN EXIT                'compruevo si la letra c esta guardada en la variable A1

IF A2= "C" THEN EXIT                'compruevo si la letra c esta guardada en la variable A2                

IF A3= "C" THEN EXIT                'compruevo si la letra c esta guardada en la variable A3                  

GOTO AGUARDA            







  error1:

  LCDOut $fe,1,"  Error sim 1  "

  PAUSE 3000

  GOTO COMANDO1

    error2:

  LCDOut $fe,1,"  Error sim 2  "

  PAUSE 3000

  GOTO COMANDO2

    error3:

  LCDOut $fe,1,"  Error sim 3  "

  PAUSE 3000

  GOTO COMANDO3





EXIT:

LCDOut $fe,1,"  LLEGO SMS.   "

Pause 5000



    end

También lo he intentado con el SERIN Y STR que supongo que es mejor:SMS VAR BYTE



SerIn2 RX,Baud,500,noresponde,[wait("+CMTI:"),STR SMS\8]                      'espera una cadena de 8 caracteres y lo guarda en SMS

pause 1000                                        

if (sms[2]="M") then goto exit                                                                        'si la segunda letra es M ir a exit

PAUSE 2000
 

D@rkbytes

Moderador
Con tantos retardos nunca vas a recibir datos correctamente, y mucho menos procesando todo dentro de un bucle.
Ese programa está muy mal hecho y sería más conveniente que usaras la interrupción por recepción del módulo USART.

Quita todos esos retardos que prácticamente son innecesarios.

Nota: Los temas sobre proceso de SMS ya han sido tratados aquí:
Envio de SMS con PBP
Aquí encontrarás más información sobre el uso de interrupciones en PBP y también sobre SMS
Curso de programación de PIC en PICBasic Pro
 
Gracias D@rkbytes por tu respuesta tan rápida. Asi como dices lo voy a intentar, a ver si termino con el proyecto. Un saludo.
 
Hola buenas, ya logre recibir los sms con el Serin2. Pero ahora tengo el problema que el Wait que pongo en el Serin2 no hace la función de esperar el tiempo que le pongo y mandarme a la función "error". Es que resulta que en lugar de esperar 1 segundo y mandarme a la etiqueta, se queda el programa encerrado y la única forma de sacarlo de allí sería al recibir un sms. He probado de cambiar Rx y Tx a otros puertos y hace lo mismo. Alguien me puede decir el porqué? les adjunto un pedazo de codigo, y gracias por todo.

Define OSC 8
Baud con 32 '19200,8,N,1

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 3


Define adc_bits 10
Define ADC_CLOCK 3
Define ADC_SAMPLEUS 50

repe var byte
NUMERO VAR BYTE
SMS VAR BYTE[7]
BF VAR BYTE[70]

TX var PORTA.5
RX var PORTA.4

ADCON1 = %10000100

TRISA = %011111
TRISB = %00000000
TRISC = %11000000
TRISD = %11111111
TRISD = %1111
PORTA = 0 : PORTA.5 = 1
PORTC =0
PORTD = 0
PORTE = 0

LCDOut $fe,1," Maniobra motor"
PAUSE 2000

ESPERA:
SerIn2 RX,Baud,1000,ERROR,[wait("+CMTI:"),STR SMS\7]
PAUSE 1000

IF SMS[3] = "M" THEN
LCDOUT $FE,1," Nou missatge "
lcdout $FE,$C7, SMS[6]
PAUSE 2000
ENDIF


error:
LCDOut $fe,1," Error sim "
PAUSE 3000
GOTO ESPERA
 
Última edición:

D@rkbytes

Moderador
El programa debería pasar a la etiqueta después de no recibir datos por un segundo, no veo por qué no lo haga.
Resulta redundante comprobar "M" dentro del arreglo, pues se supone que cuando Serin2 comprueba la cadena es porque obviamente "M" existe en el arreglo, así como los demás caracteres.
Quita esos retardos del programa. Si analizas el flujo verás que son innecesarios y afectan bastante la recepción de datos.

PICBasic suele comportarse algo extraño con el uso de los parámetros extra para Serin2, aparte es muy limitado.
Si quieres que un programa funcione mejor, te recomiendo que te pases al lenguaje C.
En C tendrás la posibilidad de realizar un programa más confiable y sin las limitaciones del Basic.
 
Tienes razón, no tiene sentido lo de comprobar la "M", ya lo he quitado. El salto a la etiqueta también me funciona bien. De quitar los retardos te refieres a los pauses? Funcionaria todo mejor si fuera más deprisa? Parece que mas o menos todo me funciona, (primero compruebo seis cifras del número de teléfono y luego la palabra de cinco letras), pero me he dado cuenta que alguna vez que recibo un sms no lee bien el número y sale algún carácter raro, esto sucede igual una vez cada diez. Al principio leía las 9 cifras del teléfono pero ahora he intentado comprobar sólo 6 a ver si me iba mejor, pero más o menos va igual. Esto es normal con picbasic o lo puedo remediar? Tengo puesto un oscilador de 8mhz, a lo mejor si lo cambio iría al 100%?. Escribo aqui la parte del programa que uso para leer el mensaje.Gracias por tu tiempo D@rkbytes.
leyendo:
LCDOUT $FE,1," Leyendo Sms ",sms[6]
SerOut2 TX,Baud,["AT+CMGR=",SMS[6],13]
SerIn2 RX,Baud,2500,leyendo,[wait("+CMGR:"),STR BF\70]
PAUSE 2000
'*********** ***************************
LCDOUT $FE,1," Comprobando num "
PAUSE 2000
LCDOUT $FE,$C3,BF[18],BF[19],BF[20],BF[21],BF[22],BF[23],BF[24],BF[25],BF[26]
PAUSE 2000
IF(BF[19]="6")AND(BF[20]="6")AND(BF[21]="8")AND (BF[22]="8")AND (BF[23]="9") AND (BF[24]="6") Then
LCDOUT $FE,1," Numero ok "
pause 2000
GOTO TEXT ' ir a comprobar texto
ELSE
LCDOUT $FE,1," Num. incorrecto"
pause 2000
GOSUB BORRAR
GOTO ESPERA
endif
 
Tal vez mejoraría si bajas la velocidad a 9600bps, usar los pines que ya vienen provistos por el fabricante dentro del chip para hacer ese tipo de comunicaciones(RC6 y RC7) y cambias las correspondientes instrucciones.

En vez de SerIn o SerOut, HSerIn y HSerOut.

Tengo varios proyectos con PIC/SIM y no tengo mayormente problemas de comunicación entre estos pero no se me ocurriría hacer una comunicación serie, emulada por software a 19200bps, cuando tengo disponible hardware embebido para resolverlo dentro del PIC.
 

D@rkbytes

Moderador
¿De quitar los retardos te refieres a los pauses?
Sí, a esos. Ten en cuenta que estás recibiendo datos externos y si existen retardos serán ignorados en el lapso de la pausa.
O sea que perderás información porque el programa estará inactivo en cada retardo.
¿Funcionaría todo mejor si fuera más deprisa?
Depende, si los eventos externos a controlar son rápidos, el programa también debe ser rápido para poder responder correctamente.
me he dado cuenta que alguna vez que recibo un sms no lee bien el número y sale algún carácter raro, esto sucede igual una vez cada diez.
Eso es normal en una transmisión serial asíncrona, por eso se emplea una verificación, y si no es correcta se piden nuevamente los datos.
El hecho de que por ir más lento se mejore la comunicación es falso, porque el protocolo sigue siendo el mismo y propenso a los mismos fallos.
El problema es el uso de retardos durante el programa, porque si lo que tiene que atender externamente es rápido, se perderán datos.

Si usas la interrupción por recepción del módulo USART las cosas pueden mejorar bastante.
Esto es porque cuando llegue un dato todo el programa se interrumpe y se presta atención al servicio de interrupciones.
Obviamente las interrupciones pueden ser varias pero serán atendidas conforme se vayan dando y posteriormente se retornará al programa principal.
Nunca he estado de acuerdo en usar polling cuando el microcontrolador cuenta con el hardware necesario.
Date cuenta que durante el polling o poleo (Bucle de proceso) la instrucción de recepción tiene que esperar hasta que se llegue a ella otra vez.
Por ende, eso también puede ocasionar que se pierdan datos.
Al principio leía las 9 cifras del teléfono pero ahora he intentado comprobar sólo 6 a ver si me iba mejor, pero más o menos va igual. ¿Esto es normal con PICBasic o lo puedo remediar?
Se puede mejorar y bastante si el programa estuviera escrito en C.
El lenguaje PICC no está tan limitado como el Basic y por lo tanto tendrás más instrucciones disponibles.
Eso te dará la posibilidad de crear funciones y subrutinas más elaboradas.
El PICBasic no tiene soporte para funciones con retorno de datos y eso lo limita bastante.

En fin, ya sea en PICBasic o PICC, mientras sigas usando esos retardos innecesarios todo va a ir mal.
 
Te agradezco el tiempo D@rkbytes, el proyecto ya casi lo tengo listo. Le he quitado retardos y mucho mejor, ahora lo recibe siempre bien. Lo que me he dado cuenta que el módulo sim 900, depende de que dispositivo le envia el sms lo muestra de una forma o otra. Por ejemplo:
..."rec unread","+34576688637",+34567688673",...
..."rec unread","+34576688637","",....
Desde un teléfono me muestra el número dos veces y desde el otro aparecen las comillas pero no el número.
Pensaba que a lo mejor podía ser por estar el número grabado en la agenda de contactos pero veo que no. Deberá ser normal?
Nota: el número de teléfono es inventado.
Gracias por vuestro trabajo.
 
Última edición:
Hola buenas, pero me ocurre que tengo el wait y el str programado con una variable de como máximo 70 caracteres( que para mi teléfono me funciona bien, me reconoce bien los textos y el número). Ahora bien, si cojo desde otro teléfono y mando un mensaje de 5 caracteres o más corto se queda el Serin2 esperando a más caracteres y no termina nunca. Si el sms es más largo lo interpreta bien y no autoriza el número. Yo supongo que como este sms tiene 9 caracteres menos el Serin2 espera a que lleguen los otros.
Gracias por vuestro interés.
 

D@rkbytes

Moderador
Serin2 pasa a la siguiente línea cuando encuentra en la cadena lo que se especificó en Wait.
Si no lo encuentra o no llegan datos saltará a la etiqueta indicada después del tiempo establecido.

Edit:
Extracto tomado del manual de PIC Basic en español:

6) La lista de items de datos a ser recibidos, puede estar precedida por uno o más calificadores entre paréntesis después del WAIT.
SERIN2 debe recibir estos bytes en un orden exacto, antes de recibir los datos.
Si algún byte recibido no concuerda con el próximo en la secuencia de calificación, recomienza el proceso de calificación.
(p. ej. el próximo byte recibido se compara con el primer item en la lista de calificadores)
Un calificador puede ser una constante, variable o una sarta de constantes.
Cada carácter de una sarta es tratado como un calificador individual.

7) WAITSTR puede ser usado como WAIT anteriormente, para forzar a SERIN2 a esperar por una sarta de caracteres de un determinado largo, antes de seguir adelante.
Una vez que los calificadores WAIT y WAITSTR están cumplidos, SERIN2 comienza a guardar los datos en las variables asociadas con cada item.
Si se usa solo el nombre de la variable, se guarda el valor del carácter ASCII.
Si la variable está precedida por BIN, DEC o HEX, SERIN2 convierte un valor binario, decimal o hexadecimal en su equivalente ASCII y guarda el resultado en esa variable.
Todos los caracteres null recibidos antes que el primer dígito del valor decimal es ignorado y descartado.
El carácter null que termina el valor también es descartado.
 
Upss... Fallo mío, me acabas de hacer ver la realidad. Claro, yo tenia puesta la etiqueta al principio del at+cmgr, entonces como cada vez que leía el sms y no le llegaba del todo volvía a leerlo y así sucesivamente. Yo pensaba que lo que ocurría era que se quedaba esperando más datos y por eso no terminaba nunca. Estaba equivocado.
Gracias a todos.
 
Hola de nuevo a todos, ya logre hacer el proyecto del 16f877 con el módulo sim 800l. Hice la comunicación serial por software con el serin2 y serout2 con una velocidad de 9600 bauds. Todo funciona bien, pero aqui viene la question:
Quería intentarlo con la comunicación de los puertos usart que tiene el pic pero no consigo que me de respuestas el módulo. He intentado con velocidades de 2400, 9600 y15200 tanto poniéndolo con baja velocidad o alta; y cambiando varios osciladores. Lo curioso es que tengo un Sim900 y éste si que me responde a la velocidad de 2400. I si en el Sim800 utilizo el Serin2 con 9600 tambien me funciona, o sea que pienso que no debe ser de la velocidad porque con Serin2 funciona y teóricamente el Sim800 detecta automáticamente la velocidad.
Hay alguna cosa que no termino de ver en relación del Sim800 y la Usart. Tambien he intentado ponerle los transistores para acoplarle Rx y Tx. Otra cosa, si conecto el módulo con el hiperterminal me responde correctamente con velocidades de 9600 o 15200.
Gracias de antemano.
La configuración de la usart es la siguiente:

DEFINE OSC 4
define HSER_TXSTA 24H
DEFINE HSER_RCSTA 90H
define HSER_BAUD 2400
DEFINE HSER_SPBRG 103
DEFINE HSER_CLROERR 1

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 3

TRISC=%10000000
portc=0

BACKLIGHT VAR PORTD.0

inicio:
HIGH BACKLIGHT
LCDOut $fe,1,"Control en DTMF "
PAUSE 1000

HSEROUT ["AT",13] 'Enviar AT al módem seguido por un retorno de carro
HSERIN 3000, error, [WAIT("OK")]'Comprobar respuesta OK, espere 3 segundos max.
LCDOut $fe,1," Modem responde "
PAUSE 2000



HSEROUT ["AT+CMGF=1",13] ''envía AT al módem
HSERIN 3000,error, [WAIT("OK")]''Comprobar respuesta OK,
LCDOut $fe,1," AT CMGF=1 "
PAUSE 2000


ERROR:
LCDOut $fe,1," ERROR HSERIN "
PAUSE 2000
GOTO inicio
End
 
Última edición:

D@rkbytes

Moderador
¿Y la palabra de configuración?
Si compilas sin establecer los fuses el compilador generará un ejecutable con el Watch Dog Timer activo.
Eso hará que el microcontrolador se reinicie cuando este timer se desborde.
Como tu programa tiene 6 largos retardos, lo hará durante cada instrucción que los tenga, no dejando que continúe a la siguiente.
O sea que prácticamente desde el primer retardo de 1 segundo el microcontrolador ya se debe estar reseteando.
 
Es que el whatch dog lo deshabilito mediante el programa. Igualmente que definir el oscilador de alta velocidad. Desde el mplab configuro los fuses. Es que lo extraño es que si modifico hserins y hserouts por serin2 y serout2 y cambio los pines si que funciona. Puede ser que el sim800l para arrancar con el hardware del pic necesite alguna configuración en especial?
 

D@rkbytes

Moderador
Al SIM800L no le importa, ni sabrá distinguir si la comunicación es por software o por hardware.
Y esto aplica para cualquier otro dispositivo serial.
Lo que realmente importa es que el protocolo sea el correcto.
 
En los datos de configuración de la Usart es necesario poner la velocidad de transmisión? por ejemplo:
define HSER_BAUD 2400
En varios ejemplos veo que si se especifica el spbrg, ya no le ponen el Hser_baud.
O sea que por la configuración que tengo, el whatch dog desactivado el cristal de 4mhz y las conexiones bien debería de funcionar?
Otra cosa, si con el serin2 y serout2 me funciona sin los transistores de acople en Rx y Tx, entiendo que utilizando los puertos c.6 y c.7 por hardware tendría que funcionar igual?
Gracias por todo.
 

D@rkbytes

Moderador
¿En los datos de configuración de la Usart es necesario poner la velocidad de transmisión?
Por ejemplo: define HSER_BAUD 2400
En varios ejemplos veo que si se especifica el SPBRG, ya no le ponen el Hser_baud.
Yo no suelo usar las definiciones del entorno, prefiero utilizar los registros directamente.
Por ejemplo, para 2400 Bps:
Código:
    ; Configuración USART: (2400 Bps @ 4 MHz. 2404 Bps Reales con 0.16% de error)
    SPBRG =    103    ; 01100111
    TXSTA =    36    ; 00100100
    RCSTA =    144    ; 10010000
¿O sea que por la configuración que tengo, el Watch Dog desactivado el cristal de 4 MHz y las conexiones bien debería de funcionar?
Eso no es lo que haría que un programa funcione, sino otras configuraciones y principalmente el código.
Y realmente queda la duda de que el Watch Dog Timer se encuentre desactivado.
Otra cosa. Si con el serin2 y serout2 me funciona sin los transistores de acople en Rx y Tx, entiendo que utilizando los pines C6 y C7 por hardware tendría que funcionar igual?
Si usas SerIn2 y SerOut2 estás realizando USART por software, así que no importa que pines uses.
Cuando se usa HSerIn y HSerOut entonces sí que se usará el Hardware del módulo USART y forzosamente se tendrán que usar los pines C6 y C7.
Solo en este caso es cuando se deben configurar los registros involucrados con el USART.
 

Arriba