Hi. I am trying this project for my thesis and need some assistance. First, sorry in advance if I make any mistakes in the language or the code (this is not related to my degree).
In this project, I am trying to send a message using RockBLOCK 9603. The message is a position, that is a latitude and a longitude obtained by a GPS. When the message is sent, the OLED display will show something like "Sent. Lat: Lon: ". Here is the code I am using, in Arduino Uno.
#include <SoftwareSerial.h>
#include <TinyGPS++.h> // TinyGPS++ library
TinyGPSPlus gps; // Create a GPS object
#define RXpin A3 // GPS RX pin
#define TXpin A2 // GPS TX pin
SoftwareSerial GPSserial(RXpin, TXpin); // Software serial for GPS
#include <U8g2lib.h> // OLED library
#include <Wire.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C disp(U8G2_R0, U8X8_PIN_NONE); // OLED display
uint32_t startGetFixmS;
uint32_t endFixmS;
char latBuffer[10]; // Buffer for latitude
char lonBuffer[10]; // Buffer for longitude
char message[30]; // Final message to send
SoftwareSerial rockBlockSerial(10, 11); // RX, TX (Arduino <-> RockBLOCK)
bool messageSent = false; // **Flag to track if message was sent**
void setup() {
delay(1000);
Serial.begin(115200);
GPSserial.begin(9600);
disp.begin();
disp.setFont(u8g2_font_helvB14_tr);
disp.clear();
disp.firstPage();
disp.setCursor(10, 15);
disp.print(F("Waiting for GPS"));
disp.nextPage();
startGetFixmS = millis();
rockBlockSerial.begin(19200); // RockBLOCK communication
Serial.println("Initializing RockBLOCK 9603...");
delay(2000); // Allow RockBLOCK to initialize
checkSignalStrength();
}
void loop() {
if (!messageSent && gpsWaitFix(5)) { // **Send only if message has not been sent**
Serial.println();
Serial.println();
Serial.print(F("Fix time: "));
Serial.print(endFixmS - startGetFixmS);
Serial.println(F(" ms"));
sendMessage(message); // **Send the message to RockBLOCK**
messageSent = true; // **Set flag to true so no more messages are sent**
} else if (messageSent) {
Serial.println("Message already sent. Halting transmission.");
while (true); // **Stop loop execution**
}
// Listen for responses from RockBLOCK
while (rockBlockSerial.available()) {
Serial.write(rockBlockSerial.read()); // Print response to Serial Monitor
}
}
bool gpsWaitFix(uint16_t waitSecs) {
uint32_t endwaitmS;
uint8_t GPSchar;
Serial.print(F("Waiting for GPS Fix ("));
Serial.print(waitSecs);
Serial.println(F(" seconds)"));
endwaitmS = millis() + (waitSecs * 1000);
while (millis() < endwaitmS) {
if (GPSserial.available() > 0) {
GPSchar = GPSserial.read();
gps.encode(GPSchar);
Serial.write(GPSchar);
}
if (gps.location.isUpdated()) {
dtostrf(gps.location.lat(), 5, 2, latBuffer);
dtostrf(gps.location.lng(), 5, 2, lonBuffer);
snprintf(message, sizeof(message), "Lat:%s Lon:%s", latBuffer, lonBuffer);
endFixmS = millis();
return true;
}
}
return false;
}
void checkSignalStrength() {
Serial.println("Checking signal strength...");
clearSerialBuffer();
rockBlockSerial.println("AT+CSQ");
delay(2000);
readResponse();
}
void displayscreenSent() {
disp.firstPage();
do {
disp.setFont(u8g2_font_helvB12_tr);
disp.setCursor(10, 15);
disp.print(F("Sent."));
disp.setCursor(10, 35);
disp.print(F("Lat: "));
disp.print(latBuffer);
disp.setCursor(10, 55);
disp.print(F("Lon: "));
disp.print(lonBuffer);
} while (disp.nextPage());
}
void sendMessage(const char* msg) {
Serial.println("Sending message: " + String(msg));
clearSerialBuffer();
rockBlockSerial.print("AT+SBDWT=");
rockBlockSerial.println(msg);
delay(2000);
if (!waitForResponse("OK")) {
Serial.println("Error writing message to buffer.");
return;
}
clearSerialBuffer();
rockBlockSerial.println("AT+SBDIX");
delay(8000);
readResponse();
Serial.println("Message sent successfully!");
// **Update OLED with "Sent. Lat: <value> Lon: <value>"**
displayscreenSent();
messageSent = true; // Mark message as sent
}
bool waitForResponse(String expected) {
unsigned long startTime = millis();
String response = "";
while (millis() - startTime < 5000) {
while (rockBlockSerial.available()) {
char c = rockBlockSerial.read();
response += c;
}
if (response.length() > 0) {
Serial.println("RockBLOCK response: " + response);
if (response.indexOf(expected) != -1) return true;
}
}
Serial.println("Error: Expected '" + expected + "'got: " + response);
return false;
}
void clearSerialBuffer() {
while (rockBlockSerial.available()) {
rockBlockSerial.read();
}
}
void readResponse() {
while (rockBlockSerial.available()) {
char c = rockBlockSerial.read();
Serial.write(c);
delay(5);
}
Serial.println();
}
However, when I run this code I do not get a GPS fix. I know it works because I have been making different tests and it works properly, as well as the RockBLOCK and the OLED. I am using the 5v pin in the Arduino Uno. If anyone has any idea of the issue, please let me know. Thank you so much.
See the software serial reference link below. You can switch between software serial interfaces, but its much much much easier to use an Arduino with two hardware serial ports;
Just in case, do you know if a GPS module can be connected to Arduino Uno and can work not using Software Serial? I have a Adafruit Ultimate GPS Breakout
My tutor suggested an alternative: initializing GPS, getting a GPS, ending the comunicaction and then start the software serial comunication with the RockBLOCK. I will try that but I wanted to ask if anybody knows if that would work.
You can do that by connecting the GPS to the Serial interface on pins 0 and 1 of the Uno but will lose the ability to print to that interface, ie the Serial monitor output. You may also need to disconnect the GPS when uploading code to the Uno as that too uses the Serial interface
That might work but would be very clumsy as you would need to constantly start and stop the two SoftwareSerial interfaces and wait until they were established again before using them
#include <SoftwareSerial.h> // Include SoftwareSerial library for communication with GPS and RockBLOCK
#include <TinyGPS++.h> // Include TinyGPS++ library to work with GPS data
TinyGPSPlus gps; // Create a TinyGPSPlus object for GPS processing
#define RXpin A3 // GPS RX pin (receives data from GPS)
#define TXpin A2 // GPS TX pin (sends data to GPS)
SoftwareSerial GPSserial(RXpin, TXpin); // Initialize SoftwareSerial for GPS communication
#include <U8g2lib.h> // Include U8g2 library for OLED display
#include <Wire.h> // Include Wire library for I2C communication with OLED
U8G2_SSD1306_128X64_NONAME_1_HW_I2C disp(U8G2_R0, U8X8_PIN_NONE); // Create an OLED display object (128x64 resolution)
uint32_t startGetFixmS; // Variable to store the timestamp when GPS fix starts
uint32_t endFixmS; // Variable to store the timestamp when GPS fix ends
char latBuffer[10]; // Buffer to store the latitude as a string
char lonBuffer[10]; // Buffer to store the longitude as a string
char message[30]; // Final message to be sent (latitude and longitude)
SoftwareSerial rockBlockSerial(10, 11); // RX, TX pins for communication with RockBLOCK (pins 10 and 11)
bool messageSent = false; // Flag to track if the message has been sent to RockBLOCK
void setup() {
delay(1000); // Wait for a second before starting setup
Serial.begin(115200); // Start Serial Monitor communication at 115200 baud
GPSserial.begin(9600); // Initialize GPS communication at 9600 baud
disp.begin(); // Initialize OLED display
disp.setFont(u8g2_font_helvB14_tr); // Set font for the display
disp.clear(); // Clear the display screen
disp.firstPage(); // Start drawing on the first page of OLED
disp.setCursor(10, 15); // Set cursor position on screen
disp.print(F("Waiting for GPS")); // Display message to indicate waiting for GPS fix
disp.nextPage(); // Display content on OLED screen
startGetFixmS = millis(); // Record the start time of the GPS fix
//rockBlockSerial.begin(19200); // Initialize RockBLOCK communication at 19200 baud
//Serial.println("Initializing RockBLOCK 9603..."); // Print message to Serial Monitor
delay(2000); // Wait for 2 seconds to allow RockBLOCK to initialize
//checkSignalStrength(); // Check the signal strength of RockBLOCK
}
void loop() {
if (!messageSent && gpsWaitFix(5)) { // If message is not sent and GPS fix is acquired within 5 seconds
Serial.println();
Serial.println();
Serial.print(F("Fix time: "));
Serial.print(endFixmS - startGetFixmS); // Print the time taken to get GPS fix
Serial.println(F(" ms"));
GPSserial.end();
delay(1000);
rockBlockSerial.begin(19200);
Serial.println("Initializing RockBLOCK 9603...");
checkSignalStrength();
sendMessage(message); // Send the message containing latitude and longitude to RockBLOCK
messageSent = true; // Set flag to true indicating message has been sent
} else if (messageSent) { // If message has already been sent
Serial.println("Message already sent. Halting transmission.");
while (true); // Halt the loop execution indefinitely
}
// Listen for responses from RockBLOCK and print them to the Serial Monitor
// while (rockBlockSerial.available()) {
// Serial.write(rockBlockSerial.read()); // Print response from RockBLOCK to Serial Monitor
//}
}
// Function to wait for GPS fix
bool gpsWaitFix(uint16_t waitSecs) {
uint32_t endwaitmS;
uint8_t GPSchar;
Serial.print(F("Waiting for GPS Fix ("));
Serial.print(waitSecs);
Serial.println(F(" seconds)"));
endwaitmS = millis() + (waitSecs * 1000); // Set the timeout duration for waiting for GPS fix
while (millis() < endwaitmS) { // Loop until the specified time has passed
if (GPSserial.available() > 0) { // If there is data available from the GPS
GPSchar = GPSserial.read(); // Read the incoming GPS data
gps.encode(GPSchar); // Encode the GPS data for TinyGPS++
Serial.write(GPSchar); // Print the raw GPS data to Serial Monitor for debugging
}
if (gps.location.isUpdated()) { // If new GPS location data is available
dtostrf(gps.location.lat(), 6, 4, latBuffer); // Convert latitude to string and store it in latBuffer
dtostrf(gps.location.lng(), 6, 4, lonBuffer); // Convert longitude to string and store it in lonBuffer
snprintf(message, sizeof(message), "Lat:%s Lon:%s", latBuffer, lonBuffer); // Format the message with latitude and longitude
endFixmS = millis(); // Record the time when GPS fix was obtained
return true; // Return true indicating a GPS fix was acquired
}
}
return false; // Return false if GPS fix is not acquired within the timeout
}
// Function to check RockBLOCK signal strength
void checkSignalStrength() {
Serial.println("Checking signal strength...");
clearSerialBuffer(); // Clear any data in RockBLOCK serial buffer
rockBlockSerial.println("AT+CSQ"); // Send command to check signal strength
delay(2000); // Wait for 2 seconds
readResponse(); // Read and print the response from RockBLOCK
}
// Function to update the OLED screen after sending the message
void displayscreenSent() {
disp.firstPage(); // Start drawing on the first page of OLED
do {
disp.setFont(u8g2_font_helvB12_tr); // Set smaller font for latitude and longitude
disp.setCursor(10, 15); // Set cursor position for displaying "Sent."
disp.print(F("Sent."));
disp.setCursor(10, 35); // Set cursor position for latitude display
disp.print(F("Lat: "));
disp.print(latBuffer); // Display the latitude
disp.setCursor(10, 55); // Set cursor position for longitude display
disp.print(F("Lon: "));
disp.print(lonBuffer); // Display the longitude
} while (disp.nextPage()); // Render the content on the OLED screen
}
// Function to send the message to RockBLOCK
void sendMessage(const char* msg) {
Serial.println("Sending message: " + String(msg)); // Print the message to be sent to Serial Monitor
clearSerialBuffer(); // Clear any existing data in the RockBLOCK serial buffer
// Send the message to RockBLOCK buffer
rockBlockSerial.print("AT+SBDWT=");
rockBlockSerial.println(msg);
delay(2000); // Wait for 2 seconds for the message to be written into the buffer
// Wait for an "OK" response
if (!waitForResponse("OK")) {
Serial.println("Error writing message to buffer."); // Print error if message failed
return;
}
clearSerialBuffer(); // Clear the serial buffer before sending the next command
// Send the command to transmit the message
Serial.println("Sending AT+SBDIX command...");
rockBlockSerial.println("AT+SBDIX");
// The RockBLOCK takes time to process this command
Serial.println("Waiting for RockBLOCK response...");
delay(10000); // Give RockBLOCK up to 10 seconds to respond
// Read and print the response from RockBLOCK
readResponse();
Serial.println("Message sent successfully!"); // Indicate that the message was sent
// Update the OLED display with the sent message
displayscreenSent();
}
// Function to wait for a specific response from RockBLOCK
bool waitForResponse(String expected) {
unsigned long startTime = millis();
String response = "";
while (millis() - startTime < 5000) { // Wait for up to 5 seconds
while (rockBlockSerial.available()) {
char c = rockBlockSerial.read(); // Read incoming data from RockBLOCK
response += c; // Append the character to the response string
}
if (response.length() > 0) { // If there is any response
Serial.println("RockBLOCK response: " + response);
if (response.indexOf(expected) != -1) return true; // Check if the expected response is received
}
}
Serial.println("Error: Expected '" + expected + "' but got: " + response);
return false; // Return false if expected response is not received
}
// Function to clear any data in the serial buffer
void clearSerialBuffer() {
while (rockBlockSerial.available()) {
rockBlockSerial.read(); // Read and discard any available data
}
}
// Function to read the response from RockBLOCK
void readResponse() {
String response = "";
unsigned long startTime = millis();
// Keep reading for up to 15 seconds to ensure we capture the full response
while (millis() - startTime < 15000) {
while (rockBlockSerial.available()) {
char c = rockBlockSerial.read(); // Read incoming data from RockBLOCK
response += c; // Append character to response string
Serial.write(c); // Print each character as it's received
}
if (response.length() > 0 && response.indexOf("+SBDIX:") != -1) {
break; // If we detected the expected response, exit early
}
}
if (response.length() > 0) {
Serial.println("\nFull RockBLOCK Response: " + response); // Print the full response
} else {
Serial.println("No response received from RockBLOCK.");
}
}
With this code I get:
OK
Full RockBLOCK Response: AT+CSQ
+CSQ:0
OK
Sending message: Lat:37.3645 Lon:-5.9880
RockBLOCK response: Օ�U���� Lon:-5.9880
OK
Sending AT+SBDIX command...
Waiting for RockBLOCK response...
AT+SBDIX
+SBDIX: 32, 9, 2, 0, 0, 0
OK
Full RockBLOCK Response: AT+SBDIX
+SBDIX: 32, 9, 2, 0, 0, 0
OK
Message already sent. Halting transmission.
The number 32 in SBDIX indicates that there is no network available so the message was not sent. I know I still have to work on this code so that it gets clearer but right now it is enough for me just to get to send the message with the position. At least, the GPS works and the RockBLOCK works too.
I tried it today and it worked!! The message was sent and I could read it clearly in RockBLOCK Admin. I know this code must be perfected but the important thing is IT WORKS.