SoftwareSerial stops working... baffled !!

Ok, I hope someone can help me here, I have come across something that…

  1. I don’t believe is happening
  2. I don’t know why it is happening
  3. I don’t know how to “fix” it

I am using a SoftwareSerial port Tx12, Rx11, and am sending commands and receiving responses to/from a DFRobot MP3 Player. This has all worked perfectly in the past, but I have now added an interface to the project using RemoteXY, some of you may be familiar with it.

I will post the interface code I am using, and you will see that I have commented out chunks of the code. If I un-comment just one of the “sections”, or just one of the message statements, my SoftSerialTx signal goes from being a clean signal with sharp edges, to a very dirty signal (pictures attached), which the player does not have a chance of receiving correctly. I am making no other changes whatsoever… The “dirty” scope trace was taken after un-commenting only the line that maps message2 to the RemoteXY structure
.
For my tests I am just sending one command to the player repeatedly, then calling do_interface(), and the Nano is just on the end of the USB lead, with my scope on pin 12 and GND, i.e. there is no other hardware involved.

It is as though there is a size limit somewhere that makes SoftwareSerial stop working correctly, but I don’t believe that to be the case.

If anyone can shed some light, I would be extremely grateful, it has got me completely baffled…

Here’s the interface code I’m using…

void do_interface() {

  RemoteXY_Handler();

// volumes
// sliders from RemoteXY are 0-100
// our volumes are 0-63
tmp_vol = map(RemoteXY.SKY_Vol, 0, 100, 0, 63);
if (tmp_vol != settings.SKY_Vol) {
  settings.SKY_Vol = tmp_vol;
  if (settings.currentMode == MODE_SKY) {
    PTsend(63 - tmp_vol);
    RemoteXY.Volume = map(tmp_vol, 0, 63, 0, 100);
  } // if (settings.currentMode == MODE_SKY)
} // if (tmp_vol != settings.SKY_Vol)  
   
tmp_vol = map(RemoteXY.AUX_Vol, 0, 100, 0, 63);
if (tmp_vol != settings.AUX_Vol) {
  settings.AUX_Vol = tmp_vol;
  if (settings.currentMode == MODE_AUX) {
    PTsend(63 - tmp_vol);
    RemoteXY.Volume = map(tmp_vol, 0, 63, 0, 100);
  } // if (settings.currentMode == MODE_AUX)
} // if (tmp_vol != settings.AUX_Vol) 
     
tmp_vol = map(RemoteXY.BT_Vol, 0, 100, 0, 63);
if (tmp_vol != settings.BT_Vol) {
  settings.BT_Vol = tmp_vol;
  if (settings.currentMode == MODE_BT) {
    PTsend(63 - tmp_vol);
    RemoteXY.Volume = map(tmp_vol, 0, 63, 0, 100);
  } // if (settings.currentMode == MODE_BT)
} // if (tmp_vol != settings.BT_Vol)
       
tmp_vol = map(RemoteXY.MP3_Vol, 0, 100, 0, 63);
if (tmp_vol != settings.MP3_Vol) {
  settings.MP3_Vol = tmp_vol;
  if (settings.currentMode == MODE_MP3) {
    PTsend(63 - tmp_vol);
    RemoteXY.Volume = map(tmp_vol, 0, 63, 0, 100);
  } // if (settings.currentMode == MODE_MP3)
} // if (tmp_vol != settings.MP3_Vol)
       
tmp_vol = map(RemoteXY.HBTY_Vol, 0, 100, 0, 63);
if (tmp_vol != settings.HBTY_Vol) {
  settings.HBTY_Vol = tmp_vol;
  if (settings.currentMode == MODE_HBTY) {
    PTsend(63 - tmp_vol);
    RemoteXY.Volume = map(tmp_vol, 0, 63, 0, 100);
  } // if (settings.currentMode == MODE_HBTY)
} // if (tmp_vol != settings.HBTY_Vol) 

if (settings.currentMode == MODE_MP3) {
  if (RemoteXY.MP3Next == 1) {  
    RemoteXY.MP3Next = 0;
    if(Media_OK == true) MP3_Next = true; 
  } // if (RemoteXY.MP3Next == 1)
  
  if (RemoteXY.MP3Prev == 1) {  
    RemoteXY.MP3Prev = 0;
    if(Media_OK == true) MP3_Prev = true; 
  } // if (RemoteXY.MP3Prev == 1)
} // if (settings.currentMode == MODE_MP3)

// Mode changes   
//    if (RemoteXY.modeSKY == 1) { 
//      RemoteXY.modeSKY = 0; 
//      settings.currentMode = MODE_SKY;
//      RemoteXY.Volume = map(settings.SKY_Vol, 0, 63, 0, 100); 
//    }
//    if (RemoteXY.modeAUX == 1) { 
//      RemoteXY.modeAUX = 0; 
//      settings.currentMode = MODE_AUX;
//      RemoteXY.Volume = map(settings.AUX_Vol, 0, 63, 0, 100); 
//    }
//    if (RemoteXY.modeBT == 1) { 
//      RemoteXY.modeBT = 0; 
//      settings.currentMode = MODE_BT; 
//      RemoteXY.Volume = map(settings.BT_Vol, 0, 63, 0, 100); 
//    }
//      if (RemoteXY.modeMP3 == 1) {
//        RemoteXY.modeMP3 = 0;  
//        if (Media_OK == true) {
//          settings.currentMode = MODE_MP3;
//          RemoteXY.Volume = map(settings.MP3_Vol, 0, 63, 0, 100);
//        }
//     }
//      if (RemoteXY.modeHBTY == 1) {
//        RemoteXY.modeHBTY = 0;
//        if (Media_OK == true) {
//          settings.lastMode = settings.currentMode; 
//          settings.currentMode = MODE_HBTY;
//          RemoteXY.Volume = map(settings.HBTY_Vol, 0, 63, 0, 100); 
//
//        }
//      }
//        
//    
//
// LEDs
  RemoteXY.ledSKY_g = 0;
  RemoteXY.ledAUX_r = 0;
  RemoteXY.ledBT_b = 0;
  RemoteXY.ledMP3_r = 0;
  RemoteXY.ledMP3_g = 0;
  RemoteXY.ledMP3_b = 0;
  RemoteXY.ledHBTY_r = 0;
  RemoteXY.ledHBTY_g = 0;
  RemoteXY.ledHBTY_b = 0;

//  switch(settings.currentMode) {
//    case MODE_SKY:
//      RemoteXY.ledSKY_g = 255;
//    break;
//    case MODE_AUX:
//      RemoteXY.ledAUX_r = 255;
//    break;
//    case MODE_BT:
//      RemoteXY.ledBT_b = 255;
//    break;
//    case MODE_MP3:
//      RemoteXY.ledMP3_r = 230;
//      RemoteXY.ledMP3_g = 178;
//      RemoteXY.ledMP3_b = 203;
//    break;
//    case MODE_HBTY:
//      RemoteXY.ledHBTY_r = 206;
//      RemoteXY.ledHBTY_g = 150;
//      RemoteXY.ledHBTY_b = 0;
//    break;
//  } // switch(settings.currentMode)

//  message1.toCharArray(RemoteXY.message1, sizeof(RemoteXY.message1));
//  message2.toCharArray(RemoteXY.message2, sizeof(RemoteXY.message2));
//  message3.toCharArray(RemoteXY.message3, sizeof(RemoteXY.message3));
//
//
  
//char key = keypad.getKey();
  
} // void do_interface()

