Possibility to obtain 2 UARTs on B524/B404x

Hi folks

We want to migrate from WiFi based Particle (Photon) to cellural.
SoMs like B524/B404X looks good except single available UART.

Maybe there is some SoftwareSerial library available for such a modules?
As far we are designing our custom PCB around it I am open to any solutions

Best,
Bogdan

The best solution is a SC16IS740 SPI or I2C UART. This library works very well on the B Series SoM. There are several models with different capabilities like the SC16IS750 and SC16IS760 that also work with that library.

Software serial doesn't work very well because of limited hardware timers and unpredictable interrupt latency on the nRF52.

1 Like

Thanks, nice finding.

As far I would need 2xUARTs I would prefer SC16IS760. Does library support 2xUARTs of single SC16IS760?
For highest performance/speed with the library you would recommend stick to I2C or SPI?

Best,
Bogdan

You can connect two SC16IS740 or 750 to the same SPI bus and that works right now.

The SC16IS752/762 dual UART is almost two of the other chips in a single package. The library doesn't currently work with it, but I looked at it several years ago and it didn't seem like it would be difficult but I never got a chance to implement it.

SPI is much faster than I2C.

@PoCLab, what is the maximum baud rate you expect? These devices have 64 byte receive and transmit FIFOs and will generate an interrupt when they read a preset level. Using SPI is best so you can move the data on or off the device as quickly as possible. However, at high baud rates, servicing the interrupts can be problematic.

In my Application sometimes I get burst of data up to 4KB on 38400
And would like to have a large buffer to be safer about potential overflows and data loss

And as far current implementation of @rickkas7 lib not using interrupts/they are tricky on nRF52. I think unless I am fastly start reading after first byte comes I will lost the data with such a small FIFO.

Anyway it's good starting point and I can handle it somehow in software unless somebody would come up with better solution.

In General it's a shame that such a good module has only 1 free UART to use.

Interrupts won't help because you can't start an SPI transaction from an ISR. That's why the library doesn't support it for sending and receiving.

Instead you should handle the requests from a worker thread, which will be more than fast enough to read 4K of data at 38400.

1 Like

@rickkas7 We have an HW setup with 2xSC16IS740 shared SPI lanes and dedicated CS for each IC.
Can you help me understand the proper initialization for 2 UARTs? My understanding that it's should be somehow similar to a dual port IC example. A short example would be highly appreciated.
We are testing with B524.

  • Use the SC16IS7xxRK library (not the older one)

  • Create two SC16IS7x0 objects, one for each chip, typically as global variables.

SC16IS7x0 serialA;
SC16IS7x0 serialB;
  • Initialize them with the appropriate CS pin and settings, typically from setup():
    serialA
        .withSPI(&SPI, D2, 4)   // SPI port, CS line, speed in MHz
        .begin(9600);

    serialB
        .withSPI(&SPI, D3, 4)   // SPI port, CS line, speed in MHz
        .begin(9600);

How can I use 2xSC16IS740 with shared SPI lines and a dedicated CS for each IC to switch between them on the fly instead of changing the CS pin status every time I want to send data to one of the two SC16IS740
Here's the code I use, when sending a sentence through serialA (with SC16IS740 channel A turned on and SC16IS740 channel B turned off), everything works. When uncommenting println from serialB,the sentence is sent to serialB regardless of the status of the CS pin- LOW

#include <SC16IS7xxRK.h>

// Pick a debug level from one of these two:
SerialLogHandler logHandler;
// SerialLogHandler logHandler(LOG_LEVEL_TRACE);

SYSTEM_THREAD(ENABLED);

SC16IS7x0 SerialA; // First SC16IS7xx module
SC16IS7x0 SerialB; // Second SC16IS7xx module

char out = ' ';

