Adding a serial port using the SC16IS740

I added a library, SC16IS740RK, that makes it possible to use up to 4 SC16IS740 I2C UARTs off the I2C bus (D0 and D1). The chips support from 50 to 115200 baud and can go higher with different oscillators.

Basically, just create the object and call begin() and it works like a regular UART like Serial1:

#include "SC16IS740RK.h"

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

SC16IS740 extSerial(Wire, 0);

char out = ' ';

void setup() {
	Serial.begin(9600);

	delay(5000);

	extSerial.begin(9600);
}

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

	extSerial.print(out);
	if (++out >= 127) {
		out = ' ';
	}
	delay(100);
}

Tested with both the Photon and Electron and 0.7.0:

On the Github there’s also the Eagle CAD files for making the handy breakout board in the picture and the BOM.

This is just the first version and I’ll eventually add interrupt support, flow control, and possibly SPI interface support.

7 Likes

@rickkas7, nice job on the library! Having interrupts and SPI would make those things fly!

1 Like

OK, I just designed a SPI with hardware flow control board and sent it off to fab, so I’ll write the software for those features when I get the boards back.

3 Likes

I’m trying to use your library for the SC16IS740RK over SPI on an Argon with 0.8.0-rc.27.

Printing a single character with extSerial.print('a') works fine but printing a string with extSerial.print("ab") doesn’t work and the Argon flashes SOS 10 / Assertion failure.

Minimal code:

#include "SC16IS740RK.h"

SC16IS740SPI extSerial(SPI, A2);

void setup() {
	extSerial.begin(9600);
	extSerial.print("ab");
}

void loop() { }

I can receive the single character at the output, so the hardware setup seems to be fine.

Is this a bug in the library or in the particle firmware or am I doing something wrong?

Can you try extSerial.write("ab", 3);?

Same problem with extSerial.write((uint8_t*)"ab", 3)

Splitting in

	extSerial.print('a');
	extSerial.print('b');
	extSerial.print('\0');

works fine.

I know there were (are) some issues with SPI and rc.27 (at least in the implementation of SPI.beginTransaction()) so it might well be an issue with the implementation of SPI on the mesh devices.

So until Rick can report back, you could copy/paste the sources for that library and add some Serial.print() statements in the SC16IS740SPI::writeInternal() and SC16IS740Base::write() functions to home in on the offending instruction.

I can reproduce the problem in SPI mode but not in I2C mode. It could be a SPI DMA issue, but I’ll have to dig into it further later.

1 Like

AFAICT you are not using DMA in your implementation

	spi.transfer(const_cast<uint8_t *>(buffer), NULL, size, NULL);

I released version 0.0.3 of the library. On mesh devices, I temporarily disabled the multi-byte SPI transfer mode since that appears to be the source of the SOS fault. It does multiple single-byte SPI transfers, which seems to work fine.

4 Likes

Wow, that was fast!
0.0.3 fixed the issue, thank you very much! This library is perfect for me as I need three serial ports on a mesh device. It makes using these ICs really easy.

Also thank you to @ScruffR for your assistance.

4 Likes

Hello @rickkas7

I just received my SC16IS740 board and I would like to use it as a second serial port on the Xenon as TX & RX are already used. It is this board:

I have connected the SC16IS740 TX to A3 and its RX to A1 . How can I tell the library to use them? What is the role of A1 & A0 on your board?

Thanks in advance for your help.

When using I2C you need to use D0/D1 and with SPI A3, A4 & A5 (assuming Photon or Electron) plus some other pin of your choosing.

1 Like

The SC16IS7xx works on the Xenon, however as ScruffR pointed out, it can connect either by I2C or SPI. If you are connecting low baud-rate devices (9600 and lower), I recommend I2C (pins D0 and D1) as it's generally easier and has sufficient performance.

Also, for the Xenon only, there are two hardware serial ports on the Xenon itself.

Serial2: This channel is optionally available on D4(TX) and D5(RX). Optional hardware flow control is available on D6(CTS) and D8(RTS) on the Xenon.

(There is no second serial port on the Argon and Boron because the second serial port connects to the network coprocessor.)

Thank you @rickkas7 and @ScruffR.

I am using it on a Xenon in i2C mode. The reason I cannot use the Xenon’s second serial port is that I am also using the Ethernet wing whose pins conflict with Xenon’s second serial port.

I would appreciate your help with the correct wiring and configuration. The wiring I am using is below. Where should the violet board’s I2C-/SPI pin connect to? GND or 3.3V?

The violet board is used with the library to interface to a serial UART sensor. The first serial port is already used with another sensor.

Because the sensor I am trying to connect to is 60 feet away, I am using a pair of RS485 to UART converters on each end. On a Photon, the RS85 converter TX goes to the Photon’s TX (not RX), and RX to RX. This configuration (along with the SoftSerial library at a speed of 38400 baud) has worked now flawlessly for months.

I am now converting the project over to a Xenon and due to the Ethernet featherwing conflicts and the lack of a SoftSerial library for mesh devices, the only solution is to use your library to add a second serial port. However, currently, I am not getting any readings from the sensor.

Can you help debug why it is not working? Is it related to wiring the RX and RX lines or something else.

Thanks in advance.

  • I2C/SPI should be high (3V3) for I2C mode
  • A0 and A1 must be tied either to GND or 3V3. Setting both to GND will use I2C address offset 0. Setting different values allows the use of more than one SC16IS7xx on the I2C bus
  • It doesn’t look like your board has I2C pull-ups so you’ll need 4.7K or 10K pull-ups to 3V3 on on SDA and SCL
  • /IRQ is not used by my library so you can leave it unconnected
  • Leave all of the IOx pins unconnected
  • Leave CTS and RTS unconnected.
2 Likes

Thank you very much @rickkas7. Will try your recommendations.

Should RX be connected to RX on RS485 converter (or to TX)?

Thanks again.

On the SC16IS7xx:

  • RX means data into the SC16IS7xx (from the serial device)
  • TX means data out of the SC16IS7xx (to the serial device)

It depends on your converter what pin it connects to.

Are you using RS485 in point-to-point or in multi-drop (linear bus) mode? While the SC16IS7xx does support multi-drop, my library does not.

re. pull-up

1 Like

Thank you, very helpful :slight_smile: