Solved! Clashing: Serial.print (output) and BT Serial (input)

Hi All.

I am trying to receive Serial input from Bluetooth, read it, print it to the Serial monitor and then write to an SD File.

The hardware is a Due, attached to a BT receiver, and with an Adafruit Datalogger on top.

The Bluetooth input is available - no problem with that. I can read it. But, after engaging the Bluetooth and when the programs attempts to Serial print, the program hangs.

During the compilation and loading the Bluetooth is switched off, so there is no Bluetooth input. The setup runs and prints is log to the monitor. Next, I engage the Bluetooth. That's when the clash begins.

Here is the Serial output. I have added debug comments. The comments show where the serial printing stopped!

Edit. Note: Bluetooth input is to pins 0 and 1.

Sketch:   /home/graham/monitoring/ArduinoUno/HRV_shells/HR_sym_receiving_due_skinny_recv/HR_sym_receiving_due_skinny_recv.ino
Uploaded: Aug 29 2018
File: 08292101.csv

Setup() completed.

Debug: Serial.available() = OK
Debu              <<<< == this is where it hangs

I believe the Serial.print (output) and BT Serial (input) are clashing. They are perhaps using the same pins for input and output?

What could the problem be?

How can I solve it?

Below is my program.

Look forward to your replies
Thanks
EGB

=======================
(The program has been cut down to remove clutter!)

#include <SPI.h>
#include <SD.h>

// ------------------------------------
// -- Inventory of Pins ---------------
// ------------------------------------
// Pin 10 set OUTPUT/HIGH for initialization - of SDCard?; other pins for control by SPI
const int chipSelectPin = 10; // 10 only for AdaFruit DataLogger
const int W5500_SS = 4; // 4 or 7; ? chip select for AdaFruit DataLogger
const int dataReadyPin = 6;
// ------------------------------------
// SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
// ------------------------------------
// Used in void do_receiving_timestamp():
String timestampString;
String readString;
char c;
// ------------------------------------
// Used in void recv_with_end_marker():
char endMarker = '\n';
// ------------------------------------
// DataLogger SD shield
File targetFile;
String outputFile;
// DateTime now; 
char file_name_buffer[8];
String fullString = "Recvr_time,Sendr_time_Ch1,Ch2,Ch3";
// ------------------------------------

// Setting time
String string_rtc;
int hh;  int mm; int ss;
int i; int j;
char s_month[5];
int year, month, day;
static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";

// <--  __DATE__ to YYYY MM DD --------------------
void set_rtc_yyyy_month_day(char const *time) { 
    sscanf(time, "%s %d %d", s_month, &day, &year);
    month = (strstr(month_names, s_month)-month_names)/3;
    month = month + 1;
}

// <-- Setting Date and Time --------------------
void set_rtc_hh_mm_ss() {
  // Because of bugs in RTC.adjust()
  string_rtc = String(__TIME__);
  char HH[3];   char MM[3]; char SS[3];
  for ( i = 0; i < 2; i++) {
    HH[i] = string_rtc.charAt(i);
    HH[i + 1] = '\0';
  }
  hh = atoi(HH);
  for ( i = 0; i < 2; i++) {
    j = i + 3;
    MM[i] = string_rtc.charAt(j);
    MM[i + 1] = '\0';
  }
  mm = atoi(MM);
  for ( i = 0; i < 2; i++) {
    j = i + 6;
    SS[i] = string_rtc.charAt(j);
    SS[i + 1] = '\0';
  }
  ss = atoi(SS);
}

// <-- Creating file name --------------------
void create_file_name() {
  set_rtc_hh_mm_ss();
  set_rtc_yyyy_month_day(__DATE__);
  sprintf(file_name_buffer,"%02d%02d%02d%02d", month, day, hh, mm );
  outputFile = String(file_name_buffer);
  outputFile += ".csv";
  Serial.println("File: " + outputFile);
}

