ChangeLog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and its stricter, better defined, brother Common Changelog.

This project adheres to Semantic Versioning.


Unreleased

GitHub Release: Unreleased

Changed

Added

Removed

Fixed


3.0.0

GitHub Release: 3.0.0

Changed

  • Made EnableInterrupt a required dependency for AVR boards while retaining compatibility with sketches that do not include its header directly.
  • BREAKING Introduced the SDI12_INTERNAL_PCINT macro to control internal PCINT ISRs on AVR boards, replacing the previous SDI12_EXTERNAL_PCINT approach.
  • Reworked command sequencing around the new recorder workflow, including retry/break behavior and cancellation handling that returns the bus to listening mode.
  • Split shared protocol timing and response-limit definitions into dedicated protocol headers/source to simplify core transport maintenance.
  • Updated and reorganized example coverage toward recorder-driven and non-blocking usage patterns.

Added

  • Added the new SDI12Recorder API implementation for phased command/response orchestration.
  • Added non-blocking recorder examples, including m_non_blocking_concurrent_logger and n_non_blocking_measurement.
  • Added a terminal-style command example (g_terminal_interface) and an examples/extras/raw_extended_commands sketch for raw command workflows.
  • Added CI coverage for SDI12_INTERNAL_PCINT example compilation.
  • Added the SDI12_RECEIVE_EVENT_COMMAND_COMPLETED keyword token.

Removed

  • Removed deprecated example sketches that were replaced by recorder-focused or reorganized examples (f_basic_data_request, g_terminal_window, i_SDI-12_interface, j_external_pcint_library, and l_verify_crc).
  • Removed extras/TestCommands.
  • Potentially breaking: Removed the macros SDI12_VALUE_STR_SIZE, SDI12_DATA_STR_SIZE, and SDI12_HV_STR_SIZE. The values can now be found in the SDI12ResponseLimits struct. These numbers are defined by the protocol specification.

Fixed

  • Added a link-time fallback EnableInterrupt implementation to prevent missing symbols in existing AVR sketches without conflicting with sketches or libraries that provide EnableInterrupt themselves.
  • Fixed parsing boundaries between command terminators (!) and response terminators (CRLF) to reduce malformed-response handling edge cases.
  • Fixed service-request and zero-value response handling edge cases in recorder-driven data collection.

2.5.2

GitHub Release: 2.5.2

Changed

  • Updated author and export exclusions in library properties and json files

2.5.1

GitHub Release: 2.5.1

Changed

  • added more defines for SDI-12 sensor address and other configurable parameters to the examples

2.5.0

GitHub Release: 2.5.0

Changed

  • Increased the default buffer size from 81 to 82 characters.

Added

  • Added a centralized configuration header for customizing SDI-12 buffering, interrupt behavior, and protocol timing.
  • Added options to select specific AVR pin-change interrupt vectors.

Removed

Fixed


2.4.0

GitHub Release: 2.4.0

Changed

  • Made receiveISR() virtual and protected so subclasses can customize receive handling.
  • Made the shared buffer-overflow state static and volatile across all SDI12 instances.
  • Moved receive parity checking from the interrupt service routine into read() and peek() so standard 7E1 and high-volume binary 8N1 data can share the receive buffer.
  • Switched ATmega640, ATmega1280, ATmega2560, ATmega1284, and ATmega1284P boards from 8-bit Timer2 to 16-bit Timer3 for SDI-12 timing.
  • Updated examples and test sketches to use protocol response windows instead of fixed post-command delays and to improve address, CRC, and retry handling.
  • Updated the bundled SDI-12 specification to version 1.4 dated February 20, 2023, and removed superseded specification files.

Added

  • Added support for high-volume binary data commands, including peekBinary(), readBinary(), timedReadBinary(), writeBytes(), and SDI12BinaryDataType_e.
  • Added getTimeout() and getTimeoutValue() to report the stream timeout and the value returned when parseInt() or parseFloat() times out.
  • Added the write(const uint8_t*, size_t) overload for writing multiple bytes.
  • Added STM32 support using micros()-based timing.
  • Added support for ATmega640 boards.

Removed

  • Removed the SDI12_IGNORE_PARITY option; standard character reads now always validate parity.
  • Removed the SDI12_YIELD() and SDI12_YIELD_MS configuration macros and their artificial read delay; timed reads and peeks provide the required waiting behavior.

Fixed

  • Fixed extra sensor wake delays that could be shortened by integer overflow.
  • Fixed overflow in receive bit-time calculations on 16-bit timers near counter rollover.

2.3.4

GitHub Release: 2.3.4 This is a re-release on the main repository of tag 2.3.3 from the similie/Arduino-SDI-12 fork with only very minor changes.

Changed


