1

I'm using the MKR NB 1500 for server sending, an ENV shield for measuring the environment, and an external lithium battery to power the circuit. The internal RTC and WDT on the NB 1500 are used.

The program is trying to measure data, send it to a server, go to sleep, wake up, and repeat the process. Under is a scetch of how the program is set up in main.cpp:

void setup()
{
    setup_watchdog(); //Sets up the watchdog timer with a 32 s bite time
    delay(1000);
    connect_GPRS_NB(); //Connects to the NB network and opens a GPRS connection
    request_NTP(); //Requests epoch1970 from the NTP server and then closes the connection
    timezone_adjustment(); //Adjusts the epoch time to my timezone (in Norway)
    set_RTC(); //Activates the SAMD21 RTC with this timezone adjusted time
    disconnect_NB(); //Disconnects from the NB network
    delay(2000); 
    disable_watchdog(); //Disables the WDT in its entirety 

void loop()
{   
    setup_watchdog(); //Sets up the watchdog timer with a 32 s bite-time
    connect_GPRS_NB(); //Connects to the NB network and opens a GPRS connection
    get_ENV_data(); //Takes measurements using the MKR NB ENV shield
    connect_to_server(); //Connects to the server in which the data will be stored
    write_to_server(); //Writes the data on the server
    disconnect_from_server(); //Disconnects from the server
    disconnect_NB(); //Disconnects from the NB network
    watchdog_reset(); //Resets the watchdog timer
   
    disable_watchdog(); //Disables the WDT in its entirety 
    LowPower.deepSleep(300000); //Goes to deep sleep for 5 minutes
    delay(2000);
}

All the functions above are written in other .cpp files and imported thru header files into the main file. The reason I'm using the RTC is because I want to log the time at which the data was sent to the server on the client side.

I set the circuit outside yesterday night and it actually sent data to the server the entire night. But the RTC did not function as I had hoped. Under is a clip-out of the data which was written on the server yesterday night:

nyktertest1.txt,11-02-23I23:39:40,Temp=22.593750,Fuktighet=31.063698,Trykk=1014.553223,Lys=9.677420
nyktertest1.txt,11-02-23I23:54:40,Temp=26.049343,Fuktighet=27.074978,Trykk=1014.549561,Lys=10.322580
nyktertest1.txt,11-02-23I23:56:34,Temp=24.909540,Fuktighet=29.182085,Trykk=1014.637695,Lys=9.032258
nyktertest1.txt,01-01-00I00:05:14,Temp=24.873356,Fuktighet=29.023129,Trykk=1012.826172,Lys=5.161290
nyktertest1.txt,01-01-00I00:10:29,Temp=22.231909,Fuktighet=34.242844,Trykk=1013.905762,Lys=5.161290
nyktertest1.txt,01-01-00I00:15:43,Temp=15.881580,Fuktighet=38.981991,Trykk=1014.769043,Lys=5.161290
nyktertest1.txt,12-02-23I00:18:39,Temp=19.047699,Fuktighet=38.823032,Trykk=1014.885742,Lys=10.967742
nyktertest1.txt,01-01-00I00:05:15,Temp=18.975330,Fuktighet=34.083885,Trykk=1015.005371,Lys=9.677420
nyktertest1.txt,01-01-00I00:10:30,Temp=20.350330,Fuktighet=33.440662,Trykk=1016.046631,Lys=3.225806
nyktertest1.txt,01-01-00I00:15:45,Temp=21.291119,Fuktighet=36.523697,Trykk=1014.721191,Lys=3.225806
nyktertest1.txt,01-01-00I00:20:59,Temp=15.338817,Fuktighet=43.358864,Trykk=1014.953369,Lys=3.225806
nyktertest1.txt,01-01-00I00:26:15,Temp=10.689146,Fuktighet=47.306919,Trykk=1015.068359,Lys=3.870968
nyktertest1.txt,01-01-00I00:31:30,Temp=8.011514,Fuktighet=48.974121,Trykk=1015.034424,Lys=3.870968
nyktertest1.txt,01-01-00I00:36:44,Temp=6.600330,Fuktighet=49.428818,Trykk=1015.172363,Lys=3.870968
nyktertest1.txt,01-01-00I00:41:59,Temp=5.731909,Fuktighet=49.321609,Trykk=1015.128174,Lys=3.870968
nyktertest1.txt,01-01-00I00:47:14,Temp=5.207238,Fuktighet=48.792984,Trykk=1015.133057,Lys=3.870968
nyktertest1.txt,01-01-00I00:52:28,Temp=4.791119,Fuktighet=48.171944,Trykk=1015.092529,Lys=3.870968
nyktertest1.txt,01-01-00I00:57:46,Temp=4.375002,Fuktighet=47.377159,Trykk=1015.114258,Lys=4.516129
nyktertest1.txt,01-01-00I01:03:01,Temp=4.157896,Fuktighet=46.929855,Trykk=1015.123535,Lys=4.516129
nyktertest1.txt,01-01-00I01:08:15,Temp=4.013159,Fuktighet=46.194218,Trykk=1015.161133,Lys=3.870968
nyktertest1.txt,01-01-00I01:13:29,Temp=3.832237,Fuktighet=45.754311,Trykk=1015.314209,Lys=3.870968
nyktertest1.txt,01-01-00I01:18:43,Temp=3.705593,Fuktighet=45.044548,Trykk=1015.297852,Lys=3.870968
nyktertest1.txt,01-01-00I01:23:57,Temp=3.560856,Fuktighet=44.948437,Trykk=1015.371582,Lys=3.870968
nyktertest1.txt,01-01-00I01:29:11,Temp=3.416119,Fuktighet=44.164742,Trykk=1015.308350,Lys=3.870968
nyktertest1.txt,01-01-00I01:34:25,Temp=3.307568,Fuktighet=43.883793,Trykk=1015.287842,Lys=3.870968
nyktertest1.txt,01-01-00I01:39:39,Temp=3.307568,Fuktighet=43.458672,Trykk=1015.299072,Lys=3.870968
nyktertest1.txt,01-01-00I01:45:10,Temp=3.162830,Fuktighet=42.959621,Trykk=1015.257324,Lys=3.225806
nyktertest1.txt,12-02-23I02:08:19,Temp=3.217106,Fuktighet=42.833935,Trykk=1015.262695,Lys=3.870968
nyktertest1.txt,12-02-23I02:13:33,Temp=3.180922,Fuktighet=42.416210,Trykk=1015.253418,Lys=3.870968
nyktertest1.txt,12-02-23I02:18:49,Temp=3.144737,Fuktighet=42.331184,Trykk=1015.185059,Lys=3.225806
nyktertest1.txt,12-02-23I02:24:03,Temp=2.945724,Fuktighet=42.268341,Trykk=1015.238281,Lys=3.870968
nyktertest1.txt,12-02-23I02:29:18,Temp=2.855265,Fuktighet=41.983696,Trykk=1015.152832,Lys=3.870968
nyktertest1.txt,12-02-23I02:34:32,Temp=2.782896,Fuktighet=42.016968,Trykk=1015.135742,Lys=3.870968

The list goes on until the morning. I was not able to only copy the time column of the datasheet, but you can see the time column on the right side of "nyktertest1.txt" which was the file I was writing the data to at the server. The three numbers on the left represent the date, so 11-02-23 is the 11 of February 2023. And the time is right next to the date, a | was used the separate the time and the date. So the data in the first row was logged at 23:39:40, which would be 11:39:40 PM.

But if you look further down the time column, only the minutes and seconds were logged correctly for a good while. It seems like the RTC values where just zeroed out. But after a while, the time was corrected again.

Here is the function for doing the NTP request:

void request_NTP()
{
    Serial.println("Starting connection to 'no.pool.ntp.org'");

    Udp.begin(localPort);
    sendNTPpacket(); // send an NTP packet to a time server
    // wait to see if a reply is available
    delay(1000);

    if ( Udp.parsePacket() ) 
    {
    Serial.println("Packet received");
    // We've received a packet, read the data from it
    Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
    
    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);

    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    UNIX_1970 = secsSince1900 - seventyYears;
    Udp.stop();
    Serial.println("UDP Closed");   
    }   

    else    
    {     
        Serial.println("No packets where recieved");    
        ///Av en eller annen grunn vil programmet stoppe her dersom en kun lukker UDP tilkoblingen
        Udp.stop();         
        Serial.println("UDP Closed");   
        Serial.println("Trying again..");
        delay(2000);
        request_NTP();
    }
}   