void setup() {
    
     // Set CS pin D5 LOW for extSerial1
    pinMode(D5, OUTPUT);
    digitalWrite(D5, LOW);

    // Set CS pin D6 HIGH for extSerial2
    pinMode(D6, OUTPUT);
    digitalWrite(D6, HIGH);
    
    
 // If you want to see the log messages at startup, uncomment the following line
    waitFor(Serial.isConnected, 100);

    // Set the baud rate of the USB serial port to 115200
  // Serial.begin(9600);


    Log.info("This is info message1");
   
    // Initialize the first SC16IS7xx module
   SerialA
         .withSPI(&SPI, D5, 4)   // SPI port, CS line (D5), speed in MHz
         .begin(9600); // Set the baud rate for extSerial1 to 9600 (or your desired rate)*/

    // Initialize the second SC16IS7xx module with a different CS line (D6)
    SerialB
           .withSPI(&SPI, D6, 4)   // SPI port, second CS line (D6), speed in MHz
           .begin(9600);


}

void loop() {
    // Rest of your loop code
  SerialA.println("UART A working");
  delay(1000);
    
  /*SerialB.println("UART B working");
  delay(1000);*/
}

I will be very grateful if you help me with an example to understand how to manage two chips quickly without rewriting the code every time and without changing the pin statuses.

Do not attempt to control the CS pins directly. It won't work.

If you want to make something that you can switch between ports, store the pointer to the one you want in a variable of type Print. For example:

Print *port = &SerialA;

port->println("UART A working");
delay(1000);

port = &SerialB;
port->println("UART B working");

More likely you'd make port a global variable or a class member and you'd set it to whatever port you want to use.

1 Like

Could you please explain how to solve the problem with the appearance of an unknown character at the end of each line that is written to the serial port monitor (screenshot below) and whether the baudrate affects it?

There is also a problem with the function of reading channels, as indicated in this piece of code, no output to the log occurs

while(extSerial.available()) {
		int c = extSerial.read();
		Log.info("received %d", c);
	}

I am adding my code that I adapted to my tasks, maybe I made a mistake in it, I will be very grateful if you indicate its availability

#include <SC16IS7xxRK.h>

// Pick a debug level from one of these two:
SerialLogHandler logHandler;

SYSTEM_THREAD(ENABLED);

SC16IS7x0 SerialA; // First SC16IS7xx module
SC16IS7x0 SerialB; // Second SC16IS7xx module

void setup() {
 // If you want to see the log messages at startup, uncomment the following line
    waitFor(Serial.isConnected, 10000);

   
    // Initialize the first SC16IS7xx module
   SerialA
         .withSPI(&SPI, D5, 4)   // SPI port, CS line (D5), speed in MHz
         .begin(115200); // Set the baud rate for extSerial1 to 9600 (or your desired rate)

    // Initialize the second SC16IS7xx module with a different CS line (D6)
    SerialB
           .withSPI(&SPI, D6, 4)   // SPI port, second CS line (D6), speed in MHz
           .begin(115200);
}

void loop() {
Print *port = &SerialA;
port->println("UART A working");
delay(1000);

port = &SerialB;
port->println("UART B working");
delay(1000);

while(SerialB.available()) {
	int c = SerialB.read();
	Log.info("received %d", c);
   }
}

Thank you in advance for your help.

println adds a CR and LF at the end of each line. You probably need to change the setting of the popup that's currently set to Both NL and CR (next to the baud rate) to some other setting.

Thanks @rickkas7 but NL & CR it's a configuration for sending data to the Particle Device + SC16IS740

I've did further testing and can confirm that method

port->write

works as expected printing single char

Method print works in the same way for single char
Println adding unexpected characters to the end
For example

port->println('a');

Prints in HEX as 0x61 0x0D 0x0A
0x61 it's ASCII "a" but what are 0x0D and 0x0A?

Any ideas?

0x0D = \r = CR
0x0A = \n = LF (or NL)

I suspect the CR is the odd character, so you can work around this by using:

print("UART A working\n");

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