PIC SMS Controller using PIC16F688
After browsing and learning from Elab, starting a project and always
left it hanging or unfinished, I finally am able to code an almost
complete project (at least the s/w portion).
Now its my time to share specially for those students and other hobbyist who are at lost as how to start an SMS controller for their various thesis or personal projects that will use SMS as a medium.
This
is an SMS controller using a PIC16F688. Why a PIC16F688? Well for
one, I have this in my parts bin and second of all, it is like an LF
series part number operating from
2.0V up to 5.5V. I am using this on a Nokia mobile phone where the
voltage level is around 2.7V. But it can also be used directly on GSM modems. This SMS controller utilizes textmode AT commands as the communication protocol.
Below is the base hardware schematic where the code is based. Once I finalize the code, I will also finalize the hardware schematic. The code is already working but still needs improvement and additional features. I am open to more suggestions on additional features or how to further optimize or improve the code.
Uploaded with ImageShack.us
Features:
Very minimalist with 4 output ports and 4 alarm input ports.
The
4 output ports (namely OUT1, OUT2, OUT3 and OUT4) can be controlled
(turned ON or OFF) using predefined keyword commands sent to the
attached mobile( or gsm modem) to the SMS controller.
OUT1_HIGH to turn on OUT1 port and LED D1
OUT1_LOW to turn off OUT1 port and LED D1
OUT2_HIGH to turn on OUT1 port and LED D2
OUT2_LOW to turn off OUT1 port and LED D2
OUT3_HIGH to turn on OUT1 port and LED D3
OUT3_LOW to turn off OUT1 port and LED D3
OUT4_HIGH to turn on OUT1 port and LED D4
OUT4_LOW to turn off OUT1 port and LED D4
The
4 alarm input ports when set or driven low will by default set or turn
on OUT1 (which could be connected to a siren) and send a corresponding
SMS Alert message to a predefined Mobile number
of the port that was triggered. It also has a configurable alarm
trigger timer (by default 5 mins) such that if the alarm is continously
active or continously being triggered within 5 minutes, it will only
send 1 SMS alert message within a 5 min. interval for a specific alarm
input port.
There is no polling on the received SMS but rather
received SMS is delivered directly to SMS Controller. You should modify
the AT+CNMI settings that work on your phone. Also, SMS alert message
are also sent directly to the network and not initially save then sent
from the phone memory.
All in all, code size is 1008 of 4096
program words and RAM used is 117 bytes of 256 bytes so there is still
enough room for additional features. Compiler used is Hitech C.
BTW, I am simulating this on proteus and an actual Nokia mobile phone attached to my pc.
Below is the code: main.c
Code: [Select]
/****************************************/
/* SMS Controller using PIC16F688 */
/* PIC16F688 SMS Controller v0.02 */
/* */
/* by */
/* KentronicsPH */
/* KentronicsPH.blogspot.com */
/* kentronicsph@gmail.com */
/* */
/* YOU ARE FREE TO USE THIS S/W */
/* AT YOUR OWN RISK! */
/* I scrounged up this code from */
/* various sources, compiler sample */
/* codes and files, advices from */
/* forums and other MCU related */
/* websites and modifying them for */
/* my own purpose. */
/* */
/* This is not a professional s/w, */
/* the purpose of which is to help */
/* fellow hobbyist and students */
/* a guide to code their own SMS */
/* controller. */
/****************************************/
#include <htc.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "usart.h"
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 8000000
#endif
#define OUT1_HIGH RC0 = 1;
#define OUT2_HIGH RC1 = 1;
#define OUT3_HIGH RC2 = 1;
#define OUT4_HIGH RC3 = 1;
#define OUT1_LOW RC0 = 0;
#define OUT2_LOW RC1 = 0;
#define OUT3_LOW RC2 = 0;
#define OUT4_LOW RC3 = 0;
#define LED_IND_ON RA5 = 1;
#define LED_IND_OFF RA5 = 0;
/*
Alarm trigger delay
If alarm has been triggered
and remains triggered, SMS
Controller will only send
an SMS message once for every
no. of ticks where 1 tick is
about 250ms
*/
#define alarm_filter 1200
#define mobile_no_01 "+639123456789"
/* PIC16F688 Configuration Fuses */
__CONFIG(FCMDIS & IESODIS & BORDIS & PWRTEN & WDTDIS & INTIO);
/* Function Declarations */
void Setup_Interrupts(void);
void Setup_16F688HW();
void TMR1_INC(void);
void Setup_Timer1();
/* Global Variables */
unsigned int alarm_timer1;
unsigned int alarm_timer2;
unsigned int alarm_timer3;
unsigned int alarm_timer4;
unsigned char alarm_flag1;
unsigned char alarm_flag2;
unsigned char alarm_flag3;
unsigned char alarm_flag4;
/* Functions */
void interrupt isr()
{
if (RCIF)
{
Write_RXBuff();
}
if (TMR1IF)
{
TMR1_INC();
}
}
void Setup_Interrupts(void)
{
INTCON = 0;
GIE = 1 ;
PEIE = 1 ;
RCIE = 1;
TMR1IE = 1; //enable timer1 interrupt
}
void Setup_16F688HW(void)
{
OSCCON = 0b01110001; // Internal Oscillator 8MHz
ANSEL = 0x00; // All ADC off
CMCON0 = 0x07; // Comparators off
/* Digital Inputs, TRIS = 1 (Input) */
TRISA0 = 1; // RA0 as alarm input 1
TRISA1 = 1; // RA1 as alarm input 2
TRISA2 = 1; // RA2 as alarm input 3
TRISA3 = 1; // RA3 as alarm input 4
//Digital Outputs, TRIS = 0 (Output) */
TRISA5 = 0; // LED indicator
TRISC0 = 0; // RC0 as alarm output 1
TRISC1 = 0; // RC1 as alarm output 2
TRISC2 = 0; // RC2 as alarm output 3
TRISC3 = 0; // RC3 as alarm output 4
OUT1_LOW RC0 = 0;
OUT2_LOW RC1 = 0;
OUT3_LOW RC2 = 0;
OUT4_LOW RC3 = 0;
LED_IND_OFF RA5 = 0;
}
void SMS_ATE0(void) // Sends echo command off
{
while (1)
{
Reset_RXBuff();
printf("ATE0\r");
__delay_ms(300);
if (strstr(RXBuff, "\r\nOK\r\n\0") != 0)
break;
}
}
void SMS_ATCMGF(void)
{
while (1)
{
Reset_RXBuff();
printf("AT+CMGF=1\r");
__delay_ms(300);
if (strstr(RXBuff, "\r\nOK\r\n\0") != 0)
break;
}
}
void SMS_ATCNMI()
{
while (1)
{
Reset_RXBuff();
printf("AT+CNMI=2,2,2,2,0\r");
__delay_ms(300); //wait for ">" character
if (strstr(RXBuff, "\r\nOK\r\n") != 0)
break;
}
}
void SMS_Send_SM(const char * message, const char * pnum)
{
printf("AT+CMGS=\"%s\"\r", pnum);
__delay_ms(300);
Reset_RXBuff;
printf("%s\x1a", message);
}
void TMR1_INC(void)
{
TMR1IF = 0;
TMR1H = 11;
TMR1L = 220;
alarm_timer1++;
alarm_timer2++;
alarm_timer3++;
alarm_timer4++;
if (alarm_timer1 >= alarm_filter)
{
alarm_flag1 = 0;
alarm_timer1 = 0;
}
if (alarm_timer2 >= alarm_filter)
{
alarm_flag2 = 0;
alarm_timer2 = 0;
}
if (alarm_timer3 >= alarm_filter)
{
alarm_flag3 = 0;
alarm_timer3 = 0;
}
if (alarm_timer4 >= alarm_filter)
{
alarm_flag4 = 0;
alarm_timer4 = 0;
}
}
void Setup_Timer1() // interrupt every 250ms
{
TMR1H = 11;
TMR1L = 220;
T1CON = 0b00110101;
}
void main(void)
{
Setup_16F688HW();
Setup_Interrupts();
Setup_Timer1();
uart_init(); // set up the USART - settings defined in usart.h
__delay_ms(1000);
SMS_ATE0();
SMS_ATCMGF();
SMS_ATCNMI();
LED_IND_ON; //Indicates PIC-Phone comms is OK!
alarm_timer1 = 0;
alarm_flag1 = 0;
alarm_timer2 = 0;
alarm_flag2 = 0;
alarm_timer3 = 0;
alarm_flag3 = 0;
alarm_timer4 = 0;
alarm_flag4 = 0;
while (1)
{
/* ALARM MONITORING */
if (RA0 == 0)
{ if (alarm_flag1 == 0 )
{
OUT1_HIGH;
SMS_Send_SM("IN1 ON", mobile_no_01);
alarm_flag1 = 1;
alarm_timer1 = 0;
__delay_ms(5000);
}
}
if (RA1 == 0)
{ if (alarm_flag2 == 0 )
{
OUT1_HIGH;
SMS_Send_SM("IN2 ON", mobile_no_01);
alarm_flag2 = 1;
alarm_timer2 = 0;
__delay_ms(5000);
}
}
if (RA2 == 0)
{ if (alarm_flag3 == 0 )
{
OUT1_HIGH;
SMS_Send_SM("IN3 ON", mobile_no_01);
alarm_flag3 = 1;
alarm_timer3 = 0;
__delay_ms(5000);
}
}
if (RA4 == 0)
{ if (alarm_flag4 == 0 )
{
OUT1_HIGH;
SMS_Send_SM("IN4 ON", mobile_no_01);
alarm_flag4 = 1;
alarm_timer4 = 0;
__delay_ms(5000);
}
}
/* COMMAND MONITORING */
Reset_RXBuff();
__delay_ms(100);
if (strstr(RXBuff, "OUT1_HIGH") != 0)
{
OUT1_HIGH;
}
else if (strstr(RXBuff, "OUT1_LOW") != 0)
{
OUT1_LOW;
}
else if (strstr(RXBuff, "OUT2_HIGH") != 0)
{
OUT2_HIGH;
}
else if (strstr(RXBuff, "OUT2_LOW") != 0)
{
OUT2_LOW;
}
else if (strstr(RXBuff, "OUT3_HIGH") != 0)
{
OUT3_HIGH;
}
else if (strstr(RXBuff, "OUT3_LOW") != 0)
{
OUT3_LOW;
}
else if (strstr(RXBuff, "OUT4_HIGH") != 0)
{
OUT4_HIGH;
}
else if (strstr(RXBuff, "OUT4_LOW") != 0)
{
OUT4_LOW;
}
}
}
usart.c
Code: [Select]
/****************************************/
/* SMS Controller using PIC16F688 */
/* PIC16F688 SMS Controller v0.02 */
/* */
/* by */
/* KentronicsPH */
/* KentronicsPH.blogspot.com */
/* kentronicsph@gmail.com */
/* */
/* YOU ARE FREE TO USE THIS S/W */
/* AT YOUR OWN RISK! */
/* I scrounged up this code from */
/* various sources, compiler sample */
/* codes and files, advices from */
/* forums and other MCU related */
/* websites and modifying them for */
/* my own purpose. */
/* */
/* This is not a professional s/w, */
/* the purpose of which is to help */
/* fellow hobbyist and students */
/* a guide to code their own SMS */
/* controller. */
/****************************************/
#define _usart_c_
#include <htc.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "usart.h"
bank2 unsigned char RXBuff[rxbuffsize];
volatile unsigned char wptr;
void putch(unsigned char byte)
{
/* output one byte */
while(!TXIF) /* set when register is empty */
continue;
TXREG = byte;
}
/*
void puts(const unsigned char * s)
{
while (*s)
putch(*s++);
}
void puts2(unsigned char * s)
{
while (*s)
putch(*s++);
}
*/
unsigned char getch()
{
/* retrieve one byte */
while(!RCIF) /* set when register is not empty */
continue;
return RCREG;
}
unsigned char getche(void)
{
unsigned char c;
putch(c = getch());
return c;
}
void Write_RXBuff(void)
{
if ((RCSTA & 0b00000110) == 0)
{
RXBuff[wptr] = toupper(RCREG);
//putch(RXBuff[wptr]);
wptr++;
if (wptr > (rxbuffsize -1))
wptr = 0;
}
else /* There is an error! */
{
CREN = 0;
CREN = 1;
}
}
void Reset_RXBuff(void)
{
wptr = 0;
memset(RXBuff, 0, rxbuffsize);
}
usart.h
Code: [Select]
/****************************************/
/* SMS Controller using PIC16F688 */
/* PIC16F688 SMS Controller v0.02 */
/* */
/* by */
/* KentronicsPH */
/* KentronicsPH.blogspot.com */
/* kentronicsph@gmail.com */
/* */
/* YOU ARE FREE TO USE THIS S/W */
/* AT YOUR OWN RISK! */
/* I scrounged up this code from */
/* various sources, compiler sample */
/* codes and files, advices from */
/* forums and other MCU related */
/* websites and modifying them for */
/* my own purpose. */
/* */
/* This is not a professional s/w, */
/* the purpose of which is to help */
/* fellow hobbyist and students */
/* a guide to code their own SMS */
/* controller. */
/****************************************/
#ifndef _SERIAL_H_
#define _SERIAL_H_
#define BAUD 9600
#define FOSC 8000000L
#define NINE 0 /* Use 9bit communication? FALSE=8bit */
#define DIVIDER ((int)(FOSC/(16UL * BAUD) -1))
#define HIGH_SPEED 1
#if NINE == 1
#define NINE_BITS 0x40
#else
#define NINE_BITS 0
#endif
#if HIGH_SPEED == 1
#define SPEED 0x4
#else
#define SPEED 0
#endif
#if defined(_16F87) || defined(_16F88)
#define RX_PIN TRISB2
#define TX_PIN TRISB5
#elif defined(_16F688)
#define RX_PIN TRISC5
#define TX_PIN TRISC4
#else
#define RX_PIN TRISC7
#define TX_PIN TRISC6
#endif
/* Serial initialization */
#define uart_init()\
RX_PIN = 1; \
TX_PIN = 1; \
SPBRG = DIVIDER; \
RCSTA = (NINE_BITS|0x90); \
TXSTA = (SPEED|NINE_BITS|0x20)
#define rxbuffsize 80
void putch(unsigned char);
/*
void puts(const unsigned char * s);
void puts2(unsigned char * s);
*/
unsigned char getch(void);
unsigned char getche(void);
void Write_RXBuff(void);
void Reset_RXBuff(void);
#ifndef _uasrt_c_
extern bank2 unsigned char RXBuff[rxbuffsize];
extern volatile unsigned char wptr;
#endif
#endif
Complete details and future s/w revisions can be found on this link.
No comments:
Post a Comment