1

I hope someone can help me. I'm building a GSM water level meter that runs on solar power, using an Arduino Pro mini, a DS3231 RTC, a JSN-SR04T - ULTRASONIC SENSOR, and a SIM800L along with a DFrobot DFR0535 solar power manager and 3.7V battery.

My project worked fine before I added the RTC; it connects to the Blynk server, gets the readings from the ultrasonic sensor, and posts them, before going to sleep.

I added the RTC in order to use it to wake up the Arduino using the interrupt signal and save some power during the evenings and no sun.

Even this works, but the interrupts stop after about 30 mins of firing. At the moment its configured to fire every 5 mins. My serial output looks like this:

enter image description here

So at this point the sketch works 100% and does exactly what I need, but unfortunately it stops after a few minutes. Do I need a pull up resistor somewhere maybe?

Any ideas?

Below is my sketch. Any help will be greatly appreciated.

    #include <avr/sleep.h>//this AVR library contains the methods that controls the sleep modes
    #define interruptPin 2 //Pin we are going to use to wake up the Arduino
    #include <DS3232RTC.h>  //RTC Library https://github.com/JChristensen/DS3232RTC
    #include <NewPing.h>
    #define BLYNK_PRINT Serial
    #define TINY_GSM_MODEM_SIM800
    #include <TinyGsmClient.h>
    #include <SoftwareSerial.h>
    #include <BlynkSimpleSIM800.h>
    #define SIM800_TX_PIN 9
    #define SIM800_RX_PIN 8
    #define uS_TO_m_FACTOR 60000000   // Conversion factor for micro seconds to minutes
    char auth[] = "a892d375xxxxxx0d5c086d6b1";
    char apn[]  = "";
    char user[] = "";
    char pass[] = "";
    const int MAX_DISTANCE = 120;                       //max distance to measure
    const int Diameter1 = 110;                                //internal Diameter of tank 1 in cm
    const int Depth1 = 110;                                 //total depth of tank 1 in cm , from sensor to base inside
    const unsigned int Period = 60000;    //period between pings, in milliseconds. i.e  1 munute = 60,000. max 65535. Want longer? use unsigned long
    const int PingPin1 = 6;                          //     GPIO5,  D1
    const int EchoPin1 = 7;                        //     GPIO4,  D2
    const int Area1 = PI * ((Diameter1 / 2) * (Diameter1 / 2));          //area of base of tank 1
    int Litres1, Distance1, WaterDepth1, Decimal, Persentage, battLevel, csq, kill;
    String gsmTime, gsmTime1;
    #include <SoftwareSerial.h>
    SoftwareSerial SerialAT(SIM800_TX_PIN, SIM800_RX_PIN);
    TinyGsm modem(SerialAT);
    //BlynkTimer timer;
    NewPing sonar = NewPing(PingPin1, EchoPin1, MAX_DISTANCE);
    //RTC Module global variables
    const int time_interval = 5; // Sets the wakeup intervall in minutes
    

    void setup() {
      Serial.begin(115200);//Start Serial 
      delay(1000);
      
      pinMode(LED_BUILTIN,OUTPUT);//We use the led on pin 13 to indecate when Arduino is A sleep
      pinMode(interruptPin,INPUT_PULLUP);//Set pin d2 to input using the buildin pullup resistor
      digitalWrite(LED_BUILTIN,HIGH);//turning LED on
      
      // initialize the alarms to known values, clear the alarm flags, clear the alarm interrupt flags
        RTC.setAlarm(ALM1_MATCH_DATE, 0, 0, 0, 1);
        RTC.setAlarm(ALM2_MATCH_DATE, 0, 0, 0, 1);
        RTC.alarm(ALARM_1);
        RTC.alarm(ALARM_2);
        RTC.alarmInterrupt(ALARM_1, false);
        RTC.alarmInterrupt(ALARM_2, false);
        RTC.squareWave(SQWAVE_NONE);
         time_t t; //create a temporary time variable so we can set the time and read the time from the RTC
        t=RTC.get();//Gets the current time of the RTC
        RTC.setAlarm(ALM1_MATCH_MINUTES , 0, minute(t)+time_interval, 0, 0);// Setting alarm 1 to go off 5 minutes from now
        // clear the alarm flag
        RTC.alarm(ALARM_1);
        // configure the INT/SQW pin for "interrupt" operation (disable square wave output)
        RTC.squareWave(SQWAVE_NONE);
        // enable interrupt output for Alarm 1
        RTC.alarmInterrupt(ALARM_1, true);
    }
    

    void loop() {
     delay(5000);//wait 5 seconds before going to sleep. In real senairio keep this as small as posible
     Going_To_Sleep();
    }
    
    void Going_To_Sleep(){
        sleep_enable();//Enabling sleep mode
        attachInterrupt(0, wakeUp, LOW);//attaching a interrupt to pin d2
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep
        digitalWrite(LED_BUILTIN, LOW); //turning LED off
        time_t t;// creates temp time variable
        t=RTC.get(); //gets current time from rtc
        Serial.println("Sleep  Time: "+String(hour(t))+":"+String(minute(t))+":"+String(second(t)));//prints time stamp on serial monitor
        delay(1000); //wait a second to allow the led to be turned off before going to sleep
        sleep_cpu();//activating sleep mode
        Serial.println("just woke up!");//next line of code executed after the interrupt
        myFunction(); 
        t=RTC.get();
        Serial.println("WakeUp Time: "+String(hour(t))+":"+String(minute(t))+":"+String(second(t)));//Prints time stamp 
        //Set New Alarm
        RTC.setAlarm(ALM1_MATCH_MINUTES , 0, minute(t)+time_interval, 0, 0);
      
      // clear the alarm flag
      RTC.alarm(ALARM_1);
      }
      
    
    void wakeUp(){
      Serial.println("Interrrupt Fired");//Print message to serial monitor
       sleep_disable();//Disable sleep mode
      detachInterrupt(0); //Removes the interrupt from pin 2;
     
    }
    
    void myFunction() {
      pinMode(13, OUTPUT);
      digitalWrite(13, HIGH); 
      SerialAT.begin(57600);
      delay(1000);// make GPIO8 output low
      Serial.println("Initializing modem...");
      modem.restart();
      Blynk.begin(auth, modem, apn, user, pass);
      delay(1000);
      Distance1 = sonar.ping_cm();                                       //get distance to the top of the water tank 1
      if (Distance1 >= Depth1 || Distance1 == 0 )  Distance1 = Depth1;                   //check it does not go negative
      WaterDepth1 = Depth1 - Distance1;                     //calculate the depth of the water
      Litres1 = ((Depth1 * (PI * (sq(Diameter1 / 2)))) - (Distance1 * (PI * (sq(Diameter1 / 2))))) / 1000;
      Persentage = (Litres1 / 1000.00) * 100;
      battLevel = modem.getBattPercent();
      csq = modem.getSignalQuality();
      Blynk.virtualWrite(V1, WaterDepth1);
      Blynk.virtualWrite(V2, Litres1);
      Blynk.virtualWrite(V3, Litres1 / 10);
      Blynk.virtualWrite(V4, Persentage);
      Blynk.virtualWrite(V5, battLevel);
      Blynk.virtualWrite(V6, csq);
      Serial.println();
      Serial.println();
      Serial.println("Water depth: " + String(WaterDepth1));
      Serial.println("Water distance: " + String(Distance1));
      Serial.println("Litres: " + String(Litres1));
      Serial.println("Percentage: " + String(Persentage));
      Serial.println("Battery: " + String(battLevel));
      Serial.println("Signal Qlty: " + String(csq));
      delay(100);
      pinMode(13, OUTPUT);
      digitalWrite(13, LOW);
    }
  • Do you have pullup resistors on SCL & SDA? – CrossRoads Feb 8 '19 at 13:22
  • nope...directly from the RTC into the pro mini...I got a few 2N2222 & MPS2222A's? Or what would you suggest? – Roelof Loots Feb 8 '19 at 13:36
  • 1
    don't use String class – Juraj Feb 8 '19 at 13:38
  • 4.7K pullups on SCL, SDA are needed for I2C to work. Internal to Atmega328P are insufficient. – CrossRoads Feb 8 '19 at 14:09
  • I think your code just hangs/crashes after some time. Try commenting out sleep_cpu(); and see if it hangs after half an hour. I don't think this has anything to do with sleeping. – Gerben Feb 8 '19 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.