Go Down

Topic: Only send message once (Read 1 time) previous topic - next topic

mrfunk

Hi I've constructed a radio monitor project.. you select your location and it tunes to the fm radio services, if any station arn't stereo.. it sends a text message..

I only want it to send a text message once per service fault.. and then if that fault self clears I want it to reset the latch, so it could text again. if the fault on one service stays continuously, I only need the one notification

so I think im looking at using a count, but this needs to be relavent per service..
I fully understand how to use count if it was just one station, but the array is throwing me off, and not sure how to reference it.

Please see the messy and complicated code I've cobbled together..

Code: [Select]
#include <GSM.h>
#include <LiquidCrystal.h>
// //#include <Si4703_Breakout.h>
#include <Wire.h>
#include <TEA5767.h>
// from https://github.com/andykarpov/TEA5767
#include <Button.h>
// from http://arduino-info.wikispaces.com/HAL-LibrariesUpdates
// PIN Number
#define PINNUMBER ""
GSM gsmAccess;     //
GSM_SMS sms;
GSMVoiceCall vcs;
// Array to hold the number for the incoming call
char numtel[20];
////////////////////////////// TEA5767 /////////////////////
TEA5767 Radio;
double old_frequency;
double frequency;
int search_mode = 0;
int search_direction;
unsigned long last_pressed;
///////////////////////////// LCD //////////////////////////
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 9, 8);

// This section descibes button connection.
const int buttonPin = A0;
const int upbuttPin = A2;
const int downbuttPin = A3;
const int selectPin =  A1;
const int smsmutePin = 6;
const int led1Pin = A4;
const int led2Pin = A5;
const int sensorPin = A15;
const int DABsoloPin = 53;
const int DABenablePin = 51;
unsigned long LastStationSwitch = 0;
int currentStation = -1;
unsigned long lastNoise;
///////////freq map//////////////////////
float Freq[][5] ={
 {
   98.2, 88.6 , 90.8, 93.0, 100.4                                                            }
 ,//Atest
 {
   99.5, 89.9 , 91.4, 104.7, 93.6                                                            }
 ,//Aberdare
 {
   98.3 , 88.7, 90.9, 93.1, 103.5                                                            }

 ,//Abergavenny
 {
   98.6 , 89.0, 91.2, 93.4, 104.3                                                         }
 ,//Abertillery
 {
   98.1 , 88.5, 90.7, 92.9, 104.0                                                         }
 ,//Blaenavon
 {
   98.5 , 88.9, 91.1, 104.7, 93.3                                                          }
 ,//Brecon
 {
   98.0 , 88.4, 90.6, 104.6, 92.8                                                          }
 ,//Carmel
 {
   89.5 , 91.7, 93.9, 96.4, 0                                                          }
 ,//kvh
 {
   99.5 , 89.9, 92.1, 94.3, 101.7                                                         }
 ,//Wenvoe
 {
   89.5 , 91.7, 93.9, 96.4, 0                                                          }
 ,//kvh
 {
   89.5 , 91.7, 93.9, 96.4, 0                                                          }
 ,//kvh
 {
   89.5 , 91.7, 93.9, 96.4, 0                                                          }
 ,//kvh
 {
   89.5 , 91.7, 93.9, 96.4, 0                                                          }
 ,//kvh

};
const int NUM_FREQS = sizeof Freq[0]/sizeof Freq[0][0];
boolean channelState[NUM_FREQS];
// variables will change:
int buttonState = 0;        
int upbuttState = 0;        
int downbuttState = 0;
int selectbuttState = 0;
int smsmuteState = 0;
int select = 0;
float channel;
//---- COUNTING ---
int countAV = 0;
int countSENT = 0;
int countMONO = 0;
// ---- DAB ---
int AVlevel = 0;
int DABsolo = 0;
int DABenable = 0;

//int DABsoloPin = 0;
//int DABenablePin = 0;

// Save data variables
String IMEI = "";

// serial monitor result messages
String errortext = "ERROR";
///////////////////////// NAME INDEX ////////////////////////////////
char * Names[] = {
 "A-RHA", "Aberdare  ", "Abergavenny  ", "Abertillery", "Blaenavon", "Brecon", "Carmel", "Kilvey Hill", "Wenvoe" };