// <-- Marking Time of Receipt --------------------
void do_receiving_timestamp() {
  set_rtc_hh_mm_ss();
  set_rtc_yyyy_month_day(__DATE__);
  sprintf(file_name_buffer,"%02d/%02d/%02d:%02d:%02d:%02d", year, month, day, hh, mm, ss );
  //interrupt_seq_number++;
  //fullString = String(non_volatile_time_of_interrupt);
  fullString += (",interrupt:");
  fullString += (file_name_buffer);
  fullString += (",");
  //fullString += String(interrupt_seq_number);
}

// <-- Receiving BT input --------------------
void recv_with_end_marker() {
    do_receiving_timestamp();
    readString = Serial.readStringUntil(endMarker);
    fullString = timestampString;
    fullString += ",";
    fullString += readString;
}

// <-- Writing to STD Output --------------------
void do_serial_write() {
  j = fullString.length();
  for (i = 0; i < j; i++) {
    Serial.print(fullString.charAt(i)); 
  }
  Serial.write("\n");
}

// <-- Checking SD access Pin --------------------
void Check_SD_access_pin() {
  if (SD.begin(chipSelectPin)) {
    Serial.println("SDCard init OK.\n");
  } else {
    Serial.println("FAIL 3: init SDCard");
    return;
  }

  Serial.println("Header to " + outputFile);
  targetFile = SD.open(outputFile, FILE_WRITE);
  if (targetFile) {
    targetFile.println(fullString);
  } else {
    Serial.println("FAIL 4: opening File");
  }
  targetFile.close();
}

// <-------------------------------------------------
// <-- Set up process -------------------------------
// <-------------------------------------------------
void setup() {
  //noInterrupts();  // Disable all interrupts before initialization
  Serial.begin(115200);
  Serial.print("Sketch:   ");   Serial.println(__FILE__);
  Serial.print("Uploaded: ");   Serial.println(__DATE__);
  pinMode(dataReadyPin, INPUT);
  pinMode(W5500_SS, OUTPUT);
  digitalWrite(W5500_SS, HIGH); // davekw7x: If it's low, the Wiznet chip corrupts the SPI bus
  delay(100);
  SPI.begin();
  delay(100);
  create_file_name();
  // < ---- SDCard present ------------>
  Serial.println("\nSetup() completed.\n");
}

// <-------------------------------------------------
// <-- On-going Loop --------------------------------
// <-------------------------------------------------
void loop() {
  if (Serial.available() > 0 ) {
    Serial.println("Debug: Serial.available() = OK");
    recv_with_end_marker();
    Serial.println("Debug: recv_with_end_marker() = OK");
    do_serial_write();
    Serial.println("Debug: do_serial_write() = OK");
  }
}

The code you've posted looks ok, except I don't see anywhere that you've established communication with BT. recv_with_end_marker() appears to be the culprit and looks as if it's trying to read from the same Serial device that you're printing to. Printing is snail-like, even at 115200. Before you attempt a read, you need to make sure the device is ready. Often a small delay will cure the problem if you don't want to check the status.

file_name_buffer is not big enough.

Hi @DKWatson

Your observations, especially #2) are similar to my understanding of the problem.

DKWatson:
.

  1. ... I don't see anywhere that you've established communication with BT.
  2. recv_with_end_marker() appears to be the culprit and looks as if it's trying to read from the same Serial device that you're printing to.
  3. Printing is snail-like, even at 115200.
  4. Before you attempt a read, you need to make sure the device is ready.
  5. Often a small delay will cure the problem if you don't want to check the status.

Can you help me with coding some ideas:

  • What can I do for #1)? The BT is physically wired into pins 0 and 1.
  • How can I separate the receiving channel from the serial printing channel?
  • I have sample code to check if input from the BT is waiting, but still, how do I get the serial print to use other pins?
  • I have tried using the "#include SoftwareSerial()" and trield allocating separate pins, but the Due envirionment wouldn't allow me to use the "#include SoftwareSerial()"

Look forward to your ideas
Thanks
EGB

  • What can I do for #1)? The BT is physically wired into pins 0 and 1.

