Software Serial issue Artemis Global Tracker

Hi everyone,

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.

Thanks!

Welcome to the forum

Is that your complete sketch ?

This needs to match the baud rate in the Serial Monitor.

Also - looks like you've only posted some of your sketch? setup() is missing.

That's not all. Hence my question

Hi,

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:

The connections are not good, so it doesn't go to the available loop right away. That's why the counter is not just 1 everytime.

  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;
  }

What do you see if you replace this code with

while (swSerial.available() > 0) 
{
  Serial.println(swSerial.read(), HEX);
}

I get 1 or 0 for the read, at least it's not weird symbols anymore.
How can I actually get the ASCII Hello World that I write in the beginning?

I think you are confused about how Serial works.

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.

Oh i see!
I'll connect the pins to an arduino UNO or something to perform the send and receive tests!

Thank you very much!

Hello,

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);
}

Here is what i see on the arduino monitor COM6:

Do you see anything weird in my code?

How do you know how many (if any) bytes are available when you read 6 ?

I'm assuming that the Artemis is sending the string everytime but i've added this and it doesn't change a thing :confused: :


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);
}

EDIT: I tried adding a connection between the two GND of the MCUs no improvement with that.

So I tried with a PWM pin AD31 and it started to transmit better but there is still some gibberish.
I wonder what could make the signal more stable.

image

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.

The most robust way to read serial is one byte at a time. Try this...

void loop() {

  while (Serial.available() > 0) 
    {
      char c = Serial.read();
      Serial.print(c);
    }

}

Hi,

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.

 int transmit_delay = 2;
   
   swSerial.write("H");
   delay(transmit_delay);
   swSerial.write("e");
   delay(transmit_delay);
   swSerial.write("l");
   delay(transmit_delay);
   swSerial.write("l");
   delay(transmit_delay);
   swSerial.write("o");
   delay(transmit_delay);

Thanks again for your help.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.