Code snippets are not very useful. The problem is likely to be in the portion that you did not post.

Running out of memory is one way to cause a problem like this. You do not seem to have told us what Arduino you have so no one can tell you how much memory is available, but the compiler provides a static memory usage report that may be useful.

Running off the end of an array is another way to cause an issue such as this. I did not see any array usage in the snippet that was posted, but who knows about the rest of the code?

I did not think it was relevent to post the whole of the code.. this issue is totally repeatable, with me just adding/taking away some of those sections of code. Absolutely no other changes are being made ...

For instance if I un-comment the section that sets the rgb values of the RemoteXY LEDs - dirty : re-comment those lines of code - clean again. There is no array handling going on, and RemoteXY is a structure .

I cannot see why a few lines of code, or even one line (message2) can compromise the capability of pin 12 to produce a clean signal.

I take your point about memory issues...

"Sketch uses 10876 bytes (35%) of program storage space. Maximum is 30720 bytes.
Global variables use 987 bytes (48%) of dynamic memory, leaving 1061 bytes for local variables. Maximum is 2048 bytes."

And I did say it was a Nano : and the issue is apparent on multiple boards, of varying parentage.

Here is the void loop();

void loop() {

  do_interface();
  MP3Cmnd(DF_RESET, 0, 0, 0);
  
} // void loop()

SoftwareSerial : speed?

Supported communication modules:

  • Bluetooth HC-05, HC-06 or compatible;
  • WiFi ESP8266;
  • Ethernet Shield W5100;

So, which RemoteXY communication module are you using?!? Are you using Bluetooth or ESP8266 with SoftwareSerial?!? Are you using Ethernet over SPI (Pins 10, 11, 12, and 13)?!? Either way you will get interaction between your use of SoftwareSerial or your use of Pins 11 and 12.

johnwasser:
So, which RemoteXY communication module are you using?!? Are you using Bluetooth or ESP8266 with SoftwareSerial?!? Are you using Ethernet over SPI (Pins 10, 11, 12, and 13)?!? Either way you will get interaction between your use of SoftwareSerial or your use of Pins 11 and 12.

Thanks for your reply : the interface is Bluetooth, but the tests were done with nothing connected to the Nano to rule out interface issues.

All the interface code is doing is some some conditional mapping and setting values - I'm curious as to how this can interact with pin 12 ?

I have a clean signal on pin 12, then uncomment the first of the "Mode Changes" sections, namely....

// Mode changes   
    if (RemoteXY.modeSKY == 1) { 
      RemoteXY.modeSKY = 0; 
      settings.currentMode = MODE_SKY;
      RemoteXY.Volume = map(settings.SKY_Vol, 0, 63, 0, 100); 
    }

There is nothing in there I can see that should affect anything : 1 test, 3 assignments ....

Here is a result of another test I have done....

  if (RemoteXY.MP3Prev == 1) {  
    RemoteXY.MP3Prev = 0;
    if(Media_OK == true) MP3_Prev = true; 
  } // if (RemoteXY.MP3Prev == 1)
  
} // if (settings.currentMode == MODE_MP3)

Clean signal on 12

  if (RemoteXY.MP3Prev == 1) {  
    RemoteXY.MP3Prev = 0;
    if(Media_OK == true) MP3_Prev = true; 
  } // if (RemoteXY.MP3Prev == 1)

  if (RemoteXY.MP3Prev == 1) {  
    RemoteXY.MP3Prev = 0;
    if(Media_OK == true) MP3_Prev = true; 
  } // if (RemoteXY.MP3Prev == 1)
  
} // if (settings.currentMode == MODE_MP3)

Dirty signal on 12 ....

just by repeating a piece of code - beats me how or why it should affect Software Serial !!?!

On a Nano, pin 12 can be affected by Timer 0. I am unsure how this could be relevant to the issue at hand.

I still maintain that the whole code is needed to analyze the issue. If the whole code cannot be posted for some reason, then some code that reproduces the problem may be needed in its entirety.

The static memory report and the use of various Arduinos suggests that this is not a memory size issue. An array issue has not been eliminated.

And I did say it was a Nano

The OP is correct that a Nano was mentioned and I missed the mention. Sorry.

daba:
Thanks for your reply : the interface is Bluetooth, but the tests were done with nothing connected to the Nano to rule out interface issues.

I am not expecting a hardware problem. I am expecting a conflict between the part of the sketch you have shown and the part of the sketch you have not shown.

