├── .github └── workflows │ └── add_issue_to_project.yml ├── .travis.yml ├── LICENSE.md ├── README.md ├── documentation └── README.md ├── examples ├── I2C_Examples__Qwiic_Iridium │ ├── Example10_LoopBack │ │ └── Example10_LoopBack.ino │ ├── Example11_LowPower │ │ └── Example11_LowPower.ino │ ├── Example12_ProductionTestPart2 │ │ └── Example12_ProductionTestPart2.ino │ ├── Example1_GetIMEI │ │ └── Example1_GetIMEI.ino │ ├── Example2_CheckCSQ │ │ └── Example2_CheckCSQ.ino │ ├── Example3_GetTime │ │ └── Example3_GetTime.ino │ ├── Example4_BasicSend │ │ └── Example4_BasicSend.ino │ ├── Example5_Sleep │ │ └── Example5_Sleep.ino │ ├── Example6_SendReceive │ │ └── Example6_SendReceive.ino │ ├── Example7_Ring │ │ └── Example7_Ring.ino │ ├── Example8_Beacon │ │ └── Example8_Beacon.ino │ └── Example9_PassThru │ │ └── Example9_PassThru.ino ├── README.md └── Serial_Examples__RockBLOCK │ ├── Example10_LoopBack │ └── Example10_LoopBack.ino │ ├── Example1_GetIMEI │ └── Example1_GetIMEI.ino │ ├── Example2_CheckCSQ │ └── Example2_CheckCSQ.ino │ ├── Example3_GetTime │ └── Example3_GetTime.ino │ ├── Example4_BasicSend │ └── Example4_BasicSend.ino │ ├── Example5_Sleep │ └── Example5_Sleep.ino │ ├── Example6_SendReceive │ └── Example6_SendReceive.ino │ ├── Example7_Ring │ └── Example7_Ring.ino │ ├── Example8_Beacon │ └── Example8_Beacon.ino │ └── Example9_PassThru │ └── Example9_PassThru.ino ├── keywords.txt ├── library.properties └── src ├── IridiumSBD.cpp └── IridiumSBD.h /.github/workflows/add_issue_to_project.yml: -------------------------------------------------------------------------------- 1 | name: Add new issue to our main project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@main 14 | with: 15 | # You can target a project in a different organization 16 | # to the issue 17 | project-url: https://github.com/orgs/sparkfun/projects/19 18 | github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }} 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | before_install: 3 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" 4 | - sleep 3 5 | - export DISPLAY=:1.0 6 | - wget http://downloads.arduino.cc/arduino-1.8.9-linux64.tar.xz 7 | - tar xf arduino-1.8.9-linux64.tar.xz 8 | - sudo mv arduino-1.8.9 /usr/local/share/arduino 9 | - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino 10 | 11 | # Arduino IDE adds a lot of noise caused by network traffic, trying to firewall it off 12 | - sudo iptables -P INPUT DROP 13 | - sudo iptables -P FORWARD DROP 14 | - sudo iptables -P OUTPUT ACCEPT 15 | - sudo iptables -A INPUT -i lo -j ACCEPT 16 | - sudo iptables -A OUTPUT -o lo -j ACCEPT 17 | - sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 18 | 19 | install: 20 | - ln -s $PWD /usr/local/share/arduino/libraries/SparkFun_Qwiic_Button_Arduino_Library 21 | - arduino --install-boards arduino:samd 22 | - arduino --pref "boardsmanager.additional.urls=https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json,https://adafruit.github.io/arduino-board-index/package_adafruit_index.json" --save-prefs 23 | - arduino --install-boards SparkFun:samd 24 | - arduino --install-boards SparkFun:apollo3 25 | - arduino --install-boards SparkFun:avr 26 | - arduino --install-boards adafruit:avr 27 | 28 | 29 | script: 30 | # compile for SparkFun RedBoard 31 | - echo Compiling for SparkFun RedBoard... 32 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example1_GetIMEI/Example1_GetIMEI.ino 33 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example2_CheckCSQ/Example2_CheckCSQ.ino 34 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example3_GetTime/Example3_GetTime.ino 35 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example4_BasicSend/Example4_BasicSend.ino 36 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example5_Sleep/Example5_Sleep.ino 37 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example6_SendReceive/Example6_SendReceive.ino 38 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example7_Ring/Example7_Ring.ino 39 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example8_Beacon/Example8_Beacon.ino 40 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example9_PassThru/Example9_PassThru.ino 41 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example10_LoopBack/Example10_LoopBack.ino 42 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example11_LowPower/Example11_LowPower.ino 43 | 44 | # compile for SparkFun Artemis 45 | - echo Compiling for SparkFun Artemis... 46 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example1_GetIMEI/Example1_GetIMEI.ino 47 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example2_CheckCSQ/Example2_CheckCSQ.ino 48 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example3_GetTime/Example3_GetTime.ino 49 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example4_BasicSend/Example4_BasicSend.ino 50 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example5_Sleep/Example5_Sleep.ino 51 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example6_SendReceive/Example6_SendReceive.ino 52 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example7_Ring/Example7_Ring.ino 53 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example8_Beacon/Example8_Beacon.ino 54 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example9_PassThru/Example9_PassThru.ino 55 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example10_LoopBack/Example10_LoopBack.ino 56 | - arduino --verify --board SparkFun:apollo3:amap3redboard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example11_LowPower/Example11_LowPower.ino 57 | 58 | # compile for SparkFun SAMD 59 | - echo Compiling for SparkFun SAMD... 60 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example1_GetIMEI/Example1_GetIMEI.ino 61 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example2_CheckCSQ/Example2_CheckCSQ.ino 62 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example3_GetTime/Example3_GetTime.ino 63 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example4_BasicSend/Example4_BasicSend.ino 64 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example5_Sleep/Example5_Sleep.ino 65 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example6_SendReceive/Example6_SendReceive.ino 66 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example7_Ring/Example7_Ring.ino 67 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example8_Beacon/Example8_Beacon.ino 68 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example9_PassThru/Example9_PassThru.ino 69 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example10_LoopBack/Example10_LoopBack.ino 70 | - arduino --verify --board SparkFun:samd:samd51_thing_plus $PWD/examples/I2C_Examples__Qwiic_Iridium/Example11_LowPower/Example11_LowPower.ino 71 | 72 | # compile for Adafruit Trinket 5 73 | - echo Compiling for Adafruit ProTrinket 5... 74 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example1_GetIMEI/Example1_GetIMEI.ino 75 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example2_CheckCSQ/Example2_CheckCSQ.ino 76 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example3_GetTime/Example3_GetTime.ino 77 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example4_BasicSend/Example4_BasicSend.ino 78 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example5_Sleep/Example5_Sleep.ino 79 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example6_SendReceive/Example6_SendReceive.ino 80 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example7_Ring/Example7_Ring.ino 81 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example8_Beacon/Example8_Beacon.ino 82 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example9_PassThru/Example9_PassThru.ino 83 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example10_LoopBack/Example10_LoopBack.ino 84 | - arduino --verify --board adafruit:avr:protrinket5 $PWD/examples/I2C_Examples__Qwiic_Iridium/Example11_LowPower/Example11_LowPower.ino 85 | 86 | # compile for Teensy 36 87 | - echo Compiling for SparkFun RedBoard... 88 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example1_GetIMEI/Example1_GetIMEI.ino 89 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example2_CheckCSQ/Example2_CheckCSQ.ino 90 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example3_GetTime/Example3_GetTime.ino 91 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example4_BasicSend/Example4_BasicSend.ino 92 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example5_Sleep/Example5_Sleep.ino 93 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example6_SendReceive/Example6_SendReceive.ino 94 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example7_Ring/Example7_Ring.ino 95 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example8_Beacon/Example8_Beacon.ino 96 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example9_PassThru/Example9_PassThru.ino 97 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example10_LoopBack/Example10_LoopBack.ino 98 | - arduino --verify --board SparkFun:avr:RedBoard $PWD/examples/I2C_Examples__Qwiic_Iridium/Example11_LowPower/Example11_LowPower.ino -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SparkFun IridiumSBD I2C Arduino Library 2 | 3 | - This library can be installed through the Arduino Library Manager: please search for **IridiumSBDi2c** 4 | 5 | - _Iridium SBD_ is Mikal's original library which does not (currently) support I2C. 6 | 7 | The Iridium 9602 and 9603N are fascinating communications modules that give devices like Arduino or Raspberry Pi™ access to the Iridium satellite network. 8 | This is a big deal, because it means that your application can now easily and inexpensively communicate from any point on or above the globe, 9 | from the heart of the Amazon to the Siberian tundra, from the Arctic to the Antarctic. 10 | This library, **IridiumSBD**, uses Iridium's **SBD** ("Short Burst Data") protocol to send and receive short messages to/from the Iridium hub. 11 | 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). 12 | 13 | Breakout boards for the 9602 and 9603N are available in different formats. Most of these breakouts use serial (UART) interfacing but **I2C (Qwiic)** is possible too and this version of 14 | the library supports both. 15 | 16 | Grateful thanks go to: 17 | 18 | - [Mikal Hart](https://github.com/mikalhart) for writing the original versions of **IridiumSBD** and for **TinyGPSPlus** 19 | 20 | ## Repository Contents 21 | 22 | - **/documentation** - Full documentation for the library (.md). 23 | - **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. They demonstrate how to use both serial and I2C interfaces. 24 | - **/src** - Source files for the library (.cpp, .h). 25 | - **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 26 | - **library.properties** - General library properties for the Arduino package manager. 27 | 28 | ## Documentation 29 | 30 | You can find documentation for the library in the [documentation folder](documentation) 31 | 32 | ## Products That Use This Library 33 | 34 | - [WRL-13745](https://www.sparkfun.com/products/13745) - The original Rock7 RockBLOCK, available from your friends at SparkFun. 35 | - [WRL-14498](https://www.sparkfun.com/products/14498) - The Rock7 RockBLOCK 9603, available from your friends at SparkFun. 36 | - [SPX-16394](https://www.sparkfun.com/products/16394) - Qwiic Iridium 9603N: provides I2C support instead of serial, allowing you to add Iridium SBD communication to any Qwiic or I2C project. 37 | - [SPX-16469](https://www.sparkfun.com/products/16469) - Artemis Global Tracker: combining the Iridium 9603N, u-blox ZOE-M8Q and TE MS8607 into a single compact tracker. 38 | 39 | ## History 40 | 41 | [Versions 1 and 2](https://github.com/mikalhart/IridiumSBD) of this library were written by Mikal Hart with generous support from [Rock 7 Mobile](http://rock7mobile.com). 42 | 43 | This version is based on Version 2.0 of IridiumSBD but has been modified to provide I2C support for the Qwiic Iridium 9603N. Serial will still work too of course. 44 | New [examples](examples) demonstrate how to use the I2C interface. The serial examples have also been restructured and enhanced. 45 | 46 | This version of the library contains a new function called _clearBuffers_ which can be used to clear the Mobile Originated or Mobile Terminated message buffers. 47 | This allows you to overcome the 'feature' (bug?) where the 9603N will automatically re-transmit the last MO message when checking for new MT messages. 48 | This closes Issues [#10](https://github.com/mikalhart/IridiumSBD/issues/10) and [#11](https://github.com/mikalhart/IridiumSBD/issues/11) in Mikal's repo. 49 | 50 | - _clearBuffers(ISBD_CLEAR_MO)_ will clear the MO buffer (default) 51 | - _clearBuffers(ISBD_CLEAR_MT)_ will clear the MT buffer 52 | - _clearBuffers(ISBD_CLEAR_BOTH)_ will clear both buffers 53 | 54 | The library also includes Pull Requests [#14 Get IMEI](https://github.com/mikalhart/IridiumSBD/pull/14) and [#21 header import guards](https://github.com/mikalhart/IridiumSBD/pull/21). 55 | There are new serial and I2C examples for _getIMEI_. 56 | 57 | Also included is a correction for Issue [#12 weak diagnostics](https://github.com/mikalhart/IridiumSBD/issues/12). 58 | 59 | Also includes a fix to let the serial Ring example work properly. 60 | 61 | ## License 62 | 63 | Like versions 1 and 2 of Mikal's library, this version is also distributed under a 64 | [GNU Lesser General Public Licence v2.1](LICENSE.md). 65 | -------------------------------------------------------------------------------- /documentation/README.md: -------------------------------------------------------------------------------- 1 | # IridiumSBD Arduino Library: Documentation 2 | 3 | Gratefully adapted from [Mikal Hart's documentation](https://github.com/mikalhart/IridiumSBD/tree/master/extras) for version 2.0 of the library. 4 | 5 | ## Overview 6 | 7 | The Iridium 9602 and 9603N are fascinating communications modules that give devices like Arduino or Raspberry Pi™ access to the Iridium satellite network. 8 | This is a big deal, because it means that your application can now easily and inexpensively communicate from any point on or above the globe, 9 | from the heart of the Amazon to the Siberian tundra, from the Arctic to the Antarctic. 10 | This library, **IridiumSBD**, uses Iridium's **SBD** ("Short Burst Data") protocol to send and receive short messages to/from the Iridium hub. 11 | 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). 12 | 13 | Breakout boards for the 9602 and 9603N are available in different formats. Most of these breakouts use serial (UART) interfacing but I2C is possible too and this version of 14 | the library supports both. A full set of [examples](../examples) demonstrate how to use both interfaces. 15 | 16 | ## Serial "3-wire" Interfacing 17 | 18 | Rock 7 have made interfacing the RockBLOCK to the Arduino quite simple. Each RockBLOCK conveniently exposes many signal lines for the client device, but it's actually 19 | only necessary to connect 4 or 5 of these to get your application up and running. In our configuration we ignore the flow control lines and talk to the RockBLOCK over what 20 | Iridium calls a "3-wire" TTL serial interface. In the wiring table below, we assume that the RockBLOCK is being powered from the Arduino 5V power bus. 21 | 22 | | RockBLOCK Connection | Arduino Connection | 23 | | --- | --- | 24 | | +5V (Power) | +5V (Power) | 25 | | GND | GND | 26 | | TX | TX Serial Pin | 27 | | RX | RX Serial Pin | 28 | | SLEEP (optional) | GPIO pin | 29 | | RING (optional) | GPIO pin | 30 | 31 | 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 32 | TTL-level serial (default 19200 baud), so you can either connect it directly to a built-in UART or create a "soft" serial on any two suitable pins. We usually opt for the 33 | latter on smaller devices like Uno to free up the UART(s) for diagnostic and other console communications. 34 | 35 | The active low SLEEP wire may be pulled high (indicating that the device is perpetually awake), but it's a good power saving technique to connect it to a general-purpose pin, 36 | allowing the library to put the RockBLOCK into a low power "sleep" state when its services are not needed. The RING line is used to alert the client that a message is available. 37 | 38 | ## I2C Interfacing 39 | 40 | Connections to the Qwiic Iridium are made via SparkFun's standard 4-pin Qwiic connector. The four pins are: 41 | 42 | | Pin | Signal | Usual Wire Color | 43 | | --- | --- | --- | 44 | | 1 | GND / 0V | Black | 45 | | 2 | **3.3V** Power | Red | 46 | | 3 | I2C Data SDA | Blue | 47 | | 4 | I2C Clock SCL | Yellow | 48 | 49 | The Qwiic Iridium has a default I2C address of 0x63; all I2C communication is done transparently through the library. 50 | If the I2C address has been changed, you can use the new value when calling the constructor. 51 | 52 | Access to the 9603N's Ring Indicator and Network Available pins is also done through the library. 53 | 54 | ## Non-blocking Retry Strategy 55 | 56 | 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 57 | 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 58 | satellites are not always overhead. In these cases, the library initiates a behind-the-scenes series of retries, waiting for satellites to appear. 59 | 60 | With a clear sky, transmissions eventually almost always succeed, but the entire process may take up to several minutes. Since most microcontroller applications cannot tolerate 61 | blocking delays of this length, **IridiumSBD** provides a callback mechanism to ensure that the Arduino can continue performing critical tasks. Specifically, if the library user 62 | provides a global C++ function with the signature 63 | 64 | ``` 65 | bool ISBDCallback(); 66 | ``` 67 | 68 | (and this is 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. 69 | In it you can take care of activities that need doing while you're waiting for the transmission to complete. As a simple example, this blinks an LED during the library operations: 70 | 71 | ``` 72 | bool ISBDCallback() 73 | { 74 | unsigned ledOn = (millis() / 1000) % 2; 75 | digitalWrite(ledPin, ledOn ? HIGH : LOW); // Blink LED every second 76 | return true; 77 | } 78 | 79 | // This transmission may take a long time, but the LED keeps blinking 80 | modem.sendSBDText("Hello, mother!"); 81 | ``` 82 | 83 | **Note:** Most IridiumSBD methods are not available from within the callback and return the error code **ISBD_REENTRANT** when called. 84 | 85 | **Note:** Your application can prematurely terminate a pending IridiumSBD operation by returning **false** from the callback. This causes the pending operation to immediately 86 | return **ISBD_CANCELLED**. 87 | 88 | ## Power Considerations 89 | 90 | The RockBLOCK module uses a "super capacitor" to supply power to the Iridium 9602/9603. As the capacitor is depleted through repeated transmission attempts, the host device's 91 | 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 device inoperative. 92 | 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 93 | battery solution. 94 | 95 | To transparently support these varying power profiles, **IridiumSBD** provides the ability to fine-tune the delay between retries. This is done by calling 96 | 97 | ``` 98 | // For USB "low current" applications 99 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 100 | ``` 101 | 102 | or 103 | 104 | ``` 105 | // For "high current" (battery-powered) applications 106 | modem.setPowerProfile(IridiumSBD::DEFAULT_POWER_PROFILE); 107 | ``` 108 | 109 | ## Construction and Startup 110 | 111 | ### Serial Interfacing 112 | 113 | To begin using the library with the serial interface, first create an **IridiumSBD** object. The **IridiumSBD** constructor binds the new object to an Arduino **Stream** (i.e. the device's 114 | serial port) and, optionally, its SLEEP and RING lines: 115 | 116 | ``` 117 | IridiumSBD(Stream &stream, int sleepPinNo = -1, int ringPinNo = -1); 118 | ``` 119 | 120 | Example startup: 121 | 122 | ``` 123 | #include 124 | #include 125 | 126 | SoftwareSerial ssIridium(18, 19); // RockBLOCK serial port on 18/19 127 | IridiumSBD modem(ssIridium, 10); // SLEEP pin on 10, RING pin not connected 128 | 129 | void setup() 130 | { 131 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 132 | modem.begin(); // Wake up the 9602 and prepare it for communications. 133 | ... 134 | ``` 135 | 136 | ### I2C Interfacing 137 | 138 | To begin using the library with the I2C interface, create an **IridiumSBD** object binding the object to Wire instead of serial: 139 | 140 | ``` 141 | IridiumSBD(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x63); 142 | ``` 143 | 144 | Example startup: 145 | 146 | ``` 147 | #include 148 | #include 149 | 150 | IridiumSBD modem(Wire); 151 | 152 | void setup() 153 | { 154 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 155 | modem.begin(); // Wake up the 9603N and prepare it for communications. 156 | ... 157 | ``` 158 | 159 | ## Data transmission 160 | 161 | The methods that make up the core of the **IridiumSBD** public interface, are, naturally, those that send and receive data. There are four such methods in **IridiumSBD**: 162 | two "send-only" functions (text and binary), and two "send-and-receive" functions (again, text and binary): 163 | 164 | ``` 165 | // Send a text message 166 | int sendSBDText(const char *message); 167 | 168 | // Send a binary message 169 | int sendSBDBinary(const uint8_t *txData, size_t txDataSize); 170 | 171 | // Send a text message and receive one (if available) 172 | int sendReceiveSBDText(const char *message, uint8_t *rxBuffer, size_t &rxBufferSize); 173 | 174 | // Send a binary message and receive one (if available) 175 | int sendReceiveSBDBinary(const uint8_t *txData, size_t txDataSize, uint8_t *rxBuffer, size_t &rxBufferSize); 176 | ``` 177 | 178 | Applications using serial and I2C interfaces make use of the same four methods, the low level communication is routed automatically to the correct interface by the library. 179 | 180 | ## Send-only and Receive-only applications 181 | 182 | Note that at the lowest-level, Iridium SBD transactions always involve the sending _and_ receiving of exactly one message (if one is available). That means that if you call 183 | the send-only variants **sendSBDText** or **sendSBDBinary** and messages happen to be waiting in your incoming (RX) message queue, the first of these is discarded and irrevocably lost. 184 | This may be perfectly acceptable for an application that doesn't care about inbound messages, but if there is some chance that you will need to process one, call **sendReceiveSBDText** 185 | or **sendReceiveSBDBinary** instead. 186 | 187 | If your application is _receive-only_, call **sendReceiveSBDText** with a **NULL** outbound message parameter. 188 | 189 | If no inbound message is available, the **sendReceive** messages indicate this by returning **ISBD_SUCCESS** and setting **rxBufferSize** to 0. 190 | 191 | ## Diagnostics 192 | 193 | **IridiumSBD** operates by maintaining a serial or I2C dialog with the Iridium 9602/3. To diagnose failures it is often useful to "spy" on this conversation. If you provide a callback function 194 | with the signature 195 | 196 | ``` 197 | void ISBDConsoleCallback(IridiumSBD *device, char c); 198 | ``` 199 | 200 | the library will call it repeatedly with data in this conversation, and your application can log it. Similarly, to inspect the run state of the library as it is working, simply provide a 201 | callback like this: 202 | 203 | ``` 204 | void ISBDDiagsCallback(IridiumSBD *device, char c); 205 | ``` 206 | 207 | These callbacks allow the host application to monitor Iridium traffic and the library's diagnostic messages. The typical usage is to simply forward both to the Arduino serial port 208 | for display in the serial monitor: 209 | 210 | ``` 211 | void ISBDConsoleCallback(IridiumSBD *device, char c) 212 | { 213 | Serial.write(c); 214 | } 215 | 216 | void ISBDDiagsCallback(IridiumSBD *device, char c) 217 | { 218 | Serial.write(c); 219 | } 220 | ``` 221 | 222 | ## Receiving Multiple Messages 223 | 224 | 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 225 | with the **getWaitingMessageCount** method. Here's an example of a loop that reads all the messages in the inbound message queue: 226 | 227 | ``` 228 | do 229 | { 230 | char rxBuffer[100]; 231 | size_t bufferSize = sizeof(rxBuffer); 232 | int status = modem.sendReceiveText(NULL, rxBuffer, bufferSize); 233 | if (status != ISBD_SUCCESS) 234 | { 235 | /* ...process error here... */ 236 | break; 237 | } 238 | if (bufferSize == 0) 239 | break; // all done! 240 | /* ...process message in rxBuffer here... */ 241 | } while (modem.getWaitingMessageCount() > 0); 242 | ``` 243 | 244 | Note that **getWaitingMessageCount** is only valid after a successful send/receive operation. 245 | 246 | ## Qwiic Iridium (I2C) Power Control 247 | 248 | Like the RockBLOCK, power for the 9603N transceiver on the Qwiic Iridium is provided by super capacitors. The correct power sequence is: 249 | - Enable the super capacitor charger 250 | - Wait for the capacitors to charge 251 | - Enable power for the 9603N 252 | - begin() the modem 253 | - Send/receive message(s) 254 | - sleep() the modem 255 | - Disable 9603N power 256 | - Disable the super capacitor charger 257 | - Place the Qwiic Iridium's ATtiny841 into low power mode (optional) 258 | 259 | The library contains a full set of methods to control the power and check the status of the Qwiic Iridium. In their most condensed form, the methods should be called as follows: 260 | 261 | ``` 262 | if (modem.isConnected()) // Check that the Qwiic Iridium is connected 263 | { 264 | modem.enableSuperCapCharger(true); // Enable the super capacitor charger 265 | while (!modem.checkSuperCapCharger()) ; // Wait for the capacitors to charge 266 | modem.enable9603Npower(true); // Enable power for the 9603N 267 | modem.begin(); // Wake up the modem 268 | modem.sendSBDText("Hello, world!"); // Send a message 269 | modem.sleep(); // Put the modem to sleep 270 | modem.enable9603Npower(false); // Disable power for the 9603N 271 | modem.enableSuperCapCharger(false); // Disable the super capacitor charger 272 | modem.enable841lowPower(true); // Enable the ATtiny841's low power mode (optional) 273 | } 274 | ``` 275 | 276 | See below for a full description of each method. 277 | 278 | ## Qwiic Iridium (I2C) Pass Thru 279 | 280 | If you want to communicate directly with the transceiver, so you can explore the AT command set manually, this is trivial when using serial. For the Qwiic Iridium, two new methods 281 | allow you to parcel up your commands, send them to the transceiver via I2C, and unparcel the replies: 282 | - **passThruI2Cread** allows you to read serial data directly from the 9603N without going through the higher level library methods. 283 | - **passThruI2Cwrite** allows you to write directly to the transceiver as if you were connected via serial. 284 | 285 | [Example 9](../examples/I2C_Examples__Qwiic_Iridium/Example9_PassThru/Example9_PassThru.ino) makes use of these methods. 286 | 287 | These methods will return a ISBD_REENTRANT error if you attempt to call them while another method is in progress. 288 | 289 | See below for a full description of each method. 290 | 291 | ## Erratum Workaround 292 | 293 | In May, 2013, Iridium identified a potential problem that could cause a satellite modem like the RockBLOCK to lock up unexpectedly. This issue only affects devices with firmware older 294 | than version TA13001: use **getFirmwareVersion()** to check yours. The library automatically employs the workaround recommended by Iridium - a successful check of the system time with 295 | AT-MSSTM before each transmission - by default for firmware that is older, but you can disable this check with: 296 | 297 | ``` 298 | modem.useMSSTMWorkaround(false); 299 | ``` 300 | 301 | ## Error return codes 302 | 303 | Many **IridiumSBD** methods return an integer error status code, with ISBD_SUCCESS (0) indicating successful completion. These include **begin**, **sendSBDText**, **sendSBDBinary**, 304 | **sendReceiveSBDText**, **sendReceiveSBDBinary**, **getSignalQuality**, and **sleep**. Here is a complete list of the possible error return codes: 305 | 306 | ``` 307 | #define ISBD_SUCCESS 0 308 | #define ISBD_ALREADY_AWAKE 1 309 | #define ISBD_SERIAL_FAILURE 2 310 | #define ISBD_PROTOCOL_ERROR 3 311 | #define ISBD_CANCELLED 4 312 | #define ISBD_NO_MODEM_DETECTED 5 313 | #define ISBD_SBDIX_FATAL_ERROR 6 314 | #define ISBD_SENDRECEIVE_TIMEOUT 7 315 | #define ISBD_RX_OVERFLOW 8 316 | #define ISBD_REENTRANT 9 317 | #define ISBD_IS_ASLEEP 10 318 | #define ISBD_NO_SLEEP_PIN 11 319 | #define ISBD_NO_NETWORK 12 320 | #define ISBD_MSG_TOO_LONG 13 321 | ``` 322 | 323 | ## IridiumSBD Interface 324 | 325 | --- 326 | ### Constructor (Serial) 327 | --- 328 | ``` 329 | IridiumSBD(Stream &stream, int sleepPinNo = -1, int ringPinNo = -1) 330 | ``` 331 | 332 | - Description: Creates an IridiumSBD library object 333 | - Returns: N/A 334 | - Parameter: **stream** - The serial port that the RockBLOCK is connected to. 335 | - Parameter: **sleepPin** - The number of the Arduino pin connected to the RockBLOCK SLEEP line. 336 | 337 | Notes: 338 | - 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. 339 | 340 | --- 341 | ### Constructor (I2C) 342 | --- 343 | ``` 344 | IridiumSBD(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x63) 345 | ``` 346 | 347 | - Description: Creates an IridiumSBD library object 348 | - Returns: N/A 349 | - Parameter: **wirePort** - The I2C (Wire) port that the Qwiic Iridium is connected to. 350 | - Parameter: **deviceAddress** - The address used by the ATtiny841 for I2C communication. 351 | 352 | Notes: 353 | - Access to the sleepPin is provided internally through the library. 354 | 355 | --- 356 | ### Startup 357 | --- 358 | ``` 359 | int begin() 360 | ``` 361 | 362 | - Description: Starts (or wakes) the RockBLOCK modem. 363 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise. 364 | - Parameter: None. 365 | 366 | Notes: 367 | - **begin()** also serves as the way to wake a RockBLOCK that is asleep. 368 | - 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. 369 | - If provided, the user's **ISBDCallback** function is repeatedly called during this operation. 370 | - This function should be called before any transmit/receive operation 371 | 372 | --- 373 | ### Data transmission 374 | --- 375 | ``` 376 | int sendSBDText(const char *message) 377 | ``` 378 | 379 | - Description: Transmits a text message to the global satellite system. 380 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise 381 | - Parameter: **message** - A 0-terminated string message. 382 | 383 | Notes: 384 | - The library calculates retries the operation for up to 300 seconds by default. (To change this value, call **adjustSendReceiveTimeout**.) 385 | - The maximum size of a transmitted packet (including header and checksum) is 340 bytes. 386 | - If there are any messages in the RX queue, the first of these is discarded when this function is called. 387 | - If provided, the user's **ISBDCallback** function is repeatedly called during this operation. 388 | 389 | --- 390 | ``` 391 | int sendSBDBinary(const uint8_t *txData, size_t txDataSize) 392 | ``` 393 | 394 | - Description: Transmits a binary message to the global satellite system. 395 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise 396 | - Parameter: **txData** - The buffer containing the binary data to be transmitted. 397 | - Parameter: **txDataSize** - The size of the buffer in bytes. 398 | 399 | Notes: 400 | - 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**.) 401 | - The maximum size of a transmitted packet (including header and checksum) is 340 bytes. 402 | - If there are any messages in the RX queue, the first of these is discarded when this function is called. 403 | - If provided, the user's **ISBDCallback** function is repeatedly called during this operation. 404 | 405 | --- 406 | ``` 407 | int sendReceiveSBDText(const char *message, uint8_t *rxBuffer, size_t &rxBufferSize) 408 | ``` 409 | 410 | - Description: Transmits a text message to the global satellite system and receives a message if one is available. 411 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise 412 | - Parameter: **message** - A 0-terminated string message. 413 | - Parameter: **rxBuffer** - The buffer to receive the inbound message. 414 | - Parameter: **rxBufferSize** - The size of the buffer in bytes. 415 | 416 | Notes: 417 | - The library calculates retries the operation for up to 300 seconds by default. (To change this value, call **adjustSendReceiveTimeout**.) 418 | - The maximum size of a transmitted packet (including header and checksum) is 340 bytes. 419 | - The maximum size of a received packet is 270 bytes. 420 | - If provided, the user's **ISBDCallback** function is repeatedly called during this operation. 421 | - 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. 422 | 423 | --- 424 | ``` 425 | int sendReceiveSBDBinary(const uint8_t *txData, size_t txDataSize, uint8_t *rxBuffer, size_t &rxBufferSize) 426 | ``` 427 | 428 | - Description: Transmits a binary message to the global satellite system and receives a message if one is available. 429 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise 430 | - Parameter: **txData** - The buffer containing the binary data to be transmitted. 431 | - Parameter: **txDataSize** - The size of the outbound buffer in bytes. 432 | - Parameter: **rxBuffer** - The buffer to receive the inbound message. 433 | - Parameter: **rxBufferSize** - The size of the buffer in bytes. 434 | 435 | Notes: 436 | - 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**.) 437 | - The maximum size of a transmitted packet (including header and checksum) is 340 bytes. 438 | - The maximum size of a received packet is 270 bytes. 439 | - If provided, the user's **ISBDCallback** function is repeatedly called during this operation. 440 | - 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. 441 | 442 | --- 443 | ### Utilities 444 | --- 445 | ``` 446 | int getSignalQuality(int &quality) 447 | ``` 448 | 449 | - Description: Queries the signal strength and visibility of satellites 450 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise 451 | - Parameter: **quality** - Return value: the strength of the signal (0=nonexistent, 5=high) 452 | 453 | Notes: 454 | - If provided, the user's **ISBDCallback** function is repeatedly called during this operation. 455 | - 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. 456 | 457 | --- 458 | ``` 459 | int getWaitingMessageCount() 460 | ``` 461 | 462 | - Description: Returns the number of waiting messages on the Iridium servers. 463 | - Returns: The number of messages waiting, or -1 if unknown. 464 | - Parameter: None. 465 | 466 | Notes: 467 | - This number is only valid if one of the send/receive methods has previously completed successfully. If not, the value returned from **getWaitingMessageCount** is -1 ("unknown"). 468 | 469 | --- 470 | ``` 471 | int getSystemTime(struct tm &tm) 472 | ``` 473 | 474 | - Description: Returns the system time from the Iridium network. 475 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise. 476 | - Parameter: **tm** - the time structure to be filled in 477 | 478 | Notes: 479 | - This method returns the Iridium network time in tm. 480 | - "tm" is a C standard library structure defined in 481 | - Note that the tm_mon field is zero-based, i.e. January is 0 482 | - This function uses AT-MSSTM, which might report "Network not found". In this case, the function returns ISBD_NO_NETWORK. 483 | 484 | --- 485 | ``` 486 | int sleep() 487 | ``` 488 | 489 | - Description: Puts the RockBLOCK into low power "sleep" mode 490 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise 491 | - Parameter: **None**. 492 | 493 | Notes: 494 | - This method gracefully shuts down the RockBLOCK and puts it into low-power standby mode by bringing the active low SLEEP line low. 495 | - Wake the device by calling **begin()**. 496 | - If provided, the user's **ISBDCallback** function is repeatedly called during this operation. 497 | 498 | --- 499 | ``` 500 | bool isAsleep() 501 | ``` 502 | 503 | - Description: indicates whether the RockBLOCK is in low-power standby mode. 504 | - Returns: **true** if the device is asleep 505 | - Parameter: **None**. 506 | 507 | --- 508 | ``` 509 | bool hasRingAsserted() 510 | ``` 511 | 512 | - Description: indicates whether the RockBLOCK's RING line has asserted 513 | - Returns: **true** if RING has asserted 514 | - Parameter: **None**. 515 | 516 | --- 517 | ``` 518 | int getFirmwareVersion(char *version, size_t bufferSize) 519 | ``` 520 | 521 | - Description: Returns a string representing the firmware revision number. 522 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise. 523 | - Parameter: **version** - the buffer to contain the version string 524 | - Parameter: **bufferSize** - the size of the buffer to be filled 525 | 526 | Notes: 527 | - This method returns the version string in the version buffer. 528 | - bufferSize should be at least 8 to contain strings like TA13001 with the 0 terminator. 529 | 530 | --- 531 | ``` 532 | void setPowerProfile(POWERPROFILE profile) 533 | ``` 534 | 535 | - Description: Defines the device power profile 536 | - Returns: **None**. 537 | - Parameter: **profile** - USB_POWER_PROFILE for low-current USB power source, DEFAULT_POWER_PROFILE for default (battery) power 538 | 539 | Notes: 540 | - This method defines the internal delays between retransmission. Low current applications may require longer delays. 541 | 542 | --- 543 | ``` 544 | void adjustATTimeout(int seconds) 545 | ``` 546 | 547 | - Description: Adjusts the internal timeout timer for serial AT commands 548 | - Returns: **None**. 549 | - Parameter: **seconds** - The maximum number of seconds to wait for a response to an AT command (default=20). 550 | 551 | Notes: 552 | - 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. 553 | - It is not expected that this method will be commonly used. 554 | 555 | --- 556 | ``` 557 | void adjustSendReceiveTimeout(int seconds) 558 | ``` 559 | 560 | - Description: Adjusts the internal timeout timer for the library send/receive commands 561 | - Returns: **None**. 562 | - Parameter: **seconds** - The maximum number of seconds to continue attempting retransmission of messages (default=300). 563 | 564 | Notes: 565 | - 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) 566 | seems to be a reasonable choice for many applications, but higher values might be more appropriate for others. 567 | 568 | --- 569 | ``` 570 | void useMSSTMWorkaround(bool useWorkaround) 571 | ``` 572 | 573 | - Description: Defines whether the library should use the technique described in the Iridium Product Advisor of 13 May 2013 to avoid possible lockout. 574 | - Returns: **None**. 575 | - 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. 576 | 577 | Notes: 578 | - 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. 579 | 580 | --- 581 | ``` 582 | void enableRingAlerts(bool enable) 583 | ``` 584 | 585 | - Description: Overrides whether the library should enable the RING alert signal pin and the unsolicited SBDRING notification. 586 | - Returns: **None**. 587 | - Parameter: **enable** - "true" if RING alerts should be enabled. 588 | 589 | Notes: 590 | - This method uses the Iridium AT+SBDMTA to enable or disable alerts. 591 | - This method take effect at the next call to **begin()**, so typically you would call this before you start your device. 592 | - RING alerts are enabled by default if the library user has specified a RING pin for the IridiumSBD constructor. Otherwise they are disabled by default. Use this method to override that as needed. 593 | 594 | --- 595 | ``` 596 | int getIMEI(char *IMEI, size_t bufferSize) 597 | ``` 598 | 599 | - Description: Returns a string representing the IMEI. 600 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise. 601 | - Parameter: **IMEI** - the buffer to contain the IMEI string. 602 | - Parameter: **bufferSize** - the size of the buffer to be filled. 603 | 604 | Notes: 605 | - This method returns the IMEI string in the IMEI buffer. 606 | - bufferSize should be at least 16 to contain the 15 digit IMEI with the 0 terminator. 607 | 608 | --- 609 | ``` 610 | int clearBuffers(int buffers = ISBD_CLEAR_MO) 611 | ``` 612 | 613 | - Description: Clears the Mobile Originated (MO), Mobile Terminated (MT) or Both message buffers. 614 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise. 615 | - Parameter: **buffers** - the buffer(s) to be cleared. 616 | 617 | Notes: 618 | - Defaults to clearing the MO buffer (**ISBD_CLEAR_MO**). 619 | - **buffers** can also be set to: **ISBD_CLEAR_MT** to clear the MT buffer; or **ISBD_CLEAR_BOTH** to clear both MO and MT buffers. 620 | 621 | --- 622 | ### Qwiic Iridium (I2C) Methods 623 | --- 624 | ``` 625 | void enableSuperCapCharger(bool enable) 626 | ``` 627 | 628 | - Description: Enables or disables the Qwiic Iridium's super capacitor charger. 629 | - Returns: None. 630 | - Parameter: **enable** - **true** will enable the charger, **false** will disable it. 631 | 632 | --- 633 | ``` 634 | bool checkSuperCapCharger() 635 | ``` 636 | 637 | - Description: Checks the status of the super capacitors. 638 | - Returns: **true** if the capacitors are charged, **false** if not. 639 | - Parameter: None. 640 | 641 | Notes: 642 | - Returns **true** when the capacitors are >= 94% charged. 643 | - If the super capacitor charger is disabled, this method will return **true** (due to the PGOOD pin being an open collector). Ensure the charger is enabled before using this method. 644 | 645 | --- 646 | ``` 647 | void enable9603Npower(bool enable) 648 | ``` 649 | 650 | - Description: Enables power for the 9603N from the super capacitors. 651 | - Returns: None. 652 | - Parameter: **enable** - **true** will enable 9603N power, **false** will disable it. 653 | 654 | Notes: 655 | - Ensure the super capacitors are charged before enabling 9603N power. Use **checkSuperCapCharger** to confirm. 656 | 657 | --- 658 | ``` 659 | void enable9603(bool enable) 660 | ``` 661 | 662 | - Description: Enables the 9603N via its SLEEP (ON/OFF) pin. 663 | - Returns: None. 664 | - Parameter: **enable** - **true** will enable the 9603N, **false** will place it in sleep mode. 665 | 666 | Notes: 667 | - The user should not need to call this function. It should probably be private. The **begin** and **sleep** methods will automatically set the pin to the correct state. 668 | 669 | --- 670 | ``` 671 | bool checkRingIndicator() 672 | ``` 673 | 674 | - Description: Checks if the Qwiic Iridium has seen a Ring Indication. 675 | - Returns: **true** if a ring indication has been seen, **false** if not. 676 | - Parameter: None. 677 | 678 | Notes: 679 | - The user should not need to call this function. It should probably be private. The **hasRingAsserted** method will automatically call **checkRingIndicator** when using I2C. 680 | - The Qwiic Iridium uses an interrupt to detect when the ring indicator signal goes low. Although the **hasRingAsserted** method will clear the flag, the flag can be cleared 681 | manually using **clearRingIndicator**. This can be useful as the flag can be re-set by a second ring indication which the user may want to ignore. 682 | 683 | --- 684 | ``` 685 | void clearRingIndicator() 686 | ``` 687 | 688 | - Description: Clears the Qwiic Iridium Ring Indicator flag. 689 | - Returns: None. 690 | - Parameter: None. 691 | 692 | Notes: 693 | - The Qwiic Iridium uses an interrupt to detect when the ring indicator signal goes low. Although the **hasRingAsserted** method will clear the flag, the flag can be cleared 694 | manually using **clearRingIndicator**. This can be useful as the flag can be re-set by a second ring indication which the user may want to ignore. 695 | 696 | --- 697 | ``` 698 | bool checkNetworkAvailable() 699 | ``` 700 | 701 | - Description: Checks the status of the 9603N's Network Available signal. 702 | - Returns: **true** if the network is available, **false** if not. 703 | - Parameter: None. 704 | 705 | Notes: 706 | - Network Available is true when the 9603N is able to receive the ring channel. It can take seconds, or sometimes up to two minutes, for NA to become true depending on the history of satellite visibility. 707 | - The send message methods will automatically re-try if the network is not available. The user does not need to call **checkNetworkAvailable** before sending a message. 708 | 709 | --- 710 | ``` 711 | void enable841lowPower(bool enable) 712 | ``` 713 | 714 | - Description: Enables the Qwiic Iridium ATtiny841's low power mode to save power. 715 | - Returns: None. 716 | - Parameter: **enable** - **true** will enable the low power mode, **false** will disable it. 717 | 718 | Notes: 719 | - The Qwiic Iridium's current draw can be reduced to approximately 1 microamp when in low power mode, if the 9603N, super capacitor charger and power LED are disabled. 720 | - The ATtiny841 will automatically wake up on I2C or serial activity or if a ring indicator interrupt is received. It is safe to leave the low power mode permanently enabled. 721 | 722 | --- 723 | ``` 724 | bool isConnected() 725 | ``` 726 | 727 | - Description: Checks if the Qwiic Iridium is connected. 728 | - Returns: **true** if the Qwiic Iridium is connected, **false** if not. 729 | - Parameter: None. 730 | 731 | Notes: 732 | - It can be useful to call this method to confirm the Qwiic Iridium is connected when starting an application. **checkSuperCapCharger** will never return **true** if the Qwiic Iridium is not connected. 733 | 734 | --- 735 | ``` 736 | int passThruI2Cwrite(uint8_t *txBuffer, size_t &txBufferSize) 737 | ``` 738 | 739 | - Description: Passes the binary data in **txBuffer** directly to the 9603N's serial pin without going through the higher level library methods. 740 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise. 741 | - Parameter: **txBuffer** - The buffer containing the binary data to be transmitted. 742 | - Parameter: **txBufferSize** - The size (length) of the _binary data_ in bytes (not the size of the buffer itself). 743 | 744 | Notes: 745 | - This method will return ISBD_REENTRANT if another method is already in progress and ISBD_SERIAL_FAILURE if the serial constructor is in use. 746 | 747 | --- 748 | ``` 749 | int passThruI2Cread(uint8_t *rxBuffer, size_t &rxBufferSize, size_t &numBytes) 750 | ``` 751 | 752 | - Description: Passes the binary data from the 9603N's serial pin directly to the user, via **rxBuffer**, without going through the higher level library methods. 753 | - Returns: ISBD_SUCCESS if successful, a non-zero code otherwise. 754 | - Parameter: **rxBuffer** - The buffer to receive the serial data from the 9603N. 755 | - Parameter: **rxBufferSize** - The size (length) of the _buffer_ in bytes. 756 | - Parameter: **numBytes** - The number of bytes returned in the buffer (>= 0, <= rxBufferSize). 757 | 758 | Notes: 759 | - This method will return ISBD_REENTRANT if another method is already in progress and ISBD_SERIAL_FAILURE if the serial constructor is in use. 760 | - The method uses the **rxBufferSize** to prevent overflowing the buffer. If the 9603N returns more serial data than the buffer can hold, a ISBD_RX_OVERFLOW error is returned. 761 | 762 | --- 763 | ### Callbacks (optional) 764 | --- 765 | ``` 766 | bool ISBDCallback() 767 | ``` 768 | 769 | - Description: An optional user-supplied callback to help provide the appearance of responsiveness during lengthy Iridium operations 770 | - Returns: **true** if the calling library operation should continue, **false** to terminate it. 771 | - Parameter: **None**. 772 | 773 | Notes: 774 | - If this function is not provided the library methods will appear to block. 775 | - This is not a library method, but an optional user-provided callback function. 776 | 777 | --- 778 | ``` 779 | void ISBDConsoleCallback(IridiumSBD *device, char c) 780 | ``` 781 | 782 | - Description: An optional user-supplied callback to sniff the conversation with the Iridium 9602/3. 783 | - Returns: **None**. 784 | - Parameter: **device** - a handle to the modem device 785 | - Parameter: **c** - a character in the conversation 786 | 787 | Notes: 788 | - Typical usage is to write c to a console for diagnostics. 789 | - This is not a library method, but an optional user-provided callback function. 790 | 791 | --- 792 | ``` 793 | void ISBDDiagsCallback(IridiumSBD *device, char c) 794 | ``` 795 | 796 | - Description: An optional user-supplied callback to monitor the library's run state. 797 | - Returns: **None**. 798 | - Parameter: **device** - a handle to the modem device 799 | - Parameter: **c** - a character in the run log 800 | 801 | Notes: 802 | - Typical usage is to write **c** to a console for diagnostics 803 | - This is not a library method, but an optional user-provided callback function. 804 | --- 805 | 806 | ## License 807 | 808 | This library is distributed under the terms of the GNU LGPL license. 809 | 810 | ## Document revision history 811 | 812 | | Version | Date | Author | Reason | 813 | | --- | --- | --- | --- | 814 | | 1.0 | 2013 | Mikal Hart | Initial draft submitted to Rock 7 for review | 815 | | 1.1 | 2014 | Mikal Hart | Added text about the AT-MSSTM erratum/workaround and changing the minimum required signal quality. Also documented related new methods **setMinimumSignalQuality** and **useMSSTMWorkaround()**. | 816 | | 2.0 | 21 October 2017 | Mikal Hart | Several API revisions. Removed **setMinimumSignalQuality** (no longer used), added support for RING monitoring (**enableRingAlerts** method, and new RING alert pin on constructor), and changed the way diagnostics are done by replacing the **attachConsole** and **attachDiags** methods with user-supplied callbacks **ISBDConsoleCallback** and **ISBDDiagsCallback**. Added getSystemTime and getFirmwareVersion utility functions. Add explanation that MSSTM workaround is no longer enabled by default if firmware is sufficiently new (TA13001 or newer). | 817 | | 3.0 | October 2019 | Paul Clark | Added I2C support for the Qwiic Iridium. Restructured the examples. Converted Mikal's documentation to markdown format. Added the feature requests (**getIMEI** and **clearBuffers**) and corrected the issues identified with version 2.0. Included a fix to let the serial Ring example work properly (**hasRingAsserted** now checks the ringPin itself instead of assuming **cancelled** will be able to do it). | 818 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example10_LoopBack/Example10_LoopBack.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Loop Back 7 | * 8 | * This sketch demonstrates how to forward a message to another RockBLOCK 9 | * via the Rock7 RockBLOCK Gateway. The message is looped back to your 10 | * RockBLOCK by prefixing the message with "RB" and the RockBLOCK serial 11 | * number of your transceiver padded out to seven digits. 12 | * 13 | * Assumptions 14 | * 15 | * The sketch assumes an Arduino Mega or other Arduino-like device with 16 | * a serial console and a hardware I2C (Wire) port. It assumes 17 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 18 | * 19 | * Open the Serial Monitor and set the Baud Rate to 115200 20 | * and the line ending to Carriage Return 21 | * 22 | * Part of the code is based on Tom Igoe's Serial Event example: 23 | * https://www.arduino.cc/en/Tutorial/SerialEvent 24 | */ 25 | 26 | #define IridiumWire Wire 27 | #define DIAGNOSTICS false // Change this to enable diagnostics 28 | 29 | // Declare the IridiumSBD object using default I2C address 30 | IridiumSBD modem(IridiumWire); 31 | 32 | String inputString = ""; // a string to hold incoming data 33 | boolean stringComplete = false; // whether the string is complete 34 | #define max_length 10 // Define maximum inputString length to avoid buffer overruns 35 | 36 | void setup() 37 | { 38 | // Start the console serial port 39 | Serial.begin(115200); 40 | while (!Serial); // Wait for the user to open the serial monitor 41 | Serial.println(F("Iridium SBD Loop Back I2C")); 42 | 43 | //empty the serial buffer 44 | while(Serial.available() > 0) Serial.read(); 45 | 46 | //wait for the user to press any key before beginning 47 | Serial.println(F("Press any key to start example.")); 48 | while(Serial.available() == 0); 49 | 50 | //clean up 51 | while(Serial.available() > 0) Serial.read(); 52 | 53 | // Start the I2C wire port connected to the satellite modem 54 | Wire.begin(); 55 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 56 | 57 | // Check that the Qwiic Iridium is attached 58 | if (!modem.isConnected()) 59 | { 60 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 61 | while(1); 62 | } 63 | 64 | // Enable the supercapacitor charger 65 | Serial.println(F("Enabling the supercapacitor charger...")); 66 | modem.enableSuperCapCharger(true); 67 | 68 | // Wait for the supercapacitor charger PGOOD signal to go high 69 | while (!modem.checkSuperCapCharger()) 70 | { 71 | Serial.println(F("Waiting for supercapacitors to charge...")); 72 | delay(1000); 73 | } 74 | Serial.println(F("Supercapacitors charged!")); 75 | 76 | // Enable 9603N power 77 | Serial.println(F("Enabling 9603N power...")); 78 | modem.enable9603Npower(true); 79 | 80 | // Begin satellite modem operation 81 | Serial.println(F("Starting modem...")); 82 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 83 | int err = modem.begin(); 84 | if (err != ISBD_SUCCESS) 85 | { 86 | Serial.print(F("Begin failed: error ")); 87 | Serial.println(err); 88 | if (err == ISBD_NO_MODEM_DETECTED) 89 | Serial.println(F("No modem detected: check wiring.")); 90 | exit(0); 91 | } 92 | 93 | inputString.reserve(max_length); // Reserve max_length bytes for the input string 94 | } 95 | 96 | /* 97 | SerialEvent occurs whenever a new data comes in the 98 | hardware serial RX. This routine is run between each 99 | time loop() runs, so using delay inside loop can delay 100 | response. Multiple bytes of data may be available. 101 | */ 102 | void serialEvent() { 103 | while (Serial.available()) { 104 | // get the new byte: 105 | char inChar = (char)Serial.read(); 106 | // check how many characters have already been received 107 | if (inputString.length() < max_length) { 108 | // we have room so add inChar to the inputString: 109 | inputString += inChar; 110 | } 111 | // if the incoming character is a carriage return, set a flag 112 | // so the main loop can do something about it: 113 | if (inChar == '\r') { 114 | stringComplete = true; 115 | } 116 | } 117 | } 118 | 119 | void loop() 120 | { 121 | // Clear the serial string and flag 122 | inputString = ""; 123 | stringComplete = false; 124 | 125 | Serial.println(F("Please enter the RockBLOCK serial number of your transceiver followed by carriage return:")); 126 | while (!stringComplete) 127 | { 128 | serialEvent(); // Check for serial event 129 | } 130 | // Process the string when a carriage return arrives: 131 | int RockBLOCK = inputString.toInt(); // Convert the serial number to int 132 | Serial.println(RockBLOCK); 133 | 134 | // Construct the message 135 | // Prefix with "RB" and the RockBLOCK serial number padded out to seven digits 136 | char outBuffer[50]; // Always try to keep message short 137 | sprintf(outBuffer, "RB%07iThis is a test message!", RockBLOCK); 138 | 139 | Serial.print(F("Transmitting message: '")); 140 | Serial.print(outBuffer); 141 | Serial.println(F("'")); 142 | 143 | int err = modem.sendSBDText(outBuffer); 144 | if (err != ISBD_SUCCESS) 145 | { 146 | Serial.print(F("Transmission failed with error code ")); 147 | Serial.println(err); 148 | } 149 | else 150 | { 151 | Serial.println(F("Message sent!")); 152 | } 153 | 154 | // Clear the MO buffer 155 | Serial.println(F("Clearing the MO buffer.")); 156 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear the MO buffer 157 | if (err != ISBD_SUCCESS) 158 | { 159 | Serial.print(F("clearBuffers failed: error ")); 160 | Serial.println(err); 161 | } 162 | 163 | Serial.println(F("Waiting for 30 seconds...")); 164 | delay(30000); 165 | 166 | // Now retrieve the loop backed message 167 | Serial.println(F("Checking if the message looped back successfully.")); 168 | 169 | uint8_t buffer[60]; 170 | size_t bufferSize = sizeof(buffer); 171 | 172 | err = modem.sendReceiveSBDText(NULL, buffer, bufferSize); 173 | 174 | if (err != ISBD_SUCCESS) 175 | { 176 | Serial.print(F("sendReceiveSBD* failed: error ")); 177 | Serial.println(err); 178 | } 179 | else // success! 180 | { 181 | Serial.print(F("Inbound buffer size is ")); 182 | Serial.println(bufferSize); 183 | if (bufferSize > 0) 184 | { 185 | Serial.print(F("The received message is: '")); 186 | for (int i=0; i // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * LowPower_I2C 7 | * 8 | * This sketch demonstrates the low power mode of the Qwiic Iridium 9603N. 9 | * 10 | * Assumptions 11 | * 12 | * The sketch assumes an Arduino Mega or other Arduino-like device with 13 | * a serial console and a hardware I2C (Wire) port. It assumes 14 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 15 | */ 16 | 17 | #define IridiumWire Wire 18 | #define DIAGNOSTICS false // Change this to enable diagnostics 19 | 20 | // Declare the IridiumSBD object using default I2C address 21 | IridiumSBD modem(IridiumWire); 22 | 23 | void setup() 24 | { 25 | // Start the console serial port 26 | Serial.begin(115200); 27 | while (!Serial); // Wait for the user to open the serial monitor 28 | Serial.println(F("Iridium SBD LowPower I2C")); 29 | 30 | //empty the serial buffer 31 | while(Serial.available() > 0) Serial.read(); 32 | 33 | //wait for the user to press any key before beginning 34 | Serial.println(F("Press any key to start example.")); 35 | while(Serial.available() == 0); 36 | 37 | //clean up 38 | while(Serial.available() > 0) Serial.read(); 39 | 40 | // Start the I2C wire port connected to the satellite modem 41 | Wire.begin(); 42 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 43 | 44 | // Check that the Qwiic Iridium is attached 45 | if (!modem.isConnected()) 46 | { 47 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 48 | while(1); 49 | } 50 | } 51 | 52 | void loop() 53 | { 54 | int signalQuality = -1; 55 | int err; 56 | 57 | // Enable the supercapacitor charger 58 | Serial.println(F("Enabling the supercapacitor charger...")); 59 | modem.enableSuperCapCharger(true); 60 | 61 | // Wait for the supercapacitor charger PGOOD signal to go high 62 | while (!modem.checkSuperCapCharger()) 63 | { 64 | Serial.println(F("Waiting for supercapacitors to charge...")); 65 | delay(1000); 66 | } 67 | Serial.println(F("Supercapacitors charged!")); 68 | 69 | // Enable power for the 9603N 70 | Serial.println(F("Enabling 9603N power...")); 71 | modem.enable9603Npower(true); 72 | 73 | // Begin satellite modem operation 74 | Serial.println(F("Starting modem...")); 75 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 76 | err = modem.begin(); 77 | if (err != ISBD_SUCCESS) 78 | { 79 | Serial.print(F("Begin failed: error ")); 80 | Serial.println(err); 81 | if (err == ISBD_NO_MODEM_DETECTED) 82 | Serial.println(F("No modem detected: check wiring.")); 83 | return; 84 | } 85 | 86 | // Example: Test the signal quality. 87 | // This returns a number between 0 and 5. 88 | // 2 or better is preferred. 89 | err = modem.getSignalQuality(signalQuality); 90 | if (err != ISBD_SUCCESS) 91 | { 92 | Serial.print(F("SignalQuality failed: error ")); 93 | Serial.println(err); 94 | return; 95 | } 96 | 97 | Serial.print(F("On a scale of 0 to 5, signal quality is currently ")); 98 | Serial.print(signalQuality); 99 | Serial.println(F(".")); 100 | 101 | // Power down the modem 102 | Serial.println(F("Putting the 9603N to sleep.")); 103 | err = modem.sleep(); 104 | if (err != ISBD_SUCCESS) 105 | { 106 | Serial.print(F("sleep failed: error ")); 107 | Serial.println(err); 108 | } 109 | 110 | // Disable 9603N power 111 | Serial.println(F("Disabling 9603N power...")); 112 | modem.enable9603Npower(false); 113 | 114 | // Disable the supercapacitor charger 115 | Serial.println(F("Disabling the supercapacitor charger...")); 116 | modem.enableSuperCapCharger(false); 117 | 118 | // Enable the ATtiny841 low power mode 119 | Serial.println(F("Enabling ATtiny841 low power mode")); 120 | modem.enable841lowPower(true); // Change this to false if you want to measure the current draw without enabling low power mode 121 | 122 | Serial.println(F("The current draw should reduce in one second from now...")); 123 | Serial.println(F("Sleeping for 30 seconds...")); 124 | 125 | delay(30000); 126 | 127 | // Disable the ATtiny841 low power mode 128 | // We don't really need to, but let's disable it anyway... 129 | // You can leave low power mode enabled and the code will work just fine. 130 | Serial.println(F("Disabling ATtiny841 low power mode")); 131 | modem.enable841lowPower(false); 132 | } 133 | 134 | #if DIAGNOSTICS 135 | void ISBDConsoleCallback(IridiumSBD *device, char c) 136 | { 137 | Serial.write(c); 138 | } 139 | 140 | void ISBDDiagsCallback(IridiumSBD *device, char c) 141 | { 142 | Serial.write(c); 143 | } 144 | #endif 145 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example12_ProductionTestPart2/Example12_ProductionTestPart2.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | #include 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Production Test Part 2 7 | * 8 | * LED_BUILTIN will flash at 0.5Hz (1sec on, 1sec off) if the test succeeds. 9 | * If the LED is off, the test is either in progress or has failed. 10 | * 11 | * This sketch demonstrates how to retrieve the Iridium system time 12 | * from the modem using the getSystemTime method. This uses 13 | * the Iridium command AT-MSSTM to acquire the time. The method will 14 | * fail if the Iridium network has not yet been acquired. 15 | * 16 | * Assumptions 17 | * 18 | * The sketch assumes the SparkFun Qwiic Iridium 9603N is connected via I2C. 19 | */ 20 | 21 | #define IridiumWire Wire 22 | #define DIAGNOSTICS false // Change this to see diagnostics 23 | 24 | // Declare the IridiumSBD object using default I2C address 25 | IridiumSBD modem(IridiumWire); 26 | 27 | // Globals to hold the current and previous satellite time 28 | struct tm old_t; // struct tm is defined in time.h 29 | struct tm new_t; // struct tm is defined in time.h 30 | time_t old_secs, new_secs; 31 | 32 | void setup() 33 | { 34 | int err; 35 | 36 | // Latest epoch began at May 11, 2014, at 14:23:55 UTC. 37 | old_t.tm_year = 2014 - 1900; 38 | old_t.tm_mon = 5 - 1; 39 | old_t.tm_mday = 11; 40 | old_t.tm_hour = 14; 41 | old_t.tm_min = 23; 42 | old_t.tm_sec = 55; 43 | old_secs = mktime(&old_t); // Convert to seconds 44 | 45 | new_t.tm_year = 2014 - 1900; 46 | new_t.tm_mon = 5 - 1; 47 | new_t.tm_mday = 11; 48 | new_t.tm_hour = 14; 49 | new_t.tm_min = 23; 50 | new_t.tm_sec = 55; 51 | new_secs = mktime(&new_t); // Convert to seconds 52 | 53 | // Start the console serial port 54 | Serial.begin(115200); 55 | //while (!Serial); // Wait for the user to open the serial monitor 56 | Serial.println(F("Qwiic Iridium 9603N - Production Test Part 2")); 57 | 58 | //empty the serial buffer 59 | while(Serial.available() > 0) Serial.read(); 60 | 61 | //wait for the user to press any key before beginning 62 | //Serial.println(F("Press any key to start example.")); 63 | //while(Serial.available() == 0); 64 | 65 | //clean up 66 | while(Serial.available() > 0) Serial.read(); 67 | 68 | // Disable the LED 69 | pinMode(LED_BUILTIN, OUTPUT); 70 | digitalWrite(LED_BUILTIN, LOW); 71 | 72 | // Start the I2C wire port connected to the satellite modem 73 | Wire.begin(); 74 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 75 | 76 | // Check that the Qwiic Iridium is attached 77 | if (!modem.isConnected()) 78 | { 79 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 80 | while(1); 81 | } 82 | 83 | // Enable the supercapacitor charger 84 | Serial.println(F("Enabling the supercapacitor charger...")); 85 | modem.enableSuperCapCharger(true); 86 | 87 | // Wait for the supercapacitor charger PGOOD signal to go high 88 | while (!modem.checkSuperCapCharger()) 89 | { 90 | Serial.println(F("Waiting for supercapacitors to charge...")); 91 | delay(1000); 92 | } 93 | Serial.println(F("Supercapacitors charged!")); 94 | 95 | // Enable power for the 9603N 96 | Serial.println(F("Enabling 9603N power...")); 97 | modem.enable9603Npower(true); 98 | 99 | // Begin satellite modem operation 100 | Serial.println(F("Starting modem...")); 101 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 102 | err = modem.begin(); 103 | if (err != ISBD_SUCCESS) 104 | { 105 | Serial.print(F("Begin failed: error ")); 106 | Serial.println(err); 107 | if (err == ISBD_NO_MODEM_DETECTED) 108 | Serial.println(F("No modem detected: check wiring.")); 109 | digitalWrite(LED_BUILTIN, LOW); // Disable the LED 110 | while(1); // Do nothing more 111 | } 112 | } 113 | 114 | void loop() 115 | { 116 | int err = modem.getSystemTime(new_t); // Ask the 9603N for the system time 117 | if (err == ISBD_SUCCESS) // Was it successful? 118 | { 119 | old_secs = mktime(&old_t); // Convert to seconds 120 | new_secs = mktime(&new_t); 121 | 122 | if (new_secs > old_secs) 123 | { 124 | digitalWrite(LED_BUILTIN, (new_secs % 2)); // Flash the LED at 0.5Hz 125 | 126 | char buf[32]; 127 | sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", 128 | new_t.tm_year + 1900, new_t.tm_mon + 1, new_t.tm_mday, new_t.tm_hour, new_t.tm_min, new_t.tm_sec); 129 | Serial.print(F("Iridium date/time is ")); 130 | Serial.println(buf); 131 | } 132 | 133 | old_t = new_t; // Update the old time 134 | } 135 | 136 | else if (err == ISBD_NO_NETWORK) // Did it fail because the 9603N has not yet seen the network? 137 | { 138 | Serial.println(F("No network detected.")); 139 | digitalWrite(LED_BUILTIN, LOW); 140 | } 141 | 142 | else 143 | { 144 | Serial.print(F("Unexpected error ")); 145 | Serial.println(err); 146 | digitalWrite(LED_BUILTIN, LOW); 147 | } 148 | 149 | // Delay 150 | delay(100UL); 151 | } 152 | 153 | #if DIAGNOSTICS 154 | void ISBDConsoleCallback(IridiumSBD *device, char c) 155 | { 156 | Serial.write(c); 157 | } 158 | 159 | void ISBDDiagsCallback(IridiumSBD *device, char c) 160 | { 161 | Serial.write(c); 162 | } 163 | #endif 164 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example1_GetIMEI/Example1_GetIMEI.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Get IMEI 7 | * 8 | * This sketch requests the satellite modem's IMEI number. 9 | * 10 | * Assumptions 11 | * 12 | * The sketch assumes an Arduino Mega or other Arduino-like device with 13 | * a serial console and a hardware I2C (Wire) port. It assumes 14 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 15 | */ 16 | 17 | #define IridiumWire Wire 18 | #define DIAGNOSTICS true // Change this to disable diagnostics 19 | 20 | // Declare the IridiumSBD object using default I2C address 21 | IridiumSBD modem(IridiumWire); 22 | 23 | void setup() 24 | { 25 | int err; 26 | 27 | // Start the console serial port 28 | Serial.begin(115200); 29 | while (!Serial); // Wait for the user to open the serial monitor 30 | Serial.println(F("Iridium SBD Get IMEI I2C")); 31 | 32 | //empty the serial buffer 33 | while(Serial.available() > 0) Serial.read(); 34 | 35 | //wait for the user to press any key before beginning 36 | Serial.println(F("Press any key to start example.")); 37 | while(Serial.available() == 0); 38 | 39 | //clean up 40 | while(Serial.available() > 0) Serial.read(); 41 | 42 | // Start the I2C wire port connected to the satellite modem 43 | Wire.begin(); 44 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 45 | 46 | // Check that the Qwiic Iridium is attached 47 | if (!modem.isConnected()) 48 | { 49 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 50 | while(1); 51 | } 52 | 53 | // Enable the supercapacitor charger 54 | Serial.println(F("Enabling the supercapacitor charger...")); 55 | modem.enableSuperCapCharger(true); 56 | 57 | // Wait for the supercapacitor charger PGOOD signal to go high 58 | while (!modem.checkSuperCapCharger()) 59 | { 60 | Serial.println(F("Waiting for supercapacitors to charge...")); 61 | delay(1000); 62 | } 63 | Serial.println(F("Supercapacitors charged!")); 64 | 65 | //empty the serial buffer 66 | while(Serial.available() > 0) Serial.read(); 67 | 68 | //wait for the user to press any key before beginning 69 | Serial.println(F("Press any key to continue.")); 70 | while(Serial.available() == 0); 71 | 72 | // Enable power for the 9603N 73 | Serial.println(F("Enabling 9603N power...")); 74 | modem.enable9603Npower(true); 75 | 76 | // Begin satellite modem operation 77 | Serial.println(F("Starting modem...")); 78 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 79 | err = modem.begin(); 80 | if (err != ISBD_SUCCESS) 81 | { 82 | Serial.print(F("Begin failed: error ")); 83 | Serial.println(err); 84 | if (err == ISBD_NO_MODEM_DETECTED) 85 | Serial.println(F("No modem detected: check wiring.")); 86 | return; 87 | } 88 | 89 | // Get the IMEI 90 | char IMEI[16]; 91 | err = modem.getIMEI(IMEI, sizeof(IMEI)); 92 | if (err != ISBD_SUCCESS) 93 | { 94 | Serial.print(F("getIMEI failed: error ")); 95 | Serial.println(err); 96 | return; 97 | } 98 | Serial.print(F("IMEI is ")); 99 | Serial.print(IMEI); 100 | Serial.println(F(".")); 101 | 102 | // Power down the modem 103 | Serial.println(F("Putting the 9603N to sleep.")); 104 | err = modem.sleep(); 105 | if (err != ISBD_SUCCESS) 106 | { 107 | Serial.print(F("sleep failed: error ")); 108 | Serial.println(err); 109 | } 110 | 111 | // Disable 9603N power 112 | Serial.println(F("Disabling 9603N power...")); 113 | modem.enable9603Npower(false); 114 | 115 | // Disable the supercapacitor charger 116 | Serial.println(F("Disabling the supercapacitor charger...")); 117 | modem.enableSuperCapCharger(false); 118 | 119 | Serial.println(F("Done!")); 120 | } 121 | 122 | void loop() 123 | { 124 | } 125 | 126 | #if DIAGNOSTICS 127 | void ISBDConsoleCallback(IridiumSBD *device, char c) 128 | { 129 | Serial.write(c); 130 | } 131 | 132 | void ISBDDiagsCallback(IridiumSBD *device, char c) 133 | { 134 | Serial.write(c); 135 | } 136 | #endif 137 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example2_CheckCSQ/Example2_CheckCSQ.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Check CSQ 7 | * 8 | * This sketch checks the Iridium signal quality and returns the status 9 | * of the Network Available signal. 10 | * 11 | * Assumptions 12 | * 13 | * The sketch assumes an Arduino Mega or other Arduino-like device with 14 | * a serial console and a hardware I2C (Wire) port. It assumes 15 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 16 | */ 17 | 18 | #define IridiumWire Wire 19 | #define DIAGNOSTICS false // Change this to enable diagnostics 20 | 21 | // Declare the IridiumSBD object using default I2C address 22 | IridiumSBD modem(IridiumWire); 23 | 24 | void setup() 25 | { 26 | int signalQuality = -1; 27 | int err; 28 | 29 | // Start the console serial port 30 | Serial.begin(115200); 31 | while (!Serial); // Wait for the user to open the serial monitor 32 | Serial.println(F("Iridium SBD Check CSQ I2C")); 33 | 34 | //empty the serial buffer 35 | while(Serial.available() > 0) Serial.read(); 36 | 37 | //wait for the user to press any key before beginning 38 | Serial.println(F("Press any key to start example.")); 39 | while(Serial.available() == 0); 40 | 41 | //clean up 42 | while(Serial.available() > 0) Serial.read(); 43 | 44 | // Start the I2C wire port connected to the satellite modem 45 | Wire.begin(); 46 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 47 | 48 | // Check that the Qwiic Iridium is attached 49 | if (!modem.isConnected()) 50 | { 51 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 52 | while(1); 53 | } 54 | 55 | // Enable the supercapacitor charger 56 | Serial.println(F("Enabling the supercapacitor charger...")); 57 | modem.enableSuperCapCharger(true); 58 | 59 | // Wait for the supercapacitor charger PGOOD signal to go high 60 | while (!modem.checkSuperCapCharger()) 61 | { 62 | Serial.println(F("Waiting for supercapacitors to charge...")); 63 | delay(1000); 64 | } 65 | Serial.println(F("Supercapacitors charged!")); 66 | 67 | // Enable power for the 9603N 68 | Serial.println(F("Enabling 9603N power...")); 69 | modem.enable9603Npower(true); 70 | 71 | // Begin satellite modem operation 72 | Serial.println(F("Starting modem...")); 73 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 74 | err = modem.begin(); 75 | if (err != ISBD_SUCCESS) 76 | { 77 | Serial.print(F("Begin failed: error ")); 78 | Serial.println(err); 79 | if (err == ISBD_NO_MODEM_DETECTED) 80 | Serial.println(F("No modem detected: check wiring.")); 81 | return; 82 | } 83 | 84 | // Print the firmware revision 85 | char version[12]; 86 | err = modem.getFirmwareVersion(version, sizeof(version)); 87 | if (err != ISBD_SUCCESS) 88 | { 89 | Serial.print(F("FirmwareVersion failed: error ")); 90 | Serial.println(err); 91 | return; 92 | } 93 | Serial.print(F("Firmware Version is ")); 94 | Serial.print(version); 95 | Serial.println(F(".")); 96 | 97 | // Get the IMEI 98 | char IMEI[16]; 99 | err = modem.getIMEI(IMEI, sizeof(IMEI)); 100 | if (err != ISBD_SUCCESS) 101 | { 102 | Serial.print(F("getIMEI failed: error ")); 103 | Serial.println(err); 104 | return; 105 | } 106 | Serial.print(F("IMEI is ")); 107 | Serial.print(IMEI); 108 | Serial.println(F(".")); 109 | 110 | // Check the signal quality. 111 | // This returns a number between 0 and 5. 112 | // 2 or better is preferred. 113 | err = modem.getSignalQuality(signalQuality); 114 | if (err != ISBD_SUCCESS) 115 | { 116 | Serial.print(F("SignalQuality failed: error ")); 117 | Serial.println(err); 118 | return; 119 | } 120 | 121 | Serial.print(F("On a scale of 0 to 5, signal quality is currently ")); 122 | Serial.print(signalQuality); 123 | Serial.println(F(".")); 124 | 125 | // Check Network Available. 126 | Serial.println(F("Checking Network Available:")); 127 | while (!modem.checkNetworkAvailable()) 128 | { 129 | Serial.println(F("Network is not available.")); 130 | Serial.println(F("(This might be because the 9603N has not yet aquired the ring channel.)")); 131 | Serial.println(F("Checking again in 10 seconds...")); 132 | delay(10000); 133 | } 134 | Serial.println(F("Network is available!")); 135 | 136 | // Power down the modem 137 | Serial.println(F("Putting the 9603N to sleep.")); 138 | err = modem.sleep(); 139 | if (err != ISBD_SUCCESS) 140 | { 141 | Serial.print(F("sleep failed: error ")); 142 | Serial.println(err); 143 | } 144 | 145 | // Disable 9603N power 146 | Serial.println(F("Disabling 9603N power...")); 147 | modem.enable9603Npower(false); 148 | 149 | // Disable the supercapacitor charger 150 | Serial.println(F("Disabling the supercapacitor charger...")); 151 | modem.enableSuperCapCharger(false); 152 | 153 | Serial.println(F("Done!")); 154 | } 155 | 156 | void loop() 157 | { 158 | } 159 | 160 | #if DIAGNOSTICS 161 | void ISBDConsoleCallback(IridiumSBD *device, char c) 162 | { 163 | Serial.write(c); 164 | } 165 | 166 | void ISBDDiagsCallback(IridiumSBD *device, char c) 167 | { 168 | Serial.write(c); 169 | } 170 | #endif 171 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example3_GetTime/Example3_GetTime.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | #include 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Time 7 | * 8 | * This sketch demonstrates how to retrieve the Iridium system time 9 | * from the modem using the getSystemTime method. This uses 10 | * the Iridium command AT-MSSTM to acquire the time. The method will 11 | * fail if the Iridium network has not yet been acquired. 12 | * 13 | * Assumptions 14 | * 15 | * The sketch assumes an Arduino Mega or other Arduino-like device with 16 | * a serial console and a hardware I2C (Wire) port. It assumes 17 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 18 | */ 19 | 20 | #define IridiumWire Wire 21 | #define DIAGNOSTICS false // Change this to see diagnostics 22 | 23 | // Declare the IridiumSBD object using default I2C address 24 | IridiumSBD modem(IridiumWire); 25 | 26 | void setup() 27 | { 28 | int err; 29 | 30 | // Start the console serial port 31 | Serial.begin(115200); 32 | while (!Serial); // Wait for the user to open the serial monitor 33 | Serial.println(F("Iridium SBD Time I2C")); 34 | 35 | //empty the serial buffer 36 | while(Serial.available() > 0) Serial.read(); 37 | 38 | //wait for the user to press any key before beginning 39 | Serial.println(F("Press any key to start example.")); 40 | while(Serial.available() == 0); 41 | 42 | //clean up 43 | while(Serial.available() > 0) Serial.read(); 44 | 45 | // Start the I2C wire port connected to the satellite modem 46 | Wire.begin(); 47 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 48 | 49 | // Check that the Qwiic Iridium is attached 50 | if (!modem.isConnected()) 51 | { 52 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 53 | while(1); 54 | } 55 | 56 | // Enable the supercapacitor charger 57 | Serial.println(F("Enabling the supercapacitor charger...")); 58 | modem.enableSuperCapCharger(true); 59 | 60 | // Wait for the supercapacitor charger PGOOD signal to go high 61 | while (!modem.checkSuperCapCharger()) 62 | { 63 | Serial.println(F("Waiting for supercapacitors to charge...")); 64 | delay(1000); 65 | } 66 | Serial.println(F("Supercapacitors charged!")); 67 | 68 | // Enable power for the 9603N 69 | Serial.println(F("Enabling 9603N power...")); 70 | modem.enable9603Npower(true); 71 | 72 | // Begin satellite modem operation 73 | Serial.println(F("Starting modem...")); 74 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 75 | err = modem.begin(); 76 | if (err != ISBD_SUCCESS) 77 | { 78 | Serial.print(F("Begin failed: error ")); 79 | Serial.println(err); 80 | if (err == ISBD_NO_MODEM_DETECTED) 81 | Serial.println(F("No modem detected: check wiring.")); 82 | return; 83 | } 84 | } 85 | 86 | void loop() 87 | { 88 | struct tm t; // struct tm is defined in time.h 89 | int err = modem.getSystemTime(t); // Ask the 9603N for the system time 90 | if (err == ISBD_SUCCESS) // Was it successful? 91 | { 92 | char buf[32]; 93 | sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", 94 | t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); 95 | Serial.print(F("Iridium date/time is ")); 96 | Serial.println(buf); 97 | } 98 | 99 | else if (err == ISBD_NO_NETWORK) // Did it fail because the 9603N has not yet seen the network? 100 | { 101 | Serial.println(F("No network detected. Waiting 10 seconds.")); 102 | } 103 | 104 | else 105 | { 106 | Serial.print(F("Unexpected error ")); 107 | Serial.println(err); 108 | return; 109 | } 110 | 111 | // Delay 10 seconds 112 | delay(10 * 1000UL); 113 | } 114 | 115 | #if DIAGNOSTICS 116 | void ISBDConsoleCallback(IridiumSBD *device, char c) 117 | { 118 | Serial.write(c); 119 | } 120 | 121 | void ISBDDiagsCallback(IridiumSBD *device, char c) 122 | { 123 | Serial.write(c); 124 | } 125 | #endif 126 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example4_BasicSend/Example4_BasicSend.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * BasicSend_I2C 7 | * 8 | * This sketch sends a "Hello, world!" message from the satellite modem. 9 | * If you have activated your account and have credits, this message 10 | * should arrive at the endpoints (delivery group) you have configured 11 | * (email address or HTTP POST). 12 | * 13 | * Assumptions 14 | * 15 | * The sketch assumes an Arduino Mega or other Arduino-like device with 16 | * a serial console and a hardware I2C (Wire) port. It assumes 17 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 18 | */ 19 | 20 | #define IridiumWire Wire 21 | #define DIAGNOSTICS false // Change this to enable diagnostics 22 | 23 | // Declare the IridiumSBD object using default I2C address 24 | IridiumSBD modem(IridiumWire); 25 | 26 | void setup() 27 | { 28 | int signalQuality = -1; 29 | int err; 30 | 31 | // Start the console serial port 32 | Serial.begin(115200); 33 | while (!Serial); // Wait for the user to open the serial monitor 34 | Serial.println(F("Iridium SBD BasicSend I2C")); 35 | 36 | //empty the serial buffer 37 | while(Serial.available() > 0) Serial.read(); 38 | 39 | //wait for the user to press any key before beginning 40 | Serial.println(F("Press any key to start example.")); 41 | while(Serial.available() == 0); 42 | 43 | //clean up 44 | while(Serial.available() > 0) Serial.read(); 45 | 46 | // Start the I2C wire port connected to the satellite modem 47 | Wire.begin(); 48 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 49 | 50 | // Check that the Qwiic Iridium is attached 51 | if (!modem.isConnected()) 52 | { 53 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 54 | while(1); 55 | } 56 | 57 | // Enable the supercapacitor charger 58 | Serial.println(F("Enabling the supercapacitor charger...")); 59 | modem.enableSuperCapCharger(true); 60 | 61 | // Wait for the supercapacitor charger PGOOD signal to go high 62 | while (!modem.checkSuperCapCharger()) 63 | { 64 | Serial.println(F("Waiting for supercapacitors to charge...")); 65 | delay(1000); 66 | } 67 | Serial.println(F("Supercapacitors charged!")); 68 | 69 | // Enable power for the 9603N 70 | Serial.println(F("Enabling 9603N power...")); 71 | modem.enable9603Npower(true); 72 | 73 | // Begin satellite modem operation 74 | Serial.println(F("Starting modem...")); 75 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 76 | err = modem.begin(); 77 | if (err != ISBD_SUCCESS) 78 | { 79 | Serial.print(F("Begin failed: error ")); 80 | Serial.println(err); 81 | if (err == ISBD_NO_MODEM_DETECTED) 82 | Serial.println(F("No modem detected: check wiring.")); 83 | return; 84 | } 85 | 86 | // Example: Print the firmware revision 87 | char version[12]; 88 | err = modem.getFirmwareVersion(version, sizeof(version)); 89 | if (err != ISBD_SUCCESS) 90 | { 91 | Serial.print(F("FirmwareVersion failed: error ")); 92 | Serial.println(err); 93 | return; 94 | } 95 | Serial.print(F("Firmware Version is ")); 96 | Serial.print(version); 97 | Serial.println(F(".")); 98 | 99 | // Example: Print the IMEI 100 | char IMEI[16]; 101 | err = modem.getIMEI(IMEI, sizeof(IMEI)); 102 | if (err != ISBD_SUCCESS) 103 | { 104 | Serial.print(F("getIMEI failed: error ")); 105 | Serial.println(err); 106 | return; 107 | } 108 | Serial.print(F("IMEI is ")); 109 | Serial.print(IMEI); 110 | Serial.println(F(".")); 111 | 112 | // Example: Test the signal quality. 113 | // This returns a number between 0 and 5. 114 | // 2 or better is preferred. 115 | err = modem.getSignalQuality(signalQuality); 116 | if (err != ISBD_SUCCESS) 117 | { 118 | Serial.print(F("SignalQuality failed: error ")); 119 | Serial.println(err); 120 | return; 121 | } 122 | 123 | Serial.print(F("On a scale of 0 to 5, signal quality is currently ")); 124 | Serial.print(signalQuality); 125 | Serial.println(F(".")); 126 | 127 | // Send the message 128 | Serial.println(F("Trying to send the message. This might take several minutes.")); 129 | err = modem.sendSBDText("Hello, world!"); 130 | if (err != ISBD_SUCCESS) 131 | { 132 | Serial.print(F("sendSBDText failed: error ")); 133 | Serial.println(err); 134 | if (err == ISBD_SENDRECEIVE_TIMEOUT) 135 | Serial.println(F("Try again with a better view of the sky.")); 136 | } 137 | 138 | else 139 | { 140 | Serial.println(F("Hey, it worked!")); 141 | } 142 | 143 | // Clear the Mobile Originated message buffer 144 | Serial.println(F("Clearing the MO buffer.")); 145 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear MO buffer 146 | if (err != ISBD_SUCCESS) 147 | { 148 | Serial.print(F("clearBuffers failed: error ")); 149 | Serial.println(err); 150 | } 151 | 152 | // Power down the modem 153 | Serial.println(F("Putting the 9603N to sleep.")); 154 | err = modem.sleep(); 155 | if (err != ISBD_SUCCESS) 156 | { 157 | Serial.print(F("sleep failed: error ")); 158 | Serial.println(err); 159 | } 160 | 161 | // Disable 9603N power 162 | Serial.println(F("Disabling 9603N power...")); 163 | modem.enable9603Npower(false); 164 | 165 | // Disable the supercapacitor charger 166 | Serial.println(F("Disabling the supercapacitor charger...")); 167 | modem.enableSuperCapCharger(false); 168 | 169 | Serial.println(F("Done!")); 170 | } 171 | 172 | void loop() 173 | { 174 | } 175 | 176 | #if DIAGNOSTICS 177 | void ISBDConsoleCallback(IridiumSBD *device, char c) 178 | { 179 | Serial.write(c); 180 | } 181 | 182 | void ISBDDiagsCallback(IridiumSBD *device, char c) 183 | { 184 | Serial.write(c); 185 | } 186 | #endif 187 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example5_Sleep/Example5_Sleep.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Sleep 7 | * 8 | * This sketch demonstrates how to put the Qwiic Iridium to sleep. The 9 | * general strategy is to call modem.begin() to start, then modem.sleep() 10 | * to stop. 11 | * 12 | * Assumptions 13 | * 14 | * The sketch assumes an Arduino Mega or other Arduino-like device with 15 | * a serial console and a hardware I2C (Wire) port. It assumes 16 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 17 | */ 18 | 19 | #define IridiumWire Wire 20 | #define DIAGNOSTICS false // Change this to see diagnostics 21 | 22 | // Declare the IridiumSBD object using default I2C address 23 | IridiumSBD modem(IridiumWire); 24 | 25 | void setup() 26 | { 27 | // Start the console serial port 28 | Serial.begin(115200); 29 | while (!Serial); // Wait for the user to open the serial monitor 30 | Serial.println(F("Iridium SBD Sleep I2C")); 31 | 32 | //empty the serial buffer 33 | while(Serial.available() > 0) Serial.read(); 34 | 35 | //wait for the user to press any key before beginning 36 | Serial.println(F("Press any key to start example.")); 37 | while(Serial.available() == 0); 38 | 39 | //clean up 40 | while(Serial.available() > 0) Serial.read(); 41 | 42 | // Start the I2C wire port connected to the satellite modem 43 | Wire.begin(); 44 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 45 | 46 | // Check that the Qwiic Iridium is attached 47 | if (!modem.isConnected()) 48 | { 49 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 50 | while(1); 51 | } 52 | 53 | // Enable the supercapacitor charger 54 | Serial.println(F("Enabling the supercapacitor charger...")); 55 | modem.enableSuperCapCharger(true); 56 | 57 | // Wait for the supercapacitor charger PGOOD signal to go high 58 | while (!modem.checkSuperCapCharger()) 59 | { 60 | Serial.println(F("Waiting for supercapacitors to charge...")); 61 | delay(1000); 62 | } 63 | Serial.println(F("Supercapacitors charged!")); 64 | 65 | // Enable power for the 9603N 66 | Serial.println(F("Enabling 9603N power...")); 67 | modem.enable9603Npower(true); 68 | } 69 | 70 | void loop() 71 | { 72 | int err; 73 | 74 | // Begin satellite modem operation 75 | Serial.println(F("Starting modem...")); 76 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 77 | err = modem.begin(); 78 | if (err != ISBD_SUCCESS) 79 | { 80 | Serial.print(F("Begin failed: error ")); 81 | Serial.println(err); 82 | if (err == ISBD_NO_MODEM_DETECTED) 83 | Serial.println(F("No modem detected: check wiring.")); 84 | return; 85 | } 86 | 87 | // Send the message 88 | Serial.println(F("Trying to send the message. This might take several minutes.")); 89 | err = modem.sendSBDText("Hello, world! (Sleep test)"); 90 | if (err != ISBD_SUCCESS) 91 | { 92 | Serial.print(F("sendSBDText failed: error ")); 93 | Serial.println(err); 94 | if (err == ISBD_SENDRECEIVE_TIMEOUT) 95 | Serial.println(F("Try again with a better view of the sky.")); 96 | } 97 | 98 | else 99 | { 100 | Serial.println(F("Hey, it worked!")); 101 | } 102 | 103 | // Clear the Mobile Originated message buffer 104 | Serial.println(F("Clearing the MO buffer.")); 105 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear MO buffer 106 | if (err != ISBD_SUCCESS) 107 | { 108 | Serial.print(F("clearBuffers failed: error ")); 109 | Serial.println(err); 110 | } 111 | 112 | // Power down the modem 113 | Serial.println(F("Putting the 9603N to sleep.")); 114 | err = modem.sleep(); 115 | if (err != ISBD_SUCCESS) 116 | { 117 | Serial.print(F("sleep failed: error ")); 118 | Serial.println(err); 119 | } 120 | 121 | // Demonstrate that device is asleep 122 | Serial.println(F("Trying to send while asleep.")); 123 | err = modem.sendSBDText("This shouldn't work."); 124 | if (err == ISBD_IS_ASLEEP) 125 | { 126 | Serial.println(F("Couldn't send: device asleep.")); 127 | } 128 | else 129 | { 130 | Serial.print(F("Send failed for some other reason: error ")); 131 | Serial.println(err); 132 | } 133 | 134 | Serial.println(F("Sleeping for a minute.")); 135 | delay(60 * 1000UL); 136 | } 137 | 138 | #if DIAGNOSTICS 139 | void ISBDConsoleCallback(IridiumSBD *device, char c) 140 | { 141 | Serial.write(c); 142 | } 143 | 144 | void ISBDDiagsCallback(IridiumSBD *device, char c) 145 | { 146 | Serial.write(c); 147 | } 148 | #endif 149 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example6_SendReceive/Example6_SendReceive.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * SendReceive 7 | * 8 | * This sketch demonstrates a basic bidirectional transmission. Before 9 | * loading this sketch, send a message to your Iridium modem from your 10 | * control panel or via email. This sketch will send a binary buffer 11 | * of 11 bytes, then attempt to read the next incoming messages (if any). 12 | * It stops when there are no more messages to read. 13 | * 14 | * Assumptions 15 | * 16 | * The sketch assumes an Arduino Mega or other Arduino-like device with 17 | * a serial console and a hardware I2C (Wire) port. It assumes 18 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 19 | */ 20 | 21 | #define IridiumWire Wire 22 | #define DIAGNOSTICS false // Change this to enable diagnostics 23 | 24 | // Declare the IridiumSBD object using default I2C address 25 | IridiumSBD modem(IridiumWire); 26 | 27 | // Define the binary test message (Fibonacci sequence) 28 | uint8_t buffer[200] = 29 | { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; 30 | 31 | void setup() 32 | { 33 | int signalQuality = -1; 34 | 35 | // Start the console serial port 36 | Serial.begin(115200); 37 | while (!Serial); // Wait for the user to open the serial monitor 38 | Serial.println(F("Iridium SBD SendReceive I2C")); 39 | 40 | //empty the serial buffer 41 | while(Serial.available() > 0) Serial.read(); 42 | 43 | //wait for the user to press any key before beginning 44 | Serial.println(F("Press any key to start example.")); 45 | while(Serial.available() == 0); 46 | 47 | //clean up 48 | while(Serial.available() > 0) Serial.read(); 49 | 50 | // Start the I2C wire port connected to the satellite modem 51 | Wire.begin(); 52 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 53 | 54 | // Check that the Qwiic Iridium is attached 55 | if (!modem.isConnected()) 56 | { 57 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 58 | while(1); 59 | } 60 | 61 | // Enable the supercapacitor charger 62 | Serial.println(F("Enabling the supercapacitor charger...")); 63 | modem.enableSuperCapCharger(true); 64 | 65 | // Wait for the supercapacitor charger PGOOD signal to go high 66 | while (!modem.checkSuperCapCharger()) 67 | { 68 | Serial.println(F("Waiting for supercapacitors to charge...")); 69 | delay(1000); 70 | } 71 | Serial.println(F("Supercapacitors charged!")); 72 | 73 | // Enable power for the 9603N 74 | Serial.println(F("Enabling 9603N power...")); 75 | modem.enable9603Npower(true); 76 | 77 | // Begin satellite modem operation 78 | Serial.println(F("Starting modem...")); 79 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 80 | int err = modem.begin(); 81 | if (err != ISBD_SUCCESS) 82 | { 83 | Serial.print(F("Begin failed: error ")); 84 | Serial.println(err); 85 | if (err == ISBD_NO_MODEM_DETECTED) 86 | Serial.println(F("No modem detected: check wiring.")); 87 | return; 88 | } 89 | 90 | // Check the signal quality (optional) 91 | err = modem.getSignalQuality(signalQuality); 92 | if (err != 0) 93 | { 94 | Serial.print(F("SignalQuality failed: error ")); 95 | Serial.println(err); 96 | exit(1); 97 | } 98 | 99 | Serial.print(F("Signal quality is ")); 100 | Serial.println(signalQuality); 101 | } 102 | 103 | static bool messageSent = false; 104 | 105 | void loop() 106 | { 107 | int err; 108 | 109 | // Read/Write the first time or if there are any remaining messages 110 | if (!messageSent || modem.getWaitingMessageCount() > 0) 111 | { 112 | size_t bufferSize = sizeof(buffer); 113 | 114 | // First time through send+receive; subsequent loops receive only (send a NULL message) 115 | if (!messageSent) 116 | err = modem.sendReceiveSBDBinary(buffer, 11, buffer, bufferSize); 117 | else 118 | err = modem.sendReceiveSBDText(NULL, buffer, bufferSize); 119 | 120 | if (err != ISBD_SUCCESS) 121 | { 122 | Serial.print(F("sendReceiveSBD* failed: error ")); 123 | Serial.println(err); 124 | } 125 | else // success! 126 | { 127 | messageSent = true; 128 | Serial.print(F("Inbound buffer size is ")); 129 | Serial.println(bufferSize); 130 | for (int i=0; i // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Ring_I2C 7 | * 8 | * This sketch demonstrates how to use the Iridium RING line to detect 9 | * when inbound messages are available and retrieve them. 10 | * 11 | * Assumptions 12 | * 13 | * The sketch assumes an Arduino Mega or other Arduino-like device with 14 | * a serial console and a hardware I2C (Wire) port. It assumes 15 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 16 | */ 17 | 18 | #define IridiumWire Wire 19 | #define DIAGNOSTICS false // Change this to enable diagnostics 20 | 21 | // Declare the IridiumSBD object using default I2C address 22 | IridiumSBD modem(IridiumWire); 23 | 24 | void setup() 25 | { 26 | int signalQuality = -1; 27 | int err; 28 | 29 | // Start the console serial port 30 | Serial.begin(115200); 31 | while (!Serial); // Wait for the user to open the serial monitor 32 | Serial.println(F("Iridium SBD Ring I2C")); 33 | 34 | //empty the serial buffer 35 | while(Serial.available() > 0) Serial.read(); 36 | 37 | //wait for the user to press any key before beginning 38 | Serial.println(F("Press any key to start example.")); 39 | while(Serial.available() == 0); 40 | 41 | //clean up 42 | while(Serial.available() > 0) Serial.read(); 43 | 44 | // Start the I2C wire port connected to the satellite modem 45 | Wire.begin(); 46 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 47 | 48 | // Check that the Qwiic Iridium is attached 49 | if (!modem.isConnected()) 50 | { 51 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 52 | while(1); 53 | } 54 | 55 | // Enable the supercapacitor charger 56 | Serial.println(F("Enabling the supercapacitor charger...")); 57 | modem.enableSuperCapCharger(true); 58 | 59 | // Wait for the supercapacitor charger PGOOD signal to go high 60 | while (!modem.checkSuperCapCharger()) 61 | { 62 | Serial.println(F("Waiting for supercapacitors to charge...")); 63 | delay(1000); 64 | } 65 | Serial.println(F("Supercapacitors charged!")); 66 | 67 | // Enable 9603N power 68 | Serial.println(F("Enabling 9603N power...")); 69 | modem.enable9603Npower(true); 70 | 71 | // Begin satellite modem operation 72 | Serial.println(F("Starting modem...")); 73 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 74 | err = modem.begin(); 75 | if (err != ISBD_SUCCESS) 76 | { 77 | Serial.print(F("Begin failed: error ")); 78 | Serial.println(err); 79 | if (err == ISBD_NO_MODEM_DETECTED) 80 | Serial.println(F("No modem detected: check wiring.")); 81 | exit(0); 82 | } 83 | 84 | // Check signal quality for fun. 85 | err = modem.getSignalQuality(signalQuality); 86 | if (err != ISBD_SUCCESS) 87 | { 88 | Serial.print(F("SignalQuality failed: error ")); 89 | Serial.println(err); 90 | return; 91 | } 92 | 93 | Serial.print(F("Signal quality is ")); 94 | Serial.println(signalQuality); 95 | 96 | // Check network available for fun. 97 | Serial.print(F("Network is ")); 98 | if (!modem.checkNetworkAvailable()) Serial.print(F("NOT ")); 99 | Serial.println(F("available!")); 100 | if (!modem.checkNetworkAvailable()) Serial.println(F("(This might be because the 9603N has not yet aquired the ring channel.)")); 101 | Serial.println(F("Begin waiting for RING...")); 102 | } 103 | 104 | 105 | void loop() 106 | { 107 | static int err = ISBD_SUCCESS; 108 | delay(100UL); // Go round the loop no more than once every 100 msec to avoid thrashing the I2C bus 109 | bool ring = modem.hasRingAsserted(); 110 | if (ring || modem.getWaitingMessageCount() > 0 || err != ISBD_SUCCESS) 111 | { 112 | if (ring) 113 | Serial.println(F("RING asserted! Let's try to read the incoming message.")); 114 | else if (modem.getWaitingMessageCount() > 0) 115 | Serial.println(F("Waiting messages available. Let's try to read them.")); 116 | else 117 | Serial.println(F("Let's try again.")); 118 | 119 | // Clear the Mobile Originated message buffer - just in case it has an old message in it! 120 | Serial.println(F("Clearing the MO buffer (just in case).")); 121 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear MO buffer 122 | if (err != ISBD_SUCCESS) 123 | { 124 | Serial.print(F("clearBuffers failed: error ")); 125 | Serial.println(err); 126 | return; 127 | } 128 | 129 | uint8_t buffer[200]; 130 | size_t bufferSize = sizeof(buffer); 131 | err = modem.sendReceiveSBDText(NULL, buffer, bufferSize); 132 | if (err != ISBD_SUCCESS) 133 | { 134 | Serial.print(F("sendReceiveSBDBinary failed: error ")); 135 | Serial.println(err); 136 | return; 137 | } 138 | 139 | Serial.println(F("Message received!")); 140 | Serial.print(F("Inbound message size is ")); 141 | Serial.println(bufferSize); 142 | for (int i=0; i<(int)bufferSize; ++i) 143 | { 144 | Serial.print(buffer[i], HEX); 145 | if (isprint(buffer[i])) 146 | { 147 | Serial.print(F("(")); 148 | Serial.write(buffer[i]); 149 | Serial.print(F(")")); 150 | } 151 | Serial.print(F(" ")); 152 | } 153 | Serial.println(); 154 | Serial.print(F("Messages remaining to be retrieved: ")); 155 | Serial.println(modem.getWaitingMessageCount()); 156 | 157 | // Clean up by making sure the Ring Indicator flag is clear. 158 | // The RI pin pulses twice (slowly!) for each message _and_ SBDRING can arrive over the serial port, 159 | // which otherwise can cause the code to go around the loop multiple times for each message! 160 | Serial.println(); 161 | Serial.println(F("Making sure the Ring Indicator flag is clear.")); 162 | modem.clearRingIndicator(); // Clear the Ring Indicator flag 163 | Serial.println(); 164 | } 165 | } 166 | 167 | #if DIAGNOSTICS 168 | void ISBDConsoleCallback(IridiumSBD *device, char c) 169 | { 170 | Serial.write(c); 171 | } 172 | 173 | void ISBDDiagsCallback(IridiumSBD *device, char c) 174 | { 175 | Serial.write(c); 176 | } 177 | #endif 178 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example8_Beacon/Example8_Beacon.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //http://librarymanager/All#SparkFun_Ublox_GPS 4 | 5 | #include //Needed for I2C communication 6 | 7 | // Include dtostrf for e.g. AVR, SAMD and APOLLO3 architectures 8 | //#include // uncomment this line if you see "'dtostrf' was not declared in this scope" compilation errors 9 | 10 | /* 11 | * Beacon 12 | * 13 | * This sketch shows how you might use a GPS with the satellite modem 14 | * to create a beacon device that periodically transmits a location 15 | * message to the configured endpoints. 16 | * 17 | * Assumptions 18 | * 19 | * The sketch assumes an Arduino Mega or other Arduino-like device with 20 | * a serial console and a hardware I2C (Wire) port. It assumes 21 | * the SparkFun Qwiic Iridium 9603N and (e.g.) SAM-M8Q or ZOE-M8Q Breakout are connected via I2C. 22 | */ 23 | 24 | #define IridiumWire Wire 25 | #define DIAGNOSTICS false // Change this to enable diagnostics 26 | 27 | // Time between transmissions (seconds) 28 | #define BEACON_INTERVAL 600 29 | 30 | // Declare the IridiumSBD object using default I2C address 31 | IridiumSBD modem(IridiumWire); 32 | 33 | // Declare the GPS object 34 | SFE_UBLOX_GPS myGPS; 35 | 36 | static const int ledPin = LED_BUILTIN; 37 | 38 | void setup() 39 | { 40 | pinMode(ledPin, OUTPUT); 41 | 42 | // Start the console serial port 43 | Serial.begin(115200); 44 | while (!Serial); // Wait for the user to open the serial monitor 45 | Serial.println(F("Iridium SBD Beacon I2C")); 46 | 47 | //empty the serial buffer 48 | while(Serial.available() > 0) Serial.read(); 49 | 50 | //wait for the user to press any key before beginning 51 | Serial.println(F("Press any key to start example.")); 52 | while(Serial.available() == 0); 53 | 54 | //clean up 55 | while(Serial.available() > 0) Serial.read(); 56 | 57 | // Start the I2C wire port connected to the satellite modem 58 | Wire.begin(); 59 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 60 | 61 | // Check that the Qwiic Iridium is attached 62 | if (!modem.isConnected()) 63 | { 64 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 65 | while(1); 66 | } 67 | 68 | Serial.println(F("Connecting to the GPS receiver...")); 69 | if (myGPS.begin() == false) //Connect to the Ublox module using Wire port 70 | { 71 | Serial.println(F("Ublox GPS not detected at default I2C address. Please check wiring. Freezing.")); 72 | while (1); 73 | } 74 | 75 | myGPS.setI2COutput(COM_TYPE_UBX); //Set the I2C port to output UBX only (turn off NMEA noise) 76 | myGPS.saveConfiguration(); //Save the current settings to flash and BBR 77 | 78 | // Enable the supercapacitor charger 79 | Serial.println(F("Enabling the supercapacitor charger...")); 80 | modem.enableSuperCapCharger(true); 81 | 82 | // Wait for the supercapacitor charger PGOOD signal to go high 83 | while (!modem.checkSuperCapCharger()) 84 | { 85 | Serial.println(F("Waiting for supercapacitors to charge...")); 86 | delay(1000); 87 | } 88 | Serial.println(F("Supercapacitors charged!")); 89 | 90 | // Enable 9603N power 91 | Serial.println(F("Enabling 9603N power...")); 92 | modem.enable9603Npower(true); 93 | 94 | // Begin satellite modem operation 95 | Serial.println(F("Starting modem...")); 96 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 97 | int err = modem.begin(); 98 | if (err != ISBD_SUCCESS) 99 | { 100 | Serial.print(F("Begin failed: error ")); 101 | Serial.println(err); 102 | if (err == ISBD_NO_MODEM_DETECTED) 103 | Serial.println(F("No modem detected: check wiring.")); 104 | exit(0); 105 | } 106 | } 107 | 108 | void loop() 109 | { 110 | unsigned long loopStartTime = millis(); 111 | 112 | // Begin listening to the GPS 113 | Serial.println(F("Beginning to listen for GPS traffic...")); 114 | 115 | // Look for GPS signal for up to 5 minutes 116 | while ((myGPS.getFixType() == 0) && millis() - loopStartTime < 5UL * 60UL * 1000UL) 117 | { 118 | blinkLED(1000); // Flash the LED 119 | delay(100UL); // getFixType every 100msec to avoid thrashing the I2C bus 120 | } 121 | 122 | // Did we get a GPS fix? 123 | if (myGPS.getFixType() == 0) 124 | { 125 | Serial.println(F("Could not get GPS fix.")); 126 | return; 127 | } 128 | 129 | Serial.println(F("A GPS fix was found!")); 130 | 131 | float latitude = ((float)(myGPS.getLatitude())) / 10000000; 132 | Serial.print(F("Lat: ")); 133 | Serial.print(latitude, 6); 134 | 135 | float longitude = ((float)(myGPS.getLongitude())) / 10000000; 136 | Serial.print(F(" Lon: ")); 137 | Serial.print(longitude, 6); 138 | Serial.print(F(" (degrees)")); 139 | 140 | float altitude = ((float)(myGPS.getAltitude())) / 1000; 141 | Serial.print(F(" Alt: ")); 142 | Serial.print(altitude, 2); 143 | Serial.println(F(" (m)")); 144 | 145 | // Start talking to the Qwiic Iridium 9603N and power it up 146 | Serial.println(F("Beginning to talk to the Qwiic Iridium 9603N...")); 147 | 148 | // Construct the message in the format: lat,lon,alt 149 | char lat_str[15]; 150 | dtostrf(latitude,8,6,lat_str); 151 | char lon_str[15]; 152 | dtostrf(longitude,8,6,lon_str); 153 | char alt_str[15]; 154 | dtostrf(altitude,4,2,alt_str); 155 | char outBuffer[60]; // Always try to keep message short 156 | sprintf(outBuffer, "%s,%s,%s", lat_str, lon_str, alt_str); 157 | 158 | Serial.print(F("Transmitting message '")); 159 | Serial.print(outBuffer); 160 | Serial.println(F("'")); 161 | 162 | int err = modem.sendSBDText(outBuffer); 163 | if (err != ISBD_SUCCESS) 164 | { 165 | Serial.print(F("Transmission failed with error code ")); 166 | Serial.println(err); 167 | } 168 | else 169 | { 170 | Serial.println(F("Message sent!")); 171 | } 172 | 173 | // Sleep 174 | digitalWrite(ledPin, LOW); 175 | int elapsedSeconds = (int)((millis() - loopStartTime) / 1000); 176 | if (elapsedSeconds < BEACON_INTERVAL) 177 | { 178 | int delaySeconds = BEACON_INTERVAL - elapsedSeconds; 179 | Serial.print(F("Waiting for ")); 180 | Serial.print(delaySeconds); 181 | Serial.println(F(" seconds")); 182 | delay(1000UL * delaySeconds); 183 | } 184 | 185 | // Wake 186 | Serial.println(F("Wake up!")); 187 | } 188 | 189 | void blinkLED(unsigned long interval) 190 | { 191 | digitalWrite(ledPin, (millis() / interval) % 2 == 1 ? HIGH : LOW); 192 | } 193 | 194 | bool ISBDCallback() 195 | { 196 | blinkLED(500); 197 | return true; 198 | } 199 | 200 | #if DIAGNOSTICS 201 | void ISBDConsoleCallback(IridiumSBD *device, char c) 202 | { 203 | Serial.write(c); 204 | } 205 | 206 | void ISBDDiagsCallback(IridiumSBD *device, char c) 207 | { 208 | Serial.write(c); 209 | } 210 | #endif 211 | -------------------------------------------------------------------------------- /examples/I2C_Examples__Qwiic_Iridium/Example9_PassThru/Example9_PassThru.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * PassThru_I2C 7 | * 8 | * This sketch allows you to send data directly from the serial console 9 | * to the modem. Characters typed in the console are relayed to the 10 | * modem and vice versa. 11 | * 12 | * The sketch assumes an Arduino Mega or other Arduino-like device with 13 | * a serial console and a hardware I2C (Wire) port. It assumes 14 | * the SparkFun Qwiic Iridium 9603N is connected via I2C. 15 | * 16 | * Open the Serial Monitor and set the Baud Rate to 115200 17 | * and the line ending to Carriage Return 18 | * 19 | * Command Response Description 20 | * AT+CGMI Iridium Get manufacturer identification 21 | * AT+CGMM Get model identification 22 | * AT+CGMR Get revision 23 | * AT+CGSN Get serial number (IMEI) 24 | * AT+CSQ Get signal quality 25 | * 26 | * To send a Mobile Originated text message and check for a new Mobile Terminated message: 27 | * AT+SBDWT=Testing123 Write a text message to the MO buffer 28 | * AT+SBDS Read the MO and MT buffer status (MO flag should be '1') 29 | * AT+SBDIX Initiate an SBD session (wait for it to complete - could take several minutes!) 30 | * AT+SBDS Read the MO and MT buffer status (MO flag should still be '1'; 31 | * MT flag will be '1' if a new message was received) 32 | * AT+SBDD0 Clear the MO buffer 33 | * AT+SBDRT Read the received text message (if there was one) 34 | * AT+SBDD1 Clear the MT buffer 35 | * AT+SBDS Read the MO and MT buffer status (Both MO and MT flags should be '0') 36 | * 37 | * The full AT command set can be found here: 38 | * http://www.rock7mobile.com/downloads/IRDM_ISU_ATCommandReferenceMAN0009_Rev2.0_ATCOMM_Oct2012.pdf 39 | * (Only a small sub-set of the commands apply to the 9603N) 40 | */ 41 | 42 | #define IridiumWire Wire 43 | #define DIAGNOSTICS false // Change this to see diagnostics 44 | 45 | // Declare the IridiumSBD object using default I2C address 46 | IridiumSBD modem(IridiumWire); 47 | 48 | #define bufferSize 100 // Tx/Rx Buffer size 49 | 50 | void setup() 51 | { 52 | int signalQuality = -1; 53 | int err; 54 | 55 | // Start the console serial port 56 | Serial.begin(115200); 57 | while (!Serial); // Wait for the user to open the serial monitor 58 | Serial.println(F("Iridium SBD PassThru I2C")); 59 | 60 | //empty the serial buffer 61 | while(Serial.available() > 0) Serial.read(); 62 | 63 | //wait for the user to press any key before beginning 64 | Serial.println(F("Press any key to start example.")); 65 | while(Serial.available() == 0); 66 | 67 | //clean up 68 | while(Serial.available() > 0) Serial.read(); 69 | 70 | // Start the I2C wire port connected to the satellite modem 71 | Wire.begin(); 72 | Wire.setClock(400000); //Set I2C clock speed to 400kHz 73 | 74 | // Check that the Qwiic Iridium is attached 75 | if (!modem.isConnected()) 76 | { 77 | Serial.println(F("Qwiic Iridium is not connected! Please check wiring. Freezing.")); 78 | while(1); 79 | } 80 | 81 | // Enable the supercapacitor charger 82 | Serial.println(F("Enabling the supercapacitor charger...")); 83 | modem.enableSuperCapCharger(true); 84 | 85 | // Wait for the supercapacitor charger PGOOD signal to go high 86 | while (!modem.checkSuperCapCharger()) 87 | { 88 | Serial.println(F("Waiting for supercapacitors to charge...")); 89 | delay(1000); 90 | } 91 | Serial.println(F("Supercapacitors charged!")); 92 | 93 | // Enable power for the 9603N 94 | Serial.println(F("Enabling 9603N power...")); 95 | modem.enable9603Npower(true); 96 | 97 | // Begin satellite modem operation 98 | Serial.println(F("Starting modem...")); 99 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); // Assume 'USB' power (slow recharge) 100 | err = modem.begin(); 101 | if (err != ISBD_SUCCESS) 102 | { 103 | Serial.print(F("Begin failed: error ")); 104 | Serial.println(err); 105 | if (err == ISBD_NO_MODEM_DETECTED) 106 | Serial.println(F("No modem detected: check wiring.")); 107 | return; 108 | } 109 | 110 | // Test the signal quality. 111 | // This returns a number between 0 and 5. 112 | // 2 or better is preferred. 113 | err = modem.getSignalQuality(signalQuality); 114 | if (err != ISBD_SUCCESS) 115 | { 116 | Serial.print(F("SignalQuality failed: error ")); 117 | Serial.println(err); 118 | return; 119 | } 120 | 121 | Serial.print(F("On a scale of 0 to 5, signal quality is currently ")); 122 | Serial.print(signalQuality); 123 | Serial.println(F(".")); 124 | 125 | Serial.println(); 126 | Serial.println(F("Enter commands terminated by Carriage Return ('\\r'):")); 127 | } 128 | 129 | void loop() 130 | { 131 | int err; 132 | 133 | uint8_t TxRxBuffer[bufferSize]; // Create a buffer 134 | size_t TxRxBufferSize = 0; // Set the buffer size to zero 135 | // Check if there is any serial data to be sent to the 9603N (and that we haven't filled the buffer) 136 | while ((Serial.available() > 0) && (TxRxBufferSize < bufferSize)) 137 | { 138 | TxRxBuffer[TxRxBufferSize] = Serial.read(); // Read a byte and store in the buffer 139 | TxRxBufferSize++; // Increment the buffer size 140 | } 141 | if (TxRxBufferSize > 0) // If there is data in the outBuffer 142 | { 143 | err = modem.passThruI2Cwrite(TxRxBuffer, TxRxBufferSize); // Write it using pass thru 144 | if (err != ISBD_SUCCESS) // If there was an error, print the error code 145 | { 146 | Serial.print(F("passThruI2Cwrite failed: error ")); 147 | Serial.println(err); 148 | } 149 | } 150 | 151 | // Set the buffer size to the maximum size of the buffer 152 | // so passThruI2Cread knows how big the buffer is (and doesn't overflow it!) 153 | TxRxBufferSize = bufferSize; 154 | size_t bytesRead = 0; // passThruI2Cread will set this to the number of serial bytes written into the buffer 155 | err = modem.passThruI2Cread(TxRxBuffer, TxRxBufferSize, bytesRead); // Read any waiting data using pass thru 156 | if (err != ISBD_SUCCESS) // If there was an error, print the error code 157 | { 158 | Serial.print(F("passThruI2Cread returned error ")); 159 | Serial.println(err); 160 | } 161 | if (bytesRead > 0) // If some data was received 162 | { 163 | size_t ptr = 0; 164 | while (ptr < bytesRead) 165 | { 166 | Serial.write(TxRxBuffer[ptr]); // Send the data one byte at a time to the serial port 167 | ptr++; 168 | } 169 | } 170 | 171 | delay(5); // Delay to avoid thrashing the I2C bus 172 | } 173 | 174 | #if DIAGNOSTICS 175 | void ISBDConsoleCallback(IridiumSBD *device, char c) 176 | { 177 | Serial.write(c); 178 | } 179 | 180 | void ISBDDiagsCallback(IridiumSBD *device, char c) 181 | { 182 | Serial.write(c); 183 | } 184 | #endif 185 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # IridiumSBD Arduino Library Examples 2 | 3 | This folder contains: 4 | - **Serial examples:** these are enhanced versions of the examples Mikal Hart wrote for Version 2.0 of this library. They will work with the Rock7 RockBLOCK, connected via Serial 5 | - **I2C examples:** these are the same examples plus new ones which are written for the Qwiic Iridium, connected via I2C 6 | 7 | ### Example 1: Get IMEI 8 | 9 | This example opens a connection to the Iridium transceiver and requests its IMEI (serial number). It will check if your transceiver is connected correctly and that the 10 | serial port is working. You do not need line rental or message credits to run this example. 11 | 12 | The Qwiic Iridium I2C example: enables the super capacitor charger; waits for the capacitors to charge (this could take approximately 20 seconds if the capacitors are 13 | fully discharged); enables power for the 9603N; gets the IMEI; puts the 9603N to sleep and powers everything down again. 14 | 15 | Iridium transceivers bought from Rock7 have two serial numbers: the International Mobile Equipment Identity is a 15 digit serial number which identifies the transceiver 16 | on the Iridium network; a five digit RockBLOCK serial number which is used to access the transceiver via the RockBLOCK Gateway. Example 10 uses the RockBLOCK serial number 17 | (not the IMEI) to loop a message back to the transceiver. 18 | 19 | ### Example 2: Check CSQ 20 | 21 | This example builds on example 1 but also checks the Iridium signal quality. It will check if your transceiver's antenna is connected correctly. You do not need line 22 | rental or message credits to run this example. 23 | 24 | The Qwiic Iridium I2C example also checks if the transceiver can receive the ring channel by checking the status of the Network Available (NA) signal. 25 | 26 | You will notice that the signal quality is not returned immediately. It takes the transceiver a few seconds to measure the signal and send a reply. 27 | 28 | ### Example 3: Get Time 29 | 30 | This example builds on example 2 but also gets the Iridium system time. The time is always returned in GMT as Iridium does not support time zones or daylight saving. 31 | You do not need line rental or message credits to run this example. 32 | 33 | ### Example 4: Basic Send 34 | 35 | This example sends a Mobile Originated (MO) "Hello, world!" test message. You will need line rental and message credits to run this example. Each message will 36 | use one message credit. You should also set up a delivery group for your transceiver so you can receive the message via email (or HTTP POST). 37 | 38 | ### Example 5: Sleep 39 | 40 | This example builds on example 4 but sends the test message once per minute, putting the transceiver to sleep between sends. 41 | 42 | _Be careful not to leave this example running for too long as it will use one message credit each time a message is sent._ 43 | 44 | ### Example 6: Send Receive 45 | 46 | This example demonstrates how to receive Mobile Terminated (MT) messages sent _to_ the transceiver. In Rock7 Operations, you can use the _Send a Message_ option to 47 | send a text message to your transceiver. Multiple messages will be queued in the Iridium system until the transceiver downloads them (one at a time). The messages 48 | will expire if not downloaded within 48 hours. 49 | 50 | During each Short Burst Data session, the transceiver can send one Mobile Originated message and in return will receive the first Mobile Terminated message from 51 | the queue (if there is one). If you only want to check for MT messages, you can do this by sending an empty (NULL) MO message. 52 | 53 | The first time around the loop, the code sends a _binary_ message (the values sent are the start of the Fibonacci sequence). The MT message, if there is one, 54 | will be downloaded and displayed in the console. The code checks the length of the MT queue and will keep going around the loop sending empty (NULL) messages and 55 | downloading MT messages until the queue is empty. In the Rock7 Operations message log, you will see these as _\[No payload\]_ Mobile Originated messages. 56 | 57 | Rock7 will charge you one message credit for every 50 bytes (or part thereof) of a message sent or received. Sending a NULL message will still use one credit even 58 | if there is nothing in the MT queue to be downloaded. 59 | 60 | ### Example 7: Ring 61 | 62 | This example demonstrates how to use the transceiver Ring Indicator to show when a new MT message is waiting to be downloaded. 63 | 64 | The code will enable the tranceiver, wait until it receives a ring indication and then download any messages in the queue. Start the code and wait until it says 65 | _Begin waiting for RING..._. Now send a new MT message from Rock7 Operations. After a few seconds you will see the code acknowledge the ring alert and it will 66 | begin downloading and displaying all the messages in the MT queue. 67 | 68 | The Iridium system needs to know your approximate location to send you ring alerts. This means you will need to have transmited at least one message before this example 69 | will work successfully. 70 | 71 | ### Example 8: Beacon 72 | 73 | This example demonstrates how to create a beacon or tracker that will transmit your GNSS (GPS) location via Iridium from _anywhere_. 74 | 75 | The serial example assumes you have a GNSS receiver connected via serial. It uses [Mikal's TinyGPS++ library](https://github.com/mikalhart/TinyGPSPlus) to parse the 76 | NMEA messages and extract your location before transmitting it via Iridium. You can install TinyGPS++ through the Arduino IDE Library Manager (search for _TinyGPS++_). 77 | 78 | The I2C example assumes you have a GNSS receiver connected via I2C. Good choices are the [SparkFun SAM-M8Q Breakout](https://www.sparkfun.com/products/15210) and the 79 | [SparkFun ZOE-M8Q Breakout](https://www.sparkfun.com/products/15193). The example uses the [SparkFun u-blox library](https://github.com/sparkfun/SparkFun_Ublox_Arduino_Library) 80 | to obtain your location. 81 | 82 | The code will send your location every 10 minutes. You can change the interval by editing the value for _BEACON_INTERVAL_. 83 | 84 | ### Example 9: Pass Thru 85 | 86 | This example is for advanced users who want to send commands directly to the transceiver to investigate how the AT command set works. Commands typed into the serial 87 | console are passed through to the transceiver and the replies are passed back. You can find example commands in the code plus a link to the full command reference. 88 | 89 | Set the serial monitor Baud rate to 115200 and the line ending to carriage return. 90 | 91 | ### Example 10: Loop Back 92 | 93 | The Rock7 RockBLOCK Gateway can be used to automatically forward messages to other RockBLOCKs _registered to the same account_. This example takes advantage of that 94 | by sending a message that asks the Gateway to loop the message back again to the same transceiver. It does this by prefixing the message with the letters "RB" 95 | and the RockBLOCK serial number of the transceiver padded out to seven digits. E.g. if the RockBLOCK serial number of your transceiver is _12345_ the message will 96 | be prefixed by _RB0012345_ 97 | 98 | The RockBLOCK Gateway is a really powerful feature as it means you can send messages from one RockBLOCK to another _anywhere_ without needing an internet connection. 99 | Please be aware that this does mean you will be charged for the message _twice_; once to transmit it and once to receive it. 100 | 101 | ### Example 11: Low Power 102 | 103 | This example demonstrates how to put the Qwiic Iridium into low power mode. With the 9603N, super capacitor charger and power LED disabled, the Qwiic Iridium will draw 104 | approximately 1 microamp when in low power mode. The ATtiny841 processor will wake up normally when it next sees activity on the I2C bus or the serial interface or 105 | receives an interrupt from the Ring Indicator signal. 106 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example10_LoopBack/Example10_LoopBack.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | #include //Needed for I2C communication 4 | 5 | /* 6 | * Loop Back 7 | * 8 | * This sketch demonstrates how to forward a message to another RockBLOCK 9 | * via the Rock7 RockBLOCK Gateway. The message is looped back to your 10 | * RockBLOCK by prefixing the message with "RB" and the RockBLOCK serial 11 | * number of your transceiver padded out to seven digits. 12 | * 13 | * Assumptions 14 | * 15 | * The sketch assumes an Arduino Mega or other Arduino-like device with 16 | * multiple HardwareSerial ports. It assumes the satellite modem is 17 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 18 | * works fine as well. 19 | * 20 | * Open the Serial Monitor and set the Baud Rate to 115200 21 | * and the line ending to Carriage Return 22 | * 23 | * Part of the code is based on Tom Igoe's Serial Event example: 24 | * https://www.arduino.cc/en/Tutorial/SerialEvent 25 | */ 26 | 27 | #define IridiumSerial Serial1 28 | #define DIAGNOSTICS false // Change this to see diagnostics 29 | 30 | IridiumSBD modem(IridiumSerial); 31 | 32 | String inputString = ""; // a string to hold incoming data 33 | boolean stringComplete = false; // whether the string is complete 34 | #define max_length 10 // Define maximum inputString length to avoid buffer overruns 35 | 36 | void setup() 37 | { 38 | // Start the serial ports 39 | Serial.begin(115200); 40 | while (!Serial); 41 | IridiumSerial.begin(19200); 42 | 43 | // Setup the Iridium modem 44 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 45 | if (modem.begin() != ISBD_SUCCESS) 46 | { 47 | Serial.println(F("Couldn't begin modem operations.")); 48 | exit(0); 49 | } 50 | 51 | inputString.reserve(max_length); // Reserve max_length bytes for the input string 52 | } 53 | 54 | /* 55 | SerialEvent occurs whenever a new data comes in the 56 | hardware serial RX. This routine is run between each 57 | time loop() runs, so using delay inside loop can delay 58 | response. Multiple bytes of data may be available. 59 | */ 60 | void serialEvent() { 61 | while (Serial.available()) { 62 | // get the new byte: 63 | char inChar = (char)Serial.read(); 64 | // check how many characters have already been received 65 | if (inputString.length() < max_length) { 66 | // we have room so add inChar to the inputString: 67 | inputString += inChar; 68 | } 69 | // if the incoming character is a carriage return, set a flag 70 | // so the main loop can do something about it: 71 | if (inChar == '\r') { 72 | stringComplete = true; 73 | } 74 | } 75 | } 76 | 77 | void loop() 78 | { 79 | // Clear the serial string and flag 80 | inputString = ""; 81 | stringComplete = false; 82 | 83 | Serial.println(F("Please enter the RockBLOCK serial number of your transceiver followed by carriage return:")); 84 | while (!stringComplete) 85 | { 86 | serialEvent(); // Check for serial event 87 | } 88 | // Process the string when a carriage return arrives: 89 | int RockBLOCK = inputString.toInt(); // Convert the serial number to int 90 | Serial.println(RockBLOCK); 91 | 92 | // Construct the message 93 | // Prefix with "RB" and the RockBLOCK serial number padded out to seven digits 94 | char outBuffer[50]; // Always try to keep message short 95 | sprintf(outBuffer, "RB%07iThis is a test message!", RockBLOCK); 96 | 97 | Serial.print(F("Transmitting message: '")); 98 | Serial.print(outBuffer); 99 | Serial.println(F("'")); 100 | 101 | int err = modem.sendSBDText(outBuffer); 102 | if (err != ISBD_SUCCESS) 103 | { 104 | Serial.print(F("Transmission failed with error code ")); 105 | Serial.println(err); 106 | } 107 | else 108 | { 109 | Serial.println(F("Message sent!")); 110 | } 111 | 112 | // Clear the MO buffer 113 | Serial.println(F("Clearing the MO buffer.")); 114 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear the MO buffer 115 | if (err != ISBD_SUCCESS) 116 | { 117 | Serial.print(F("clearBuffers failed: error ")); 118 | Serial.println(err); 119 | } 120 | 121 | Serial.println(F("Waiting for 30 seconds...")); 122 | delay(30000); 123 | 124 | // Now retrieve the loop backed message 125 | Serial.println(F("Checking if the message looped back successfully.")); 126 | 127 | uint8_t buffer[60]; 128 | size_t bufferSize = sizeof(buffer); 129 | 130 | err = modem.sendReceiveSBDText(NULL, buffer, bufferSize); 131 | 132 | if (err != ISBD_SUCCESS) 133 | { 134 | Serial.print(F("sendReceiveSBD* failed: error ")); 135 | Serial.println(err); 136 | } 137 | else // success! 138 | { 139 | Serial.print(F("Inbound buffer size is ")); 140 | Serial.println(bufferSize); 141 | if (bufferSize > 0) 142 | { 143 | Serial.print(F("The received message is: '")); 144 | for (int i=0; i // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | /* 4 | * Get IMEI 5 | * 6 | * This sketch requests the satellite modem's IMEI number. 7 | * 8 | * Assumptions 9 | * 10 | * The sketch assumes an Arduino Mega or other Arduino-like device with 11 | * multiple HardwareSerial ports. It assumes the satellite modem is 12 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 13 | * works fine as well. 14 | */ 15 | 16 | #define IridiumSerial Serial1 17 | #define DIAGNOSTICS false // Change this to see diagnostics 18 | 19 | // Declare the IridiumSBD object 20 | IridiumSBD modem(IridiumSerial); 21 | 22 | void setup() 23 | { 24 | int signalQuality = -1; 25 | int err; 26 | 27 | // Start the console serial port 28 | Serial.begin(115200); 29 | while (!Serial); 30 | 31 | // Start the serial port connected to the satellite modem 32 | IridiumSerial.begin(19200); 33 | 34 | // Begin satellite modem operation 35 | Serial.println(F("Starting modem...")); 36 | err = modem.begin(); 37 | if (err != ISBD_SUCCESS) 38 | { 39 | Serial.print(F("Begin failed: error ")); 40 | Serial.println(err); 41 | if (err == ISBD_NO_MODEM_DETECTED) 42 | Serial.println(F("No modem detected: check wiring.")); 43 | return; 44 | } 45 | 46 | // Get the IMEI 47 | char IMEI[16]; 48 | err = modem.getIMEI(IMEI, sizeof(IMEI)); 49 | if (err != ISBD_SUCCESS) 50 | { 51 | Serial.print(F("getIMEI failed: error ")); 52 | Serial.println(err); 53 | return; 54 | } 55 | Serial.print(F("IMEI is ")); 56 | Serial.print(IMEI); 57 | Serial.println(F(".")); 58 | } 59 | 60 | void loop() 61 | { 62 | } 63 | 64 | #if DIAGNOSTICS 65 | void ISBDConsoleCallback(IridiumSBD *device, char c) 66 | { 67 | Serial.write(c); 68 | } 69 | 70 | void ISBDDiagsCallback(IridiumSBD *device, char c) 71 | { 72 | Serial.write(c); 73 | } 74 | #endif 75 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example2_CheckCSQ/Example2_CheckCSQ.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | /* 4 | * Check CSQ 5 | * 6 | * This sketch checks the Iridium signal quality. 7 | * 8 | * Assumptions 9 | * 10 | * The sketch assumes an Arduino Mega or other Arduino-like device with 11 | * multiple HardwareSerial ports. It assumes the satellite modem is 12 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 13 | * works fine as well. 14 | */ 15 | 16 | #define IridiumSerial Serial1 17 | #define DIAGNOSTICS false // Change this to see diagnostics 18 | 19 | // Declare the IridiumSBD object 20 | IridiumSBD modem(IridiumSerial); 21 | 22 | void setup() 23 | { 24 | int signalQuality = -1; 25 | int err; 26 | 27 | // Start the console serial port 28 | Serial.begin(115200); 29 | while (!Serial); 30 | 31 | // Start the serial port connected to the satellite modem 32 | IridiumSerial.begin(19200); 33 | 34 | // Begin satellite modem operation 35 | Serial.println(F("Starting modem...")); 36 | err = modem.begin(); 37 | if (err != ISBD_SUCCESS) 38 | { 39 | Serial.print(F("Begin failed: error ")); 40 | Serial.println(err); 41 | if (err == ISBD_NO_MODEM_DETECTED) 42 | Serial.println(F("No modem detected: check wiring.")); 43 | return; 44 | } 45 | 46 | // Print the firmware revision 47 | char version[12]; 48 | err = modem.getFirmwareVersion(version, sizeof(version)); 49 | if (err != ISBD_SUCCESS) 50 | { 51 | Serial.print(F("FirmwareVersion failed: error ")); 52 | Serial.println(err); 53 | return; 54 | } 55 | Serial.print(F("Firmware Version is ")); 56 | Serial.print(version); 57 | Serial.println(F(".")); 58 | 59 | // Get the IMEI 60 | char IMEI[16]; 61 | err = modem.getIMEI(IMEI, sizeof(IMEI)); 62 | if (err != ISBD_SUCCESS) 63 | { 64 | Serial.print(F("getIMEI failed: error ")); 65 | Serial.println(err); 66 | return; 67 | } 68 | Serial.print(F("IMEI is ")); 69 | Serial.print(IMEI); 70 | Serial.println(F(".")); 71 | 72 | // Check the signal quality. 73 | // This returns a number between 0 and 5. 74 | // 2 or better is preferred. 75 | err = modem.getSignalQuality(signalQuality); 76 | if (err != ISBD_SUCCESS) 77 | { 78 | Serial.print(F("SignalQuality failed: error ")); 79 | Serial.println(err); 80 | return; 81 | } 82 | 83 | Serial.print(F("On a scale of 0 to 5, signal quality is currently ")); 84 | Serial.print(signalQuality); 85 | Serial.println(F(".")); 86 | } 87 | 88 | void loop() 89 | { 90 | } 91 | 92 | #if DIAGNOSTICS 93 | void ISBDConsoleCallback(IridiumSBD *device, char c) 94 | { 95 | Serial.write(c); 96 | } 97 | 98 | void ISBDDiagsCallback(IridiumSBD *device, char c) 99 | { 100 | Serial.write(c); 101 | } 102 | #endif 103 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example3_GetTime/Example3_GetTime.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | #include 3 | /* 4 | * Time 5 | * 6 | * This sketch demonstrates how to retrieve the Iridium system time 7 | * from the modem using the getSystemTime method. This uses 8 | * the Iridium command AT-MSSTM to acquire the time. The method will 9 | * fail if the Iridium network has not yet been acquired. 10 | * 11 | * Assumptions 12 | * 13 | * The sketch assumes an Arduino Mega or other Arduino-like device with 14 | * multiple HardwareSerial ports. It assumes the satellite modem is 15 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 16 | * works fine as well. 17 | */ 18 | 19 | #define IridiumSerial Serial1 20 | #define DIAGNOSTICS false // Change this to see diagnostics 21 | 22 | // Declare the IridiumSBD object 23 | IridiumSBD modem(IridiumSerial); 24 | 25 | void setup() 26 | { 27 | int err; 28 | 29 | // Start the console serial port 30 | Serial.begin(115200); 31 | while (!Serial); 32 | 33 | // Start the serial port connected to the satellite modem 34 | IridiumSerial.begin(19200); 35 | 36 | // If we're powering the device by USB, tell the library to 37 | // relax timing constraints waiting for the supercap to recharge. 38 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 39 | 40 | // Begin satellite modem operation 41 | Serial.println(F("Starting modem...")); 42 | err = modem.begin(); 43 | if (err != ISBD_SUCCESS) 44 | { 45 | Serial.print(F("Begin failed: error ")); 46 | Serial.println(err); 47 | if (err == ISBD_NO_MODEM_DETECTED) 48 | Serial.println(F("No modem detected: check wiring.")); 49 | return; 50 | } 51 | } 52 | 53 | void loop() 54 | { 55 | struct tm t; 56 | int err = modem.getSystemTime(t); 57 | if (err == ISBD_SUCCESS) 58 | { 59 | char buf[32]; 60 | sprintf(buf, "%d-%02d-%02d %02d:%02d:%02d", 61 | t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); 62 | Serial.print(F("Iridium time/date is ")); 63 | Serial.println(buf); 64 | } 65 | 66 | else if (err == ISBD_NO_NETWORK) // Did it fail because the transceiver has not yet seen the network? 67 | { 68 | Serial.println(F("No network detected. Waiting 10 seconds.")); 69 | } 70 | 71 | else 72 | { 73 | Serial.print(F("Unexpected error ")); 74 | Serial.println(err); 75 | return; 76 | } 77 | 78 | // Delay 10 seconds 79 | delay(10 * 1000UL); 80 | } 81 | 82 | #if DIAGNOSTICS 83 | void ISBDConsoleCallback(IridiumSBD *device, char c) 84 | { 85 | Serial.write(c); 86 | } 87 | 88 | void ISBDDiagsCallback(IridiumSBD *device, char c) 89 | { 90 | Serial.write(c); 91 | } 92 | #endif 93 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example4_BasicSend/Example4_BasicSend.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | /* 4 | * BasicSend 5 | * 6 | * This sketch sends a "Hello, world!" message from the satellite modem. 7 | * If you have activated your account and have credits, this message 8 | * should arrive at the endpoints (delivery group) you have configured 9 | * (email address or HTTP POST). 10 | * 11 | * Assumptions 12 | * 13 | * The sketch assumes an Arduino Mega or other Arduino-like device with 14 | * multiple HardwareSerial ports. It assumes the satellite modem is 15 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 16 | * works fine as well. 17 | */ 18 | 19 | #define IridiumSerial Serial1 20 | #define DIAGNOSTICS false // Change this to see diagnostics 21 | 22 | // Declare the IridiumSBD object 23 | IridiumSBD modem(IridiumSerial); 24 | 25 | void setup() 26 | { 27 | int signalQuality = -1; 28 | int err; 29 | 30 | // Start the console serial port 31 | Serial.begin(115200); 32 | while (!Serial); 33 | 34 | // Start the serial port connected to the satellite modem 35 | IridiumSerial.begin(19200); 36 | 37 | // Begin satellite modem operation 38 | Serial.println(F("Starting modem...")); 39 | err = modem.begin(); 40 | if (err != ISBD_SUCCESS) 41 | { 42 | Serial.print(F("Begin failed: error ")); 43 | Serial.println(err); 44 | if (err == ISBD_NO_MODEM_DETECTED) 45 | Serial.println(F("No modem detected: check wiring.")); 46 | return; 47 | } 48 | 49 | // Example: Print the firmware revision 50 | char version[12]; 51 | err = modem.getFirmwareVersion(version, sizeof(version)); 52 | if (err != ISBD_SUCCESS) 53 | { 54 | Serial.print(F("FirmwareVersion failed: error ")); 55 | Serial.println(err); 56 | return; 57 | } 58 | Serial.print(F("Firmware Version is ")); 59 | Serial.print(version); 60 | Serial.println(F(".")); 61 | 62 | // Example: Print the IMEI 63 | char IMEI[16]; 64 | err = modem.getIMEI(IMEI, sizeof(IMEI)); 65 | if (err != ISBD_SUCCESS) 66 | { 67 | Serial.print(F("getIMEI failed: error ")); 68 | Serial.println(err); 69 | return; 70 | } 71 | Serial.print(F("IMEI is ")); 72 | Serial.print(IMEI); 73 | Serial.println(F(".")); 74 | 75 | // Example: Test the signal quality. 76 | // This returns a number between 0 and 5. 77 | // 2 or better is preferred. 78 | err = modem.getSignalQuality(signalQuality); 79 | if (err != ISBD_SUCCESS) 80 | { 81 | Serial.print(F("SignalQuality failed: error ")); 82 | Serial.println(err); 83 | return; 84 | } 85 | 86 | Serial.print(F("On a scale of 0 to 5, signal quality is currently ")); 87 | Serial.print(signalQuality); 88 | Serial.println(F(".")); 89 | 90 | // Send the message 91 | Serial.println(F("Trying to send the message. This might take several minutes.")); 92 | err = modem.sendSBDText("Hello, world!"); 93 | if (err != ISBD_SUCCESS) 94 | { 95 | Serial.print(F("sendSBDText failed: error ")); 96 | Serial.println(err); 97 | if (err == ISBD_SENDRECEIVE_TIMEOUT) 98 | Serial.println(F("Try again with a better view of the sky.")); 99 | } 100 | 101 | else 102 | { 103 | Serial.println(F("Hey, it worked!")); 104 | } 105 | 106 | // Clear the Mobile Originated message buffer 107 | Serial.println(F("Clearing the MO buffer.")); 108 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear MO buffer 109 | if (err != ISBD_SUCCESS) 110 | { 111 | Serial.print(F("clearBuffers failed: error ")); 112 | Serial.println(err); 113 | } 114 | 115 | Serial.println(F("Done!")); 116 | } 117 | 118 | void loop() 119 | { 120 | } 121 | 122 | #if DIAGNOSTICS 123 | void ISBDConsoleCallback(IridiumSBD *device, char c) 124 | { 125 | Serial.write(c); 126 | } 127 | 128 | void ISBDDiagsCallback(IridiumSBD *device, char c) 129 | { 130 | Serial.write(c); 131 | } 132 | #endif 133 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example5_Sleep/Example5_Sleep.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | /* 4 | * Sleep 5 | * 6 | * This sketch demonstrates how to use the RockBLOCK Sleep pin. The 7 | * general strategy is to call modem.begin() to start, then modem.sleep() 8 | * to stop. 9 | * 10 | * Assumptions 11 | * 12 | * The sketch assumes an Arduino Mega or other Arduino-like device with 13 | * multiple HardwareSerial ports. It assumes the satellite modem is 14 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 15 | * works fine as well. 16 | * 17 | * This sketch also assumes that pin 4 is connected to ON/OFF 18 | */ 19 | 20 | #define IridiumSerial Serial1 21 | #define SLEEP_PIN 4 22 | #define DIAGNOSTICS false // Change this to see diagnostics 23 | 24 | // Declare the IridiumSBD object (note SLEEP pin) 25 | IridiumSBD modem(IridiumSerial, SLEEP_PIN); 26 | 27 | void setup() 28 | { 29 | // Start the console serial port 30 | Serial.begin(115200); 31 | while (!Serial); 32 | 33 | // Start the serial port connected to the satellite modem 34 | IridiumSerial.begin(19200); 35 | } 36 | 37 | void loop() 38 | { 39 | // Begin satellite modem operation 40 | Serial.println(F("Starting modem...")); 41 | int err = modem.begin(); 42 | if (err != ISBD_SUCCESS) 43 | { 44 | Serial.print(F("Begin failed: error ")); 45 | Serial.println(err); 46 | if (err == ISBD_NO_MODEM_DETECTED) 47 | Serial.println(F("No modem detected: check wiring.")); 48 | return; 49 | } 50 | 51 | // Send the message 52 | Serial.println(F("Trying to send a message. This might take several minutes.")); 53 | err = modem.sendSBDText("Hello, world! (Sleep test)"); 54 | if (err != ISBD_SUCCESS) 55 | { 56 | Serial.print(F("sendSBDText failed: error ")); 57 | Serial.println(err); 58 | if (err == ISBD_SENDRECEIVE_TIMEOUT) 59 | Serial.println(F("Try again with a better view of the sky.")); 60 | } 61 | 62 | else 63 | { 64 | Serial.println(F("Hey, it worked!")); 65 | } 66 | 67 | // Clear the Mobile Originated message buffer 68 | Serial.println(F("Clearing the MO buffer.")); 69 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear MO buffer 70 | if (err != ISBD_SUCCESS) 71 | { 72 | Serial.print(F("clearBuffers failed: error ")); 73 | Serial.println(err); 74 | } 75 | 76 | // Put modem to sleep 77 | Serial.println(F("Putting modem to sleep.")); 78 | err = modem.sleep(); 79 | if (err != ISBD_SUCCESS) 80 | { 81 | Serial.print(F("sleep failed: error ")); 82 | Serial.println(err); 83 | } 84 | 85 | // Demonstrate that device is asleep 86 | Serial.println(F("Trying to send while asleep.")); 87 | err = modem.sendSBDText("This shouldn't work."); 88 | if (err == ISBD_IS_ASLEEP) 89 | { 90 | Serial.println(F("Couldn't send: device asleep.")); 91 | } 92 | else 93 | { 94 | Serial.print(F("Send failed for some other reason: error ")); 95 | Serial.println(err); 96 | } 97 | 98 | Serial.println(F("Sleeping for a minute.")); 99 | delay(60 * 1000UL); 100 | } 101 | 102 | #if DIAGNOSTICS 103 | void ISBDConsoleCallback(IridiumSBD *device, char c) 104 | { 105 | Serial.write(c); 106 | } 107 | 108 | void ISBDDiagsCallback(IridiumSBD *device, char c) 109 | { 110 | Serial.write(c); 111 | } 112 | #endif 113 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example6_SendReceive/Example6_SendReceive.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | /* 4 | * SendReceive 5 | * 6 | * This sketch demonstrates a basic bidirectional transmission. Before 7 | * loading this sketch, send a message to your Iridium modem from your 8 | * control panel or via email. This sketch will send a binary buffer 9 | * of 11 bytes, then attempt to read the next incoming messages (if any). 10 | * It stops when there are no more messages to read. 11 | * 12 | * Assumptions 13 | * 14 | * The sketch assumes an Arduino Mega or other Arduino-like device with 15 | * multiple HardwareSerial ports. It assumes the satellite modem is 16 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 17 | * works fine as well. 18 | * 19 | */ 20 | 21 | #define IridiumSerial Serial1 22 | #define DIAGNOSTICS false // Change this to see diagnostics 23 | 24 | IridiumSBD modem(IridiumSerial); 25 | 26 | // Define the binary test message (Fibonacci sequence) 27 | uint8_t buffer[200] = 28 | { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 }; 29 | 30 | void setup() 31 | { 32 | int signalQuality = -1; 33 | 34 | // Start the serial ports 35 | Serial.begin(115200); 36 | while (!Serial); 37 | IridiumSerial.begin(19200); 38 | 39 | // Setup the Iridium modem 40 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 41 | if (modem.begin() != ISBD_SUCCESS) 42 | { 43 | Serial.println(F("Couldn't begin modem operations.")); 44 | exit(0); 45 | } 46 | 47 | // Check the signal quality (optional) 48 | int err = modem.getSignalQuality(signalQuality); 49 | if (err != 0) 50 | { 51 | Serial.print(F("SignalQuality failed: error ")); 52 | Serial.println(err); 53 | exit(1); 54 | } 55 | 56 | Serial.print(F("Signal quality is ")); 57 | Serial.println(signalQuality); 58 | } 59 | 60 | static bool messageSent = false; 61 | 62 | void loop() 63 | { 64 | int err; 65 | 66 | // Read/Write the first time or if there are any remaining messages 67 | if (!messageSent || modem.getWaitingMessageCount() > 0) 68 | { 69 | size_t bufferSize = sizeof(buffer); 70 | 71 | // First time through send+receive; subsequent loops receive only (send a NULL message) 72 | if (!messageSent) 73 | err = modem.sendReceiveSBDBinary(buffer, 11, buffer, bufferSize); 74 | else 75 | err = modem.sendReceiveSBDText(NULL, buffer, bufferSize); 76 | 77 | if (err != ISBD_SUCCESS) 78 | { 79 | Serial.print(F("sendReceiveSBD* failed: error ")); 80 | Serial.println(err); 81 | } 82 | else // success! 83 | { 84 | messageSent = true; 85 | Serial.print(F("Inbound buffer size is ")); 86 | Serial.println(bufferSize); 87 | for (int i=0; i // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | /* 4 | * Ring 5 | * 6 | * This sketch demonstrates how to use the Iridium RING line to detect 7 | * when inbound messages are available and retrieve them. 8 | * 9 | * Assumptions 10 | * 11 | * The sketch assumes an Arduino Mega or other Arduino-like device with 12 | * multiple HardwareSerial ports. It assumes the satellite modem is 13 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 14 | * works fine as well. 15 | * 16 | * This sketch assumes the Ring Indicator pin is connected to Arduino pin 5 17 | * 18 | */ 19 | 20 | #define IridiumSerial Serial1 21 | #define RING_PIN 5 22 | #define DIAGNOSTICS false // Change this to see diagnostics 23 | 24 | IridiumSBD modem(IridiumSerial, -1, RING_PIN); 25 | 26 | void setup() 27 | { 28 | int signalQuality = -1; 29 | 30 | // Start the serial ports 31 | Serial.begin(115200); 32 | while (!Serial); 33 | IridiumSerial.begin(19200); 34 | 35 | // Setup the Iridium modem 36 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 37 | if (modem.begin() != ISBD_SUCCESS) 38 | { 39 | Serial.println(F("Couldn't begin modem operations.")); 40 | exit(0); 41 | } 42 | 43 | // Check signal quality for fun. 44 | int err = modem.getSignalQuality(signalQuality); 45 | if (err != 0) 46 | { 47 | Serial.print(F("SignalQuality failed: error ")); 48 | Serial.println(err); 49 | return; 50 | } 51 | 52 | Serial.print(F("Signal quality is ")); 53 | Serial.println(signalQuality); 54 | Serial.println(F("Begin waiting for RING...")); 55 | } 56 | 57 | 58 | void loop() 59 | { 60 | static int err = ISBD_SUCCESS; 61 | bool ring = modem.hasRingAsserted(); 62 | if (ring || modem.getWaitingMessageCount() > 0 || err != ISBD_SUCCESS) 63 | { 64 | if (ring) 65 | Serial.println(F("RING asserted! Let's try to read the incoming message.")); 66 | else if (modem.getWaitingMessageCount() > 0) 67 | Serial.println(F("Waiting messages available. Let's try to read them.")); 68 | else 69 | Serial.println(F("Let's try again.")); 70 | 71 | // Clear the Mobile Originated message buffer - just in case it has an old message in it! 72 | Serial.println(F("Clearing the MO buffer (just in case).")); 73 | err = modem.clearBuffers(ISBD_CLEAR_MO); // Clear MO buffer 74 | if (err != ISBD_SUCCESS) 75 | { 76 | Serial.print(F("clearBuffers failed: error ")); 77 | Serial.println(err); 78 | return; 79 | } 80 | 81 | uint8_t buffer[200]; 82 | size_t bufferSize = sizeof(buffer); 83 | err = modem.sendReceiveSBDText(NULL, buffer, bufferSize); 84 | if (err != ISBD_SUCCESS) 85 | { 86 | Serial.print(F("sendReceiveSBDBinary failed: error ")); 87 | Serial.println(err); 88 | return; 89 | } 90 | 91 | Serial.println(F("Message received!")); 92 | Serial.print(F("Inbound message size is ")); 93 | Serial.println(bufferSize); 94 | for (int i=0; i<(int)bufferSize; ++i) 95 | { 96 | Serial.print(buffer[i], HEX); 97 | if (isprint(buffer[i])) 98 | { 99 | Serial.print(F("(")); 100 | Serial.write(buffer[i]); 101 | Serial.print(F(")")); 102 | } 103 | Serial.print(F(" ")); 104 | } 105 | Serial.println(); 106 | Serial.print(F("Messages remaining to be retrieved: ")); 107 | Serial.println(modem.getWaitingMessageCount()); 108 | } 109 | } 110 | 111 | #if DIAGNOSTICS 112 | void ISBDConsoleCallback(IridiumSBD *device, char c) 113 | { 114 | Serial.write(c); 115 | } 116 | 117 | void ISBDDiagsCallback(IridiumSBD *device, char c) 118 | { 119 | Serial.write(c); 120 | } 121 | #endif 122 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example8_Beacon/Example8_Beacon.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | #include // NMEA parsing: http://arduiniana.org 3 | 4 | /* 5 | * Beacon 6 | * 7 | * This sketch shows how you might use a GPS with the satellite modem 8 | * to create a beacon device that periodically transmits a location 9 | * message to the configured endpoints. 10 | * 11 | * Assumptions 12 | * 13 | * The sketch assumes an Arduino Mega or other Arduino-like device with 14 | * multiple HardwareSerial ports. It assumes the satellite modem is 15 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 16 | * works fine as well. This assumes a 9600 baud GPS is connected to Serial2 17 | */ 18 | 19 | #define IridiumSerial Serial1 20 | #define GPSSerial Serial2 21 | 22 | #define GPSBaud 9600 23 | #define DIAGNOSTICS false // Change this to see diagnostics 24 | 25 | // Time between transmissions (seconds) 26 | #define BEACON_INTERVAL 600 27 | 28 | IridiumSBD modem(IridiumSerial); 29 | TinyGPSPlus tinygps; 30 | static const int ledPin = LED_BUILTIN; 31 | 32 | void setup() 33 | { 34 | pinMode(ledPin, OUTPUT); 35 | 36 | // Start the serial ports 37 | Serial.begin(115200); 38 | while (!Serial); 39 | IridiumSerial.begin(19200); 40 | GPSSerial.begin(GPSBaud); 41 | 42 | // Assume battery power 43 | modem.setPowerProfile(IridiumSBD::DEFAULT_POWER_PROFILE); 44 | 45 | // Setup the Iridium modem 46 | if (modem.begin() != ISBD_SUCCESS) 47 | { 48 | Serial.println(F("Couldn't begin modem operations.")); 49 | exit(0); 50 | } 51 | } 52 | 53 | void loop() 54 | { 55 | unsigned long loopStartTime = millis(); 56 | 57 | // Begin listening to the GPS 58 | Serial.println(F("Beginning to listen for GPS traffic...")); 59 | 60 | // Look for GPS signal for up to 7 minutes 61 | while ((!tinygps.location.isValid() || !tinygps.date.isValid()) && 62 | millis() - loopStartTime < 7UL * 60UL * 1000UL) 63 | { 64 | if (GPSSerial.available()) 65 | tinygps.encode(GPSSerial.read()); 66 | } 67 | 68 | // Did we get a GPS fix? 69 | if (!tinygps.location.isValid()) 70 | { 71 | Serial.println(F("Could not get GPS fix.")); 72 | Serial.print(F("GPS characters seen = ")); 73 | Serial.println(tinygps.charsProcessed()); 74 | Serial.print(F("Checksum errors = ")); 75 | Serial.println(tinygps.failedChecksum()); 76 | return; 77 | } 78 | 79 | Serial.println(F("A GPS fix was found!")); 80 | 81 | // Step 3: Start talking to the RockBLOCK and power it up 82 | Serial.println(F("Beginning to talk to the RockBLOCK...")); 83 | char outBuffer[60]; // Always try to keep message short 84 | sprintf(outBuffer, "%d%02d%02d%02d%02d%02d,%s%u.%09lu,%s%u.%09lu,%lu,%ld", 85 | tinygps.date.year(), 86 | tinygps.date.month(), 87 | tinygps.date.day(), 88 | tinygps.time.hour(), 89 | tinygps.time.minute(), 90 | tinygps.time.second(), 91 | tinygps.location.rawLat().negative ? "-" : "", 92 | tinygps.location.rawLat().deg, 93 | tinygps.location.rawLat().billionths, 94 | tinygps.location.rawLng().negative ? "-" : "", 95 | tinygps.location.rawLng().deg, 96 | tinygps.location.rawLng().billionths, 97 | tinygps.speed.value() / 100, 98 | tinygps.course.value() / 100); 99 | 100 | Serial.print(F("Transmitting message '")); 101 | Serial.print(outBuffer); 102 | Serial.println(F("'")); 103 | 104 | int err = modem.sendSBDText(outBuffer); 105 | if (err != ISBD_SUCCESS) 106 | { 107 | Serial.print(F("Transmission failed with error code ")); 108 | Serial.println(err); 109 | } 110 | 111 | // Sleep 112 | int elapsedSeconds = (int)((millis() - loopStartTime) / 1000); 113 | if (elapsedSeconds < BEACON_INTERVAL) 114 | { 115 | int delaySeconds = BEACON_INTERVAL - elapsedSeconds; 116 | Serial.print(F("Waiting for ")); 117 | Serial.print(delaySeconds); 118 | Serial.println(F(" seconds")); 119 | delay(1000UL * delaySeconds); 120 | } 121 | 122 | // Wake 123 | Serial.println(F("Wake up!")); 124 | } 125 | 126 | void blinkLED() 127 | { 128 | digitalWrite(ledPin, (millis() / 1000) % 2 == 1 ? HIGH : LOW); 129 | } 130 | 131 | bool ISBDCallback() 132 | { 133 | blinkLED(); 134 | return true; 135 | } 136 | 137 | #if DIAGNOSTICS 138 | void ISBDConsoleCallback(IridiumSBD *device, char c) 139 | { 140 | Serial.write(c); 141 | } 142 | 143 | void ISBDDiagsCallback(IridiumSBD *device, char c) 144 | { 145 | Serial.write(c); 146 | } 147 | #endif 148 | -------------------------------------------------------------------------------- /examples/Serial_Examples__RockBLOCK/Example9_PassThru/Example9_PassThru.ino: -------------------------------------------------------------------------------- 1 | #include // Click here to get the library: http://librarymanager/All#IridiumSBDI2C 2 | 3 | /* 4 | * PassThru 5 | * 6 | * This sketch allows you to send data directly from the Serial console 7 | * to the modem. Characters typed in the console are relayed to the 8 | * modem and vice versa. 9 | * 10 | * The sketch assumes an Arduino Mega or other Arduino-like device with 11 | * multiple HardwareSerial ports. It assumes the satellite modem is 12 | * connected to Serial1. Change this as needed. SoftwareSerial on an Uno 13 | * works fine as well. 14 | * 15 | * Open the Serial Monitor and set the Baud Rate to 115200 16 | * and the line ending to Carriage Return 17 | * 18 | * Command Response Description 19 | * AT+CGMI Iridium Get manufacturer identification 20 | * AT+CGMM Get model identification 21 | * AT+CGMR Get revision 22 | * AT+CGSN Get serial number (IMEI) 23 | * AT+CSQ Get signal quality 24 | * 25 | * To send a Mobile Originated text message and check for a new Mobile Terminated message: 26 | * AT+SBDWT=Testing123 Write a text message to the MO buffer 27 | * AT+SBDS Read the MO and MT buffer status (MO flag should be '1') 28 | * AT+SBDIX Initiate an SBD session (wait for it to complete - could take several minutes!) 29 | * AT+SBDS Read the MO and MT buffer status (MO flag should still be '1'; 30 | * MT flag will be '1' if a new message was received) 31 | * AT+SBDD0 Clear the MO buffer 32 | * AT+SBDRT Read the received text message (if there was one) 33 | * AT+SBDD1 Clear the MT buffer 34 | * AT+SBDS Read the MO and MT buffer status (Both MO and MT flags should be '0') 35 | * 36 | * The full AT command set can be found here: 37 | * http://www.rock7mobile.com/downloads/IRDM_ISU_ATCommandReferenceMAN0009_Rev2.0_ATCOMM_Oct2012.pdf 38 | * (Only a small sub-set of the commands apply to the 9603N) 39 | */ 40 | 41 | #define IridiumSerial Serial1 42 | #define DIAGNOSTICS false // Change this to see diagnostics 43 | 44 | IridiumSBD modem(IridiumSerial); 45 | 46 | void setup() 47 | { 48 | int signalQuality = -1; 49 | 50 | // Start the serial ports 51 | Serial.begin(115200); 52 | while (!Serial); 53 | IridiumSerial.begin(19200); 54 | 55 | // Setup the Iridium modem 56 | modem.setPowerProfile(IridiumSBD::USB_POWER_PROFILE); 57 | if (modem.begin() != ISBD_SUCCESS) 58 | { 59 | Serial.println(F("Couldn't begin modem operations.")); 60 | exit(0); 61 | } 62 | 63 | // Check the signal quality (optional) 64 | int err = modem.getSignalQuality(signalQuality); 65 | if (err != 0) 66 | { 67 | Serial.print(F("SignalQuality failed: error ")); 68 | Serial.println(err); 69 | exit(1); 70 | } 71 | 72 | Serial.print(F("Signal quality is ")); 73 | Serial.println(signalQuality); 74 | 75 | Serial.println(F("Enter commands terminated by Carriage Return ('\\r'):")); 76 | } 77 | 78 | void loop() 79 | { 80 | if (Serial.available()) 81 | IridiumSerial.write(Serial.read()); 82 | if (IridiumSerial.available()) 83 | Serial.write(IridiumSerial.read()); 84 | } 85 | 86 | #if DIAGNOSTICS 87 | void ISBDConsoleCallback(IridiumSBD *device, char c) 88 | { 89 | Serial.write(c); 90 | } 91 | 92 | void ISBDDiagsCallback(IridiumSBD *device, char c) 93 | { 94 | Serial.write(c); 95 | } 96 | #endif 97 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map for IridiumSBD 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | IridiumSBD KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | sendSBDBinary KEYWORD2 17 | sendReceiveSBDBinary KEYWORD2 18 | sendSBDText KEYWORD2 19 | sendReceiveSBDText KEYWORD2 20 | getSignalQuality KEYWORD2 21 | getWaitingMessageCount KEYWORD2 22 | sleep KEYWORD2 23 | isAsleep KEYWORD2 24 | setPowerProfile KEYWORD2 25 | adjustATTimeout KEYWORD2 26 | adjustSendReceiveTimeout KEYWORD2 27 | adjustStartupTimeout KEYWORD2 28 | useMSSTMWorkaround KEYWORD2 29 | getSystemTime KEYWORD2 30 | getFirmwareVersion KEYWORD2 31 | hasRingAsserted KEYWORD2 32 | enableRingAlerts KEYWORD2 33 | ISBDCallback KEYWORD2 34 | ISBDConsoleCallback KEYWORD2 35 | ISBDDiagsCallback KEYWORD2 36 | enableSuperCapCharger KEYWORD2 37 | checkSuperCapCharger KEYWORD2 38 | enable9603Npower KEYWORD2 39 | checkRingIndicator KEYWORD2 40 | clearRingIndicator KEYWORD2 41 | checkNetworkAvailable KEYWORD2 42 | enable9603 KEYWORD2 43 | clearBuffers KEYWORD2 44 | getIMEI KEYWORD2 45 | isConnected KEYWORD2 46 | passThruI2Cread KEYWORD2 47 | passThruI2Cwrite KEYWORD2 48 | configureSleepPin KEYWORD2 49 | setSleepPin KEYWORD2 50 | beginSerialPort KEYWORD2 51 | endSerialPort KEYWORD2 52 | 53 | ####################################### 54 | # Constants (LITERAL1) 55 | ####################################### 56 | 57 | ISBD_SUCCESS LITERAL1 58 | ISBD_ALREADY_AWAKE LITERAL1 59 | ISBD_SERIAL_FAILURE LITERAL1 60 | ISBD_PROTOCOL_ERROR LITERAL1 61 | ISBD_CANCELLED LITERAL1 62 | ISBD_NO_MODEM_DETECTED LITERAL1 63 | ISBD_SBDIX_FATAL_ERROR LITERAL1 64 | ISBD_SENDRECEIVE_TIMEOUT LITERAL1 65 | ISBD_RX_OVERFLOW LITERAL1 66 | ISBD_REENTRANT LITERAL1 67 | ISBD_IS_ASLEEP LITERAL1 68 | ISBD_NO_SLEEP_PIN LITERAL1 69 | ISBD_NO_NETWORK LITERAL1 70 | ISBD_MSG_TOO_LONG LITERAL1 71 | DEFAULT_POWER_PROFILE LITERAL1 72 | USB_POWER_PROFILE LITERAL1 73 | ISBD_CLEAR_MO LITERAL1 74 | ISBD_CLEAR_MT LITERAL1 75 | ISBD_CLEAR_BOTH LITERAL1 76 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=IridiumSBDi2c 2 | version=3.0.6 3 | author=Mikal Hart and Paul Clark (PaulZC) 4 | maintainer=SparkFun Electronics 5 | sentence=This library supports satellite data transmissions from anywhere on earth using the RockBLOCK family of Iridium 9602 and 9603 modems. 6 | paragraph=It works on other Iridium devices too including the Qwiic Iridium 9603N (I2C). Messages are "twitter length" and can be sent to and from the device using email, HTTP POST, or the Rock7 console. Great for tracking balloons, vehicles, and ocean floaters. 7 | category=Communication 8 | url=https://github.com/sparkfun/SparkFun_IridiumSBD_I2C_Arduino_Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/IridiumSBD.h: -------------------------------------------------------------------------------- 1 | /* 2 | IridiumSBD - An Arduino library for Iridium SBD ("Short Burst Data") Communications 3 | Suggested and generously supported by Rock Seven Location Technology 4 | (http://rock7mobile.com), makers of the brilliant RockBLOCK satellite modem. 5 | Copyright (C) 2013-2017 Mikal Hart 6 | All rights reserved. 7 | 8 | Updated by Paul Clark to provide I2C support for the Qwiic Iridium 9603N 9 | 10 | This library is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU Lesser General Public 12 | License as published by the Free Software Foundation; either 13 | version 2.1 of the License, or (at your option) any later version. 14 | 15 | This library is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | Lesser General Public License for more details. 19 | 20 | You should have received a copy of the GNU Lesser General Public 21 | License along with this library; if not, write to the Free Software 22 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 | */ 24 | 25 | #include // for FlashString 26 | #include // for Stream 27 | 28 | #ifndef IRIDIUM_SBD // https://github.com/mikalhart/IridiumSBD/pull/14 29 | #define IRIDIUM_SBD 30 | 31 | #if (ARDUINO >= 100) 32 | #include "Arduino.h" 33 | #else 34 | #include "WProgram.h" 35 | #endif 36 | 37 | #include 38 | 39 | //Platform specific configurations 40 | 41 | //Define the size of the I2C buffer based on the platform the user has 42 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 43 | #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 44 | 45 | //I2C_BUFFER_LENGTH is defined in Wire.H 46 | #define I2C_BUFFER_LENGTH BUFFER_LENGTH 47 | 48 | #elif defined(__SAMD21G18A__) 49 | 50 | //SAMD21 uses RingBuffer.h 51 | #define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE 52 | 53 | //#elif __MK20DX256__ 54 | //Teensy 55 | 56 | #endif 57 | 58 | #ifndef I2C_BUFFER_LENGTH 59 | 60 | //The catch-all default is 32 61 | #define I2C_BUFFER_LENGTH 32 62 | 63 | #endif 64 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 65 | 66 | #define ISBD_LIBRARY_REVISION 3 // Changed by Paul to reflect substantial update for I2C functions 67 | #define ISBD_DEFAULT_AT_TIMEOUT 30 68 | #define ISBD_MSSTM_RETRY_INTERVAL 10 69 | #define ISBD_DEFAULT_SBDIX_INTERVAL 10 70 | #define ISBD_USB_SBDIX_INTERVAL 30 71 | #define ISBD_DEFAULT_SENDRECEIVE_TIME 300 72 | #define ISBD_STARTUP_MAX_TIME 240 73 | #define ISBD_MAX_MESSAGE_LENGTH 340 74 | #define ISBD_MSSTM_WORKAROUND_FW_VER 13001 75 | 76 | #define ISBD_SUCCESS 0 77 | #define ISBD_ALREADY_AWAKE 1 78 | #define ISBD_SERIAL_FAILURE 2 79 | #define ISBD_PROTOCOL_ERROR 3 80 | #define ISBD_CANCELLED 4 81 | #define ISBD_NO_MODEM_DETECTED 5 82 | #define ISBD_SBDIX_FATAL_ERROR 6 83 | #define ISBD_SENDRECEIVE_TIMEOUT 7 84 | #define ISBD_RX_OVERFLOW 8 85 | #define ISBD_REENTRANT 9 86 | #define ISBD_IS_ASLEEP 10 87 | #define ISBD_NO_SLEEP_PIN 11 88 | #define ISBD_NO_NETWORK 12 89 | #define ISBD_MSG_TOO_LONG 13 90 | 91 | #define ISBD_CLEAR_MO 0 92 | #define ISBD_CLEAR_MT 1 93 | #define ISBD_CLEAR_BOTH 2 94 | 95 | typedef const __FlashStringHelper *FlashString; 96 | 97 | class IridiumSBD 98 | { 99 | public: 100 | int begin(); 101 | int sendSBDText(const char *message); 102 | int sendSBDBinary(const uint8_t *txData, size_t txDataSize); 103 | int sendReceiveSBDText(const char *message, uint8_t *rxBuffer, size_t &rxBufferSize); 104 | int sendReceiveSBDBinary(const uint8_t *txData, size_t txDataSize, uint8_t *rxBuffer, size_t &rxBufferSize); 105 | int getSignalQuality(int &quality); 106 | int getSystemTime(struct tm &tm); 107 | int getFirmwareVersion(char *version, size_t bufferSize); 108 | int getWaitingMessageCount(); 109 | bool isAsleep(); 110 | bool hasRingAsserted(); 111 | int sleep(); 112 | 113 | typedef enum { DEFAULT_POWER_PROFILE = 0, USB_POWER_PROFILE = 1 } POWERPROFILE; 114 | void setPowerProfile(POWERPROFILE profile); // 0 = direct connect (default), 1 = USB 115 | void adjustATTimeout(int seconds); // default value = 20 seconds 116 | void adjustSendReceiveTimeout(int seconds); // default value = 300 seconds 117 | void adjustStartupTimeout(int seconds); // default value = 240 seconds 118 | void useMSSTMWorkaround(bool useMSSTMWorkAround); // true to use workaround from Iridium Alert 5/7/13 119 | void enableRingAlerts(bool enable); 120 | 121 | int clearBuffers(int buffers = ISBD_CLEAR_MO); 122 | int getIMEI(char *IMEI, size_t bufferSize); 123 | 124 | // Functions for the Qwiic Iridium (only - not valid when using serial on the RockBLOCK) 125 | void enableSuperCapCharger(bool enable); 126 | bool checkSuperCapCharger(); 127 | void enable9603Npower(bool enable); 128 | bool checkRingIndicator(); 129 | void clearRingIndicator(); 130 | bool checkNetworkAvailable(); 131 | void enable9603(bool enable); 132 | void enable841lowPower(bool enable); 133 | bool isConnected(); 134 | int passThruI2Cread(uint8_t *rxBuffer, size_t &rxBufferSize, size_t &numBytes); 135 | int passThruI2Cwrite(uint8_t *txBuffer, size_t &txBufferSize); 136 | 137 | // Weak functions to configure and set the sleep pin - user can overwrite with a custom functions if required 138 | void configureSleepPin() __attribute__((weak)); 139 | void setSleepPin(uint8_t enable) __attribute__((weak)); 140 | 141 | // Weak functions to begin and end the Serial port after power(true) and before power(false) 142 | void beginSerialPort() __attribute__((weak)); 143 | void endSerialPort() __attribute__((weak)); 144 | 145 | IridiumSBD(Stream &str, int sleepPinNo = -1, int ringPinNo = -1) 146 | { 147 | useSerial = true; 148 | stream = &str; 149 | sbdixInterval = ISBD_USB_SBDIX_INTERVAL; 150 | atTimeout = ISBD_DEFAULT_AT_TIMEOUT; 151 | sendReceiveTimeout = ISBD_DEFAULT_SENDRECEIVE_TIME; 152 | startupTimeout = ISBD_STARTUP_MAX_TIME; 153 | remainingMessages = -1; 154 | asleep = true; 155 | reentrant = false; 156 | sleepPin = sleepPinNo; 157 | sleepPinConfigured = false; 158 | ringPin = ringPinNo; 159 | msstmWorkaroundRequested = true; 160 | ringAlertsEnabled = {ringPinNo != -1}; 161 | ringAsserted = false; 162 | lastPowerOnTime = 0UL; 163 | head = SBDRING; 164 | tail = SBDRING; 165 | nextChar = -1; 166 | i2c_ser_buffer_tail = 0; 167 | i2c_ser_buffer_head = 0; 168 | if (sleepPin != -1) 169 | pinMode(sleepPin, OUTPUT); 170 | if (ringPin != -1) 171 | pinMode(ringPin, INPUT); 172 | } 173 | 174 | IridiumSBD(TwoWire &wirePort = Wire, uint8_t deviceAddress = 0x63) 175 | { 176 | useSerial = false; 177 | wireport = &wirePort; 178 | deviceaddress = deviceAddress; 179 | sbdixInterval = ISBD_USB_SBDIX_INTERVAL; 180 | atTimeout = ISBD_DEFAULT_AT_TIMEOUT; 181 | sendReceiveTimeout = ISBD_DEFAULT_SENDRECEIVE_TIME; 182 | startupTimeout = ISBD_STARTUP_MAX_TIME; 183 | remainingMessages = -1; 184 | asleep = true; 185 | reentrant = false; 186 | sleepPin = -1; 187 | sleepPinConfigured = false; 188 | ringPin = -1; 189 | msstmWorkaroundRequested = false; 190 | ringAlertsEnabled = true; 191 | ringAsserted = false; 192 | lastPowerOnTime = 0UL; 193 | head = SBDRING; 194 | tail = SBDRING; 195 | nextChar = -1; 196 | i2c_ser_buffer_tail = 0; 197 | i2c_ser_buffer_head = 0; 198 | } 199 | 200 | private: 201 | Stream * stream; // Communicating with the Iridium 202 | TwoWire * wireport; 203 | uint8_t deviceaddress; 204 | bool useSerial; 205 | 206 | //Create the I2C_Serial buffer 207 | #define I2C_SER_MAX_BUFF 64 // RX buffer size 208 | char i2c_ser_buffer[I2C_SER_MAX_BUFF]; 209 | int i2c_ser_buffer_tail; 210 | int i2c_ser_buffer_head; 211 | 212 | //Qwiic Iridium ATtiny841 I2C buffer length 213 | #define TINY_I2C_BUFFER_LENGTH 32 214 | 215 | //Define the maximum number of serial bytes to be requested from the ATtiny841 216 | #define SER_PACKET_SIZE 8 217 | 218 | // Timings 219 | int sbdixInterval; 220 | int atTimeout; 221 | int sendReceiveTimeout; 222 | int startupTimeout; 223 | unsigned long lastCheck = 0; // The time in millis when the I2C bus was last checked (limits I2C traffic) 224 | const uint8_t I2C_POLLING_WAIT_MS = 5; //Limit checking of new characters to every 5 ms (roughly 10 chars at 19200 baud) 225 | 226 | // State variables 227 | int remainingMessages; 228 | bool asleep; 229 | bool reentrant; 230 | int sleepPin; 231 | bool sleepPinConfigured; 232 | int ringPin; 233 | bool msstmWorkaroundRequested; 234 | bool ringAlertsEnabled; 235 | bool ringAsserted; 236 | unsigned long lastPowerOnTime; 237 | 238 | // Internal utilities 239 | bool noBlockWait(int seconds); 240 | bool waitForATResponse(char *response=NULL, int responseSize=0, const char *prompt=NULL, const char *terminator="OK\r\n"); 241 | 242 | int internalBegin(); 243 | int internalSendReceiveSBD(const char *txTxtMessage, const uint8_t *txData, size_t txDataSize, uint8_t *rxBuffer, size_t *prxBufferSize); 244 | int internalGetSignalQuality(int &quality); 245 | int internalMSSTMWorkaround(bool &okToProceed); 246 | int internalSleep(); 247 | 248 | int doSBDIX(uint16_t &moCode, uint16_t &moMSN, uint16_t &mtCode, uint16_t &mtMSN, uint16_t &mtLen, uint16_t &mtRemaining); 249 | int doSBDRB(uint8_t *rxBuffer, size_t *prxBufferSize); // in/out 250 | void power(bool on); 251 | 252 | void send(FlashString str, bool beginLine = true, bool endLine = true); 253 | void send(const char *str); 254 | void sendlong(const char *str); 255 | void send(uint16_t n); 256 | 257 | bool cancelled(); // call ISBDCallback and see if client cancelled the operation 258 | 259 | void diagprint(FlashString str); 260 | void diagprint(const char *str); 261 | void diagprint(uint16_t n); 262 | 263 | void consoleprint(FlashString str); 264 | void consoleprint(const char *str); 265 | void consoleprint(uint16_t n); 266 | void consoleprint(char c); 267 | void SBDRINGSeen(); 268 | 269 | // Unsolicited SBDRING filter technology 270 | static const char SBDRING[]; 271 | static const int FILTERTIMEOUT = 10; 272 | const char *head, *tail; 273 | int nextChar; 274 | void filterSBDRING(); 275 | int filteredavailable(); 276 | int filteredread(); 277 | 278 | // I2C_SER buffer functions 279 | int i2cSerAvailable(); 280 | int i2cSerRead(); 281 | void i2cSerPoke(char serChar); 282 | 283 | // Read serial data from the 9603 284 | void check9603data(); 285 | 286 | // Read the state of the Iridium pins and update IO_REGISTER 287 | void check9603pins(); 288 | // Set the Iridium pins 289 | void set9603pins(uint8_t pins); 290 | 291 | //Define the I2C 'registers' 292 | #define IO_REG 0x10 // Read/write to/from the I/O pins 293 | #define LEN_REG 0xFD // The serial length regsiter: 2 bytes (MSB, LSB) indicating how many serial characters are available to be read 294 | #define DATA_REG 0xFF // The serial data register: used to read and write serial data from/to the 9603N 295 | 296 | //Create the IO 'register' 297 | //A '1' in any of the bits indicates that the pin is ON (not necessarily that it is HIGH!) 298 | byte IO_REGISTER; 299 | 300 | //These are the bit definitions for the IO 'register' 301 | const uint8_t IO_SHDN = (1 << 0); // LTC3225 !SHDN : Read / Write 302 | const uint8_t IO_PWR_EN = (1 << 1); // 9603N power enable via the P-FET : Read / Write 303 | const uint8_t IO_ON_OFF = (1 << 2); // 9603N ON_OFF pin : Read / Write 304 | const uint8_t IO_RI = (1 << 3); // 9603N Ring Indicator _flag_ : Read / Write (Set if RI has been seen, cleared by writing a 0 to this bit) 305 | const uint8_t IO_NA = (1 << 4); // 9603N Network Available : Read only 306 | const uint8_t IO_PGOOD = (1 << 5); // LTC3225 PGOOD : Read only 307 | const uint8_t IO_LOW_PWR = (1 << 6); // ATtiny841 low power mode : Read / Write : Set to enable low power mode 308 | 309 | // Clear the MO/MT/Both buffers 310 | int internalClearBuffers(int buffers = 0); 311 | 312 | // Get the IMEI 313 | // https://github.com/mikalhart/IridiumSBD/pull/21 314 | int internalGetIMEI(char *IMEI, size_t bufferSize); 315 | 316 | // Functions to support I2C to serial pass thru 317 | int internalPassThruI2Cread(uint8_t *rxBuffer, size_t &rxBufferSize, size_t &numBytes); 318 | int internalPassThruI2Cwrite(uint8_t *txBuffer, size_t &txBufferSize); 319 | }; 320 | 321 | #endif 322 | --------------------------------------------------------------------------------