I am trying to use this universal tracker with the Iridium Rockblock. I have tried the the BasicSend and SendReceive examples with the SODAQ One v2 device, and they work perfectly. However, when I try to insert this same functionality into the transmit() function in the Universal Tracker, it hangs at the isbd.sendReceiveSBDBinary function.
I added the global variables:
int sleep_pin = 10;
IridiumSBD isbd(Serial, sleep_pin);
In the setup loop I added:
Serial.begin(19200);
if (DEBUG)
{
isbd.attachConsole(SerialUSB);
isbd.attachDiags(SerialUSB);
}
In the transmit function I added:
if (SENDRECEIVE) {
debugPrintln("SENDRECEIVE");
debugPrintln("Will wake up Rockblock");
isbd.begin();
debugPrintln("Done waking up Rockblock");
isbd.useMSSTMWorkaround(false);
isbd.setPowerProfile(1);
isbd.setMinimumSignalQuality(1);
int signalQuality = -1; //placeholder for signalQuality
isbd.setPowerProfile(1); //low power application
int err = isbd.getSignalQuality(signalQuality);
if (err != 0)
{
debugPrint("SignalQuality failed: error ");
debugPrintln(err);
return;
}
debugPrint("Signal quality is ");
debugPrintln(signalQuality);
// uint8_t buffer[200] =
// { latitude, longitude, altitude };
uint8_t buffer[200];
size_t bufferSize = sizeof(sendBuffer);
err = isbd.sendReceiveSBDBinary(buffer, 20, sendBuffer, bufferSize);
if (err != 0)
{
debugPrint("sendReceiveSBDText failed: error ");
debugPrintln(err);
return;
}
debugPrint("Inbound buffer size is ");
debugPrintln(bufferSize);
for (int i=0; i<bufferSize; ++i)
{
SerialUSB.write(buffer[i]);
debugPrint("(");
SerialUSB.print(buffer[i], HEX);
debugPrint(") ");
}
debugPrint("Messages left: ");
debugPrintln(isbd.getWaitingMessageCount());
isbd.sleep();
}
I have attached a file that shows the output log of when I run this on my SODAQ. Even though in this case the signal quality is 0, I had these same issues when the signal quality was higher.
The thing is , when I try the Basic SendReceive test, everything works with a CSQ of 5. Is it possible that the SODAQ Universal Tracker disables some pins such as the RX/TX pins? In addition, waking up the Rockblock requires the use of a sleep pin (I am using D10). The Rockblock seems to work fine with the SODAQ when I use other code.
I also tried to change the buffer I am sending to:
uint8_t buffer[200] =
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
I then ended up getting these error messages:
Will wake up Rockblock
Calling internalBegin
Powering on RockBLOCK...!
>> AT
Waiting for response OK
<< AT
OK
>> ATE1
Waiting for response OK
<< ATE1
OK
>> AT&D0
Waiting for response OK
<< AT&D0
OK
>> AT&K0
Waiting for response OK
<< AT&K0
OK
InternalBegin: success!
Done waking up Rockblock
>> AT+CSQ
Waiting for response OK
<< AT+CSQ
+CSQ:5
OK
Signal quality is 5
internalSendReceive
>> AT+SBDWB=20
Waiting for response READY
<< AT+SBDWB=20
READY
[ bytes]Checksum:210
Waiting for response 0
OK
<<
0
OK
>> AT+CSQ
Waiting for response OK
<< AT+CSQ
+CSQ:5
OK
>> AT+SBDIX
Waiting for response OK
<< AT+SBDIX
I do not believe there is an issue with the Rockblock, as I was able to send messages successfully using it with the SODAQ.
However, after doing some further digging, I found that the places the Iridium library failed were where it used millis(). This is why the code hangs at certain points. I believe it has to do with the watchdog timer that the Universal Tracker has implemented.
I tried to mitigate the issue by changing one function:
bool IridiumSBD::smartWait(int seconds)
{
// for (unsigned long start=millis(); millis() - start < 1000UL * seconds;)
// if (cancelled())
// return false;
sodaq_wdt_safe_delay(1000UL*seconds);
return true;
}
This helped stop hanging in one spot, but because the use of millis() is present throughout IridiumSBD.cpp, the code now starts hanging in other places. Do you have any ideas on how I could mitigate these errors?
It is correct when you enable a watchdog and you don’t reset it in time, the watchdog will reset the board.
You can safely change all delay(x) by sodaq_wdt_safe_delay(x).
To use the for loop and have a watchdog enabled you need to reset the watchdogtimer
sodaq_wdt_reset(); or sodaq_wdt_safe_delay(x);
for (unsigned long start=millis(); millis() - start < 1000UL * seconds;)
sodaq_wdt_reset();
if (cancelled())
return false;
If this doen’t solve your problem can you send me your Github link or upload your code and used libraries in a zip here?
Then I can have a quick look to see if I have a solution for you.
I have had a look at the IridiumSBD library, and there are multiple points which could trigger the watch dog timer (WDT). These are mainly a sort of wait for response loop.
Since you are using the SerialUSB for the debug output, it is likely that the reset is appearing as a freeze. This is due to the SerialUSB connection being reset when the board is reset (by the WDT).
When the tracker starts up it should show the cause of the most recent reset. However, if you are using SerialUSB for the output, this is usually missed as the connection is closed when the board is reset.
I would normally recommend using another UART for debug. However, this might be difficult as the Roadblock device is using the only externally available UART one the SodaqOne. (It is possible to add another UART mapping if required, but this will take some modification of the board description files.)
If you can find a terminal emulator which will automatically attempt to reopen a closed connection (if such exists), you should be able to catch the cause of the reset and confirm that it is the WDT.
I am going to create a WDT compliant version of the Roadblock library. However, at least initially, I won’t be able to test it directly myself. I may need your help in testing out the changes.
I understand. I can look for this terminal emulator, but I would definitely appreciate if you could help with the library refactoring process.
I will definitely be able to test any code that you post! How long do you think it will take you to create a WDT compliant version of the Roadblock library?
If you would like, once we start testing the compliant version of the library, we can talk on the phone or google hangouts to sort out any issues. Feel free to reach out to me at divyab@veerum.com.
Yes that is the library I am using. I really appreciate your support!
Thank you for the input! In a similar sense, I was able to solve the problem by adding sodaq_wdt_reset() to the Iridium callback function in the ino file.
My only concern is with the power(…) method where it calls up to a two second delay. This could in theory trigger a WDT on a shorter period (the tracker uses an 8s period).
in IridiumSBD.cpp the function IridiumSBD::power(bool on), specifically line 629.
Probably best to swap delay(x) for smartWait(x) as this uses the same call back functionality. The call back functionality is designed to give you the opportunity to cancel any of the sequences, if required.
If you swap those methods directly, then there is no issue with the cancellation functionality as the result of smartWait(x), here, will be ignored.
Thank you for pointing this out. I implemented this change, but I am still seeing an issue where the Rockblock fails to wake up every 2nd time the transmit function is called. I have mitigated this issue by implementing a simple retry, but I would love if you could help me get to the root of this issue.
What debug messages do you see when it fails to wake up?
The internalBegin() function will either output “No modem detected.” or “InternalBegin: success!”.
If you are seeing the success message, and reordering some of the instructions seemed to help, it may be that the device requires a longer delay to wake up.