Our full technical support staff does not monitor this forum. If you need assistance from a member of our staff, please submit your question from the Ask a Question page.

Log in or register to post/reply in the forum.

RockBlock+ Iridium SBD modem

--dd-- Oct 23, 2020 01:38 AM

Hi, is anyone using RockBlock+ with Campbell dataloggers. If so, would you mind sharing an example program?


GTProdMgr Oct 30, 2020 11:27 AM

It looks like the RockBlock+ is "9602 modem" compatible, so it should work. There are two approaches to Iridium you can take on these dataloggers. The first way to use a lower level approach with Serial CRBasic commands over RS-232 and using the AT command set. See example program below.  The second method, which isn't as flexible, but requires much less CRBasic code (Transmit only) is to use GOESTable and GOESField. Instead of selecting the TX325 or TX321 which are GOES devices for the "Model", you can choose the COM9602/Iridum modem. You simply define a DataTable with the data in it that you want to transmit, then you put the GOESTable instruction at the top of the table's Definition, and then put the GOESField instruction immediately before any Sample, Maximum, Minimum or other output instruction whose data you want to transmit. When the table is called, then the data gets transmitted. You also have to put a SerialOpen instruction at the beginning of the program to establish the RS-232 connection between the datalogger and the 9602 modem. Here is a program that illustrates the GOESTable method :


Const IridiumPort = ComRS232 'Com port on the CR300 to which the COM9602, COM9522B or other SBD-capable modem/radio is connected

Public SimStage As Float 'Simulated stage height reading (water level)
Public IridTx_Result As String *800

'boolean controller
Public CallGOESTable As Boolean

'Table for Iridium Transmissions
DataTable(IridiumTx, True, -1)
   GOESTable(IridTx_Result,IridiumPort,2,0,FALSE,TRUE,2) 'Model =2, COM9602(Iridium)
   Sample(1, SimStage, IEEE4)   

  SimStage = 20.143
  PortSet(C1,1) 'Apply power to the 9602
  SerialOpen (IridiumPort,19200,3,0,400) 'Initialize the serial connection -- serial settings for the 9602

	Scan (5,Sec,0,0)
	  If CallGOESTable Then
	    SimStage += 0.01
	    CallTable IridiumTx
	    CallGOESTable = False



In the above program, set the boolean variable CallGOESTable to true when you want to attempt a transmission.

Here is a program that uses the low-level serial and AT commands - In this program you will need to set multiple boolean variables to true to step through the process (exploratory/test program). Use "LoadMO" then "SendMO" then "CheckMOResult" for a basic transmit, GetSystemInfo and CheckRadioSignal can also be used for troubleshooting :


Const IridiumPort = ComRS232 'Com port on the CR300 to which the COM9602, COM9522B or other SBD-capable modem/radio is connected

Public Payload As String *250 'String to be sent to Iridium network
Public MsgStringMO As String *335 'Full command string and payload for sending message to Iridium network

Public SendMOResult As String *100 'Response from radio after sending MO message
Public SBD_TxResult As Long 'Integer response from radio after sending MO message
Public MOResult As String *50 'English text interpretation of response from radio after sending MO message

Public MsgStringMT As String *250 'Message Received from Iridium Network (MT=Mobile Terminated, Incoming)
Public PullDownResult As String *50 'Response from radio after pulling down message from Satellite into MT buffer
Public SBD_RxResult(5) As Long 'Integer response from radio after pulling down message from Satellite into MT buffer

Public CheckRadioResult As String *100 'Response from radio after checking Signal Strength
Public SS_RxResult As Long 'Integer response from radio after checking Signal Strength

Public RadioManufacturer As String *32
Public RadioModel As String *32
Public RadioRevision As String *200
Public RadioSerialNumber As String *50
Public PushMOResult As String *64 'For testing only

