I'm having trouble making the software serial work. I'm using the Artemis Global Tracker. I'm using the custom SoftwareSerial library made for the Artemis :
I get weird symbols in the serial monitor primarly squares and sometimes '?'
Here is my code :
// Start the software serial port
swSerial.begin(9600);
swSerial.listen();
//while (!swSerial); // Wait for the user to open the serial monitor
// Start the console serial port
Serial.begin(115200);
while (!Serial); // Wait for the user to open the serial monitor
void loop()
{
digitalWrite(LED, LOW);
delay(1000);
Serial.println(F("Press the RESET button to restart the example"));
byte val = 0xFF;
String str = "Hello World";
int str_len = str.length()+1;
char char_array[str_len];
str.toCharArray(char_array,str_len);
swSerial.write(char_array);
counter++;
while (swSerial.available() > 0)
{
Serial.println("Bytes available:");
Serial.println(swSerial.available());
Serial.print(F("Counter: "));
Serial.println(counter);
swSerial.print(swSerial.read())
Serial.println("Data from SoftwareSerial port:");
Serial.println(swSerial.readString());
delay(1000);
counter = 0;
}
// blank line to separate data from the two ports:
digitalWrite(LED, HIGH);
delay(1000);
}
Let me know if you have any idea of what might be the issue.
Here is the complete sketch actually, I wanted to make it simpler to read:
#include "Arduino.h"
#include <SoftwareSerial.h>
SoftwareSerial swSerial(D42, D43);
int counter = 0;
// Artemis Tracker pin definitions
#define spiCS1 4 // D4 can be used as an SPI chip select or as a general purpose IO pin
#define geofencePin 10 // Input for the ZOE-M8Q's PIO14 (geofence) pin
#define busVoltagePin 13 // Bus voltage divided by 3 (Analog in)
#define iridiumSleep 17 // Iridium 9603N ON/OFF (sleep) pin: pull high to enable the 9603N
#define iridiumNA 18 // Input for the Iridium 9603N Network Available. Satellite search can update between 4s to 120s depending if satellite is visible or not
#define LED 19 // White LED
#define iridiumPwrEN 22 // ADM4210 ON: pull high to enable power for the Iridium 9603N
#define gnssEN 26 // GNSS Enable: pull low to enable power for the GNSS (via Q2)
#define superCapChgEN 27 // LTC3225 super capacitor charger: pull high to enable the super capacitor charger
#define superCapPGOOD 28 // Input for the LTC3225 super capacitor charger PGOOD signal
#define busVoltageMonEN 34 // Bus voltage monitor enable: pull high to enable bus voltage monitoring (via Q4 and Q3)
#define spiCS2 35 // D35 can be used as an SPI chip select or as a general purpose IO pin
#define iridiumRI 41 // Input for the Iridium 9603N Ring Indicator. Notifies device of the queued message coming from Mission Control
// Make sure you do not have gnssEN and iridiumPwrEN enabled at the same time!
// If you do, bad things might happen to the AS179 RF switch!
void gnssON(void) // Enable power for the GNSS
{
am_hal_gpio_pincfg_t pinCfg = g_AM_HAL_GPIO_OUTPUT; // Begin by making the gnssEN pin an open-drain output
pinCfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
pin_config(PinName(gnssEN), pinCfg);
delay(1);
digitalWrite(gnssEN, LOW); // Enable GNSS power (HIGH = disable; LOW = enable)
}
void gnssOFF(void) // Disable power for the GNSS
{
am_hal_gpio_pincfg_t pinCfg = g_AM_HAL_GPIO_OUTPUT; // Begin by making the gnssEN pin an open-drain output
pinCfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
pin_config(PinName(gnssEN), pinCfg);
delay(1);
digitalWrite(gnssEN, HIGH); // Disable GNSS power (HIGH = disable; LOW = enable)
}
void setup()
{
// Configure the I/O pins
pinMode(LED, OUTPUT);
pinMode(iridiumPwrEN, OUTPUT); // Configure the Iridium Power Pin (connected to the ADM4210 ON pin)
digitalWrite(iridiumPwrEN, LOW); // Disable Iridium Power
pinMode(superCapChgEN, OUTPUT); // Configure the super capacitor charger enable pin (connected to LTC3225 !SHDN)
digitalWrite(superCapChgEN, LOW); // Disable the super capacitor charger
gnssOFF(); // Disable power for the GNSS
// Start the software serial port
swSerial.begin(9600);
swSerial.listen();
//while (!swSerial); // Wait for the user to open the serial monitor
// Start the console serial port
Serial.begin(115200);
while (!Serial); // Wait for the user to open the serial monitor
delay(100);
Serial.println();
Serial.println();
Serial.println(F("Artemis Global Tracker"));
Serial.println(F("Example: Blink"));
Serial.println();
//empty the serial buffer
while(Serial.available() > 0)
Serial.read();
//wait for the user to press any key before beginning
Serial.println(F("Please check that the Serial Monitor is set to 115200 Baud"));
Serial.println(F("and that the line ending is set to Newline."));
Serial.println(F("Then click Send to start the example."));
Serial.println();
while(Serial.available() == 0)
;
}
void loop()
{
digitalWrite(LED, LOW);
delay(1000);
Serial.println(F("Press the RESET button to restart the example"));
byte val = 0xFF;
String str = "Hello World";
int str_len = str.length()+1;
char char_array[str_len];
str.toCharArray(char_array,str_len);
swSerial.write(char_array);
counter++;
while (swSerial.available() > 0)
{
Serial.println("Bytes available:");
Serial.println(swSerial.available());
Serial.print(F("Counter: "));
Serial.println(counter);
swSerial.print(swSerial.read());
Serial.println("Data from SoftwareSerial port:");
String str = swSerial.readString();
Serial.println(str);
delay(1000);
counter = 0;
}
// blank line to separate data from the two ports:
digitalWrite(LED, HIGH);
delay(1000);
}
It's already matching the baudrate of the monitor here's a screenshot of how it looks:
You sent "Hello World"... but that's sent from the Arduino to the other device (GPS unit I presume).
That is not the same as what you will receive... that will come from whatever is on the other end of the connection (sent from the GPS to the Arduino). So it looks like the GPS unit is sending 0x00's and 0x01's...
Oh I forgot to mention it!
I just put a loopback between TX and RX. I chose D42 and D43 pins as such.
Since on the board there is only two UARTs (one for USB to serial to flash the code and the other for the Iridium satcom) and I need a third UART I decided to use SoftwareSerial.
This is why I said that we're supposed to receive Hello World.
The other possibility is just the poor connection due to the quality of the cable. I'm using this: digikey part ID : 599
That's quite an important piece of missing information.
As I understand it, you cannot do a loopback test as you have described as Software Serial is only half duplex... you cannot send/receive simultaneously.
So I've tried to send a Hello string to an arduino UNO and then display it on monitor. I'm receiving 4 characters but only the first is accurate. The rest is gibberish.
Here is the sender code:
#include "Arduino.h"
#include <SoftwareSerial.h>
SoftwareSerial swSerial(D42, D43);
int counter = 0;
// Artemis Tracker pin definitions
#define spiCS1 4 // D4 can be used as an SPI chip select or as a general purpose IO pin
#define geofencePin 10 // Input for the ZOE-M8Q's PIO14 (geofence) pin
#define busVoltagePin 13 // Bus voltage divided by 3 (Analog in)
#define iridiumSleep 17 // Iridium 9603N ON/OFF (sleep) pin: pull high to enable the 9603N
#define iridiumNA 18 // Input for the Iridium 9603N Network Available. Satellite search can update between 4s to 120s depending if satellite is visible or not
#define LED 19 // White LED
#define iridiumPwrEN 22 // ADM4210 ON: pull high to enable power for the Iridium 9603N
#define gnssEN 26 // GNSS Enable: pull low to enable power for the GNSS (via Q2)
#define superCapChgEN 27 // LTC3225 super capacitor charger: pull high to enable the super capacitor charger
#define superCapPGOOD 28 // Input for the LTC3225 super capacitor charger PGOOD signal
#define busVoltageMonEN 34 // Bus voltage monitor enable: pull high to enable bus voltage monitoring (via Q4 and Q3)
#define spiCS2 35 // D35 can be used as an SPI chip select or as a general purpose IO pin
#define iridiumRI 41 // Input for the Iridium 9603N Ring Indicator. Notifies device of the queued message coming from Mission Control
// Make sure you do not have gnssEN and iridiumPwrEN enabled at the same time!
// If you do, bad things might happen to the AS179 RF switch!
void gnssON(void) // Enable power for the GNSS
{
am_hal_gpio_pincfg_t pinCfg = g_AM_HAL_GPIO_OUTPUT; // Begin by making the gnssEN pin an open-drain output
pinCfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
pin_config(PinName(gnssEN), pinCfg);
delay(1);
digitalWrite(gnssEN, LOW); // Enable GNSS power (HIGH = disable; LOW = enable)
}
void gnssOFF(void) // Disable power for the GNSS
{
am_hal_gpio_pincfg_t pinCfg = g_AM_HAL_GPIO_OUTPUT; // Begin by making the gnssEN pin an open-drain output
pinCfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN;
pin_config(PinName(gnssEN), pinCfg);
delay(1);
digitalWrite(gnssEN, HIGH); // Disable GNSS power (HIGH = disable; LOW = enable)
}
void setup()
{
// Configure the I/O pins
pinMode(LED, OUTPUT);
pinMode(iridiumPwrEN, OUTPUT); // Configure the Iridium Power Pin (connected to the ADM4210 ON pin)
digitalWrite(iridiumPwrEN, LOW); // Disable Iridium Power
pinMode(superCapChgEN, OUTPUT); // Configure the super capacitor charger enable pin (connected to LTC3225 !SHDN)
digitalWrite(superCapChgEN, LOW); // Disable the super capacitor charger
gnssOFF(); // Disable power for the GNSS
// Start the software serial port
swSerial.begin(9600);
swSerial.listen();
//while (!swSerial); // Wait for the user to open the serial monitor
// Start the console serial port
Serial.begin(115200);
while (!Serial); // Wait for the user to open the serial monitor
delay(100);
Serial.println();
Serial.println();
Serial.println(F("Artemis Global Tracker"));
Serial.println(F("Example: Blink"));
Serial.println();
//empty the serial buffer
while(Serial.available() > 0)
Serial.read();
//wait for the user to press any key before beginning
Serial.println(F("Please check that the Serial Monitor is set to 115200 Baud"));
Serial.println(F("and that the line ending is set to Newline."));
Serial.println(F("Then click Send to start the example."));
Serial.println();
while(Serial.available() == 0)
;
}
void loop()
{
digitalWrite(LED, LOW);
delay(1000);
Serial.println(F("Press the RESET button to restart the example"));
/*
byte val = 0xFF;
String str = "Hello World";
int str_len = str.length()+1;
char char_array[str_len];
str.toCharArray(char_array,str_len);
*/
swSerial.write("Hello");
digitalWrite(LED, HIGH);
delay(1000);
}
Receiver code:
char mystr[12];
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
Serial.readBytes(mystr,6);
Serial.println(mystr);
delay(1000);
}
I'm assuming that the Artemis is sending the string everytime but i've added this and it doesn't change a thing :
char mystr[12];
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
while (Serial.available() > 0)
{
int avail = Serial.available();
Serial.readBytes(mystr,avail);
Serial.println(mystr);
}
delay(1000);
}
So I've tried sending one character and it worked fine the 'H' was displayed very well, no glitch. When I tried sending two characters "He" it started writing some gibberish.
I wonder if the problem is at the receiving side maybe.
So I finally figured what was the issue here. It was a transmission problem.
It seems that Software Serial needs some delay between the sending of each character. (at least regarding this custom library for Artemis boards).
I tested different delay values and here it seems that approximately 2 ms is the minimum delay for a stable sending with no gibberish.