Hi, is anyone using RockBlock+ with Campbell dataloggers. If so, would you mind sharing an example program?
https://www.rock7.com/products/rockblock-plus-enclosed-waterproof-satellite-tracking
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)
GOESField(4,1,5,5,"")
Sample(1, SimStage, IEEE4)
EndTable
BeginProg
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
EndIf
NextScan
EndProg
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
BeginProg
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.
PortSet(C1,RadioOn)
If GetSystemInfo Then
'CGMI,CGMM,CGMR,CGSN
'Manufacturer, Model,Revision,Serial Number
SerialFlush (IridiumPort)
SerialOut(IridiumPort,"AT+CGMI" & CHR(13) & CHR(10),CHR(13) & CHR(10),1,200)
SerialIn(RadioManufacturer,IridiumPort,100,CHR(13),100)
SerialOut(IridiumPort,"AT+CGMM" & CHR(13) & CHR(10),CHR(13) & CHR(10),1,200)
SerialIn(RadioModel,IridiumPort,100,CHR(13),100)
SerialOut(IridiumPort,"AT+CGMR" & CHR(13) & CHR(10),"Call ",1,200)
SerialIn(RadioRevision,IridiumPort,100,0,100)
SerialOut(IridiumPort,"AT+CGSN" & CHR(13) & CHR(10),"AT+CGSN" & CHR(13) & CHR(10),1,200)
SerialIn(RadioSerialNumber,IridiumPort,100,CHR(13),100)
GetSystemInfo = False
EndIf
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)
SerialOut(IridiumPort,MsgStringMO,"OK",1,200)
LoadMO = False
EndIf
If SendMO Then
'Instruct radio to Transmit MO buffer up to satellite
' ["AT+SBDI" & CRLF]
SerialFlush(IridiumPort)
SerialOut(IridiumPort,"AT+SBDI" & CHR(13) & CHR(10),"+SBDI: ",1,3000)
SendMO = False
CheckMOResult = True
EndIf
If CheckMOResult Then
MOResult = "Checking for MO Send Result..."
SerialIn(SendMOResult,IridiumPort,100,0,100)
SplitStr (SBD_TxResult,SendMOResult,",",1,0)
If SBD_TxResult <> 1 Then
MOResult = "Warning -- Unexpected Send Result: " & SBD_TxResult 'Delay(1,5,sec)
Else
MOResult = "Successful Send of MO Buffer to Iridium Network: " & SBD_TxResult
End If
CheckMOResult = False
End If
If MailboxCheck Then
'[+SBDI]
MailboxCheck = False
EndIf
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)
SerialIn(PushMOResult,IridiumPort,100,0,100)
PushMOIntoMT = False
EndIf
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,MsgStringMO,"OK",1,200)
SerialFlush(IridiumPort)
SerialOut(IridiumPort,"AT+SBDIX" & CHR(13) & CHR(10),"+SBDIX: ",1,5000)
SerialIn(PullDownResult,IridiumPort,100,0,100)
SplitStr(SBD_RxResult(),PullDownResult,",",5,0)
PullDownMT = False
EndIf
If RetrieveMT Then
'Receive message from radio MT buffer (Incoming, MT=Mobile Terminated)
'[+SBDRT] RT=Retrieve Text
SerialFlush(IridiumPort)
SerialOut(IridiumPort,"AT+SBDRT" & CHR(13) & CHR(10),"+SBDRT" & CHR(13),1,300)
SerialIn(MsgStringMT,IridiumPort,200,23,64)
RetrieveMT = False
EndIf
If CheckRadioSignal Then
' [CSQ] Check Signal Quality
SS_RxResult = 0 'IridiumSS_timeout = Timer (2,Sec,0 )
CheckRadioResult = "Checking Signal Strength on radio/modem..."
SerialFlush(IridiumPort)
SerialOut(IridiumPort,"AT+CSQ" & CHR(13) & CHR(10),"",1,0)
SerialIn(CheckRadioResult,IridiumPort,1100,"OK",100)
SplitStr(SS_RxResult,CheckRadioResult,"",1,0)
CheckRadioSignal = False
EndIf
NextScan
EndProg
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.
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
'https://www.rock7.com/products/rockblock-plus-enclosed-waterproof-satellite-tracking
'https://www.rock7.com/products/rockblock-9603-compact-plug-play-satellite-transmitter
'https://www.rock7.com/downloads/RockBLOCK-Developer-Guide-Mk2.pdf
'https://www.rock7.com/downloads/ATC_Iridium_ISU_AT_Command_Reference_MAN0009_v5.pdf
'(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
#EndIf
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
#EndIf
'Main Program
BeginProg
#If RockBlock9603 Then
SerialOpen (RockBlock_COM_PORT,19200,16,0,400,2) 'IRIDIUM 9603, LVTTL
#EndIf
#If RockBlockPlus Then
SerialOpen (RockBlock_COM_PORT,19200,16,0,400,0) 'RockBlock+, RS-232
#EndIf
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_GetID()
RockBlock_firmvareVersion()
RockBlock_GetIMEI()
RockBlock_SignalQuality()
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
Else
ExitDo 'No massages left in que
EndIf
Loop
EndIf
EndIf
RockBlock_stop() 'Turn off power, and clear MO buffer
run_code = false
EndIf
#EndIf
NextScan
EndProg
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
Public SBDS_MOFlag, SBDS_MOMSN, SBDS_MTFlag, SBDS_MTMSN
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)
DataTime(1)
Sample 1,RockBlock_message_out,String
Sample 1,SBDIX_MOMSN,String
EndTable
DataTable (RockBlock_inbox,1,RockBlock_inbox_size)
DataTime(1)
Sample 1,RockBlock_message_in,String
Sample 1,SBDIX_MTMSN,String
EndTable
'Define functions------------------------------------
'Send to serial and read respons
Function Send_ATcommand(AT_cmd As String)
SerialFlush(RockBlock_COM_PORT)
SerialOut(RockBlock_COM_PORT, AT_cmd + CRLF, CRLF, 3, 20)
SerialIn(serialInput, RockBlock_COM_PORT, 20, -1, 400)
EndFunction
'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
Else
Return false
EndIf
EndFunction
'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)
#Else
Delay (1,1,Sec)
#EndIf
Send_ATcommand("AT") 'Check serial comunication
Send_ATcommand("AT&K0") 'turn off flow control
Return Serial_OK(serialInput)
EndFunction
'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)
#EndIf
Return Serial_OK(serialInput)
EndFunction
'Clear MO buffer
Function RockBlock_clrMObuffer() As Boolean
Send_ATcommand("AT+SBDD0") 'Clear MO buffer
RockBlock_message_out = "" 'clear
Return Serial_OK(serialInput)
EndFunction
'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)
EndIf
SerialIn(serialInput, RockBlock_COM_PORT, 20, -1, 400)
Return Serial_OK(serialInput)
EndFunction
'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)
EndFunction
'Initiate SBD session
Function RockBlock_SBDsession() As Boolean
Dim i
For i = 1 To RockBlock_SBDIX_retry
SerialFlush(RockBlock_COM_PORT)
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
EndIf
Return true
Else
Return false
EndIf
EndFunction
'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
Else
Return false
EndIf
EndFunction
'Get model number
Function RockBlock_GetID() As Boolean
Send_ATcommand("AT+CGMM")
SplitStr (RockBlock_ID,serialInput, CRLF, 1, 6)
Return Serial_OK(serialInput)
EndFunction
'Get Firmware Version
Function RockBlock_firmvareVersion() As Boolean
Send_ATcommand("AT+CGMR")
SplitStr(RockBlock_firmvare(), serialInput, CRLF, 7, 6)
Return Serial_OK(serialInput)
End Function
'Get IMEI
Function RockBlock_GetIMEI() As Boolean
Send_ATcommand("AT+CGSN")
SplitStr (RockBlock_IMEI,serialInput, CRLF, 1, 6)
Return Serial_OK(serialInput)
EndFunction
'Get signal quality
Function RockBlock_SignalQuality() As Boolean
Send_ATcommand("AT+CSQF")
SplitStr (RockBlock_signal,serialInput, "", 1, 10)
Return Serial_OK(serialInput)
End Function