This is the sendNTPpacket() function which was used in the request_NTP() function above:

void sendNTPpacket() 
{
    //Serial.println("1");
    // set all bytes in the buffer to 0
    memset(packetBuffer, 0, NTP_PACKET_SIZE);
    // Initialize values needed to form NTP request
    // (see URL above for details on the packets)
    //Serial.println("2");
    packetBuffer[0] = 0b11100011;   // LI, Version, Mode
    packetBuffer[1] = 0;     // Stratum, or type of clock
    packetBuffer[2] = 6;     // Polling Interval
    packetBuffer[3] = 0xEC;  // Peer Clock Precision
    // 8 bytes of zero for Root Delay & Root Dispersion
    packetBuffer[12]  = 49;
    packetBuffer[13]  = 0x4E;
    packetBuffer[14]  = 49;
    packetBuffer[15]  = 52;

    // all NTP fields have been given values, now
    // you can send a packet requesting a timestamp:
    Udp.beginPacket(NTP_server, NTP_port); //NTP requests are to port 123

    Udp.write(packetBuffer, NTP_PACKET_SIZE);
    Udp.endPacket();
    delay(1000);
}

This is the function for adjusting the UNIX time to my own timezone:

void timezone_adjustment()
{
    TimeChangeRule NoCET = {"CET", Fourth, Sun, Oct, 3, +60};
    TimeChangeRule NoCEST = {"CEST", Fourth, Sun, Mar, 2, +120};
    Timezone Norway(NoCET, NoCEST);
    UNIX_adjusted_No = Norway.toLocal(UNIX_1970);
}

This is the function for setting up the RTC:

void set_RTC()
{
    const int RTC_second = second(UNIX_adjusted_No);
    const int RTC_minute = minute(UNIX_adjusted_No);
    const int RTC_hour = hour(UNIX_adjusted_No);
    const int RTC_day = day(UNIX_adjusted_No);
    const int RTC_month = month(UNIX_adjusted_No);
    const int RTC_year = year(UNIX_adjusted_No)%100;
    
    /// Starter RTC klokken
    rtc.begin();
    //rtc.setTime(RTC_hour, RTC_minute, RTC_second);
    //rtc.setDate(RTC_day, RTC_month, RTC_year);
    rtc.setYear(RTC_year);
    rtc.setMonth(RTC_month);
    rtc.setDay(RTC_day);
    rtc.setHours(RTC_hour);
    rtc.setMinutes(RTC_minute);
    rtc.setSeconds(RTC_second);
}

And this is the buffer being sent to the server:

sprintf(buffer,"/cgi-bin/tof.cgi?nyktertest1.txt,%02d-%02d-%02dI%02d:%02d:%02d,VannTemp=%lf,LuftTemp=%lf,Fuktighet=%lf,Trykk=%lf,Lys=%lf",rtc.getDay(),rtc.getMonth(),rtc.getYear(),rtc.getHours(),rtc.getMinutes(),rtc.getSeconds(),water_temp,air_temp,humidity,pressure,illuminance);

I don't think the RTC is just half its values. I think the watchdog might have bit on the third loop, meaning the program had to do an NTP request at startup to initialize the RTC. But the UNIX time was not successfully received from the server, so the RTC was initialized with all clock values being 0. The program continued to log for a couple of cycles as you can see on the datasheet. But then the watchdog bit again and the circuit was reset. But the NTP request was done successfully this time, and therefore the time was logged correctly until the morning when I picked it up.

This is only my theory though and I am not sure of it. What to you think is happening? And what would be a fix?

Another problem that I noticed in the morning was that the RTC seemed to be lagging over 5 minutes behind the real-time. Is this a normal issue with the SAMD21 RTC? Because im planning to eventually have this Arduino log data for weeks or months without me touching it. Having the clock fall behind after longer time periods would then be a huge problem.

Edit: Under is the write_to_server() function:

void write_to_NTNU_server()
{
    Serial.println("Sending the buffer");
    char buffer[256] = {}; 
    client.print("GET ");
    sprintf(buffer,"/cgi-bin/tof.cgi?nyktertest1.txt,%02d-%02d-%02dI%02d:%02d:%02d,VannTemp=%lf,LuftTemp=%lf,Fuktighet=%lf,Trykk=%lf,Lys=%lf",rtc.getDay(),rtc.getMonth(),rtc.getYear(),rtc.getHours(),rtc.getMinutes(),rtc.getSeconds(),water_temp,air_temp,humidity,pressure,illuminance);
    Serial.println(buffer);
    client.print(buffer);
    client.println(" HTTP/1.1");
    client.print("Host: ");
    client.println(NTNU_server);

    client.println("Connection: close");
    client.println();
    Serial.println("Buffer sent");
}

Here is the code for creating the client object from the NBClient class:

NBClient client;
11
  • always format all printout as code
    – jsotola
    Commented Feb 12, 2023 at 19:35
  • please reduce your program to the simplest code that exhibits to problem
    – jsotola
    Commented Feb 12, 2023 at 19:40
  • Thank you for the tips. I thought all of the code I pasted could give information about the source of the problem. But I will try to reduce it.
    – 5TableLegs
    Commented Feb 12, 2023 at 19:48
  • that is how code debugging works ... remove parts of the code that may not be causing the problem and test
    – jsotola
    Commented Feb 12, 2023 at 21:20
  • It looks like Udp.parsePacket() returns the packet size. An incorrect size could give incorrect results. Can you please check that the correct packet size arrives?
    – Nick Gammon
    Commented Feb 12, 2023 at 22:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.