Większość programów piszę dla innych i tak też było w tym przypadku.
Znajomy zbudował układ monitorujący altankę...
Kiedy któryś z czujników zostanie pobudzony a układ monitorujący jest aktywny to urządzenie wyśle SMS
na numer telefonu właściciela.
Urządzenie posiada dwa wejścia na linie z czujnikami magnetycznymi (okna/drzwi itp.), wejście czujnika ruchu PIR, wejście 1WIRE monitorujące temperaturę oraz wejście z zasilacza informujące o tym czy układ pracuje na baterii czy też jest ładowany.
W układzie jest kilka diod informujących o stanie urządzenia. Jedna z nich pokazuje stan zalogowania do sieci GSM
Z SIM800L nie zaobserwowałem podobnych problemów, ale podobno SIM900 potrafi przestać radośnie migać diodą i wtedy wymagany jest restart.
Powstał więc układ nadzorujący miganie dioda NET i potrafi sprawnie określić czy układ w ogóle miga, czy miga raz na 3 sekundy itd.
Wiem że można odczytywać stan zalogowania poprzez komendy, ale takie było życzenie znajomego więc taki moduł w programie istnieje.
Program przedstawiam bo może komuś się przyda jakiś jego kawałek.
Zwierając zworkę można nawet po zaprogramowaniu przyuczyć urządzenie do nowego numeru telefonu.
Uzbraja się po zatelefonowaniu. Nieznane numery odrzuca. Tak więc samo sterowanie w jedną stronę jest bezkosztowe.
Dodatkowo jeśli w momencie wystąpienia zdarzenia nie będzie sieci to SMS zostanie wysłany zaraz po zalogowaniu.
Przekaźniki włączamy wysyłając dużymi literami WYJ1 albo WYJ2 (to można zmieniać)
Po spacji wpisujemy ON lub OFF. Można nawet sterować dwoma na raz.
WYJ1 ON
WYJ1 OFF
WYJ1 ON WYJ2 OFF
Działa STATUS - wysyła SMS z wszystkimi parametrami
Działa TEMP (nie podłaczałem DS18B20 ale wierze że zafuczy ;)- wysyła SMS z temperaturą
Dodałem czas na ustabilizowanie się zmiany zasilania 2,5s
Po uzbrojeniu lub rozbrojeniu wysyła SMS o podjętej akcji ;)
$regfile = "m8def.dat" $crystal = 8000000 $hwstack = 32 $swstack = 32 $framesize = 200 $baud = 9600 '19200 '9600 Tested $projecttime = 2 Config Submode = New '--[SETTINGS CONSTANTS]-- Const Owner_number_ = "+48700700" '<<<<<< WRITE YOUR NUMBER HERE Const Prefix = "+48" Const Time_value = 112 '112 x 25ms = 2800ms / szuka sieci to wartosć ~30 Const Max_wait_time = 20 '20sec wait for Led to start blinking Const Alarm_temp = 45 Const Net_watcher = 1 Const Sim900 = 0 ' 1 for 20s wait after boot Const C_dbg = 0 ' 1 for debug output on PORTD.6 Baud 19200 '--[LANGUAGE PACK FOR SMS]-- Const _pir = "PIR SENS " Const Motion_ = "Motion detected!, " Const Zone1_ = "Zone1" Const Zone2_ = "Zone2" Const Alrm = " Alarm!, " Const Okay = " OK!, " Const Norm_temp = "Temperature is normal, " Const High_temp = "Temperature is to high!, " Const Sens_temp = "Temperature sensor corupted, " Const Pwr_dwn = " PWR Supply is down" Const Pwr_up = " PWR Supply work now" Const Store_nmb = "New number stored " Const System = "Monitoring " Const _aktywny = "aktywny!" Const _dezaktywowany = "dezaktywowany!" Const _wy1 = "WYJ1" Const _wy2 = "WYJ2" Const _on = "ON" Const _off = "OFF" '************************************************** '* TIMER2 CONFIG FOR TIME BASE * '************************************************** Config Timer2 = Timer , Prescale = 1024 , Compare = Disconnect , Clear Timer = 1 Compare2 = 195 '25ms @8MHz Dim 25ms As Byte , 1s As Byte '************************************************** '* I/O HARDWARE CONFIG * '************************************************** Config Portc.4 = Output : Armed_led Alias Portc.4 : Set Armed_led Config Portc.3 = Output : Led_temp Alias Portc.3 : Set Led_temp Config Portc.2 = Output : Led_sens_2 Alias Portc.2 : Set Led_sens_2 Config Portc.1 = Output : Led_sens_1 Alias Portc.1 : Set Led_sens_1 Config Portc.0 = Output : Led_pir Alias Portc.0 : Set Led_pir Config Portb.1 = Output : Rled Alias Portb.1 : Set Rled Config Portb.0 = Output : Gled Alias Portb.0 : Set Gled Config Portb.5 = Output : Pk1 Alias Portb.5 Config Portd.6 = Output : Pk2 Alias Portd.6 Config Pinb.3 = Input : Portb.3 = 1 : Mag1 Alias Pinb.3 'magnetic sensor 1 Config Pinb.4 = Input : Portb.4 = 1 : Mag2 Alias Pinb.4 'magnetic sensor 2 Config Pind.7 = Input : Portd.7 = 1 : Pir Alias Pind.7 Config Pind.3 = Input : Portd.3 = 1 : Jumper Alias Pind.3 Config Pinc.5 = Input : Portc.5 = 1 : Pwr_supply_sig Alias Pinc.5 'Power supply monitoring Config Pind.4 = Input : Portd.4 = 1 : Gsm_led Alias Pind.4 'GSM blink LEED monitoring Config Portd.2 = Output : Portd.2 = 0 : Restart_pin Alias Portd.2 Config Portd.5 = Output : Dbg_led Alias Portd.5 'LED for debug purposes 1Hz blink if not used '************************************************** '* BACKGROUND UART RECEIVER * '************************************************** Config Serialin0 = Buffered , Size = 200 , Bytematch = 10 ' from SIM800 react when LF (line feed)received Open "COM1:" For Binary As #1 Config Input1 = Crlf , Echo = Cr Echo Off '************************************************** '* 1WIRE CONFIG FOR DS18B20 * '************************************************** Config 1wire = Portb.2 '************************************************** '* VARIABLES * '************************************************** '--[VARIABLES 1WIRE]-- Dim Bytes(9) As Byte , Sum As Byte , Errors As Byte Dim T As Integer At Bytes Overlay 'dwa pierwsze bajty tablicy tworzą tez Integer ;) Dim Temperature As String * 20 '--[VARIABLES GSM]-- Dim Got_match As Byte , Inp_str As String * 200 Dim Caller_nr As String * 15 , Pos1 As Byte , Pos2 As Byte Dim Init_gsm As Byte , Init_cnt As Byte , Lock As Byte Dim Wait_check As Byte , Send_msg_flg As Byte , Send_cnt As Byte Dim New_msg As String * 140 , Owner_rings_cnt As Byte , Monitor_state_old As Byte Dim Input_gsm As Byte I_error Alias 1 I_okay Alias 2 I_ring Alias 3 I_number Alias 4 I_hang Alias 5 I_sms Alias 6 Dim Init_seq As Byte , Waiting_cnt As Byte '--[commands for clarity]-- Const Set_defaulf = "ATZ" ' reset all settings Const At_ = "AT" ' no comment Const Echo_off = "ATE0" ' disable echo received commands Const Call_progress = "ATX0" Const Show_inc_number = "AT+CLIP=1" ' enable showing incomming calls numbers Const Get_sms = "AT+CMGR=1" ' get the msg "Read SMS Message" Const Del_sms = "AT+CMGD=1" ' del msg of index 1 Const Send_msg = "AT+CMGS=" 'should be followed by ; Chr(34) ; Num ; Chr(34) Const Set_txt = "AT+CMGF=1" 'select msg format (default 0=PDU so must be changed to 1=TXT) Const Network = "AT+CREG?" 'do we have net? 'loging to network +CREG: 0,2 'logged in +CREG: 0,5 Const Show_new_msg = "AT+CNMI=2,2,0,0" 'new msg will be print to terminal and no SIM memory used Const Hang_up = "ATH" '--[MEMORIZED VARIABLES]-- Dim Ee_check As Byte , Ee_check_ee As Eram Byte : Const Mem_ee = 10 'needed for first run Dim Owner_nr As String * 15 , Owner_nr_ee As Eram String * 15 Dim Is_armed As Byte , Is_armed_ee As Eram Byte 'mem alarm is off/on Dim Pk1_mem As Byte , Pk1_ee As Eram Byte Dim Pk2_mem As Byte , Pk2_ee As Eram Byte '--[MONITORING VARIABLES]-- Dim Owner_learn As Byte , New_state As Byte , Test_pin As Byte Dim Mag1_state As Byte , Mag2_state As Byte , Pir_state As Byte , Temp_state As Byte , Pwr_state As Byte Dim Pwr_cnt As Byte , Helpb As Byte Sub Get_temp Local Error As Byte Error = 0 1wreset 1wwrite &HCC 1wwrite &HBE Bytes(1) = 1wread(9) 'odczytaj 9 bajtów do tablicy (8 bajtów i CRC obliczone przez czujnik) If Bytes(8) = &H10 Then 'sprawdzenie czy ósmy bajt zawiera &H10 Sum = Crc8(bytes(1) , 8) 'sam oblicz CRC z ośmiu bajtów If Sum = Bytes(9) Then 'jeśli nasze obliczenia zgadzaja się z tymi od czujnika... T = T * 10 T = T \ 160 ' temp z dokładnością do 1 stopnia, bez przecinka) Temperature = " T=" + Str(t) + "st.C " Else Error = 1 End If Else Error = 1 End If If Error = 1 Then If Errors < 3 Then Incr Errors Else New_state = 3 Temperature = " DS18B20 ERROR " End If Else Errors = 0 Select Case T Case Is < 44 : New_state = 0 Case Is > 45 : New_state = 1 End Select End If 1wreset 1wwrite &HCC 1wwrite &H44 'przygotuj nastepny odczyt temperatury End Sub Sub Get_caller_nr Pos1 = Instr(inp_str , "{034}") 'find first quotation sign Incr Pos1 'add one for search next quotation sign Pos2 = Instr(pos1 , Inp_str , "{034}") 'search from first quotation+1 for second qotation sign Pos2 = Pos2 - Pos1 'calc number of char between quotations Caller_nr = Mid(inp_str , Pos1 , Pos2) 'cut only caller nr. If Len(caller_nr) <= 9 Then 'if number is without prefix Caller_nr = Prefix + Caller_nr 'then add prefix End If End Sub Function Check_on_off(byval Start_point As Byte)as Byte Incr Start_point If Instr(start_point , Inp_str , _off) > 0 Then Check_on_off = 1 If Instr(start_point , Inp_str , _on) > 0 Then Check_on_off = 2 End Function Sub Pir_sub Select Case Pir_state Case 0 : New_msg = New_msg + _pir + Motion_ Case 1 : New_msg = New_msg + _pir + Okay End Select End Sub Sub System_sub New_msg = New_msg + System If Is_armed = 1 Then New_msg = New_msg + _aktywny Else New_msg = New_msg + _dezaktywowany End Sub Sub Temp_sub New_msg = New_msg + Temperature End Sub Sub Pk1_sub New_msg = New_msg + "," + _wy1 + " " If Pk1_mem = 1 Then New_msg = New_msg + _on Else New_msg = New_msg + _off End Sub Sub Pk2_sub New_msg = New_msg + "," + _wy2 + " " If Pk2_mem = 1 Then New_msg = New_msg + _on Else New_msg = New_msg + _off End Sub Sub Pwr_sub Select Case Pwr_state Case 0 : New_msg = New_msg + Pwr_dwn Case 1 : New_msg = New_msg + Pwr_up End Select End Sub Sub Zone1_sub Select Case Mag1 Case 0 : New_msg = New_msg + Zone1_ + Okay Case 1 : New_msg = New_msg + Zone1_ + Alrm End Select End Sub Sub Zone2_sub Select Case Mag2 Case 0 : New_msg = New_msg + Zone2_ + Okay Case 1 : New_msg = New_msg + Zone2_ + Alrm End Select End Sub '************************************************** '* SUB FOR GSM900 WATCHDOG :D * '************************************************** Dim Pulse_counter As Word , Net_status As Byte , Pulse_mark As Byte Dim Sig_bad As Byte , Sig_good As Byte , Old_status As Byte No_network Alias 0 : Logged_into_network Alias 1 Sub Check_net 'co 25ms If Gsm_led = 0 Then 'jesli dioda mignęła If Pulse_mark = 1 Then 'jesli ustawiona flaga stanu wysokiego Pulse_mark = 0 'skasuj flage aż do nastepnego rising If Pulse_counter > Time_value Then 'jeśli musiało upłynąc wiecej czasu niż 2,8s If Sig_good < 1 Then Incr Sig_good Else Net_status = Logged_into_network 'mamy impuls w przeciągu ... Sig_bad = 0 'kasuj licznik błedów End If Else 'jeśli impuls nastąpił wcześniej to pewnie miga co sekunde If Net_status = 1 Then Incr Sig_bad 'nie kasuj flagi od razu tylko czekaj do dwóch razy If Sig_bad = 3 Then 'jeśli błedy Sig_bad = 0 : Sig_good = 0 Net_status = No_network 'kasuj flage czyli brak sieci End If 'Print #6 , Pulse_counter End If End If 'nie sprawdzaj ponownie do ustalenia sie stanu wysokiego Pulse_counter = 0 'kasuj licznik jeśli stan niski Else 'jeśli stan wysoki to czekamy na impuls masowy Pulse_mark = 1 'ustaw juz flage że był stan wysoki Incr Pulse_counter 'zwiekszaj licznik If Pulse_counter > 240 Then 'jeśli w ogóle nie miga to resetuj licznik 240x25=6000ms 6s Pulse_counter = 0 If Net_status = 1 Then Init_seq = 0 Net_status = No_network 'i skasuj flage czyli brak sieci 'restart SIM900 End If End If End Sub '************** [PROGRAM START] ******************* Wait 1 'one sec for Led test Reset Led_pir Reset Led_sens_1 Reset Led_sens_2 Reset Led_temp Reset Rled Reset Gled Armed_led = Is_armed 'Armed Led depends of memorized alarm state '************************************************** '* MEMORY READ * '************************************************** 'if first run then programm eeprom Ee_check = Ee_check_ee If Ee_check <> Mem_ee Then Ee_check_ee = Mem_ee Owner_nr_ee = Owner_number_ Is_armed_ee = 0 Pk1_ee = 1 Pk2_ee = 1 End If '************************************************** '* NEW OWNER NUMBER LEARNING IF NEEDED * '************************************************** If Jumper = 0 Then Owner_learn = 1 : Is_armed_ee = 0 Pk1_ee = 0 Pk2_ee = 0 End If ' read eeprom normally Owner_nr = Owner_nr_ee Is_armed = Is_armed_ee Pk1_mem = Pk1_ee : Pk1 = Pk1_mem Pk2_mem = Pk2_ee Monitor_state_old = Is_armed #if Sim900 = 1 Wait 20 #endif #if C_dbg = 1 Open "COMD.6:19200,8,N,1" For Output As #6 'opcjonalny port programowy Print #6 , "Debug start" #else Pk2 = Pk2_mem #endif '--[PREPARE DS18B20]-- 1wreset 1wwrite &HCC 1wwrite &H44 '--------------------- Mag1_state = Mag1 Mag2_state = Mag2 Pir_state = Pir Pwr_state = Pwr_supply_sig Temp_state = New_state Enable Interrupts Do '--[PARSE RECEIVED STRING]-- If Got_match = 1 Then Got_match = 0 If Inp_str <> "" Then If Instr(inp_str , "OK") > 0 Then Input_gsm = I_okay End If If Instr(inp_str , "+CLIP:") > 0 Then Call Get_caller_nr Input_gsm = I_number End If If Instr(inp_str , "+CMT:") > 0 Then Call Get_caller_nr Input_gsm = I_sms End If If Instr(inp_str , "RING") > 0 Then Input_gsm = I_ring End If If Instr(inp_str , "NO CARRIER") > 0 Then Input_gsm = I_hang End If If Instr(inp_str , "ERROR") > 0 Then Input_gsm = I_error End If End If If Input_gsm = I_sms Then Waitms 500 Wait_check = 5 'don`t check Net Led if UART is active End If Select Case Input_gsm Case I_error #if C_dbg = 1 : Print #6 , "Error" : #endif Case I_ring #if C_dbg = 1 : Print #6 , "Incomming call from" ; : #endif Case I_number 'Print #6 , "Nr " ; Caller_nr If Caller_nr = Owner_nr Then #if C_dbg = 1 : Print #6 , " Owner ;)" : #endif If Lock = 0 Then If Is_armed = 0 Then Is_armed = 1 : #if C_dbg = 1 : Print #6 , "Armed!" : #endif '--[it is possible to arm device with some broken circuits]-- Mag1_state = Mag1 Mag2_state = Mag2 Pir_state = Pir Pwr_state = Pwr_supply_sig Temp_state = New_state New_msg = System + _aktywny Else Is_armed = 0 : #if C_dbg = 1 : Print #6 , "Disarmed" : #endif New_msg = System + _dezaktywowany End If Is_armed_ee = Is_armed End If If Owner_rings_cnt < 2 Then Incr Owner_rings_cnt Else Owner_rings_cnt = 0 Print #1 , Hang_up 'reject call End If Else #if C_dbg = 1 : Print #6 , " new number" : #endif If Lock = 0 Then If Owner_learn = 1 Then Owner_learn = 0 Owner_nr = Caller_nr : Owner_nr_ee = Owner_nr New_msg = Store_nmb + Owner_nr : Send_msg_flg = 1 Else Print #1 , Hang_up 'reject call End If End If End If Lock = 5 'lock to not switch states until end of call Case I_hang #if C_dbg = 1 : Print #6 , "Call end" : #endif Owner_rings_cnt = 0 Case I_sms #if C_dbg = 1 : Print #6 , "SMS from " ; Caller_nr ; "{010}" ; Inp_str : #endif '--[ SWITCH RELAY #1 VIA SMS]------------------------------------ Pos1 = Instr(inp_str , "WYJ1") ' search if word WYJ1 is in the message If Pos1 > 0 Then ' if there although once Helpb = Check_on_off(pos1) ' this function check next word (ON or OFF) Select Case Helpb ' function return value Case 1 : Reset Pk1 ' if 0 then nothing happends (some error) Case 2 : Set Pk1 ' but 1 or 2 switch LED ON/OFF ;) End Select Pk1_mem = Pk1 : Pk1_ee = Pk1_mem Call Pk1_sub : Send_msg_flg = 1 End If '--------------------------------------------------------------- #if C_dbg = 0 '--[SWITCH RELAY #2 VIA SMS]------------------------------------ Pos1 = Instr(inp_str , "WYJ2") ' search if word WYJ2 is in the message If Pos1 > 0 Then ' if there although once Helpb = Check_on_off(pos1) ' this function check next word (ON or OFF) Select Case Helpb ' function return value Case 1 : Reset Pk2 ' if 0 then nothing happends (some error) Case 2 : Set Pk2 ' but 1 or 2 switch LED ON/OFF ;) End Select Pk2_mem = Pk2 : Pk2_ee = Pk2_mem Call Pk2_sub : Send_msg_flg = 1 End If '--------------------------------------------------------------- #endif Pos1 = Instr(inp_str , "STATUS") If Pos1 > 0 Then Call System_sub Call Temp_sub Call Pir_sub Call Zone1_sub Call Zone2_sub Call Pwr_sub Call Pk1_sub Call Pk2_sub Send_msg_flg = 1 End If Pos1 = Instr(inp_str , "TEMP") If Pos1 > 0 Then Call Temp_sub : Send_msg_flg = 1 End If End Select If Tifr.ocf2 = 1 Then Tifr.ocf2 = 1 #if Net_watcher = 1 If Wait_check = 0 Then Call Check_net 'don`t check LED if UART is active #else Net_status = 1 #endif If Old_status <> Net_status Then Old_status = Net_status Select Case Net_status Case 0 Reset Gled #if C_dbg = 1 : Print #6 , "No network" : #endif Case 1 Set Gled #if C_dbg = 1 : Print #6 , "Logged in" : #endif End Select End If '--[IF MONITOR IS ACTIVE]-- If Is_armed = 1 Then ' one SMS if detected '--[PIR MOTION SENSOR]----------------------- Test_pin = Pir If Pir_state <> Test_pin Then Pir_state = Pir If Pir = 0 Then 'falling edge only #if C_dbg = 1 : Print #6 , "PIR state=" ; Pir_state : #endif Call Pir_sub : Send_msg_flg = 1 End If End If ' ' one SMS until back to normal state ' '--[WINDOW MAGNETIC SENSORS 1]--------------- Test_pin = Mag1 If Mag1_state <> Test_pin Then Mag1_state = Mag1 If Mag1 = 1 Then 'rising edge #if C_dbg = 1 : Print #6 , "Mag1_state=" ; Mag1_state : #endif Call Zone1_sub : Send_msg_flg = 1 End If End If ' ' one SMS until back to normal state ' '--[WINDOW MAGNETIC SENSORS 2]--------------- Test_pin = Mag2 If Mag2_state <> Test_pin Then Mag2_state = Mag2 If Mag2 = 1 Then 'rising edge Call Zone2_sub : Send_msg_flg = 1 End If End If ' ' ' '--[DS18B20 TEMPERATURE SENSOR]-------------- If Temp_state <> New_state Then Temp_state = New_state Select Case Temp_state Case 0 : New_msg = New_msg + Norm_temp : Send_msg_flg = 1 Case 1 : New_msg = New_msg + High_temp : Send_msg_flg = 1 Case 2 : New_msg = New_msg + Sens_temp : Send_msg_flg = 1 End Select End If ' '--[POWER SUPPLY----------------------------- Test_pin = Pwr_supply_sig If Pwr_state <> Test_pin Then If Pwr_cnt < 100 Then Incr Pwr_cnt Else Pwr_state = Pwr_supply_sig Call Pwr_sub : Send_msg_flg = 1 End If Else Pwr_cnt = 0 End If ' 'if Armed End If ' 25ms x 40 = 1000ms = 1s '--[1SEC ROUTINES]---------------------------- Incr 1s If 1s = 40 Then 1s = 0 Call Get_temp ' if init must be done '--[INIT]----------------------------------- Select Case Init_seq Case 0 : Set Restart_pin : Incr Init_seq '--[RESET SIM900]-- Case 1 : Reset Restart_pin : Incr Init_seq Case 2 If Net_status = 0 Then Incr Waiting_cnt If Waiting_cnt = Max_wait_time Then Waiting_cnt = 0 : Init_seq = 0 End If Else '--[WAIT FOR LOG]-- Incr Init_seq End If Case 3 : Print #1 , At_ : Incr Init_seq : #if C_dbg = 1 : Print #6 , "Init step 1.." ; : #endif Case 4 : Print #1 , Echo_off : Incr Init_seq : #if C_dbg = 1 : Print #6 , "2.." ; : #endif Case 5 : Print #1 , Show_inc_number : Incr Init_seq : #if C_dbg = 1 : Print #6 , "3.." ; : #endif Case 6 : Print #1 , Set_txt : Incr Init_seq : #if C_dbg = 1 : Print #6 , "4.." ; : #endif Case 7 : Print #1 , Show_new_msg : Incr Init_seq : #if C_dbg = 1 : Print #6 , "5..Init done!" : #endif 'case 8 : Should be OK End Select '------------[INIT END]-------------------- ' flag is cleared only if successful '--[MESSAGE SENDING]----------------------- If Send_msg_flg = 1 Then If Net_status = Logged_into_network Then If Init_seq = 8 Then 'init done If Lock = 0 Then #if C_dbg = 1 : Print #6 , "Sending msg" : #endif Select Case Send_cnt Case 0 : Print #1 , Send_msg ; "{034}" ; Owner_nr ; "{034}" : Incr Send_cnt : Set Rled Case 1 : Print #1 , New_msg ; "{026}" ; : Incr Send_cnt Case 2 To 6 : Incr Send_cnt : If Input_gsm = I_okay Then Send_cnt = 7 Case 7 : Send_msg_flg = 0 : New_msg = "" : Send_cnt = 0 : Reset Rled End Select End If End If End If End If #if Net_watcher = 1 If Wait_check > 0 Then Decr Wait_check 'every second decr Lock #endif If Lock > 0 Then 'lock to not switch modes until end of call Decr Lock If Lock = 0 Then If Monitor_state_old <> Is_armed Then Monitor_state_old = Is_armed Send_msg_flg = 1 'also SMS will be sent after hang up ;) End If End If End If Toggle Dbg_led 'end if 1s End If Armed_led = Is_armed Led_sens_1 = Mag1 Led_sens_2 = Mag2 Led_pir = Not Pir 'end if 25ms End If Input_gsm = 0 Loop End Serial0charmatch: $asm !PUSH R6 !PUSH R24 !PUSH R26 !PUSH R27 !PUSH R30 !in R24, sreg !PUSH R24 $end Asm Input #1 , Inp_str Got_match = 1 ' Tuned with NoSave Tool $asm !POP R24 !out sreg, r24 !POP R30 !POP R27 !POP R26 !POP R24 !POP R6 $end Asm Return