Wiz-IO / Arduino-Quectel-BC66

Arduino port for Quectel BC66 LTE Narow Band modules ( OpenCPU based )
46 stars 21 forks source link

Support for BC66 (cell mlts not working + callback doubt) #9

Closed pgaspar96 closed 5 years ago

pgaspar96 commented 5 years ago

Hi and thank you for your work.

I'm uploading your file "info.ino" to my BC66 board and everything works fine except for Dev.getMlts(mlts, 322); which returns nothing.

I really need to get the date time and so I was trying to send the first two AT commands (the ones you say that are required once) to check if that was the problem but I think the AT cmds are not being sent and I can't get the callback working.

I'm trying to make the callback like this based on what you said here:

// Attempt to make a callback
static int callback(){
  return Dev.GET_QCGDEFCONT(char *line, u32 len, NULL);
  }

This is how I'm sending the AT cmd:

DBG("Sending cmd AT+QSPCHSC=1");
  if ( ret = Dev.send("AT+QSPCHSC=1",1000,NULL,NULL) ) {  // without callback
    Serial.println("[ERROR] cmd scrampling");             // allways prints error
    }

And this is how I'm trying to get the date time:

void loop()
{
  delay(1000);
  char mlts[322];
  Dev.getMlts(mlts, 322);
  Serial.printf("Cell mlts    %s\n", mlts); //never prints the date
}
Wiz-IO commented 5 years ago

Hi,

the cell MLTS is valid second after cell is connected and is just for info (maybe your cell not support this)

after connection use class RTC get() https://github.com/Wiz-IO/framework-quectel/blob/master/arduino/cores/bc66/RTC.cpp#L37

or Quectel RTC API https://github.com/Wiz-IO/framework-quectel/blob/master/arduino/cores/bc66/RTC.cpp#L50

If time is not valid you need SNTP....

for full AT support look Quectel API Ql_RIL_SendATCmd()

or https://github.com/Wiz-IO/framework-quectel/blob/master/arduino/cores/bc66/DEV.cpp#L250

pgaspar96 commented 5 years ago

Thank you for the fast response.

I used RTC but the time is not valid. Do you know how to setup a SNTP? I've been searching and I can only find NTP using Wi-Fi or Ethernet.

Wiz-IO commented 5 years ago

any Arduino library for NTP.... Are you sure you have Internet on the module?

pgaspar96 commented 5 years ago

Yes, I even connected it to an MQTT server and sent messages.

pgaspar96 commented 5 years ago

I'm now trying to use the NTPClient and some code I got from here and I'm getting this error:

C:\Users\cooki\Documents\Arduino\libraries\NTPClient\NTPClient.cpp: In member function 'bool NTPClient::forceUpdate()':

C:\Users\cooki\Documents\Arduino\libraries\NTPClient\NTPClient.cpp:84:81: error: expression list treated as compound expression in functional cast [-fpermissive]

   unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);

C:\Users\cooki\Documents\Arduino\libraries\NTPClient\NTPClient.cpp:85:80: error: expression list treated as compound expression in functional cast [-fpermissive]

   unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);

Code related to the NTP:

#include <nbUDP.h>
#include <NTPClient.h>

nbUDP udp;
const long utcOffsetInSeconds = 0;
NTPClient timeClient(udp, "pool.ntp.org", utcOffsetInSeconds);
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

In setup: timeClient.begin();

In loop:

  timeClient.update();
  Serial.print(daysOfTheWeek[timeClient.getDay()]);
  Serial.print(", ");
  Serial.print(timeClient.getHours());
  Serial.print(":");
  Serial.print(timeClient.getMinutes());
  Serial.print(":");
  Serial.println(timeClient.getSeconds());
  //Serial.println(timeClient.getFormattedTime());
  delay(1000);
Wiz-IO commented 5 years ago

try edit library word() to makeWord()

pgaspar96 commented 5 years ago

