First shot at SoftwareSerial on Photon (beta state)

I’ve had the need for a simple SoftwareSerial implementation on the Photon to get the cheap MP3 player module and a Nextion display connected to a Photon.
So I just clobbered together a simple SparkTimerLibrary driven ParticleSoftSerial library.

I hope others might find it useful.

Any suggestions for improvement welcome!
Besides SparkTimerLibrary it also requires 0.6.0-rc.2, due to the use of the new Logging feature (which could be removed too).

Max baud rate is not brilliant (31250, under good conditions 38400, for very short transmissions even 57600), but for my needs quite enough.
With lower latency (and higher priority) interrupts, that could be helped a bit - I guess.


Hi @ScruffR,

Is this a hint that I should be studying what you have done here (or just coincidence)?

I am referencing my thread (have not looked into how to link to it yet) about ISO 9141 which is a serial communications protocol for automotive which I now understand is not natively supported by the particle microprocessors (unlike the CAN protocol), and would have to be done through software.

I am mainly looking for assurances that the focus of my efforts are on the right track.
Of course, learning is never wasted, but learning to accomplish a new capability for the Photon is better!
My project is bigger in scope than I first thought (and completely off-topic from the reason why I bought my first Photon).

Thanks (again :grinning: ),

Just a coincidence :smiley:

To add a link, you can

  • just insert the URL (with white spaces either side of it), or
  • you can use this notation
    [your link description](URL) (this time, not ehite spaces between parentheses and URL)
  • you can use the link symbol (:link:) in the toolbar

@ScruffR, I have been working on using your code to develop a library for the automotive K-Line protocols.
I realized you use ‘pss’ as a flag to ensure only one instance of ParticleSoftSerial is allowed at any time.
My thought it would be a good idea to use a common flag to ensure that only one instance is allowed at any time of ParticleSoftSerial OR my ParticleSoftKLine. Given our codes heavily use the same resources, it only makes sense to protect the operation of the Particle device.

My best thought so far is to ask if it makes sense to put a common flag in @peekay123 's SparkIntervalTimer library so any heavy user of timers could be aware of other heavy users.

Thoughts on the best way to do this? I want to go with a solution that makes strategic sense for all of us.

@cyclin_al, the issue is not with the SparkIntervalTimer library but with the user ISR. SoftSerial has a “heavy” ISR and the reason why only one instance is allowed.

I’m not sure what “same resources” you mean. Hardware timers are uniquely assigned to their own ISR in SparkIntervalTimer. As I mentioned, it is the ISR service code which is the issue. You could have 7 timers running with small ISRs and not even tax the Photon. It’s really up to the programmer to understand their system and design accordingly. Perhaps in your case the overhead of ParticleSoftSerial is not suitable for your application.

1 Like

I should explain my situation further. I see potential use cases in the automotive field where someone (like me) would want to have an application using 2 serial lines and K-Line at the same time. For example, K-Line to the engine control unit, serial to a GPS, and another serial for debugging, another device, etc. One serial line could use the built-in capabilities of a Photon. That leaves a serial line and K-Line to be done in software, but not at the same time.

I agree that SoftSerial has a “heavy” ISR, which is better articulated than saying the “same resources”.
In which case, ParticleSoftKLine also has a “heavy” ISR. It is essentially a serial protocol with unique timing and baud changes (switching between 5 baud and 10.4k baud at times).

The key phrase becomes “not at the same time” and I started looking at what ParticleSoftSerial and ParticleSoftKLine used in common (ie SparkIntervalTimer) as a mechanism to be aware of each other’s instances.

I am assuming that a firmware application could choose to include ParticleSoftSerial or ParticleSoftKLine or both.
Up to now, I have not considered integrating ParticleSoftSerial and ParticleSoftKLine into a common library, but I suppose that could be done to manage the heavy ISR. I still think I want to avoid this approach and keep ParticleSoftSerial and ParticleSoftKLine independent (but aware) of each other.

Is there another way to think about this?

@cyclin_al, personally I would use a coprocessor for doing the K-Line communications. Even a simple ATiny85 might do the job and it could be connected via SPI or I2C to the Photon. Nonetheless, I believe what you are looking for is a mutex mechanism that will only allow one object to do software serial at a time. As I indicated before, this is not a timer issue but resource (in this case, virtual) issue. Making K-Line inherit from ParticleSoftwareSerial would allow the object to have a mutex that can be set to lock out any others until the mutex is released.


In ParticleSoftSerial.cpp, you have the following table of constants:

static const BAUD_TIMING btTable[] =
//    baud  �s/start  �s/bit 1/baudrate 
//                    shorter due to call latency
//  { 115200,     3,     9 }, // exact    8.68056�s
  {  57600,     9,    16 }, //         17.36111�s
  {  38400,    24,    24 }, //         26.04167�s
  {  31250,    31,    31 }, //         32.00000�s
  {  28800,    37,    33 }, //         34.72222�s
  {  19200,    61,    51 }, //         52.08333�s
  {  14400,    90,    68 }, //         69.44444�s
  {   9600,   140,   104 }, //        104.16667�s
  {   4800,   295,   208 }, //        208.33333�s
  {   2400,   610,   417 }, //        416.66667�s
  {   1200,  1230,   833 }, //        833.33333�s
  {    600,  2500,  1667 }, //       1666.66667�s
  {    300,  5000,  3333 }, //       3333.33333�s
  {      0,     0,     0 }  // end mark

I wanted to add in some specific baud rates (10400 & 5 baud) in my ParticleSoftKLine.cpp,
but I wanted to know how you determined the timing. I first assumed the timings would have a linear relationship with the baud rate, which I then realized is not the case.
What method did you use to determine the timing?

That was empiric. Since the interrupts have some considerable latency with the Particle hardware abstraction layer in place and the changing the periode between start bit and data takes some time too, it was easiest to take these measurements with an oszilloscope instead of finding a formula that takes the two constant latency times into consideration.
But with baud rates on the low side these latencies will have less and less impact.

On the other hand, I guess you could just draw a graph of the two time-values over the baud rate and find the nearest value to your desired rate.
And for 5 baud you just take the µs for 1.5 (300000µs) and 1 bit (200000µs).
For 10400 one bit would be 96.15µs so your two values would be around 126 & 95 (give or take)

1 Like

@ScruffR, Thanks for the response. That confirms I should cobble together a DIY logic analyzer or try harder to save up for an oscilloscope. I suspected that it was empiric.

In the meantime, I found my error in estimating the empirical values.
For 10400, I will start with 128 & 95.
For 5, I will start with 300000 & 200000.
The numbers are much closer now…

1 Like

@ScruffR is this library compatible or tested with the Particle Mesh?

@emil01 it is not compatible.

thanks @peekay123