IridiumSBD

The Rock 7 RockBLOCK is a fascinating new communications module that gives TTL-level devices like Arduino access to the Iridium satellite network.  This is a big deal, because it means that your application can now easily and inexpensively communicate from any point on the surface of the globe, from the heart of the Amazon to the Siberian tundra.

This library, IridiumSBD, uses the RockBLOCK/Iridium’s SBD (“Short Burst Data”) protocol to send and receive short messages to/from the Iridium hub.  SBD is a “text message”-like technology that supports the transmission of text or binary messages up to a certain maximum size (270 bytes received, 340 bytes transmitted).

For more information, visit the Rock 7 website.

“3-Wire” Wiring

Rock 7 have made interfacing to the Arduino quite simple.  Each RockBLOCK ships with a 10-pin JST-terminated cable that snaps onto the RockBLOCK and conveniently exposes the various signal lines for the client device to connect to.  It’s actually only necessary to connect 4 or 5 of these to get your Arduino application up and running.   In our configuration we ignore the flow control lines and talk to the RockBLOCK over what Iridium calls a “3-wire” TTL serial interface.  In wiring table below, we assume that the RockBLOCK is being powered from the Arduino 5V power bus.

RockBLOCK Connection Arduino Connection
+5V (Power) +5V (Power)
GND GND
TX TX Serial Pin*
RX RX Serial Pin*
SLEEP +5V or GPIO pin*

A minimal “3-wire” connection to RockBLOCK

*The TX and RX lines are labeled on the RockBLOCK as viewed from the Arduino, so the TX line would be transmitting serial data to the RockBLOCK.  These lines support TTL-level serial (default 19200 baud), so you can either connect it directly to the/a built-in UART or create a “soft” serial on any two suitable pins.  We usually opt for the latter choice to free up the UART(s) for diagnostic and other console communications.  The active low SLEEP wire may be connected to a 5V line (indicating that the device is perpetually awake), but it’s a good power saving technique to connect it to a general-purpose pin,  allowing the library to put the RockBLOCK in a low power “sleep” state when its services are not needed.

Non-blocking Retry Strategy

The nature of satellite communications is such that it often takes quite a long time to establish a link.  Satellite communications are line-of-sight, so having a clear view of an unclouded sky greatly improves speed and reliability; however, establishing contact may be difficult even under ideal conditions for the simple reason that at a given time no satellite may immediately be overhead.  In these cases, the library initiates a moderately elaborate behind-the-scenes series of retries, waiting for a satellite to appear.

With a clear sky, transmissions almost always succeed after a few of these retries, but the entire process may take up to several minutes.  Since most microcontroller applications cannot tolerate blocking delays of this length, IridiumSBD provides a callback mechanism to ensure that the Arduino can continue performing critical tasks.  That is, if the library user provides a global C++ function with the signature

bool ISBDCallback();

(and this is highly recommended for all but the most trivial applications), then that function will be called repeatedly while the library is waiting for long operations to complete.  In it you can take care of activities that need doing while you’re waiting for the transmission to complete.  Simple example:

bool ISBDCallback()
{
   unsigned ledOn = (bool)((millis() / 1000) % 2);
   digitalWrite(ledPin, ledOn); // Blink LED every second
   return true;
}
...
// This transmission may take a long time, but the LED keeps blinking
isbd.sendSBDText("Hello, mother!");

Note: It is not permitted to call most IridiumSBD methods from within the callback.  Doing so will immediately return ISBD_REENTRANT.

Note: Your application can prematurely terminate a pending IridiumSBD operation by returning false from the callback.  Doing so causes the pending operation to return ISBD_CANCELLED.

Power Considerations

The RockBLOCK module uses a “super capacitor” to supply power to the Iridium 9602.  As the capacitor is depleted through repeated transmission retries, the host device’s power bus replenishes it.  Under certain low power conditions it is important that the library not retry too quickly, as this can drain the capacitor and render the 9602 inoperative.  In particular, when powered by a low-power 90 mA max USB supply, the interval between transmit retries should be extended to as much as 60 seconds, compared to 20 for, say, a high-current battery solution.

To transparently support these varying power profiles, IridiumSBD provides the ability to fine-tune the delay between retries.  This is done by calling

isbd.setPowerProfile(1); // For USB "low current" applications

or

isbd.setPowerProfile(0); // For "high current" applications

Construction and Startup

To begin using the library, first create an IridiumSBD object.  The IridiumSBD constructor binds the new object to an Arduino Stream (i.e. the RockBLOCK serial port) and, optionally, the RockBlock SLEEP line:

IridiumSBD(Stream &stream, int sleepPinNo = -1);

Example startup:

#include "IridiumSBD.h"
#include "SoftwareSerial.h"

SoftwareSerial ssIridium(18, 19); // RockBLOCK serial port on 18/19

IridiumSBD isbd(ssIridium, 10);   // RockBLOCK SLEEP pin on 10