'Step through each operation one at a time - boolean controllers
Public RadioOn As Boolean
Public GetSystemInfo As Boolean
Public LoadMO As Boolean
Public SendMO As Boolean
Public CheckMOResult As Boolean 
Public MailboxCheck As Boolean
Public PushMOIntoMT As Boolean 'For Testing only
Public PullDownMT As Boolean 
Public RetrieveMT As Boolean
Public CheckRadioSignal As Boolean

  Payload = "Test of Iridium Short Burst Data"
  SerialOpen (IridiumPort,19200,3,0,400) 'Initialize the serial connection -- serial settings for the 9602

  Scan (10,Sec,0,0)
    'Note: Using Port C1 for now to turn the Radio+Modem on/off (hard-coded)
    'Explore whether Vx1,Vx2 work, etc.
    If GetSystemInfo Then
      'Manufacturer, Model,Revision,Serial Number
      SerialFlush (IridiumPort)
      SerialOut(IridiumPort,"AT+CGMI" & CHR(13) & CHR(10),CHR(13) & CHR(10),1,200)
      SerialOut(IridiumPort,"AT+CGMM" & CHR(13) & CHR(10),CHR(13) & CHR(10),1,200)
      SerialOut(IridiumPort,"AT+CGMR" & CHR(13) & CHR(10),"Call ",1,200)
      SerialOut(IridiumPort,"AT+CGSN" & CHR(13) & CHR(10),"AT+CGSN" & CHR(13) & CHR(10),1,200)
      GetSystemInfo = False

    If LoadMO Then
      'Populate MO buffer on the radio (Mobile Originated/Outgoing)
      ' ["AT+SBDWT=" & Message string to be sent] -- WT=Write Text (WB=Write Binary)
      MsgStringMO = "AT+SBDWT=" & SecsSince1990(Status.Timestamp,4) & " :: " & Payload & CHR(13) & CHR(10)
      SerialFlush (IridiumPort)
      LoadMO = False

    If SendMO Then
      'Instruct radio to Transmit MO buffer up to satellite
      ' ["AT+SBDI" & CRLF]
      SerialOut(IridiumPort,"AT+SBDI" & CHR(13) & CHR(10),"+SBDI: ",1,3000)
      SendMO = False
      CheckMOResult = True
    If CheckMOResult Then
      MOResult = "Checking for MO Send Result..."
      SplitStr (SBD_TxResult,SendMOResult,",",1,0)
      If SBD_TxResult <> 1 Then
	  MOResult = "Warning -- Unexpected Send Result: " & SBD_TxResult 'Delay(1,5,sec)
	  MOResult = "Successful Send of MO Buffer to Iridium Network: " & SBD_TxResult
      End If
      CheckMOResult = False
    End If

    If MailboxCheck Then
      MailboxCheck = False
    If PushMOIntoMT Then
      'For Testing only: Pushes content of the MO buffer over into the MT buffer
      SerialFlush (IridiumPort)
      SerialOut(IridiumPort,"AT+SBDTC" & CHR(13) & CHR(10),"SBDTC",1,200)
      PushMOIntoMT = False
    If PullDownMT Then
      'Receive message from Iridium satellite into MT buffer (Incoming, MT=Mobile Terminated)
      SerialFlush (IridiumPort)
      SerialOut(IridiumPort,"AT+SBDD1" & CHR(13) & CHR(10),"0",1,200) 'Clear mobile terminated (MT) buffer
      MsgStringMO = "AT+SBDWT=" & SecsSince1990(Status.Timestamp,4) & " :: " & Payload & CHR(13) & CHR(10)
      SerialOut(IridiumPort,"AT+SBDIX" & CHR(13) & CHR(10),"+SBDIX: ",1,5000)
      PullDownMT = False

    If RetrieveMT Then
      'Receive message from radio MT buffer (Incoming, MT=Mobile Terminated)
      '[+SBDRT] RT=Retrieve Text
      SerialOut(IridiumPort,"AT+SBDRT" & CHR(13) & CHR(10),"+SBDRT" & CHR(13),1,300)
      RetrieveMT = False

    If CheckRadioSignal Then
      ' [CSQ] Check Signal Quality
      SS_RxResult = 0 'IridiumSS_timeout = Timer (2,Sec,0 )
      CheckRadioResult = "Checking Signal Strength on radio/modem..."
      SerialOut(IridiumPort,"AT+CSQ" & CHR(13) & CHR(10),"",1,0)
      CheckRadioSignal = False




GTProdMgr Oct 30, 2020 11:57 AM

If you are using the CR300 datalogger, then another option is to look at the HydroLink software (available for free download) https://www.campbellsci.com/hydro-link. You can select from a sensor set in the program and specify outputs, and then the program is automatically generated and loaded onto the datalogger. You have access to generic SDI-12 sensors, voltages, pulses, some rain gages and also the CS475A radar, CS451 pressure transducer, the ClimaVue weather station and then LevelVue bubbler. Once all of that is set up, you can specify Iridium as the transmit mechanism (9602 compatible) and define what you want to transmit. Everything is done automatically for you as far as the CRBasic program, including all of the Iridium communications.

--dd-- Nov 3, 2020 03:17 AM

Indeed, RockBlock is using the 9602 and 9603 Iridium modem so your code should work just fine. Anyway, before i got your answer, I put togheter a set of functions and a test program that sends and recives SBD messages and store them in inbox and outbox tables. This code have been tested with a RockBlock 9603.

Thanks Alberto Dallolio who got me started with the AT commands and functions.


