1

I have ATMega328p chip, and I have HC-06 on pin A5, A4 (RX, TX) and I have another device on pin 10, 9 (RX,TX).

I want to be able to send some command on BT via Bluetooth Terminal and pass raw (exact) command to that device unchanged just to log on my computer (on my serial monitor) incoming command from BT and to log the response from device the same way on serial monitor and pass unmodified to HC-06.

How can I do that?

I tried by using "listen()" method but sometimes I get some weird character while I'm transferring\reading data, so not sure how to do this.

All baud rates are 9600.

6
  • 1
    You can only reliably use one SoftwareSerial port at once.
    – Majenko
    Aug 4, 2016 at 21:33
  • Not even with that "listen" function?
    – ShP
    Aug 4, 2016 at 21:38
  • Even with listen(). You can't do anything at all whilst writing on a SoftwareSerial port. That includes listening on another SoftwareSerial port. So anything that arrives on the first port whilst you are writing earlier data out of the second port will become corrupted or not arrive at all.
    – Majenko
    Aug 4, 2016 at 21:42
  • Your question isn't clear at all. Who sends the commands? Who responds? What exactly do you want to achieve? Aug 4, 2016 at 22:39
  • I want to log communication between HC-06 and another hardware via Arduino. Mobile phone send command to HC-06, HC-06 to Arduino, Arduino to third device, and vice versa. What isn't clear there?
    – ShP
    Aug 5, 2016 at 1:31

2 Answers 2

2

You can have high-speed debugging by utilizing either I2C or SPI to send to a second Arduino. That second Arduino can be devoted to receiving debugging information and passing it on (via serial to your PC).

I describe the process here.

The general idea is to add some stuff to the DuT (device under test) to output via SPI/I2C.

Example code:

// make true to debug, false to not
#define DEBUG true

#include <SPI.h>

// conditional debugging
#if DEBUG 

  #define beginDebug()  do { SPI.begin (); SPI.setClockDivider(SPI_CLOCK_DIV8); } while (0)
  #define Trace(x)      SPIdebug.print   (x)
  #define Trace2(x,y)   SPIdebug.print   (x,y)
  #define Traceln(x)    SPIdebug.println (x)
  #define Traceln2(x,y) SPIdebug.println (x,y)
  #define TraceFunc()   do { SPIdebug.print (F("In function: ")); SPIdebug.println (__PRETTY_FUNCTION__); } while (0)

  class tSPIdebug : public Print
  {
  public:
    virtual size_t write (const byte c)  
      { 
      digitalWrite(SS, LOW); 
      SPI.transfer (c); 
      digitalWrite(SS, HIGH); 
      return 1;
      }  // end of tSPIdebug::write
  }; // end of tSPIdebug

  // an instance of the SPIdebug object
  tSPIdebug SPIdebug;

#else
  #define beginDebug()  ((void) 0)
  #define Trace(x)      ((void) 0)
  #define Trace2(x,y)   ((void) 0)
  #define Traceln(x)    ((void) 0)
  #define Traceln2(x,y) ((void) 0)
  #define TraceFunc()   ((void) 0)
#endif // DEBUG


long counter;
unsigned long start;

void setup() {
  start = micros ();

  beginDebug ();
  Traceln (F("Commenced device-under-test debugging!"));
  TraceFunc ();  // show current function name

}  // end of setup

void foo ()
  {
  TraceFunc (); // show current function name
  }

void loop() 
{

  counter++;
  if (counter == 100000)
  {
    Traceln (F("100000 reached."));
    Trace (F("took "));
    Traceln (micros () - start);
    counter = 0;
    foo ();
  }  // end of if

}  // end of loop

The other Arduino (which receives the debugging information) simply echoes it to Serial:

char buf [1000];
volatile int inpoint, outpoint;

void setup (void)
{
  Serial.begin (115200);   // debugging

  Serial.println ();
  Serial.println (F("Commencing debugging session ..."));
  Serial.println ();

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // now turn on interrupts
  SPCR |= bit (SPIE);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register
int next = inpoint + 1;  // next insert point

  // wrap-around at end of buffer
  if (next >= sizeof buf)
    next = 0;

  if (next == outpoint)  // caught up with removal point?
    return;  // give up

  // insert at insertion point
  buf [inpoint] = c;
  inpoint = next;  // advance to next

}  // end of interrupt routine SPI_STC_vect

void loop (void)
{
  // insertion and removal point the same, nothing there
  noInterrupts ();  // atomic test of a 16-bit variable
  if (outpoint == inpoint)
    {
    interrupts ();
    return;
    }
  interrupts ();

  // display anything found in the circular buffer
  Serial.print (buf [outpoint]);

  noInterrupts ();
  if (++outpoint >= sizeof buf)
    outpoint = 0;  // wrap around
  interrupts ();

}  // end of loop

SPI is quite fast, so the overhead of doing the debugging should be slight. The receiving end can batch up the debugging information (up to a point which is about 1000 characters) and then send it to your PC via Serial.


I made a library out of the relevant code. The library is available from:

http://gammon.com.au/Arduino/SPI_Debugging.zip

Example using the library:

// make true to debug, false to not
#define DEBUG true

#include <SPI.h>
#include <SPI_Debugging.h>

long counter;
unsigned long start;

void setup() {
  start = micros ();

  beginDebug ();
  Traceln (F("Commenced device-under-test debugging!"));
  TraceFunc ();  // show current function name

}  // end of setup

void foo ()
  {
  TraceFunc (); // show current function name
  }

void loop() 
{

  counter++;
  if (counter == 100000)
  {
    Traceln (F("100000 reached."));
    Trace (F("took "));
    Traceln (micros () - start);
    counter = 0;
    foo ();
  }  // end of if

}  // end of loop

There is a similar library for I2C debugging:

http://gammon.com.au/Arduino/I2C_Debugging.zip

Example of doing I2C debugging:

// make true to debug, false to not
#define DEBUG true
const byte SLAVE_ADDRESS = 100;  // which address debugging goes to

#include <Wire.h>
#include <I2C_Debugging.h>


long counter;
unsigned long start;

void setup() {
  start = micros ();

  beginDebug ();
  Traceln (F("Commenced device-under-test debugging!"));
  TraceFunc ();  // show current function name
}  // end of setup

void foo ()
  {
  TraceFunc (); // show current function name
  }

void loop() 
{

  counter++;
  if (counter == 100000)
  {
    Traceln (F("100000 reached."));
    Trace (F("took "));
    Traceln (micros () - start);
    counter = 0;
    foo ();
  }  // end of if

}  // end of loop

All of the examples illustrate using a #define to turn the debugging output on or off, so you can leave the debugging prints there in case things go wrong, but with debugging disabled they won't have any penalty.

0

How can I do that?

You can't.

It is impossible to use two SoftwareSerial ports together. Simply because while you are writing to one port everything else stops. Interrupts are disabled, and receiving requires interrupts. So anything that arrives while you are sending will either be lost or corrupted.

The only solution is to use a board with multiple hardware UARTs like the Mega or any of the more powerful alternatives to Arduino such as chipKIT or Teensy.

2
  • Would using that hardware UART instead of second software UART fix the problem? For example to use one software serial for that bluetooth, and hardware UART for that other device...
    – ShP
    Aug 5, 2016 at 1:32
  • While not having it tested yet. That would be the solution I'd try. The hardware UART gives you all the functionality for free without interfering with other parts of your software.
    – Kwasmich
    Aug 5, 2016 at 7:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.