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