Let
us make a Bascom program for SMS - driven
automat! by Vilko Sustic
Attached is a fully working sample program
for an SMS driven automat. You can use this example to build your own project
based on it. The program and its subroutines are provided 'as is'. However you
are free to remove some subroutines and add your own code but you have to be
careful with others.. Dim I As Byte
Dim J As Byte
Dim K As Byte
Dim L As Byte
Dim M As Byte
Dim N As Word
The above work variables are used by
diferent soubroutines and also available for use in your program. The
subroutines save the original values of the variables to stack and restore
afterwards. Dim X As Byte
Dim Bajt As Byte
Dim Y(1) As Byte
Dim Niz As String * 18 'X=2
Dim Pdu As String * 34 'X=21 multiple of 7!
Dim Text As String * 38 'X=56 multiple of 8!
Dim Telno As String * 14 'X=95
Const Xpdu = 21 'multiple of 7!
Const Xtext = 56 'multipleo of 8!
Const Xtelno = 95
Const Xkonec = 120
String variables must be kept in the same
order and size. Any byte of any string
variable can be addressed by using the variable Y with appropriate index.
Variable Niz is a string variable. It is
used to store the commands to send to GSM and for receiving replies back. The
subroutine to send the command is Poslji: Poslji:
Disable Serial
Set Scon.1
Print Niz
Reset Scon.1
push {i}
For I = 2 To 16
Y(i) = 0
Next
Pop {i}
X = 2
Enable Serial
Return
It sends the command, it clears the
variable string and it sets variable X to 2, in order to prepare the index for
being used in the Serial interrupt routine, which is responsible to intercept
the reply. The Serial Interrupt routine is this:
Si_rtn:
Dim Pdubit As Bit
Dim Levi As Bit
Bajt = Inkey()
Scon.1 = 0
If Bajt <> 0 Then
If X < 10 Then : Reset Pdubit : End If
If Pdubit = 0 Then
If Bajt = &H0A Then : Bajt = &H2F : End If
Y(x) = Bajt
If Bajt <> &H0D And X < Xtext Then : Incr X : End If 'ignore carriage return
If X > 15 And Bajt = &H2F Then : Set Pdubit : Set Levi : End If
Else
Bajt = Bajt - &H30
If Bajt > 9 Then : Bajt = Bajt - 7 : End If
If Levi = 1 Then
Shift Bajt , Left , 4
Y(x) = Bajt
Reset Levi
Else
Y(x) = Y(x) Or Bajt
Incr X
Set Levi
End If
End If
End If
Return
It puts the intercepted byte to the next
byte of the variable Niz. It uses the variable X as the index, and that is why
you should not use this variable while gsm reply is expected. If the reply is long when an SMS
message is read, it puts the reply behind the variable Niz in the variable Pdu,
but it takes two intercepted characters among 0-F for one byte of the variable
PDU.
It takes some time to receive a reply from
the GSM, so we should wait a bit before analizing the reply. Instead of using wait statements,
we use time interrupt driven code to do it.
We define Timer0 Interrupt procedure: Config Timer0 = Timer , Gate = Internal , Mode = 1
On Timer0 Titi
Load Timer0 , 180
And
Titi:
Load Timer0 , 180
Incr Tistevec
Return
This way we get 20 interrupts per seconds
using this method. So we count them at the begining of main program loop: Do
If Tistevec > 20 Then
Tistevec = Tistevec - 20
Incr Sekunde
If Sekunde > 59 Then
Sekunde = Sekunde - 60
Incr Minute
...
If we intend to send a GSM command, we use
a second to send it one or two seconds after we analyze the reply: If Sekunde = 3 Then 'vsako 3. sekundo minute
Niz = "AT+CALM=1"
Gosub Poslji
End If
If Sekunde = 4 Then 'vsako 4. sekundo minute
Y(18) = 0
Locate 1 , 1 'prikaži odgovor
Lcd Niz ; "
"
Locate 2 , 1
If Y(3) <> &H4F Or Y(4) <> &H4B Then ' ali je odgovor OK ?
Lcd "Ni C35i!!"
Reset C35i
Else
Lcd " "
Y(3) = 0
Set C35i
End If
End If
Each 3rd second of a
minute we send the command AT+CALM and we expect the reply OK in the 4th
second. If the reply OK is not received, we have no connection with the GSM and
we reset the bit C35i, which indicates the connection.
In a similar way
we read SMS when it’s received: If Sekunde = 5 And C35i = 1 Then 'vsako 5. sekundo minute
Niz = "AT+CMGL=0" ' Daj sporočilo!
Gosub Poslji
End If
If Sekunde = 8 And C35i = 1 Then 'vsako 8. sekundo odgovor
'/OK/ če ni smsa
'/+CMGL: 9,0,,23 ....pdu... OK
' 0D0A 0D0A0D0A 0D0A če je sms
If Y(3) <> &H4F And C35i = 1 Then ' Je SMS!
Gosub Pdutxt 'Transformacija PDU v Text in Telno
Each 5th second we
send AT+CMGL=0 Command and each 8th second we analyze the reply. If the answer
is OK, then no message has arrived. If the answer is not OK, then an SMS
message has been received and read into the variables Niz and Pdu ( and if
message is very long also in Text). We call subroutine Pdutxt to transform it into variables Telno
and Text.
Subroutine Pdutxt to
transforms information found in Niz:
+CMGL:
9,0,,23 t
into command
AT+CMGD=9
to delete the message in GSM.
In the same 8th
second we call subroutine Poslji to delete the message and and we start
analizing the received message, which resides in Text and of course Telno.
When we wish to send
an SMS, we prepare it in Telno and in the GSM telno where the SMS is to be sent
and in Text the message itself. The
actual sending is done in two phases. It has to be done in two different seconds.
First we prepare the GSM handyphone for receiving a message and then we
actually send the message. Therefore there are two subroutines, putsms1 and
putsms2. For actual triggering we set a
bit Sendbit. If Sekunde = 21 Then 'vsako 21. sekundo minute
' Če je postavljen bit Sendbit, pošljemo vsebino iz Text na Telno
X = 2
If Sendbit = 1 And C35i = 1 Then : Gosub Putsms1 : End If
End If
If Sekunde = 22 Then 'vsako 22. sekundo minute
X = 2
If Sendbit = 1 And C35i = 1 Then : Gosub Putsms2 : End If
Reset Sendbit
End If
Here’s an example of how to control some relays. There are 5 relays to
be controlled 'Releji in Led diode
Rele1 Alias P1.0
Rele2 Alias P1.1
Rele3 Alias P1.2
Rele4 Alias P1.3
'Rele5 Alias P1.4
Led1 Alias P1.4
' Števci minut za releje:
Dim Relestevec(5) As Word
The appropriate
counters for each relay one are minute counters. If the counter is zero, the
relay is off, if not,the relay in on. ' krmiljenje relejev:
If Relestevec(1) <> 0 Then : Reset Rele1 : Else : Set Rele1 : End If
If Relestevec(2) <> 0 Then : Reset Rele2 : Else : Set Rele2 : End If
If Relestevec(3) <> 0 Then : Reset Rele3 : Else : Set Rele3 : End If
If Relestevec(4) <> 0 Then : Reset Rele4 : Else : Set Rele4 : End If
' If Relestevec(5) <> 0 Then : Reset
Rele5 : Else : Set Rele5 : End If
We decrement each
relay-counter every minute: Incr Minute
' vsako minuto odštevamo števce relejev, če niso 0
For I = 1 To 5
If Relestevec(i) <> 0 Then
Decr Relestevec(i)
End If
Next
If we receive a
message like this:
Tr 2:30 4:6000
3:0
It should be
interpreted as this command: relay2 on for 30 minutes, relay 4 on for 6000
minutes, relay 3 off immediately, the others remain unchanged,
We intercept this
commant in 8th second: If Y(xtext) = &H54 And Y(i) = &H72 Then : Gosub Tr : End If 'set rele
Subroutine Tr sets
appropriate counters and afterwards prepares message about all relays counter
to be sent to originator. Text = "Raport:
" 'Še sestavimo poročilo
For I = 1 To 5
Niz = Str(i)
Niz = Niz + ":"
Niz = Niz + Str(relestevec(i))
Niz = Niz + " "
Text = Text + Niz
Next
So after calling the
subroutine, we set the bit Sendbit to trigger sending. If Command is not
recognised as a valid command, then the
original SMS is sent back to originator.
Download source code here
I hope this will
help.
Vilko Sustic |