The Arduino DUE has three additional 3.3V TTL serial ports: Serial1 on pins 19 (RX) and 18 (TX); Serial2 on pins 17 (RX) and 16 (TX), Serial3 on pins 15 (RX) and 14 (TX). Pins 0 and 1 are also connected to the corresponding pins of the ATmega16U2 USB-to-TTL Serial chip.

The Bluetooth module should be connected to one of the additional hardware serial ports.

I would follow the advice of cattledog. If, for some reason, you are determined to use the same port at the monitor/USB, it gets really messy and probably not something you want to deal with. It's a path chosen when there are no other options. You have options. Stay away from SoftwareSerial, full stop. Besides the fact it won't work on the Due, it bogarts resources. Use the resources available to you.

No free code. Find out how to use the additional ports you have at your disposal. You'll need to change/add just a few characters to your code. Learn which ones and you'll understand that much more. Once done, post your new code and results and we'll have another look. Good luck, you're 95% the way there.

Thanks @Catlledo and @DKW, I switched my BT serial input to pins 19 (RX) and 18 (TX), as you both recommended. Makes sense. But, the program hangs in exactly the same place, see bottom of reply.

cattledog:
The Arduino DUE has three additional 3.3V TTL serial ports: Serial1 on pins 19 (RX) and 18 (TX); Serial2 on pins 17 (RX) and 16 (TX), Serial3 on pins 15 (RX) and 14 (TX). Pins 0 and 1 are also connected to the corresponding pins of the ATmega16U2 USB-to-TTL Serial chip.

The Bluetooth module should be connected to one of the additional hardware serial ports.

DKWatson:
I would follow the advice of cattledog.

Edit: Key code changes are Serial to Serial1:

void setup(){
  Serial.begin(115200);
  Serial1.begin(115200);
}
void loop() {
  if (Serial1.available() > 0 ) {
    Serial.println("Debug: Serial.available() = OK");
    recv_with_end_marker();
    Serial.println("Debug: recv_with_end_marker() = OK");
    do_serial_write();
  }
}
void recv_with_end_marker() {
    readString = Serial1.readStringUntil(endMarker);
}

I'm missing out on some very basic understanding. That last 5% is a barrier! Can you help push me through it !!!

... look forward to your further ideas
Regards
EGB

=================

Sketch:   /home/graham/monitoring/ArduinoUno/HRV_shells/HR_sym_receiving_due_w_RTC/HR_sym_receiving_due_w_RTC.ino
Uploaded: Aug 30 2018
File: 08300641.csv

Initializing SD card...SDCard OK
SDCard init OK.

Header to 08300641.csv
File: 08300641.csv

Files: Name, Date, Size (bytes): 
08300641.CSV  2000-01-01 01:00:00 70
End


Setup() completed.

Debug: Serial.available() = OK
Deb               <<<=== hangs at this serial output

Deb <<<=== hangs at this serial output

One of the very few places where SerialN.flush() is useful is exactly this situation. Something is preventing the interrupts from firing that should be moving the rest of the serial data out. After each Serial.print(), add a Serial.flush().

The recv_with_end_marker() code that you are using did NOT originally use Strings and was NOT a blocking function. Why did you butcher that function?

arduino_new:
file_name_buffer is not big enough.

Hey there, @arduino_new!

Cracked it! That was a key issue. You were right!

I used the same buffer variable for different length inputs. This resulted in a buffer overflow, which caused the program to hang.

Thanks a million!
Regards
EGB

PaulS:
One of the very few places where SerialN.flush() is useful is exactly this situation. Something is preventing the interrupts from firing that should be moving the rest of the serial data out. After each Serial.print(), add a Serial.flush().

The recv_with_end_marker() code that you are using did NOT originally use Strings and was NOT a blocking function. Why did you butcher that function?

I love it! Yes, @PaulS, I do butcher my code - and as we see above - it causes all sorts of problems, even mayhem! When will I learn!

Your Serial1.flush() idea is appreciated: Now that I have got things working, I will use that when I re-install my interrupt code.

My Due is working. Thank you all!
Thank you.
EGB