From the pictures it looks like Pin 12 (MISO) has been switch from OUTPUT to INPUT. When SoftwareSerial sets it to 1 it becomes INPUT_PULLUP and goes to a weak 5V. When SoftwareSerial sets it to 0 it becomes INPUT and goes High Impedance (basically open circuit). Whatever load is on it pulls the line slowly low. That line would be set as an INPUT if the SPI interface is enabled. MISO is the Master In/Slave Out line of the SPI interface.

johnwasser:
I am not expecting a hardware problem. I am expecting a conflict between the part of the sketch you have shown and the part of the sketch you have not shown.

From the pictures it looks like Pin 12 (MISO) has been switch from OUTPUT to INPUT. When SoftwareSerial sets it to 1 it becomes INPUT_PULLUP and goes to a weak 5V. When SoftwareSerial sets it to 0 it becomes INPUT and goes High Impedance (basically open circuit). Whatever load is on it pulls the line slowly low. That line would be set as an INPUT if the SPI interface is enabled. MISO is the Master In/Slave Out line of the SPI interface.

I don't have permission to post the whole sketch - I will try to reproduce the issue in another sketch later.

Your description of how pin 12 works hasn't explained why I see the effects shown on my jpg's with the Nano just dangling on the end of the USB lead, there is no "load" on pin 12 to "slowly pull it low". I am not using SPI.

My project has HardwareSerial for the Bluetooth connection to RemoteXY, SoftwareSerial to connect to the DFPlayer Mini, and I2C communication to a PT2314 Audio Processor Module. No devices are connected to anything when I see the dirty traces, simply created by un-commenting 3 lines of code as I have explained.

daba:
Your description of how pin 12 works hasn't explained why I see the effects shown on my jpg's with the Nano just dangling on the end of the USB lead, there is no "load" on pin 12 to "slowly pull it low". I am not using SPI.

I was under the impression that your oscilloscope probe was connected to Pin 12 at the time.

johnwasser:
I was under the impression that your oscilloscope probe was connected to Pin 12 at the time.

Yes, and obviously for both traces - why should they be different just because I add/remove 3 or 4 lines of innocuous code ?

Just a thought…

Add a couple of lines of code not associated with RemoteXY
Say a Serial.println() to the screen, and observe the results
If you’re getting similar results, try looking at memory usage at runtime

I just wonder if RemoteXY is doing a lot of dynamic allocation?

Got a full sketch that exhibits the problem, but it is too big for posting here. Ive put it on dropbox

SoftwareSerial_Test

darrob - I did your suggestion, see the end of the file, yes, a single Serial.println() makes the pin 12 trace go dirty. EDIT: Note I used the "F" option for the println.....

I doubt RemoteXY is doing much, just mapping variables in and out, you can see its structure in the listing.

There is an attach option that'll take larger files that you'll see at the bottom of the window when you're posting a response.

Got it, wildbill

I have added the freememory library, and that sketch, with a dirty pin 12, is continually reporting 877 bytes free, so I don’t think it’s a memory issue.

I have attached the sketch, save people going to dropbox.

SoftSerialTest.ino (21.3 KB)

just took a look at variables: for me it's a memory problem.

did you try a bigger board? (mega?)

demkat1:
just took a look at variables: for me it's a memory problem.

did you try a bigger board? (mega?)

I've only got a teensy 3.2 to try it on, but PCB's are made for the Nano....

If it was a memory problem, would the sketch continue to run ?

Same effect on both a Nano and an Uno I found, no real surprise there (same chip).

Here are the compiler results for both.

UNO
Free for
Program Global Local Pin 12
Memory %age Variables Variables Clean ?
10752 33 987 1061 YES
11076 34 989 1059 NO

NANO
Free for
Program Global Local Pin 12
Memory %age Variables Variables Clean ?
10752 35 987 1061 YES
11076 36 989 1059 NO

EDIT : formatting shoddy, but you can see I have over half the memory free for local variable, and I can’t see what might be using it…