Notes on Arduino Streams and Software Serial

In this library, the Arduino communicates with the computer for debugging, the modem for sending data, and some sensors (like the MaxBotix MaxSonar) via instances of Arduino TTL streams. The streams can either be an instance of

Because of the limited number of serial ports available on most boards, I suggest giving first priority (i.e. the first (or only) hardware serial port, "Serial") to your programming and debugging stream going to your PC (if you intend to debug), second priority to the stream for the modem, and third priority to any sensors that require a stream for communication.

The very commonly used build-in version of the software serial library for AVR processors uses interrupts that conflict with several other sub-libraries or this library and cannot be used. I repeat. You cannot use the built-in version of SoftwareSerial!. You simply cannot. It will not work. Period. This is not a bug that will be fixed.

See the section on Processor/Board Compatibility for more specific notes on what serial ports are available on the various supported processors.

Hardware Serial

For stream communication, hardware serial should always be your first choice, if your processor has enough hardware serial ports. Hardware serial ports are the most stable and have the best performance of any of the other streams. Hardware serial ports are also the only option if you need to communicate with any device that uses even or odd parity, more than one stop bit, or does not use 8 data bits. (That is, hardware serial ports are the only way to communicate with a device that doesn't use the 8N1 configuration. Again, always use a hardware serial port for communication if possible!

To use a hardware serial stream, you do not need to include any libraries or write any extra lines. You can simply write in Serial# where ever you need a stream. If you would like to give your hardware serial port an easy-to-remember alias, you can use code like this:

1HardwareSerial* streamName = &Serial;

AltSoftSerial

If the proper pins are available, AltSoftSerial by Paul Stoffregen is also superior to SoftwareSerial, especially at slow baud rates. AltSoftSerial is compatible with ModularSensors "out of the box" - that is, you don't need and modifications to the library or extra defines or build flags to make it work. The biggest drawback to AltSoftSerial is that it is limited to a single set of pins on any given processor. That means you can only ever have one instance of it running at a time. On the EnviroDIY Mayfly, the AltSoftSerial pins are 5 (Transmit/Tx/Dout) and 6 (Receive/Rx/Din).

To use AltSoftSerial:

1#include <AltSoftSerial.h.
2// include the AltSoftSerial library
3AltSoftSerial streamName.
4// Create an instance of AltSoftSerial

NeoSWSerial

Another possible serial port emulator is NeoSWSerial. While not as stable as AltSoftSerial, it supports using any pin with pin change interrupts for communication. To use NeoSWSerial with ModularSensors, you must add the line -D NEOSWSERIAL_EXTERNAL_PCINT to the build flags section of your platformio.ini file If you are using the ArduinoIDE, you must find and open the library install location and open and modify the NeoSWSerial.h file. Find and remove the two slashes from the start of the line //#define NEOSWSERIAL_EXTERNAL_PCINT) and then recompile the library. There are instructions in the NeoSWSerial ReadMe on how to use EnableInterrupt to activate NeoSWSerial. Note that NeoSWSerial must be used with great care with the SDI-12 communication library on most 8MHz processors (including the EnviroDIY Mayfly). The two libraries can be compiled together, but because they are in competition for a timer, you must be very careful to enable and disable each when using the other.. The way this (ModularSensors) uses the SDI-12 library resets the timer settings when ending communication, so you should be able to use the two libraries together. Please test your configuration before deploying it!

After correctly compiling NeoSWSerial, to use it:

1#include <NeoSWSerial.h> // for the stream communication
2const int8_t neoSSerial1Rx = 11; // data in pin
3const int8_t neoSSerial1Tx = -1; // data out pin
4NeoSWSerial neoSSerial1(neoSSerial1Rx, neoSSerial1Tx);
5// To use NeoSWSerial in this library, we define a function to receive data
6// This is just a short-cut for later
7void neoSSerial1ISR() {
8 NeoSWSerial::rxISR(*portInputRegister(digitalPinToPort(neoSSerial1Rx)));
9}

After creating the stream instances, you must always remember to "begin" your stream within the main setup function.

1streamName.begin(BAUD_RATE);

Additionally, for the EnviroDIY modified version of SoftwareSerial, (or NeoSWSerial) you must enable the interrupts in your setup function:

1// Allow enableInterrrupt to control the interrupts for software serial
2enableInterrupt(rx_pin, neoSSerial1ISR, CHANGE);

Neutered SoftwareSerial

The EnviroDIY modified version of SoftwareSerial removes direct interrupt control from the SoftwareSerial library, making it dependent on another interrupt library, but able to be compiled with ModularSensors. This is, by far, the least stable serial port option and should only be used on sensors that are not very picky about the quality of the serial stream or that only require one-way communication (ie, only posting data rather than needing to receive commands).

To use the EnviroDIY modified version of SoftwareSerial:

1#include <SoftwareSerial_ExtInts.h.
2// include the SoftwareSerial library
3SoftwareSerial_ExtInts streamName(tx_pin, rx_pin);

After creating the stream instances, you must always remember to "begin" your stream within the main setup function.

1streamName.begin(BAUD_RATE);

Additionally, for the EnviroDIY modified version of SoftwareSerial, you must enable the interrupts in your setup function:

1// Allow enableInterrrupt to control the interrupts for software serial
2enableInterrupt(rx_pin, SoftwareSerial_ExtInts::handle_interrupt, CHANGE);

SAMD SERCOMs

Example code for creating more serial ports on an Adafruit feather M0 using the SERCOMs is available in the menu a la carte example.

Here are some helpful links for more information about the number of serial ports available on some of the different Arduino-style boards: