/*****************************************************/ /* FABLAB LANNION KERNEL OPEN SOURCE */ /* Contributors: David Blaisonneau, Nicolas Guédon */ /* Lannion FabLab website: http://fablab-lannion.org */ /*****************************************************/ //~ Included libraries #include #include #include ///////////////////////////// // Start of debug management. If DEBUG var is defined, all LOG_LN, LOG function are replaced by Serial.println, Serial.print in the program. Help to maintain and lighten the code // Use or not of GSM SHIELD. If GSM_NOT_USED is defined, GSM shield is activated during arduino loop. // Comment or uncomment the DEBUG OR GSM_NOT_USED vars // //#define DEBUG //#define GSM_NOT_USED #ifdef DEBUG #define LOG_LN Serial.println #define LOG Serial.print #else #define LOG_LN #define LOG #endif #ifdef GSM_NOT_USED #define MAIN_ROUTINE routine_fake #else #define MAIN_ROUTINE routine #endif // End of debug management //////////////////////////// //~ Sensor pin definition #define LIGHTSENSOR 0 #define MASSSENSOR 1 #define TEMPSENSOR 2 //~ SLEEP, in millisecond not bigger than 4.194.304 (=69.9min) (2^22 = 2^32/1024 -> calc to microsec) //~ GSM routine is nearly 15 seconds //~ Define a timer between each Database update //#define SLEEP 1800000 // 30 minutes #define SLEEP 30000 // 30s //~ Number of time we dont send SMS if the values of sensors dont change #define NOCHANGE 4 //~ SERVICE PHONE NUMBER (Emerginov platform open source) //~ For debug purpose, you can check platform status by sending a SMS to the number with "ping". The platform shall answer "pong" to say all is Ok. #define PHONE_NUMBER "\"+33645113265\"\r" //~ #define PHONE_NUMBER "\"+33645117979\"\r" //~ Light threshold (can be customized permite to define if we are night or day): #define LUMISEUIL 950 //~ SIM PIN #define PIN "0000" //~ RUCHE ID #define RUCHE "101" //~ Service SMS prefix #define SMS_TEXT_PREFIX "Bz " //~ TEMPO, delay after each AT command #define TEMPO 2000 //~ GSM Shield Switch PIN #define GSMSWITCHPIN 9 //~ AT commands #define AT_CMD_ENTER_PIN "AT+CPIN=\"" #define AT_CMD_INIT_SMS "AT+CMGF=1\r" #define AT_CMD_SEND_SMS "AT+CMGS=" #define AT_CMD_DEL_SMS "AT+CMGD=1,4\r" #define AT_CMD_GET_TIME "AT+CCLK?\r" #define AT_CMD_CR "\r" #define END_OF_FILE "\x1A" SoftwareSerial mySerial(7,8); //~ Initiate sensors data int sensor_lum = 0; int sensor_mass = 0; int sensor_temp = 0; //~ Initiate sensors data from previous measure (1 because we want value different from initial sensor values) int prev_sensor_mass = 5; //~ Define some data String text = ""; int nbSaut = 0; int instability = 2; char buffer[25]; //~ Initiate (code during arduino boot) void setup(){ pinMode(GSMSWITCHPIN, OUTPUT); pinMode(13, OUTPUT); mySerial.begin(19200); // the GPRS baud rate Serial.begin(19200); // the Serial baud rate delay(500); Narcoleptic.disableTimer1(); Narcoleptic.disableTimer2(); Narcoleptic.disableSPI(); Narcoleptic.disableWire(); } //~ Function loop (code during arduino up time) void loop(){ LOG_LN("/////// WAKE UP ARDUINO ///////"); LOG(">>> The time: "); LOG_LN(millis() + Narcoleptic.millis()); delay(500); MAIN_ROUTINE(); //Main function for data process, call routine if we are not in debug mode, and routine_fake if debug is activated LOG_LN("/////// GO SLEEP ARDUINO ///////"); delay(500); SleepNightOrDay(); // Different timer if the light sensor detect its the night or its the day } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //~ Custom function //~ SleepNightOrDay: Manage sleeptime depend on light sensor for night or day. void SleepNightOrDay(){ if ( analogRead(LIGHTSENSOR) < LUMISEUIL){ // Send every SLEEP minutes Narcoleptic.delay(SLEEP); }else{ // Delay * 8 : Send every 4h during the night (8 times of sleep)(delay function can't be use for timer up than 69minutes) Narcoleptic.delay(SLEEP); Narcoleptic.delay(SLEEP); Narcoleptic.delay(SLEEP); Narcoleptic.delay(SLEEP); Narcoleptic.delay(SLEEP); Narcoleptic.delay(SLEEP); Narcoleptic.delay(SLEEP); Narcoleptic.delay(SLEEP); } } //~ routine_fake: For debug or test, use this function again routine usual function (disable sms sending, just serial info are enabled) void routine_fake(){ LOG_LN("============ WE ARE IN THE FAKE ROUTINE FOR DEBUG DON'T WORRY ============"); prev_sensor_mass = sensor_mass; sensor_mass = analogRead(MASSSENSOR); LOG("> PREVIOUS WEIGHT: "); LOG_LN(prev_sensor_mass); LOG("> ACTUAL WEIGHT: "); LOG_LN(sensor_mass); if(areTheWeightChangeOrNot()){ LOG("> GET THE WEIGHT SENSOR VALUE... => "); LOG_LN(sensor_mass); sensor_temp = analogRead(TEMPSENSOR); LOG("> GET THE TEMPERATURE SENSOR VALUE... => "); LOG_LN(sensor_temp); sensor_lum = analogRead(LIGHTSENSOR); LOG("> GET THE LIGHT SENSOR VALUE... => "); LOG_LN(sensor_lum); } else { LOG("> GET THE WEIGHT SENSOR VALUE... => "); LOG_LN(sensor_mass); LOG(">>> Number of iteration without sending ==> "); LOG_LN(nbSaut); LOG_LN(">>> Weight doesn't change. No SMS sending"); } } //~ routine: Main SMS sending process void routine(){ LOG_LN("============ WE ARE IN THE REAL ROUTINE SO CARE PLEASE ============"); prev_sensor_mass = sensor_mass; sensor_mass = analogRead(MASSSENSOR); LOG("> PREVIOUS WEIGHT: "); LOG_LN(prev_sensor_mass); LOG("> ACTUAL WEIGHT: "); LOG_LN(sensor_mass); if(areTheWeightChangeOrNot()){ //Switch on GSM Shield LOG_LN("// WAKE UP GSM SHIELD //"); switchGSM(true); showSerialData(); //Get values from sensors dataSensorValuesUpdate(); // Create text to send text = SMS_TEXT_PREFIX; text += RUCHE; text += " "; text += sensor_mass; text += " "; text += sensor_temp; text += " "; text += sensor_lum; // Send SMS LOG_LN("<<<<<< SEND SMS >>>>>"); LOG_LN(text); sendTextMessage(PHONE_NUMBER, text ); showSerialData(); // Switch off GSM LOG_LN("// GO SLEEP GSM SHIELD //"); switchGSM(false); showSerialData(); } else { LOG_LN(nbSaut); LOG_LN(">>> Weight doesn't change. No SMS sending"); } LOG_LN("============ END OF THE REAL ROUTINE ============"); } //~ dataSensorValuesUpdate: Update sensor values, print on serial for debugging, update data (sensor_xxx), void dataSensorValuesUpdate(){ // Get and print on serial sensor values LOG_LN("> GET THE WEIGHT SENSOR VALUE... => "); LOG_LN(sensor_mass); sensor_temp = analogRead(TEMPSENSOR); LOG("> GET THE TEMPERATURE SENSOR VALUE... => "); LOG_LN(sensor_temp); sensor_lum = analogRead(LIGHTSENSOR); LOG("> GET THE LIGHT SENSOR VALUE... => "); LOG_LN(sensor_lum); } //~ areTheWeightChangeOrNot: Check is there is a change on weight, if not we send less often (like NOCHANGE times). Return true or false boolean areTheWeightChangeOrNot() { // Can change +instability and -instability if((sensor_mass <= prev_sensor_mass+instability && sensor_mass >= prev_sensor_mass-instability) && nbSaut < NOCHANGE){ nbSaut++; return false; } else { nbSaut=0; return true; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~ All function control for shield SMS sending //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~ sendTextMessage void sendTextMessage(String number, String text){ pushGSM(AT_CMD_INIT_SMS); pushGSM(AT_CMD_SEND_SMS); pushGSM(number); pushGSM(text); pushGSM(END_OF_FILE); pushGSM(AT_CMD_DEL_SMS); } //~ pushGSM void pushGSM(String text){ mySerial.print(text); delay(TEMPO); } //~ sendTextMessage void showSerialData(){ while(mySerial.available()!=0) Serial.write(mySerial.read()); } //~ switchGSM void switchGSM(bool power){ pushGSM("AT+CPIN?\r"); delay(2000); if ( ( mySerial.available()!=0 && !power ) // switch off || ( mySerial.available()==0 && power ) // switch on ){ digitalWrite(GSMSWITCHPIN, HIGH); delay(3000); digitalWrite(GSMSWITCHPIN, LOW); delay(5000); if ( power && PIN != ""){ String pinCmd = AT_CMD_ENTER_PIN; pinCmd += PIN; pinCmd += "\""; pushGSM(pinCmd); pushGSM(AT_CMD_CR); } } }