const int NAME_COUNT = sizeof Names / sizeof Names[0];
int NameIndex = 0;
// ____________________________________________________________________________________________
void setup()
{

 Wire.begin();
 Radio.init();

 // initialize the pushbutton pin as an input:
 pinMode(buttonPin, INPUT);  
 pinMode(upbuttPin, INPUT);
 pinMode(downbuttPin, INPUT);
 pinMode(selectPin, INPUT);
 pinMode(smsmutePin, INPUT);
 pinMode(led1Pin, OUTPUT);
 pinMode(led2Pin, OUTPUT);
 pinMode(DABsoloPin, INPUT);
 digitalWrite(DABsoloPin, HIGH);
 pinMode(DABenablePin, INPUT);
 digitalWrite(DABenable, HIGH);


 ///pinMode(LEDAVPin, OUTPUT);

 // initialize serial communications and wait for port to open:
 Serial.begin(9600);
 while (!Serial) {
   ; // wait for serial port to connect. Needed for Leonardo only
 }
 Serial.println("Receive Voice Call");
 /////////////////////// LCD BOOT  turn on display? ////////////////////
 lcd.begin(16, 2);
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print("Radio SPY by DM");
 delay(2000);
 lcd.clear();
 lcd.setCursor(0,0);
 lcd.print("--Please  Wait--");
 lcd.setCursor(0, 1);

 lcd.print("-GSM Connecting-");
 // connection state
 boolean notConnected = true;
 // Start GSM shield
 // If your SIM has PIN, pass it as a parameter of begin() in quotes
 while(notConnected)
 {
   if(gsmAccess.begin(PINNUMBER)==GSM_READY)
   {
     notConnected = false;
     digitalWrite(A5, HIGH);
     lcd.clear();
     lcd.setCursor(0, 0);
     lcd.print(" GSM  Connected");
     delay(1000);
     lcd.clear();
   }
   else
   {
     Serial.println("Not connected !");
     digitalWrite(A5, LOW);
     lcd.setCursor(0, 1);
     lcd.clear();
     lcd.print("NO GSM !");
     delay(1000);
   }
 }

 vcs.hangCall();

 Serial.println("Waiting for a call");

 ///////////////// SELECT SITE NAME //////////////////////
 while(select==0){
   // read the state of the pushbutton value:
   upbuttState = digitalRead(upbuttPin);
   downbuttState = digitalRead(downbuttPin);
   selectbuttState = digitalRead(selectPin);

   // if it is, the upbuttState is HIGH:
   if (upbuttState == HIGH) {    
     // increment name
     NameIndex = (NameIndex+1)%NAME_COUNT;
   } // Wrap around

   //if it is, the upbuttState is HIGH:
   if (downbuttState == HIGH) {    
     // increment name
     NameIndex = (NameIndex-1)%NAME_COUNT;
     if (NameIndex < 0) {
       NameIndex=NAME_COUNT-1;
     }
   } // Wrap around

   if (selectbuttState == HIGH){
     select=1;
   }
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("> ");
   lcd.setCursor(2,0);
   lcd.print (Names[NameIndex]);
   lcd.setCursor(0,1);
   lcd.print("Select Location ");

   delay(150);
   lcd.clear();
 }
 lcd.clear();
 for (int i =0; i < NUM_FREQS; i++)
 {
   channelState[i] = true;
 }
}


mrfunk

Here is the loop... (sorry was limited in post size)