void setup()
{
   isbd.setPowerProfile(1); // This is a low power application
   isbd.begin(); // Wake up the 9602 and prepare it to communicate.
   ...

Data transmission

The methods that make up the meat of the IridiumSBD public interface, are, naturally, those that enable the sending and receiving of data.  There are four such functions in IridiumSBD, two “send-only” functions (text and binary), and two “send-and-receive” functions (again, text and binary):

// Send a text message
int sendSBDText(const char *message);

// Send a binary message
int sendSBDBinary(const uint8_t *txData, size_t txDataSize);

// Send a text message and receive one (if available)
int sendReceiveSBDText(const char *message, uint8_t *rxBuffer,
   size_t &rxBufferSize);

// Send a binary message and receive one (if available)
int sendReceiveSBDBinary(const uint8_t *txData, size_t txDataSize,
   uint8_t *rxBuffer, size_t &rxBufferSize);

Send-only and Receive-only applications

Note that at the lowest-level, SBD transactions always involve the sending and receiving of exactly one message (if one is available).  That means that if you call the simpler variants sendSBDText or sendSBDBinary and there happen to messages in your incoming (RX) message queue, the first of these is discarded and irrevocably lost.  This may be perfectly acceptable for a “send-only” application that never expects to receive messages, but if there is some chance that you will need to process an inbound message, call sendReceiveSBDText or sendReceiveSBDBinary instead.

If your application is receive-only, simply call sendReceiveSBDText with a NULL outbound message parameter.

If no inbound message is available, the sendReceive* messages indicate this by returning ISBD_SUCCESS and setting rxBufferSize to 0.

Diagnostics

IridiumSBD provides two methods for performing self-diagnostics.  These are

void attachConsole(Stream &stream);
void attachDiags(Stream &stream);

These allow the host application to provide a Stream object (serial port) that can be used to monitor the RockBLOCK serial traffic and diagnostic messages, respectively.  The typical usage is to simply use the Arduino serial port to monitor both of these—assuming that it is connected to a PC serial console and not otherwise used:

isbd.attachConsole(Serial);
isbd.attachDiags(Serial);

Receiving Multiple Messages

After every successful SBD send/receive operation, the Iridium satellite system informs the client how many messages remain in the inbound message queue.  The library reports this value with the getWaitingMessageCount method.  Here’s an example of a loop that reads all the messages in the inbound message queue:

do
{
   char rxBuffer[100];
   size_t bufferSize = sizeof(rxBuffer);
   int status = isbd.sendReceiveText("Hello?", rxBuffer, bufferSize);
   if (status != ISBD_SUCCESS)
   {
      /* ...process error here... */
      break;
   }
   if (bufferSize == 0)
      break; // all done!
   /* ...process message in rxBuffer here... */

} while (isbd.getWaitingMessageCount() > 0);

Erratum Workarounds and other Tweaks

In May, 2013, Iridium identified a potential problem that could cause a satellite modem like the RockBLOCK to lock up unexpectedly.  In a product bulletin they stated that though future versions of the Iridium firmware would resolve this issue, current software should work around it by adding an “MSSTM” software query to the device.  IridiumSBD employs this important workaround by default, but you can disable it with:

isbd.useMSSTMWorkaround(false);

Similarly, Iridium recommend that transmission be deferred until the signal quality has reached at least 2 (on a scale of 0 to 5, as reported by getSignalQuality()).  However, there are times when it is advantageous to use a lower (or higher) value than 2 as this default minimum.  To change the default minimum from 2, use:

isbd.setMinimumSignalQuality(1);

Error return codes

Many  IridiumSBD methods return an integer error status code, with ISBD_SUCCESS (0) indicating successful completion.  These include begin, sendSBDText, sendSBDBinary, sendReceiveSBDText, sendReceiveSBDBinary, getSignalQuality, and sleep.  Here is a complete list of the possible error return codes:

#define ISBD_SUCCESS             0
#define ISBD_ALREADY_AWAKE       1
#define ISBD_SERIAL_FAILURE      2
#define ISBD_PROTOCOL_ERROR      3
#define ISBD_CANCELLED           4
#define ISBD_NO_MODEM_DETECTED   5
#define ISBD_SBDIX_FATAL_ERROR   6
#define ISBD_SENDRECEIVE_TIMEOUT 7
#define ISBD_RX_OVERFLOW         8
#define ISBD_REENTRANT           9
#define ISBD_IS_ASLEEP           10
#define ISBD_NO_SLEEP_PIN        11

Interface Documentation

IridiumSBD(Stream &stream, int sleepPinNo = -1);

Description:   Creates an IridiumSBD library object
Returns:            N/A [constructor]
Parameter:      stream – The serial port that the RockBLOCK is connected to.
Parameter:      sleepPin - The number of the Arduino pin connected to the RockBLOCK SLEEP line.
Note: Connecting and using the sleepPin is recommended for battery-based solutions.  Use sleep() to put the RockBLOCK into a low-power state, and begin() to wake it back up.

int begin();

Description:   Starts (or wakes) the RockBLOCK modem.
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise.
Parameter:      None.
Notes

  • begin() also serves as the way to wake a RockBLOCK that is asleep.
  • At initial power up, this method make take several tens of seconds as the device charges.  When waking from sleep the process should be faster.
  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.
  • This function should be called before any transmit/receive message

int sendSBDText(const char *message);

Description:   Transmits a text message to the global satellite system.
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise;
Parameter:      message – A 0-terminated string message.
Notes

  • The library calculates retries the operation for up to 300 seconds by default.  (To change this value, call adjustSendReceiveTimeout.)
  • The maximum size of a transmitted packet (including header and checksum) is 340 bytes.
  • If there are any messages in the RX queue, the first of these is discarded when this function is called.
  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.

int sendSBDBinary(const uint8_t *txData, size_t txDataSize);

Description:   Transmits a binary message to the global satellite system.
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise;
Parameter:      txData – The buffer containing the binary data to be transmitted.
Parameter:      txDataSize - The size of the buffer in bytes.
Notes

  • The library calculates and transmits the required headers and checksums and retries the operation for up to 300 seconds by default.  (To change this value, call adjustSendReceiveTimeout.)
  • The maximum size of a transmitted packet (including header and checksum) is 340 bytes.
  • If there are any messages in the RX queue, the first of these is discarded when this function is called.
  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.

int sendReceiveSBDText(const char *message, uint8_t *rxBuffer, size_t &rxBufferSize);

Description:   Transmits a text message to the global satellite system and receives a message if one is available.
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise;
Parameter:      message – A 0-terminated string message.
Parameter:      rxBuffer – The buffer to receive the inbound message.
Parameter:      rxBufferSize - The size of the buffer in bytes.
Notes

  • The library calculates retries the operation for up to 300 seconds by default.  (To change this value, call adjustSendReceiveTimeout.)
  • The maximum size of a transmitted packet (including header and checksum) is 340 bytes.
  • The maximum size of a received packet is 270 bytes.
  • If there are any messages in the RX queue, the first of these is discarded when this function is called.
  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.
  • The library returns the size of the buffer actually received into rxBufferSize.  This value should always be set to the actual buffer size before calling sendReceiveSBDText.

int sendReceiveSBDBinary(const uint8_t *txData, size_t txDataSize, uint8_t *rxBuffer, size_t &rxBufferSize);

Description:   Transmits a binary message to the global satellite system and receives a message if one is available.
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise;
Parameter:      txData – The buffer containing the binary data to be transmitted.
Parameter:      txDataSize - The size of the outbound buffer in bytes.
Parameter:      rxBuffer – The buffer to receive the inbound message.
Parameter:      rxBufferSize - The size of the buffer in bytes.
Notes

  • The library calculates and transmits the required headers and checksums and retries the operation for up to 300 seconds by default.  (To change this value, call adjustSendReceiveTimeout.)
  • The maximum size of a transmitted packet (including header and checksum) is 340 bytes.
  • The maximum size of a received packet is 270 bytes.
  • If there are any messages in the RX queue, the first of these is discarded when this function is called.
  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.

int sendReceiveSBDBinary(const uint8_t *txData, size_t txDataSize,

uint8_t *rxBuffer, size_t &rxBufferSize);
Description:   Transmits a binary message to the global satellite system and receives a message if one is available.
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise;
Parameter:      txData – The buffer containing the binary data to be transmitted.
Parameter:      txDataSize - The size of the outbound buffer in bytes.
Parameter:      rxBuffer – The buffer to receive the inbound message.
Parameter:      rxBufferSize - The size of the buffer in bytes.
Notes

  • The library calculates and transmits the required headers and checksums and retries the operation for up to 300 seconds by default.  (To change this value, call adjustSendReceiveTimeout.)
  • The maximum size of a transmitted packet (including header and checksum) is 340 bytes.
  • The maximum size of a received packet is 270 bytes.
  • If there are any messages in the RX queue, the first of these is discarded when this function is called.
  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.

int getSignalQuality(int &quality);

Description:   Queries the signal strength and visibility of satellites
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise;
Parameter:      quality – Return value: the strength of the signal (0=nonexistent, 5=high)
Notes

  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.
  • This method is mostly informational.  It is not strictly necessary for the user application to verify that a signal exists before calling one of the transmission functions, as these check signal quality themselves.

int getWaitingMessageCount();

Description:   Returns the number of waiting messages on the Iridium servers.
Returns:            The number of messages waiting.
Parameter:      None.
Notes

  • This number is only valid if one of the send[Receive] methods have previously completed successfully.  If not, the value returned from getWaitingMessageCount is -1 (“unknown”).

int sleep();

Description:   Puts the RockBLOCK into low power “sleep” mode
Returns:            ISBD_SUCCESS if successful, a non-zero code otherwise;
Parameter:      None.
Notes

  • This method gracefully shuts down the RockBLOCK and puts it into low-power standby mode by bringing the active low SLEEP line low.
  • Wake the device by calling begin.
  • If provided, the user’s ISBDCallback function is repeatedly called during this operation.

bool isAsleep();

Description:   indicates whether the RockBLOCK is in low-power standby mode.
Returns:            true if the device is asleep
Parameter:      None.

void setPowerProfile(int profileNo);

Description:   Defines the device power profile
Returns:            None.
Parameter:      profileNo – 1 for low-current USB power source, 0 for default power
Notes

  • This method defines the internal delays between retransmission.  Low current applications need longer delays.

void adjustATTimeout(int seconds);

Description:   Adjusts the internal timeout timer for serial AT commands
Returns:            None.
Parameter:      seconds – The maximum number of seconds to wait for a response to an AT command (default=20).
Notes

  • The Iridium 9602 frequently does not respond immediately to an AT command.  This value indicates the number of seconds IridiumSBD should wait before giving up.
  • It is not expected that this method will be commonly used.

void adjustSendReceiveTimeout(int seconds);

Description:   Adjusts the internal timeout timer for the library send[Receive] commands
Returns:            None.
Parameter:      seconds – The maximum number of seconds to continue attempting retransmission of messages (default=300).
Notes

  • This setting indicates how long IridiumSBD will continue to attempt to communicate with the satellite array before giving up.  The default value of 300 seconds (5 minutes) seems to be a reasonable choice for many applications, but higher values might be more appropriate for others.

void setMinimumSignalQuality(int quality);

Description:   Defines the minimum signal quality needed to begin a send/receive transmission.
Returns:            None.
Parameter:      quality – The minimum signal quality on a scale of 0 (nonexistent) to 5 (superb) needed before the library allows a transmission to begin. (default=2)
Notes

  • Iridium recommend using 2 for this value, although there are occasions where 1 might be used.

void useMSSTMWorkaround(bool useWorkaround);

Description:   Defines whether the library should use the technique described in the Iridium Product Advisor of 13 May 2013 to avoid possible lockout.
Returns:            None.
Parameter:      useWorkaround – “true” if the workaround should be employed; false otherwise.  This value is set internally to “true” by default, on the assumption that the attached device may have an older firmware.
Notes

  • Affected firmware versions include TA11002 and TA12003.  If your firmware version is later than these, you can save some time by setting this value to false.

void attachConsole(Stream &stream)

Description:   Binds stream as the library output console.
Returns:            None.
Parameter:      stream – The stream object (typically a serial port) that will monitor the serial traffic to/from the RockBLOCK device.
Notes

  • This is a diagnostic routine.  Use it to monitor traffic on a PC console.

void attachDiags(Stream &stream)

Description:   Binds stream as the library diagnostic stream
Returns:            None.
Parameter:      stream – The stream object (typically a serial port) that will display library diagnostic messages.
Notes

  • This is a diagnostic routine.  Use it to monitor debug messages on a PC console.
  • If this functionality is no longer needed, you can recover system resources by recompiling the library source without diagnostics.  Change the line near the top of IridiumSBD.h to
#define ISBD_DIAGS             0

bool ISBDCallback()

Description:   This is not a library method, but an (optional) user-provided callback
Returns:            true if the operation should continue, false to terminate it.
Parameter:      None.
Notes

  • If this function is not provided the library methods will block.

License

This library is distributed under the terms of the GNU LGPL license.

Download

The latest revision of the library is 1.0. Download from GitHub.

Revision history

0.1   – Initial draft submitted to Rock 7 for review
0.2   – Added text about the AT-MSSTM erratum/workaround and changing the minimum required signal quality.  Also documented related new methods setMinimumSignalQuality()  and useMSSTMWorkaround().
1.0 – Posted initial version.

 

Page last updated on August 31, 2013 at 6:49 pm
100 Responses → “IridiumSBD”

  1. Danny

    1 year ago

    I have now solved a few of my own problems, so I wanted to share my insights here.

    The Error 10 problem was very vexing, but I have pretty much solved it after learning the following things:

    1) If you are on the low power profile (profile 1) and attempt to send messages too often, I believe the super capacitor on the RockBlock drains down. After enough attempts, the RockBlock stops responding, and the IridiumSBD library thinks the RockBlock is “asleep.” The key is to completely stop attempts to send messages for at least one minute before retrying. You can stop attempts by making ISBDCallback return a “false.”

    2) The content of ISBDCallback must return a true. This seems obvious now, but I spent a long time learning this lesson. You will get lots of errors until you fix this. My ISBDCallback looks something like this now:

    bool ISBDCallback()
    {
    if (cancelSendingMessageBoolean = true)
    {
    return false;
    }
    else
    {
    theFunctionIWantToDoWhileTryingToSendAMessage();
    return true;
    }
    }

    This code does the processes I want until I toggle a boolean that cancels the send process. At that point, the IridiumSBD library clears the RockBlock’s EEPROM, and then the code returns to void loop().

    3) the RockBlock can suck a LOT of current on the 5V line of the UART breakout header. If I attach a “limitless” current source to a fresh RockBlock, about 500 mA will be drawn for a short time as the capacitor charges. Rock7 documents this phenomenon, but my guess is that most people probably don’t take to heart and just blindly hook up the RockBlock’s power to their Arduino’s 5V pin. This caused lots of problems for me because my Arduino is also powering a variety of delicate 5V sensors. Voltage dips caused all kinds of issues. The best way to fix this is to hook up your Arduino’s 5V out to the RockBlock’s USB power breakout which is mercifully limited to 90 mA current draw. The wiring gets a little ugly because you have serial communication going to one header and power going to another, but overall the system is much more stable.

    One problem I am STILL having that is causing most of my current issues is that signal quality checks (AT+CSQ) return wildly different values one minute to the next. I will send a message with while having a signal quality of “5″ and then just one minute later the signal quality is “0.” I cannot figure this out. Any ideas?


  2. Hayan

    1 year ago

    hello,My name is Hayan from algeria.
    i have a little bit question if you can give me response ?
    is it possible to integrate RockBLOCK with opentracker v2.0 arduino based gps/glonass tracker ?
    it fully open source and 100% Arduino compatible GPS/GLONASS vehicle tracker with a powerful 32-bit ARM Cortex-M3 CPU.
    [...]
    thank you Mikal Hart.
    Hayan – Student in embedded Systems.


  3. Mikal

    1 year ago

    Thank you Danny. We have a somewhat similar application where a high-altitude balloon reports position, altitude, temperature, speed, etc. approximately every three minutes. This is generally pretty reliable. We sometimes get error 7, but after that things seem to resume fine and we get a fairly regular 3-minute cadence of messages. In the next few weeks I’ll be studying IridiumSBD with an eye on improvements.

    There are a couple of improvements I have in mind with the ISBDCallback mechanism.

    I can’t imagine how you get into the state where even AT\r\n doesn’t elicit any response from the modem. I’ve never seen that (except in on modem that we fried by accident–and that one never recovered).

    Keep in touch please. It seems like you are doing interest stuff. And thanks for the kind comments.


  4. Mikal

    1 year ago

    @Danny–

    Ah, I didn’t see your follow on until now. But I can tell you that the “wildly varying” signal quality is completely expected. It has to do with the fact that the Iridium satellites are not geostationary. You may be fully charged with a perfect view of the sky, but if an Iridium satellite doesn’t happen to be overhead at the moment you check the signal quality, it very well may be “0″.

    Thanks again…


  5. Mikal

    1 year ago

    Hi Hayan–

    If your device is 5V TTL compatible–and I bet it is–it should be able to talk to RockBLOCK.


  6. Victor

    1 year ago

    Hi Mikal!

    First thank you for your awesome work, it’s being very helpful in a project which on I’m working. But I’ve been facing an issue, and I don’t know if it’s something that I did wrong: when I execute a begin() after a sleep() it doesn’t awake the device (or at least it doesn’t show the AT commands at the serial output) and of course doesn’t send the message.

    Could you help me?

    Thanks in advance!


  7. Mikal

    1 year ago

    @Victor,

    I haven’t done a lot of testing with this configuration–though I expect to soon. Is it possible that you need to wait for “up to 180 seconds” for the supercap to refill?


  8. Victor

    1 year ago

    Hi Mikal,

    Thanks for the quick reply. At the developers guide (https://www.rock7mobile.com/downloads/RockBLOCK-Developer-Guide.pdf) says this:

    “It is possible to enter a low-power ‘sleep’ mode, by switching off the Iridium 9602. This is done using the sleep pin on the direct header. In this mode, RockBLOCK will only require about 20uA. The internal charge will be maintained, so it will be possible to transmit almost immediately on wake-up”

    Also it explains that those 180 seconds is only at the beginning:

    “On initial connection to a power supply, the on-board charge store must charge. At 90mA, this can take up to 180 seconds to reach full charge”

    Anyway, I’ll try to wait that amount of time. Perhaps do I need to set the power profile to 0?

    Thanks again!


  9. Victor

    1 year ago

    Hi Mikal,

    Don’t worry, I already solved it :)

    Best regards,


  10. Mikal

    1 year ago

    What was the secret, Victor? :)


  11. Richard

    1 year ago

    This seems like a very simple question but I’m struggling to find the answer. The datasheets that I have found give plenty of info concerning the AT commands while in command mode for the 9602. What I’m missing is how do I get the 9602 into command mode?

    The 9602 evidently comes default as a 9-wire interface and I would like to get to the command mode so that I can change it to a 3-wire interface so I can use your Arduino code.

    I’m using a factory 9602 and not the RockBlock.


  12. RAJ

    1 year ago

    Will this library work on bare Iridium 9602 modem?


  13. Richard

    1 year ago

    Okay, maybe that wasn’t the right question. I see now that it should automatically start off in command mode. The question then is Should the CTS, DTR, etc. have to be set a certain way in order for it to start responding to “AT” commands? It seems like RTS & DTR should be held low. It also seems like if DSR is showing low that the 9602 is ready for commands. I’m holding RTS & DTR low, and DSR is showing that it is being set low by the 9602, but I’m getting no response from the 9602 when it comes to “AT” commands.


  14. Mikal

    1 year ago

    @Richard–

    The 9602 is not like an old-fashioned modem, where you put it in command or data modes. I think it’s always in command mode.


  15. Mikal

    1 year ago

    @RAJ,

    We designed it to work on any 9602 device but we never tested it on anything but the Rock7 RockBLOCK.


  16. Mikal

    1 year ago

    @Richard,

    I’m not sure whether the RockBLOCK (are you using RockBLOCK?) pulls up or down RTS, DTR, CTS, etc. (probably does), but I know that in my applications I simply ignore all those signals. I use SLEEP, TX, RX, and of course the power rails.


  17. okojkwu kennedy

    1 year ago

    i am new to this and got the Rockblock ruggedised version that comes wit a USB terminal. Cutting this exposes 4 wires( 5v, +D,-D, Gnd)? In this case which is tx, rx, sleep etc. Is there any other way i can connect to Arduino uno.


  18. Mikal

    1 year ago

    Hi okojkwu… No, I’m afraid that the USB connector is entirely incompatible with the signals that are provided with the header in the “naked” version of the RockBlock.


  19. okojkwu kennedy

    1 year ago

    Hi Mikal, any other way then of connecting this rugged rockblock version to be used with Arduino in tracking project? Any diagram or examples?


  20. Luis

    1 year ago

    Hi Mikal,

    I’ve been trying to get this code to work with an Arduino Due, which I’m having issues with that stem from the fact that SoftwareSerial is not supported on the Due. This has made it rather difficult to initialize an IridiumSBD object. Since there are 4 serial ports, ‘Serial1′ (or 2-4) should work, however i keep getting errors like:
    “In member function ‘int IridiumSBD::internalSendReceiveSBD(const char*, const uint8_t*, size_t, uint8_t*, size_t*)’:
    IridiumSBD.cpp:259: error: call of overloaded ‘console(size_t&)’ is ambiguous”

    when trying define an IridiumSBD object as: “IridiumSBD isbd(Serial1,-1);”

    I’ve tried other hacks to pass Serial1 through, but have hit roadblocks involving trying to pass a USARTClass where the code is looking for a Stream.

    Any help would be HIGHLY appreciated.


  21. Mikal

    1 year ago

    Luis/Stephen,

    I will fix this in the next release, but the problem causing the “call of overloaded ‘console…” is the fact that on Due a size_t is 32-bits. In the meantime, I think you can temporarily work around this problem by changing this line

          console(txDataSize);
    

    to

          console((uint16_t)txDataSize);
    

    then restarting the Arduino IDE. I’ll try to build a better fix. Thanks for finding that.


  22. Luis

    1 year ago

    Mikal, you are a gentleman and a scholar. Thank you VERY much for the patch advice and your appreciated work on developing this library.


  23. Phil Smith

    1 year ago

    I’d like to report what looks like a bug in the internalMSSTMWorkaround() method in the Iridiumsbd.cpp code.

    I’ve written a simple program to talk to the Rock7 from an Arduino, based on the examples in the documentation using the sendReceiveSBDText() method.
    This used to work (back in August), but now doesn’t. What I think is the problem is that the return from the Rock7 to the -MSSTM command is the time, in hexadecimal. The time (in some odd units of 90ms) now starts in “a” because it is returned as a hex number. This is then checked by:
    okToProceed = isdigit(msstmResponseBuf[0]);
    However, the isdigit() looks for 0…9, so hex numbers starting in a…f fail this test, so okToProceed gets set to false. This means that the remainder of the sendReceiveSBDText() doesn’t get run, and the message doesn’t get sent. [Note that this is a bit of a shorthand explanation since there are both internal and external versions of most of the methods in the library, but you should be able to follow the code in the .cpp file if you want the details.]

    I’m guessing that back in August the time started in a digit in hexadecimal, and hence okToProceed gets set to true.

    My workaround is to use useWorkaround(false), so it doesn’t run the internalMSSTMWorkaround() method. [I've actually put useWorkaround(false) in the header file, line 98.]

    I haven’t thoroughly tested out my hypothesis since I have a later version of the Rock7 firmware that doesn’t need the workaround, but this might be helpful if someone else is having a similar problem.

    Whilst I’m sending this in, I’d also like to point out that the example in the documentation on page 4 has the line:

    int status = isbd.sendReceiveText(“Is anyone home?”, rxBuffer, bufferSize);

    but the method in the library is: sendReceiveSBDText().

    I hope these are both correct and helpful.


  24. Mikal

    1 year ago

    @Phil Smith,

    Thanks very much for both of the observations, which are entirely correct. I’ve published a fix for the error with the MSSTM parser, and will fix the documentation later today. Sorry about the hassle!


  25. Phil Smith

    1 year ago

    Something else that I came across and doesn’t seem ideal, is that if you call begin() when the Rock Block is already powered up, the RockBlock gets turned off, because of the line:

    if (ret != ISBD_SUCCESS) power(false);

    I changed it to:

    if (ret != ISBD_SUCCESS && ret !=ISBD_ALREADY_AWAKE) power(false);

    which leaves it on if it were already on.

    Of course, you could check if the RockBlock was on before calling begin(), but it seems a bit unnecessary that begin() would turn it off if already on. There doesn’t seem to be a problem with going through begin() again if already on.

    Apart from these few problems, the library has been extremely helpful, so thank you for sharing it.


  26. Mikal

    1 year ago

    @Phil Smith,

    Excellent! Thanks very much.


  27. Aria

    1 year ago

    Hi Mikal,

    I am having a problem with my RockBLOCK module. I have it connected via direct header pins to an Arduino Mega using HardwareSerial. Everything works great initially, and I get a message sent over the iridium network. I put the RockBLOCK to sleep for 3 minutes, and begin it again after this time. However, it simply doesn’t turn on. When I execute a begin() after a sleep() it doesn’t awake the device (or at least it doesn’t show the AT commands at the serial output) and of course doesn’t send the message. I know others have had this problem but I don’t know what the solution is. Can you shed some light on this?

    Thanks!
    Aria


  28. Mj

    1 year ago

    Hey All:

    We currently have an arduino based program that runs with the older SBD library that communicated with our rockblock naked.

    Around November, we started getting the Dreaded iridium error 7. The rockblock checks out as working when plugged into a computer and using hyperterminal, etc.
    Our programmer has gone on to other things and finding a good coder that understands the library, etc. has been hard to come by. (I am an engineer and our other partner is a hydrologist – so no luck with coding there.) I have tried to rap my head around it, but CAD and MIG welding is my wheelhouse, not c++.

    So I am reaching out to coders who frequent this page. We are in need of assistance. We would gladly contract with someone via Elance or other coder contractor site to update our code.

    If you are interested, or know of a coder that would be, please reach out.

    Thanks

    oceanstudy1@gmail.com


  29. PlumB

    1 year ago

    Thanks for your work on this, it has been very helpful!

    I found a bug in doSBDRB() when using a hardware serial port on the Mega 2560. When reading incoming data the for loop is not waiting for data to arrive. I was only getting the first 1 or 2 bytes written to the buffer I passed it. The rest was old data. I made the following changes and it seems to be working:

    for (int i=0; i= 1000UL * atTimeout)
    return ISBD_SENDRECEIVE_TIMEOUT;
    }
    // if (stream.available())
    // {
    uint8_t c = stream.read();
    if (rxBuffer && prxBufferSize)
    if (*prxBufferSize > 0)
    {
    *rxBuffer++ = c;
    (*prxBufferSize)–;
    }
    else
    {
    rxOverflow = true;
    }
    // }

    // if (millis() – start >= 1000UL * atTimeout)
    // return ISBD_SENDRECEIVE_TIMEOUT;
    }

    Other than that, this library has been great!


  30. PlumB

    1 year ago

    for (int i=0; size > i; ++i)
    {
    // wait for the data to come in
    while (!stream.available())
    {
    if (cancelled())
    return ISBD_CANCELLED;
    if (millis() – start >= 1000UL * atTimeout)
    return ISBD_SENDRECEIVE_TIMEOUT;
    }

    uint8_t c = stream.read();
    if (rxBuffer && prxBufferSize)
    if (*prxBufferSize > 0)
    {
    *rxBuffer++ = c;
    (*prxBufferSize)–;
    }
    else
    {
    rxOverflow = true;
    }
    }


  31. Mikal

    1 year ago

    @Mj,

    Did you get my email? This is a known bug that was fixed a couple of months ago. Please download the latest library and try again.


  32. Mikal

    1 year ago

    @PlumB, that looks correct, but why does it fix the problem you are seeing? I can’t see how data could be lost.


  33. Michael Bueno

    1 year ago

    Mikal,

    I was wondering if you have had any opportunity to test your IridiumSBD library using an iridium 9603 SBD modem. (This modem is smaller and lighter than the 9602 in the rockblock.)

    If so, did it work OK? If not, would you have any reason to believe your library would *not* work with the 9603?

    I want to be like you :) and send up a high-altitude weather balloon, and am trying to decide between the 9602 and 9603 modems.

    Thanks!

    Michael


  34. Mikhail

    1 year ago

    Hi Mikal!
    I have Arduino Mega2560 and Rock7 RockBlock
    I work with hardwareserial & nss = Serial1

    I can sennd text and binar message very well, receive them on core.rock7.com account, but…
    I absolutely cannot receive message on modem… no Plain, no HEX
    sending messages with core.rock7.com account!

    For example, default sketch SendReceive, trying to send number 25 as a hex with core.rock7.com – i received on modem (with MSSTMWorkaround enabled):

    OK
    >> AT-MSSTM

    <> AT+SBDIX

    <> AT+SBDRB

    <> AT+CSQ

    <> AT+SBDIX

    <> AT+SBDRB

    << AT+SBDRB
    [Binary size:1][csum:9472]Inbound buffer size is 1
    K(4B) Messages left: 0

    It looks like some thing wrong with Receive method in a library, or with communicating with Rock7 Core… All received message cannot be converted to 25, absolutely.
    Please help, what could be wrong??


  35. Mikhail

    1 year ago

    …addition example

    (with MSSTMWorkaround enabled):
    << AT+SBDRB
    [Binary size:1][csum:9472]Inbound buffer size is 1
    ћ(9E) Messages left: 0

    (and with MSSTMWorkaround disabled):
    << AT+SBDRB
    [Binary size:1][csum:9472]Inbound buffer size is 1
    K(4B) Messages left: 0

    9E and 4K is not a number 25 in any case (HEX, BIN, etc.) but why??


  36. Mikal

    1 year ago

    @Mikhail–

    I’ll do some testing this month and see if I can’t replicate your results. What message are you sending to the RockBLOCK and how are you sending it?


  37. PlumB

    1 year ago

    Mikal,

    I believe the if(stream.available()) function was being called before the next byte was sent from the RockBlock. This caused it to skip the code that stores the data to the buffer (because the data was not yet available), and it would finish the for loop before any additional data became available. I only saw this problem using hardware serial. I assume software serial is slower and thus provided enough time for the next byte to be sent from the RockBlock. Waiting for stream.available() to return true in the for loop solved my problem.


  38. Sarah

    1 year ago

    hi, I am trying to use the rockblock with my ardunio mega for a high altitude weather balloon project. When we use the code provided the serial monitor only returns the word AT, we get no connection with the rockblock on their mobile site. any idea whats going on?


  39. Mikal

    1 year ago

    @Sarah, have you connected TX to TX? If so that’s wrong. Connect RX to TX and TX to RX. Make sure both are 5V.


  40. Michael Bueno

    1 year ago

    Mikal,
    I am trying to use the BasicSend example from your iridium library example code. I have determined that when I call

    isbd.begin();

    It never seems to recognize the modem. I wait for what seems like 8*30 seconds (or 4 minutes), which I am guessing is a timeout. Then it seems like the modem gets switched off.

    Any suggestions on why this would be happening, and/or an idea of what I am doing wrong?

    I tried your example using both softwareSerial (on a nano) and hardwareSerial (on a Mega2560) for the communication to the modem.

    I have tried swapping the rx and tx lines in case they are labelled backwards (i.e., tx->rx, rx->tx and tx->tx, rx->rx) but get the same perplexing result.

    Thanks for any feedback you can offer.

    -Michael


  41. Michael Bueno

    1 year ago

    Mikal,

    I found the problem specified in my previous post regarding:


  42. Michael Bueno

    1 year ago

    Whoops! Sorry for not finishing prior message!

    Mikal,

    I have been attempting to use your arduiniana iridium library with an iridium 9603 SBD (short burst data) modem, and wanted to report on my progress thus far…

    I found the problem I specified in my previous post regarding:

    “trying to use the BasicSend example”

    …where it seemed as if the modem was switched off. It was silly in retrospect. I had a faulty U.FL -> SMA pigtail between my modem and antenna that was not allowing *any* communication to the satellite network at all (as would be expected)!

    *** Luckily *** I followed my usual purchasing rules of procuring *more than one* of any component (unless financially prohibitive). This has saved me more than once when I either received a faulty component (like the aforementioned pigtail), or I fried a component while testing (which, I am not embarrassed to admit, happens from time to time).

    My second *functional* pigtail solved this problem.

    To review, I am trying to use your iridium library with an iridium 9603 SBD modem (as opposed to the iridium 9602 modem that is housed in the RockBLOCK and with which your library was originally intended to function).

    I purchased my iridium 9603 modem from GIT Satellite Communications (http://www.gitsat.com) for only $175 (U.S.), which is considerably less than other SBD resellers prices of over $300 U.S. They also provide a service plan.

    After solving my pigtail issue, I was still having difficulty communicating with the satellite array. I regressed to attempting to manually enter ‘AT’ commands to the modem while hooked up to my computer.

    For this part of my testing, I hooked up the 9603 to TX/RX/GND to my computer and ran a terminal application to talk to the modem. The (default) serial port (usb) settings for the 9603 are:

    19200 baud, 8 data bits, no parity, 1 stop bit, no flow control

    I used an FTDI adapter to physically connect the 9603 modem to my computer using a USB cable. This adapter was set to use *3.3V* (as opposed to 5V) for the logic. This is important, as a 3.3V ftdi adapter does the logic level shifting required to communicate with the 9603. (I suppose an in-line logic level converter could be used just the same.)

    I was still having problems communicating with the modem. I received no responses as I tried to manually type ‘AT’ commands to the modem.

    I told the GITsat technical team what I was trying to do, and that I was trying to use an iridium 9602-designated arduino library with the 9603. I asked them about the similarity/dissimilarity between the two modem models, and they told me that functionally, both modems are *almost identical*. They use the same AT commands, and GITsat has reported that *at least some* of the code designed for the 9602 *has worked unmodified* with the 9603. The tech folks at GITsat have been super-helpful in addressing my communications woes.

    Some things I learned from them include:

    Your Arduiniana iridium library works in what iridium calls “3-wire mode”. This is where the only communication lines that are *actively used by the modem* are the RX and TX (in addition to the GND, power, etc.). Many RS-232 serial connections apparently use the CTS/RTS, DTR/DSR, etc. connections (like typical modems, fax machines, etc.) In “3-wire mode”, only the TX/RX/GND are used *for the communications*.

    Some of the other pins on the modem DO need connecting, however…

    The Iridium 9603 has a 20-pin interface. This includes (two) +5V for power, (two) GND, the TX and RX pins we need to connect, and the other communication pins such as CTS/RTS, etc. It is also important to distinguish that the logic for the 9603 is 3.3V (not 5V). Thus, depending on what you are using to talk to it with, you may need a logic level converter (i.e., if using the 9603 with a 5V arduino). The modem needs 5V to operate, however.

    (Not sure about the 9602 logic level voltage, but I thought I would mention the the required logic level of the 9603 for those interested…)

    Upon beginning to test my modem, I hooked up the necessary pins and attempted to use the library examples, but cannot get things to work. I am getting no communication with the satellite array or even the modem!

    GITsat technical support took the time to explain RS-232 protocol in some detail. They told me that for “3-wire” mode, several of the *otherwise unused* communications pins on the modem *needed to be grounded*.

    This is how they told me to hook it up:

    (beginning of quotation)…

    To use only three wires (transmit data, receive data and ground) you can ground pins 3, 4, 8, 13, 14, 15 and 18 on the 9603 connector. Pins 16 and 17 can unconnected. Pin 5 is the on/off control and should be high (>2.0V according to the table). Pin 6 on the 9603 (DF_S_TX, an input) should go to pin 3 on a DB9 male connector on a USB-RS232 cable. Pin 7 on the 9603 (DF_S_RX, an output) should go to pin 2 on the USB-RS232 cable. Pin 5 on the DB9 (signal ground) should go to the ground on the 9603.

    … (end of GITsat quotation)

    I hooked up the pins as suggested, and the modem sprung to life! I was now getting diagnostics about my signal strength and other commands the library was issuing to the modem, as well as the responses from the modem! The problem I was having was due to not having grounded the unused *input* communications pins. Setting these to ground as per GITsat’s recommendation made *all the difference*.

    I should mention also, while trying to manually enter ‘AT’ commands on a serial terminal, I learned that there are two ‘AT’ commands that put the 9603 modem into 3-wire mode. These are handled by your iridium library, but it was helpful to know these commands while troubleshooting my communications issues and attempting to enter ‘AT’ commands manually.

    These are:

    AT&D0

    AT&K0

    To summarize, hooking up the unused *input* pins of the 9603 to ground (as instructed by GITsat tech support) allowed me to use your library with an iridium 9603 modem!

    I am still having some issues, however. When I try to send an SBD text string such as:

    AT+SBDWT=Hello, world!

    …, I get this error:

    << AT+SBDIX
    sendSBDText failed: error 3

    Error 3 is a "protocol error". I am not yet certain, but I am guessing this might be an issue related to parsing the strings returned by the modem. Perhaps these returned strings slightly differ between the 9602/9603…

    In any event, I am having some tangible success using your library with the 9603 and wanted to report on my progress thus far! I am now on to trying to debug the "protocol error" I am receiving when I attempt to send text with the library…

    Incidentally, I thought I would mention that I am using an arduino mega 2560 R3 for testing. I am using two *hardware* serial ports (instead of one or more softwareSerial ones). My testing thus far has included a slightly modified version of the "BasicSend" example (provided with the library). I modified it to retry the example communication *inside* the loop, so it iterates and I get to monitor the results of several communications attempts.

    For those starting out with electronics/arduino/etc. and trying to integrate an iridium SBD modem into a project, I provide this warning:

    Don't use the arduino's 5V pin to POWER your 9603 modem. It does not supply ample current and might break your arduino (or at least not allow the SBD modem and/or arduino to function correctly)! Use a separate power supply or voltage regulator that provides a clean 5V and at least 500mA of current (a bit of overkill current-wise, perhaps, but in this case, a bit of a buffer power-wise is reassuring)…

    One more thing I thought I should mention (that is fairly IMPORTANT):

    When using the iridium 9603 SBD modem, I tried hooking up the RX/TX lines *both* ways, not sure where the TX/RX modem pins connected to the arduino's TX/RX pins. (Is that RX/TX relative to the *sender*, the *receiver*, or what?) After getting it to work, I am pleased to report that the iridium 9603 TX pin should connect to an arduino's TX pin, and the 9603's RX pin should go to the arduino's RX pin.

    I am not sure, but *this may differ* from the iridium 9602 (and RockBLOCK's) TX/RX connections as mentioned in other users' comments about 9602 operation.

    Mikal,

    Thanks for the generous contribution of your library! Without it, I would be *so much further* from getting my iridium 9603 SBD modem to function! I hope to report full functionality in the near future!

    -Michael


  43. Michael Bueno

    1 year ago

    ***correction from above post about iridium 9603 SBD modem follows ***

    The ‘AT’commands that put the iridium 9603 into 3-wire mode are:

    AT&D(followed by the digit *zero* (with NO spaces))

    and

    AT&K(followed by the digit *zero* with no spaces)

    Not sure why these appear (to me at least) as lowercase ‘o’ characters instead of the digit (zero)…

    -Michael


  44. Michael Bueno

    1 year ago

    Ahhh… I now realize that the zero digits look like lower case ‘o’ (oh) characters due to the font…

    In any event, they are both supposed to be *zero*


  45. Raul Gio

    1 year ago

    Hello Mikal, as part of a project with the GSMA, I’m planning on using the library you created and the Iridium modem to send the readings of a sensor that communicates with an Arduino DUE via the serial port.

    First of all, is that possible? the sensor communicates via 9600, the information received is selected, cropped and sent via 19200 to the Serial Monitor. This is done because only a few substrings of the original string sent are necessary for the information we need.
    Could I be able to do the same using the SBDText option, or is there another way?

    I’m also curious to know if, the fact that I’m using Serial communication before starting to use SoftwareSerial, might turn up some complications since they sometimes can be used to perform the same tasks.

    I would like to know also if there’s a timer on the library or if there´s any problem if I import one from another library (SimpleTimer), since we want to receive the processed readings every 30 seconds.

    Thank you very much for your time reading this and I hope you can help me.


  46. Jon

    1 year ago

    Hi there,
    I am trying to use your Rockblock library in conjunction with an Adafruit nRF8001 Bluetooth module. It seems when I try to activate the Bluetooth module and Rockblock at the sametime, the Arduino (Mega) locks up. I can run Bluetooth or the Rockblock but not both at the same time. Do you have any idea how they might be competing with each other?


  47. Mikal

    12 months ago

    @Raul Gio,

    If you are using Due, I wouldn’t use SoftwareSerial. Just use 2 of Due’s 4 hardware serial ports. I think this would work with Iridium, though I should warn you that it is very unlikely that you will be able to reliably transmit something every 30 seconds. SBD transmissions rely heavily on the luck of where the satellites are and cloud cover, etc. It often takes several minutes to establish contact and transmit data.


  48. Mikal

    12 months ago

    @Jon, are you using different serial ports for each?

2 Trackbacks For This Post
  1. Talking to Satellites! | Arduiniana

    [...] IridiumSBD [...]

  2. RockBlock Configuration | The Official Skyence Blog

    [...] code online in a couple of weeks so stay tuned for that if you’re interested. It is based off this brilliant library which has cut out a lot of the hard work for [...]

Leave a Reply