'Program to send and recive messages with RockBlock+ or RockBlock 9603 Iridium modem
'(c)2020 john.hulth@geo.uio.no and alberto.dallolio@ntnu.no

ConstTable (Station_Constants)
  Const SCAN_INTERVAL = 20                'Measurement sample interval in Sec
  Const RockBlock9603 = true              'RockBlock 9603, LVTTL, orange TXD -> C1; yellow RXD -> C2; red -> 5v external
  Const RockBlockPlus = false             'RockBlock+, RS-232

  #If RockBlock9603 OR RockBlockPlus
    Const RockBlock_COM_PORT = ComC1      'Serial com port
    Const RockBlock_SBDIX_retry = 10      'Number of retries to connect to sattelites (~20 sec/retry)
    Const RockBlock_SW_power = false      'SW12_1, SW12_2 or false (12V)
    Const RockBlock_outbox_size = 1000    'Number of messages in outbox table
    Const RockBlock_inbox_size = 100      'Number of messages in inbox table
EndConstTable 'Station_Constants

Public run_code As Boolean 'set flag true to run RockBlock code

#If RockBlock9603 OR RockBlockPlus
  Include "CPU:RockBlock.CR6" 'Include RockBlock variables, tables and functions

'Main Program
  #If RockBlock9603 Then
    SerialOpen (RockBlock_COM_PORT,19200,16,0,400,2) 'IRIDIUM 9603, LVTTL

  #If RockBlockPlus Then
    SerialOpen (RockBlock_COM_PORT,19200,16,0,400,0) 'RockBlock+, RS-232

  Scan (SCAN_INTERVAL,Sec,5,0)

    #If RockBlock9603 OR RockBlockPlus
      RockBlock_message_out = "Hello World " + Status.TimeStamp(4,1) 'Create a uniqe test message
      If run_code Then 
        RockBlock_begin()  'Power on, Check serial comunication and turn off flow control
        RockBlock_SendASCII(RockBlock_message_out)  'Send data to outbox
        RockBlock_status() 'Check status
        If SBDS_MOFlag = 1 Then 'Check if data is ready to be sent
          If RockBlock_SBDsession() 'Initiate SBD Session, send and check for incoming messages
            RockBlock_clrMObuffer() 'Clear MO buffer after massage is sent
            Do While SBDIX_MT_status = 1 'Message in inbox
              RockBlock_recive() 'Recive message from inbox
              If SBDIX_MT_queued > 0 'Message in que
                RockBlock_SBDsession() 'Check for next massage
                ExitDo 'No massages left in que
        RockBlock_stop() 'Turn off power, and clear MO buffer
        run_code = false



 Include-file must be named RockBlock.CR6 and uploaded to logger.

'Filename: RockBlock.CR6
'Include-file with RockBlock variables, tables and functions
'(c)2020 john.hulth@geo.uio.no and alberto.dallolio@ntnu.no

'Declare Private Variables----------------------------
Dim serialInput As String * 400
Const CRLF = CHR(13) + CHR(10)

Public RockBlock_message_out As String * 340 'message to send
Public RockBlock_message_in As String * 270 'message recieved

Dim SBDSArray(4) As String

Dim SBDIXArray(6) As String
Public SBDIX_MO_status, SBDIX_MOMSN, SBDIX_MT_status, SBDIX_MTMSN, SBDIX_MT_length, SBDIX_MT_queued

Public RockBlock_ID As String * 50
Public RockBlock_IMEI As String
Public RockBlock_firmvare(7) As String * 50
Public RockBlock_signal

'Define Data Tables---------------------------------
DataTable (RockBlock_outbox,1,RockBlock_outbox_size)
  Sample 1,RockBlock_message_out,String
  Sample 1,SBDIX_MOMSN,String

DataTable (RockBlock_inbox,1,RockBlock_inbox_size)
  Sample 1,RockBlock_message_in,String
  Sample 1,SBDIX_MTMSN,String

'Define functions------------------------------------
'Send to serial and read respons
Function Send_ATcommand(AT_cmd As String)
  SerialOut(RockBlock_COM_PORT, AT_cmd + CRLF, CRLF, 3, 20)
  SerialIn(serialInput, RockBlock_COM_PORT, 20, -1, 400)

'Check that the respons end with OK
Function Serial_OK(serialInput As String * 400) As Boolean
  If InStr (1,serialInput,"OK",2) > 0 Then
    Return true
    Return false

'Power up, check serial comunication and turn off flow control
Function RockBlock_begin() As Boolean
  #If RockBlock_SW_power = SW12_1 OR RockBlock_SW_power = SW12_2
    SW12 (RockBlock_power, 1)
    Delay (1,20,Sec)
    Delay (1,1,Sec)
  Send_ATcommand("AT") 'Check serial comunication
  Send_ATcommand("AT&K0") 'turn off flow control
  Return Serial_OK(serialInput)