Code: [Select]
void loop()
{

 // Check the status of the voice call
 switch (vcs.getvoiceCallStatus())
 {
 case IDLE_CALL: // Nothing is happening
   lcd.setCursor(6,1);
   lcd.print("    ");
   break;

 case RECEIVINGCALL: // Yes! Someone is calling us
   lcd.setCursor(6,1);
   lcd.print("RING");
   Serial.println("RECEIVING CALL");

   // Retrieve the calling number
   vcs.retrieveCallingNumber(numtel, 20);

   // Answer the call, establish the call
   vcs.answerCall();
   currentStation=-1;
   break;      

 case TALKING:  // In this case the call would be established
   lcd.setCursor(6,1);
   lcd.print("CALL");

   delay(100);
   //vcs.hangCall();

   break;
   //////////////////______________________________
 }



 DABsolo = digitalRead(DABsoloPin);
 if(DABsolo == HIGH){
   unsigned char buf[5];
   unsigned long current_millis = millis();

   if (current_millis>LastStationSwitch+(TALKING ==vcs.getvoiceCallStatus()?10000:2000)) // hold station 10secs if in call, or 2secs normal in loop
   {
     if (currentStation != -1 && Radio.read_status(buf) == 1)
     {
       int stereo = Radio.stereo(buf);


       if (stereo)
       {
         countMONO=0;
         channelState[currentStation] = true;
       }

       else  

         if(countMONO>=14)//// increase to add reliabity.
       {
         digitalWrite(A4, LOW);

         lcd.clear();
         lcd.setCursor(0,1);
         lcd.print("--- FM FAULT ---");
         delay(1000);
         lcd.clear();
         if (smsmuteState == HIGH)
         {
           lcd.setCursor(0,0);
           lcd.print("GSM  SEND  MUTED");
           delay(1000);
           lcd.clear();
         }
         if (smsmuteState == LOW && channelState[currentStation])//// HERE IS THE SMS SEND FOR A SERVICE FAULT, after say 14 failed stereo detections in the loop,
         {
           channelState[currentStation] = false;
           lcd.clear();
           sms.beginSMS("0mmmmmm2");
           lcd.print("SMS SENDING >>>>");
           sms.print("ammmmm\xFEgmail.com ");
           sms.print(Names[NameIndex]);
           sms.print("  ");
           sms.print(channel);
           sms.print(" SHUT DOWN");
           sms.endSMS();  
           lcd.clear();
           lcd.setCursor(0, 1);
           lcd.print("SMS SENT OK");
           delay(1000);
           lcd.clear();
         }
       }
     }
     currentStation++;
     if(currentStation>=NUM_FREQS)
     {
       currentStation =0;
     }
     LastStationSwitch=current_millis;///////////////////
     channel=Freq[NameIndex][currentStation];
     Radio.set_frequency(channel);/////////////// TUNE station
     delay(200);// allow time to tune

     smsmuteState = digitalRead(smsmutePin);


   }

   // unsigned char buf[5];
   if (Radio.read_status(buf) == 1)
   {
     delay(200);//delay here to help buufer?
     float current_freq =  floor (Radio.frequency_available (buf) / 100000 + .5) / 10;
     int signal_level = Radio.signal_level(buf);
     lcd.clear();
     lcd.setCursor(0,0);
     lcd.print(current_freq);
     lcd.setCursor(6,0);
     lcd.print("MHz");
     lcd.setCursor(10,0);
     lcd.print(signal_level *  100 / 15);
     lcd.setCursor(13,0);
     lcd.print("%");
     lcd.setCursor(15, 0);
     lcd.print(countMONO);
     int stereo = Radio.stereo(buf);
     delay(10);
     if (stereo)
     {
       lcd.setCursor(14, 0);
       lcd.print("ST ");
       digitalWrite(A4, HIGH);
       delay(10);
     }
     else
     {

       countMONO++;
       digitalWrite(A4, LOW);
     }

   }
 }


 DABenable = digitalRead(DABenablePin);
 if(DABenable==LOW)
 {
   if(DABsolo==LOW)
   {
     lcd.setCursor(0,0);
     lcd.print("    DAB solo    ");
   }
   AVlevel = analogRead(sensorPin);
   lcd.setCursor(12,1);
   if(AVlevel<1000)
   {
     lcd.print(" ");
   }
   if(AVlevel<100)
   {
     lcd.print(" ");
   }
   if(AVlevel<10)
   {
     lcd.print(" ");
   }
   lcd.print(AVlevel, 1024);
   lcd.setCursor(10,1);
   lcd.print("  A");
   lcd.setCursor(0,1);
   if(countAV<1000)
   {
     lcd.print(" ");
   }
   if(countAV<100)
   {
     lcd.print(" ");
   }
   if(countAV<10)
   {
     lcd.print(" ");
   }
   lcd.print(countAV);

   if(AVlevel<70 && countAV<1200)
   {

     delay(100);
     countAV++;
   }

   else

       if(AVlevel<70 &&countAV>119 && countSENT<1)
     {
       lcd.clear();
       sms.beginSMS("nnnnnnn2");
       lcd.print("DAB FAULT >>>>");
       sms.print("ardbbkjhbjhbjhbxFEgmail.com ");
       sms.print(Names[NameIndex]);

       sms.print(" DAB DEMOD FAIL !");
       sms.endSMS();  
       lcd.clear();
       lcd.setCursor(0, 1);
       lcd.print("SMS SENT OK");
       delay(2000);
       lcd.clear();
       countSENT++;
     }


     else

         if(AVlevel>72) // && count==0)
       {

         countAV=0;
         countSENT=0;
       }

   delay(100);
 }


}

MarkT

You are looking to report transitions between states, not states themselves.

Here the states are normal and fault.  If you see a fault state and the previous
state was normal, then you send a message.  After checking you set previous
state to the current state and recheck at the next scheduled time.

Code: [Select]

#define NORMAL 0
#define FAULT 1
byte  state = NORMAL, previous_state = NORMAL ;

void check_and_report ()
{
  state = determine_current_state () ;
  if (state == FAULT && previous_state == NORMAL)
  {
    report_anomally ()
  }
  previous_state = state ;
}

void loop ()
{
  ..
  ..
  check_and_report () ;
  .. // any other stuff
}


Of course this approach generalises if you want to ensure a fault state isn't transient, delay a little
and recheck before reporting...
[ I DO NOT respond to personal messages, I WILL delete them unread, use the forum please ]

Go Up