2.3.3

GitHub Release: 2.3.3 This is a fork release from similie/Arduino-SDI-12, made because ESP32 recorders that talked to older sensors reliably on v2.1.4 stopped reading them on v2.2.0 and later. Everything added since v2.1.4 is kept; the changes here restore the receive tolerance and the transmit timing guarantee that v2.1.4 had, and make both adjustable at build time.

Changed

  • Widened the default receive window on processors that use micros() (ESP32, ESP8266, Particle, Giga, and anything else at or above 48MHz) from 50 ticks (95 on 48MHz boards) to 416 - half of one bit.
    • SDI12Timer::bitTimes() counts bits as (dt + RX_WINDOW_FUDGE) / TICKS_PER_BIT, so the fudge is exactly how early a level change may arrive, while TICKS_PER_BIT - RX_WINDOW_FUDGE is how late it may arrive. At 50 the window was +783/-50 µs, which is why a bus with slow edges failed: an RC-loaded line delays the rising edge, shortening the interval that starts on it, and an interval that is more than 50 µs short counts as zero bits. The ISR returns on a zero-bit interval without advancing prevBitTCNT, so the remainder of that character is assembled from the wrong level, which then trips the parity check and (because _parityFailure is only cleared when the next command is sent) discards the rest of the response.
    • Half of a bit centers the window, giving ±416 µs. v2.1.4 tolerated about -128 µs here, so this is more forgiving than the version it is meant to restore.
    • AVR and SAMD defaults are unchanged.

Added

  • SDI12_RX_WINDOW_FUDGE build flag to override RX_WINDOW_FUDGE on any board (-D SDI12_RX_WINDOW_FUDGE=50 restores the v2.3.2 value).
  • SDI12_TX_DISABLE_INTERRUPTS build flag to disable interrupts while transmitting on processors at or above 48MHz, where v2.2.0 stopped doing so. This restores the v2.1.4 behavior for boards running an RTOS, where a task switch can stretch a bit past tolerance. Off by default.
  • SDI12_LINE_BREAK_MICROS and SDI12_LINE_MARK_MICROS are now overridable at build time (v2.1.4 used 12300 and 8500; the defaults remain 12100 and 8400).
  • A compile-time check that rejects an RX_WINDOW_FUDGE of a whole bit or wider, which would otherwise silently shift every character by one bit.
  • extras/rx_window_model/rx_window_model.py, a model of the receive ISR for the v2.1.4, v2.3.2, and v2.3.3 bit-assembly logic. It reports how often a response decodes against edge skew, ISR jitter, and sensor baud error, so the effect of a window width can be checked without hardware.

2.3.2

GitHub Release: 2.3.2

Changed

  • Increased fudge time again for processors at TICKS_PER_SECOND == 500000 && TIMER_INT_SIZE == 16

2.3.1

GitHub Release: 2.3.1

Changed

  • Increased fudge time for SAMD51 processors and those with matching clocks.
  • Changed order of pinMode/digitalWrite to correctly disable resistors.

Added

  • Added a check for too-many-bits for devices that use > 8 bit timers.

Fixed

  • Corrected spelling and formatting errors.

2.3.0 - 2025-03-04

GitHub Release: 2.3.0

Added

  • Added support for Particle boards, thanks to @joaquinperaza
    • These boards use millis() and default interrupts like other 48MHz boards, but without the digitalPinToInterrupt() macro.
  • Added (completely untested) support for Arduino Giga

Changed

  • Breaking Changed the parseInt(), parseFloat(), and peekNextDigit() functions so that they are better customized for reading from a data response request.
    • Any LookupMode or ignore inputs will be ignored.
  • Potentially Breaking Parity checking can no longer be turned off. Characters that fail parity checks will not be returned from the buffer.
  • Change fudge for 48MHz boards using millis() from 50 to 95 based on comments in #145
  • Reset bit timer when entering listening state.
  • Verify that at least one bit time has passed before processing a pin change interrupt, where possible.

Fixed

  • Fixed un-setting of clocks and timers on SAMD (SAMD51 and SAMD21) boards.
  • Fix check for the LookaheadMode enum to use the Espressif Arduino core version instead of the IDF version.

2.2.1 - 2024-12-09

GitHub Release: 2.2.1

Added

  • Added support for Arduino ESP32 Core versions >3.x.x, based on IDF >5.1.x

Fixed

  • Reordered steps to unset the prescaler on SAM/D boards. The incorrect order was causing a hang when waiting for sync.

2.2.0 - 2024-08-14

GitHub Release: 2.2.0