'Turn off power, and clear SBD buffers
Function RockBlock_stop() As Boolean
  Send_ATcommand("AT+SBDD2") 'Clear SBD buffers
  RockBlock_message_out = "" 'clear
  #If RockBlock_SW_power = SW12_1 OR RockBlock_SW_power = SW12_2
    Send_ATcommand("AT*F") 'flush pending writes to Eeprom (must re-power to start serial communication)
    Delay (1,1,Sec)
    SW12 (RockBlock_SW_power,0)
  Return Serial_OK(serialInput)

'Clear MO buffer
Function RockBlock_clrMObuffer() As Boolean
  Send_ATcommand("AT+SBDD0") 'Clear MO buffer
  RockBlock_message_out = "" 'clear
  Return Serial_OK(serialInput)

'Send ASCII data
Function RockBlock_SendASCII(RockBlock_message_out As String * 340) As Boolean
  Send_ATcommand("AT+SBDWT") 'Send data
  If InStr (1,serialInput,"READY",2) > 0 Then
    SerialOut(RockBlock_COM_PORT, RockBlock_message_out + CRLF, CRLF, 3, 20)
  SerialIn(serialInput, RockBlock_COM_PORT, 20, -1, 400)
  Return Serial_OK(serialInput)

'Check SBD status
Function RockBlock_status() As Boolean
  Send_ATcommand("AT+SBDS") 'MT buffer status
  SplitStr(SBDSArray(), serialInput, "", 4, 10) 'Parse message
  SBDS_MOFlag = SBDSArray(1) '0) No MO message waiting; 1) MO message in buffer
  SBDS_MOMSN = SBDSArray(2)  'MO Sequence Number
  SBDS_MTFlag = SBDSArray(3) '0) No TO message waiting; 1) MT message in buffer
  SBDS_MTMSN = SBDSArray(4)  'MT Sequence Number
  Return Serial_OK(serialInput)

'Initiate SBD session
Function RockBlock_SBDsession() As Boolean
  Dim i
  For i = 1 To RockBlock_SBDIX_retry
    SerialOut(RockBlock_COM_PORT, "AT+SBDIX" + CRLF, CRLF, 3, 20) 
    Delay (1,20,Sec) 'Needs delay to wait for satellite connection
    SerialIn(serialInput, RockBlock_COM_PORT, 20, -1, 400)
    SplitStr(SBDIXArray(), serialInput, "", 6, 10)'Parse message
    SBDIX_MO_status = SBDIXArray(1) '0-2) Message sent; 5-65) Error
    SBDIX_MOMSN = SBDIXArray(2)     'MO Sequence Number
    SBDIX_MT_status = SBDIXArray(3) '0) Nothing to receive; 1) Message received; 2) Error
    SBDIX_MTMSN = SBDIXArray(4)     'MT Sequence Number
    SBDIX_MT_length = SBDIXArray(5) 'Length of MT message
    SBDIX_MT_queued = SBDIXArray(6) 'MT messages in que
    If SBDIX_MO_status < 5 Then ExitFor 'Exit for-loop if connection is established
  Next i
  If Serial_OK(serialInput) AND SBDIX_MO_status < 5 Then
    If Len(RockBlock_message_out) > 0
      CallTable RockBlock_outbox 'store message in outbox table
    Return true
    Return false

'Recive data
Function RockBlock_recive() As Boolean
  Send_ATcommand("AT+SBDRT") 'Recive data
  RockBlock_message_in = Mid (serialInput,12,SBDIX_MT_length)
  If Serial_OK(serialInput) Then
    CallTable RockBlock_inbox 'store message in inbox table
    Return true
    Return false

'Get model number
Function RockBlock_GetID() As Boolean
  SplitStr (RockBlock_ID,serialInput, CRLF, 1, 6)
  Return Serial_OK(serialInput)

'Get Firmware Version
Function RockBlock_firmvareVersion() As Boolean
  SplitStr(RockBlock_firmvare(), serialInput, CRLF, 7, 6)
  Return Serial_OK(serialInput)
End Function

Function RockBlock_GetIMEI() As Boolean
  SplitStr (RockBlock_IMEI,serialInput, CRLF, 1, 6)
  Return Serial_OK(serialInput)

'Get signal quality
Function RockBlock_SignalQuality() As Boolean
  SplitStr (RockBlock_signal,serialInput, "", 1, 10)
  Return Serial_OK(serialInput)
End Function

Log in or register to post/reply in the forum.