It worked, thank you! Yet I must be doing something wrong. I debugged and everytime this line of the NTPClient executes the board resets: cb = this->_udp->parsePacket();

Function where line is:

bool NTPClient::forceUpdate() {
  #ifdef DEBUG_NTPClient
    Serial.println("Update from NTP Server");
  #endif

  this->sendNTPPacket();

  // Wait till data is there or timeout...
  byte timeout = 0;
  int cb = 0;
  do {
    delay ( 10 );
    cb = this->_udp->parsePacket();
    if (timeout > 1000) return false; // timeout after 1000 ms
    timeout++;
  } while (cb == 0);

    Serial.println("Packet sent");

  this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time

  this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);

  unsigned long highWord = makeWord(this->_packetBuffer[40], this->_packetBuffer[41]);
  unsigned long lowWord = makeWord(this->_packetBuffer[42], this->_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;

  this->_currentEpoc = secsSince1900 - SEVENZYYEARS;

  return true;
}

I think the problem might be on the way I set up the UDP client. Is it correct to use ?

#include <nbUDP.h>
#include <NTPClient.h>

nbUDP udp;
const long utcOffsetInSeconds = 0;
NTPClient timeClient(udp, "pool.ntp.org", utcOffsetInSeconds);
Wiz-IO commented 5 years ago

Yes, you need use nbUDP for BC66 https://github.com/Wiz-IO/Arduino-Quectel-BC66/tree/master/libraries/Ethernet/src

Why you need UTC, if you send MQTT message, the server knows when it arrived

and I think the module automatically finds NTP when there is an internet and adjusts the Rtc for module NTP support - ask your local Quectel support, and see AT commnads

Wiz-IO commented 5 years ago

look BC66 AT command AT+QNTP then RTC will be synchronized

pgaspar96 commented 5 years ago

Thank you, I managed to sync the time with an NTP server using that cmd:

//AT+QNTP=<contextID>,<server>[,<port>][,<autosettime>]
char cmd_sync[] = "AT+QNTP=1,\"ntp.ist.utl.pt\",123,1\r"; 
DBG("\nsending command %s - length %d\r\n", cmd_sync, Ql_strlen(cmd_sync));
Ql_RIL_SendATCmd(cmd_sync, Ql_strlen(cmd_sync), callback, NULL, 300);

Unfortunately we are now in the daylight saving time (aka summer time) and the clock is behind by 1 hour. I tried to change the time zone and the hour like this:

ST_Time time_gmt;
Ql_GetLocalTime(&time_gmt);
time_gmt.timezone = 1;
Ql_SetLocalTime(&time_gmt);

But it is not working. Do you have any idea how I can solve the problem? I also searched for a cmd to change the timezone but there is only one to check for changes in the timezone.

Wiz-IO commented 5 years ago

Hi make timeout more... ( Ql_RIL_SendATCmd ) I think Quectel stdlib not support timezone...

Wiz-IO commented 5 years ago
static int eu_dst(const time_t * timer) {
    uint32_t t = *timer - 946684800;
    if ((uint8_t) (t >> 24) >= 194) t -= 3029443200U;
    t = (t + 655513200) / 604800 * 28;
    if ((uint16_t) (t % 1461) < 856) return 3600;
    else return 0;
}

static int (*dst_ptr) (const time_t *) = eu_dst;

static int timeZoneOffset = 2 * 3600;

int isDst(const time_t * timer) {
    return eu_dst(timer);
}
pgaspar96 commented 5 years ago

I don't understand how to apply that code to the RTC.

I'm doing something like this:

time_t t = RTC.get();
int aux = isDst(&t);
Serial.printf("\naux: %d",aux);

isDst() is returning 3600 and that is correct but how do I apply that to the RTC? Also I'm using RTC.ascTime() to print the date.

Wiz-IO commented 5 years ago

isDst( now UTC ) return seconds if datetime is in DST period "winter" give 0 seconds "summer" give 3600 plus (timezone * 3600) give your local time

now + ( timezone * 3600) + isDst( now )