Changed

  • Added python version to GitHub actions (for PlatformIO)
  • Switched to reusable workflows for GitHub actions
  • Consolidated timer prescaler math
  • Moved bitTimes and mul8x8to16 functions to the timers files
  • Replace c-style casts with c++ style casts
  • Do not disable interrupts during Tx for processors over 48MHz
  • Cast all timer values and math to the proper type for the processor timer being read
    • SAMD21 boards now use the full 16-bits of the timer rather than only the first 8-bits.
    • AVR xU4 boards (ie, 32u4/Leonardo) still use the 10-bit timer as an 8-bit timer.
  • Shortened name of espressif ISR access macro from ESPFAMILY_USE_INSTRUCTION_RAM to ISR_MEM_ACCESS
    • This does not change any functionality of the macro, just the name.
  • Moved defines to the top of the SDI12_boards.h file
  • Renamed the "tools" directory to "extras" in compliance with Arduino library standards.
  • Updated copyright and license texts
  • SAMD boards now partially revert clock and prescaler settings when an SDI-12 instance is ended.
    • Prescalers are reset to factory settings, the clock divisor is not reset

Added

  • Added CRC checking
  • Added support for SAMD51 processors using dedicated timers
  • Added parity checking on character reception
    • This can be disabled by defining the macro SDI12_IGNORE_PARITY
  • Allowing (without testing) processors over 48MHz to use micros() function
  • Added a 'yield' function within stream functions to allow the buffer to fill
    • The yield time can be modified using the macro SDI12_YIELD_MS

Removed

  • Offloaded some internal header file documentation to markdown files
  • Consolidated redundant READTIME and TCNTX macros, removing TCNTX
  • Removed documentation m_span commands

Fixed

  • Added an extra addition/removal of interrupts for espressif boards in the begin function to properly initialize the interrupts and avoid a later error with the gpio_install_isr_service.

2.1.4 - 2021-05-05

GitHub Release: 2.1.4

Changed

  • BREAKING Reverted the default wake delay to 0ms.
    • In 92055d377b26fa862c43d1429de1ccbef054af01 this was bumped up to 10ms, which caused problems for several people.
    • The delay can now also be set using the build flag -D SDI12_WAKE_DELAY=#

2.1.3 - 2021-03-24

GitHub Release: 2.1.3

Changed

  • Migrate from Travis to GitHub actions

2.1.1 - 2020-08-20

GitHub Release: 2.1.1

Fixed

  • fixes for the timer and pre-scaler for the ATTiny, courtesy of @gabbas1

2.1.0 - 2020-07-10

GitHub Release: [2.1.0] DOI

To comply with requirements for inclusion in the Arduino IDE, the word Arduino has been removed from the name of this library! The repository name is unchanged.

Changed

1.3.6 - 2019-08-29

GitHub Release: 1.3.6

Fixed

  • A very minor update to fix compiler warnings found when using -Wextra in addition to -Wall.

1.3.5 - 2019-07-01

GitHub Release: 1.3.5

Changed

  • SAMD boards will no longer have a conflict with the Tone functions in the Arduino core. AVR boards will still conflict. If you need to use Tone and SDI-12 together for some reason on an AVR boards, you must use the "delayBase" branch.
  • Examples were also updated and given platformio.ini files.

1.3.4 - 2019-10-29

GitHub Release: 1.3.4

Changed

  • Made the timer changes into a compiled class.
  • NOTE: Maintaining interrupt control for SAMD processors as there are no interrupt vectors to be in conflict. Because the pin mode changes from input to output and back, allowing another library to control interrupts doesn't work.

1.3.3 - 2018-05-11

GitHub Release: 1.3.3

Changed

  • Now unsetting timer prescalers and setting the isActive pointer to NULL in both the end and the destructor functions.
  • Also some clean-up of the examples.

1.3.1 - 2018-04-06

GitHub Release: 1.3.1

Added

  • Changed the incoming data ISR to use a processor timer, this makes the reception more stable, especially when the ISR is controlled by an external library. This also creates some conflicts with other libraries that use Timer2.

Changed

  • Made changes to the write functions to use the timer to reduce the amount of time that all system interrupts are off.
  • Forcing all SDI-12 objects to use the same buffer to reduce ram usage.

1.1.0 - 2018-03-15

GitHub Release: 1.1.0

Added

  • Added notes and an empty constructor/populated begin method to allow this library to be more easily called inside of other libraries.

1.0.6 - 2018-03-09

GitHub Release: 1.0.6

Fixed

  • Fixes the time-out values for the ParseInt and ParseFloat to be -9999. This was the intended behavior all along, but at some point those functions changed in the stream library and the identically named functions within SDI-12 intended to "hide" the stream functions ceased to be called.

1.0.1 - 2017-05-16

GitHub Release: 1.0.1 The first "official" release of this interrupt-based SDI-12 library for AVR and SAMD Arduino boards.