Awesome
AceSegmentWriter
A companion library to the AceSegment
library. This provides higher-level convenience classes for writing decimal
numbers, hex numbers, temperature, clock digits, characters, and strings to
seven segment LED modules. The following classes are provided: PatternWriter
,
NumberWriter
, ClockWriter
, TemperatureWriter
, CharWriter
,
StringWriter
, LevelWriter
, and StringScroller
.
Initially, this code was part of the AceSegment library and depended directly on
the LedModule
class of that library. Later the direct dependency was removed
by converting the Writer classes into generic code using C++ templates. The
classes now depend on the T_LED_MODULE
template type which should implement
the public methods that appear in the LedModule
class. But T_LED_MODULE
is
not required to inherit from LedModule
which preserves the decoupling
between the AceSegmentWriter and AceSegment libraries.
Version: 0.5 (2023-03-16)
Changelog: CHANGELOG.md
Table of Contents
- Installation
- Documentation
- High Level Overview
- Usage
- Resource Consumption
- System Requirements
- Bugs And Limitations
- Alternative Libraries
- License
- Feedback and Support
- Authors
<a name="Installation"></a>
Installation
The latest stable release is available in the Arduino IDE Library Manager. Search for "AceSegmentWriter". Click install.
The development version can be installed by cloning the GitHub
repository, checking out the
default develop
branch, then manually copying over to or symlinking from the
./libraries
directory used by the Arduino IDE. (The result is a directory or
link named ./libraries/AceSegmentWriter
.)
The master
branch contains the stable releases.
<a name="SourceCode"></a>
Source Code
The source files are organized as follows:
src/AceSegmentWriter.h
- main header filesrc/ace_segment_writer/
- implementation filestests/
- unit tests which require AUnitexamples/
- example sketchesdocs/
- contains the doxygen docs and additional manual docs
<a name="Dependencies"></a>
Dependencies
This library library has a direct, compile-time dependency on:
- AceCommon (https://github.com/bxparks/AceCommon)
The following libraries are recommended, and they are added in the depends
property of library.properties
so that they are automatically installed by the
Arduino Library Manager for convenience. However, client applications are not
required to use these. Other libraries with the same interface and
functionality can be substituted if desired.
- AceSegment (https://github.com/bxparks/AceSegment)
- AceSPI (https://github.com/bxparks/AceSPI)
- AceTMI (https://github.com/bxparks/AceTMI)
- AceWire (https://github.com/bxparks/AceWire)
The unit tests depend on:
- AUnit (https://github.com/bxparks/AUnit)
Some of the examples may depend on the following which may need to be installed manually:
- AceButton (https://github.com/bxparks/AceButton)
<a name="Documentation"></a>
Documentation
- this
README.md
file - Doxygen docs
- On Github pages.
<a name="Examples"></a>
Examples
The following example sketches are provided:
- Basic
- All of the examples assume an LED module based on the TM1637 controller chip. These LED modules are readily found on retail outlets like eBay or Amazon. You can reconfigure the examples to use a different LED module.
- PatternWriterDemo
- NumberWriterDemo
- ClockWriterDemo
- TemperatureWriterDemo
- CharWriterDemo
- StringWriterDemo
- LevelWriterDemo
- StringScrollerDemo
- Intermediate
- WriterTester
- demo of the various
src/writer
classes - supports multiple LED modules based on different controller chips
though
#define
macros - depends on AceButton (https://github.com/bxparks/AceButton) library
- uses 2 buttons for "single step" debugging mode
- demo of the various
- WriterTester
- Benchmarks
- MemoryBenchmark: determines the size of the various components of the library
- No
AutoBenchmark
program.- These Writer classes simply write into the in-memory buffer provided
by the underying
T_LED_MODULE
class. - The execution time is too fast to be easily measured and does not seem worth the effort.
- These Writer classes simply write into the in-memory buffer provided
by the underying
<a name="HighLevelOverview"></a>
High Level Overview
<a name="ClassesAndTypes"></a>
Classes and Types
Here are the classes and types in the library:
T_LED_MODULE
- Generic type for classes in this library. It is assumed to implement the
public methods of the
LedModule
class of the AceSegment library.
- Generic type for classes in this library. It is assumed to implement the
public methods of the
PatternWriter
- Class that knows how to write segment bit patterns to a
T_LED_MODULE
. - Other Writer classes are built upon this by composition.
- Class that knows how to write segment bit patterns to a
NumberWriter
- A class that writes integers in decimal or hexadecimal format to the
T_LED_MODULE
. - A few additional characters are supported:
kDigitSpace
,kDigitMinus
- A class that writes integers in decimal or hexadecimal format to the
ClockWriter
- A class that writes a clock string "hh:mm" to
T_LED_MODULE
. - Builds on top of
NumberWriter
.
- A class that writes a clock string "hh:mm" to
TemperatureWriter
- A class that writes temperatures with a degrees symbol or optionally with "C" or "F" symbol.
- Builds on top of
NumberWriter
.
CharWriter
- A class that convert an ASCII character represented by a
char
(code 0-127) to a bit pattern used bySegmentDriver
class. - Not all ASCII characters can be rendered on a seven segment display
legibly but the
CharWriter
tries its best.
- A class that convert an ASCII character represented by a
StringWriter
- A class that prints strings of
char
to aCharWriter
, which in turns, prints to theT_LED_MODULE
. - Builds on top of
CharWriter
.
- A class that prints strings of
StringScoller
- Scroll a string left and right.
LevelWriter
- Display specified number of bars from left to right, 2 bars per digit.
<a name="DependencyDiagram"></a>
Dependency Diagram
The conceptual dependency diagram among these classes looks something like this:
StringScroller StringWriter ClockWriter TemperatureWriter
\ / \ /
v v v v
CharWriter NumberWriter LevelWriter
\ | /
v v v
PatternWriter<T_LED_MODULE>
|
v
T_LED_MODULE
|
| (depends on AceSegment if
| T_LED_MODULE is set to LedModule)
v
AceSegment
Library
/ | \
v v v
AceWire AceTMI AceSPI
Library Library Library
<a name="DigitAndSegmentAddressing"></a>
Digit and Segment Addressing
The T_LED_MODULE
type must support the same conventions for addressing
the digits and segments as defined by the AceSegment library:
- digits start at position 0 on the left and increase to the right
- segments are assigned bits 0 to 7 of an unsigned byte (type
uint8_t
) with segmenta
assigned to bit 0, segmentg
assigned to bit 6, and the optional decimal point assigned to bit 7
+------------+ +------------+ +------------+
| aaaa | | aaaa | | aaaa |
| f b | | f b | | f b |
| f b | | f b | | f b |
| gggg | | gggg | * * * | gggg |
| e c | | e c | | e c |
| e c | | e c | | e c |
| dddd dp | | dddd dp | | dddd dp |
+------------+ +------------+ +------------+
Digit 0 Digit 1 Digit {N-1}
Segment: dp g f e d c b a
Bit: 7 6 5 4 3 2 1 0
Some 4-digit LED modules are designed to be used in a clock to display the hour
and minute components of the time as HH:MM
. In these modules, it is common for
the decimal point on Digit 1 to be replaced with the colon
segment between
Digit 1 and Digit 2. In these modules, sometimes the decimal points for the
other digits work normally, but sometimes, the remaining decimal points do not
work at all.
<a name="Usage"></a>
Usage
<a name="HeaderAndNamespace"></a>
Include Header and Namespace
Only a single header file AceSegmentWriter.h
is required to use this library.
To prevent name clashes with other libraries that the calling code may use, all
classes are defined in the ace_segment
namespace. (This is the same namespace
used by the AceSegment library to make it easier to use them together.) To use
the code without prepending the ace_segment::
prefix, use the using
directive:
#include <Arduino.h>
#include <AceSegmentWriter.h>
using namespace ace_segment;
<a name="T_LED_MODULE"></a>
T_LED_MODULE
All Writer classes directly (or indirectly) wrap around an underlying LED module
class with the generic T_LED_MODULE
type. It is assumed to implement the same
public methods of the
LedModule
class from AceSegment. However, the Writer classes in this library are
implemented as C++ templates, so the T_LED_MODULE
type does not need to
inherit from the LedModule
class. The public methods of T_LED_MODULE
should look like this:
class LedModule {
public:
uint8_t size() const;
void setPatternAt(uint8_t pos, uint8_t pattern);
uint8_t getPatternAt(uint8_t pos) const;
void setBrightness(uint8_t brightness);
void getBrightness() const;
void setDecimalPointAt(uint8_t pos, bool state = true);
};
<a name="PatternWriter"></a>
PatternWriter
The PatternWriter
class is the most basic wrapper around an T_LED_MODULE
object, and provides more convenient interfaces to writing to the LED module. It
provides the following features on top of T_LED_MODULE
:
- Validation is performed on the digit
pos
parameter. If thepos
is not valid, then the method returns immediately without performing any action. - Entire strings (both normal strings and
PROGMEM
strings) can be written to the led module. - The
setDecimalPointAt()
convenience function adds a decimal point at the specifiedpos
location. - The
clear()
andclearToEnd()
functions provide ways to clear the LED display. - A stateful cursor that remembers its current
pos
digit in theLedModule
.
All other XxxWriter
classes are built on top of this class. If multiple
writers are used in an application (which happens often because each Writer is
responsible for writing different things), the application should make sure that
only a single instance of PatternWriter
is created. Otherwise, the "current"
position may become confusing.
The public methods and constants of the class look like this:
namespace ace_segment {
const uint8_t kPattern0 = 0b00111111;
const uint8_t kPattern1 = 0b00000110;
const uint8_t kPattern2 = 0b01011011;
const uint8_t kPattern3 = 0b01001111;
const uint8_t kPattern4 = 0b01100110;
const uint8_t kPattern5 = 0b01101101;
const uint8_t kPattern6 = 0b01111101;
const uint8_t kPattern7 = 0b00000111;
const uint8_t kPattern8 = 0b01111111;
const uint8_t kPattern9 = 0b01101111;
const uint8_t kPatternA = 0b01110111;
const uint8_t kPatternB = 0b01111100;
const uint8_t kPatternC = 0b00111001;
const uint8_t kPatternD = 0b01011110;
const uint8_t kPatternE = 0b01111001;
const uint8_t kPatternF = 0b01110001;
const uint8_t kPatternSpace = 0b00000000;
const uint8_t kPatternMinus = 0b01000000;
const uint8_t kPatternDeg = 0b01100011;
const uint8_t kPatternP = 0b01110011;
template <typename T_LED_MODULE>
class PatternWriter {
public:
explicit PatternWriter(T_LED_MODULE& ledModule);
T_LED_MODULE& ledModule() const;
uint8_t size() const;
void home();
uint8_t pos() const;
void pos(uint8_t pos);
void writePattern(uint8_t pattern);
void writePatterns(const uint8_t patterns[], uint8_t len);
void writePatterns_P(const uint8_t patterns[], uint8_t len);
void writeDecimalPoint(bool state = true);
void setDecimalPointAt(uint8_t pos, bool state = true);
void clear();
void clearToEnd();
};
}
The writePattern()
function writes the given pattern
at the current pos
.
The pos
is automatically incremented by one.
The writeDecimalPoint()
function writes a decimal point in the previous
digit, because that's where the decimal point is located on a seven-segment LED
display. If the current position is 0
, this function does nothing. If the
current position is equal to ledModule.size()
which is one position after the
end, this function sets the decimal point on the last digit.
The setDecimalPointAt()
function writes the decimal point at the given pos
.
This provides an escape hatch in cases where writeDecimalPoint()
is not
sufficient.
The decimal point is stored as bit 7 (the most significant bit) of the uint8_t
byte for a given digit. This bit is cleared by the writePattern()
and
writePatterns()
functions. So the writeDecimalPoint()
and
setDecimalPointAt() methods must be called **after** the
writePattern()`
methods.
The pos()
function sets or gets the current position.
The home()
function sets the current position to 0.
The clear()
function clears all the digits of the ledModule
. The
clearToEnd()
clears only the digits from the current position to the end. In
both cases, the home()
function is automatically called to set the position to
0.
Here is how to create an instance of PatternWriter
from an instance of
LedModule
:
PatternWriter<LedModule> patternWriter(ledModule);
<a name="NumberWriter"></a>
NumberWriter
The NumberWriter
can print integers to the T_LED_MODULE
using decimal (0-9)
or hexadecimal (0-9A-F) formats. On platforms that support it (AVR and ESP8266),
the bit mapping table is stored in flash memory to conserve static memory.
The public methods of this class looks something like this:
namespace ace_segment {
const uint8_t kNumDigitPatterns = 18;
extern const uint8_t kDigitPatterns[kNumDigitPatterns];
typedef uint8_t digit_t;
const digit_t kDigitSpace = 0x10;
const digit_t kDigitMinus = 0x11;
template <typename T_LED_MODULE>
class NumberWriter {
public:
explicit NumberWriter(PatternWriter<T_LED_MODULE>& ledModule);
T_LED_MODULE& ledModule();
PatternWriter<T_LED_MODULE>& patternWriter();
uint8_t size() const;
void home();
void writeDigit(digit_t c);
void writeDigits(digit_t s[], uint8_t len);
void writeDec2(uint8_t d, uint8_t padPattern = kPattern0);
void writeDec4(uint16_t dd, uint8_t padPattern = kPattern0);
void writeBcd(uint8_t bcd);
void writeHexByte(uint8_t b);
void writeHexWord(uint16_t w);
void writeUnsignedDecimal(uint16_t num, int8_t boxSize = 0);
void writeSignedDecimal(int16_t num, int8_t boxSize = 0);
void writeFloat(float x, uint8_t places = 2);
void writeDecimalPoint(bool state = true);
void clear();
void clearToEnd(uint8_t pos);
};
}
The digit_t
type semantically represents the character set supported by this
class. It is implemented as an alias for uint8_t
, which unfortunately means
that the C++ compiler will not warn about mixing this type with another
uint8_t
. The range of this character set is from [0,15]
plus 2 additional
symbols, so [0,17]
:
ace_segment::kDigitSpace
ace_segment::kDigitMinus
An instance of NumberWriter
is created like this:
PatternWriter<LedModule> patternWriter(ledModule);
NumberWriter<LedModule> numberWriter(patternWriter);
<a name="ClockWriter"></a>
ClockWriter
There are special, 4 digit, seven segment LED displays which replace the decimal point with the colon symbol ":" between the 2 digits on either side so that it can display a time in the format "hh:mm".
The public methods of this class look like this:
namespace ace_segment {
template <typename T_LED_MODULE>
class ClockWriter {
public:
explicit ClockWriter(
NumberWriter<T_LED_MODULE>& numberWriter,
uint8_t colonDigit = 1);
T_LED_MODULE& ledModule();
PatternWriter<T_LED_MODULE>& patternWriter();
NumberWriter<T_LED_MODULE>& numberWriter();
uint8_t size() const;
void home();
void writeHourMinute24(uint8_t hh, uint8_t mm);
void writeHourMinute12(uint8_t hh, uint8_t mm);
void writeColon(bool state = true);
void clear();
void clearToEnd(
};
}
An instance of ClockWriter
is created like this:
PatternWriter<LedModule> patternWriter(ledModule);
NumberWriter<LedModule> numberWriter(patternWriter);
ClockWriter<LedModule> clockWriter(numberWriter);
You can write the letters A
and P
using the underlying patternWriter()
:
clockWriter.patternWriter().writePattern(ace_segment::kPatternA);
<a name="TemperatureWriter"></a>
TemperatureWriter
This class supports writing out temperatures in degrees Celsius or Fahrenheit. The public methods of this class looks something like this:
namespace ace_segment {
const uint8_t kPatternDegree = 0b01100011;
const uint8_t kPatternC = 0b00111001;
const uint8_t kPatternF = 0b01110001;
template <typename T_LED_MODULE>
class TemperatureWriter {
public:
explicit TemperatureWriter(NumberWriter<T_LED_MODULE>& numberWriter);
T_LED_MODULE& ledModule();
PatternWriter<T_LED_MODULE>& patternWriter();
NumberWriter<T_LED_MODULE>& numberWriter();
uint8_t size() const;
void home();
uint8_t writeTemp(int16_t temp, boxSize = 0);
uint8_t writeTempDeg(int16_t temp, boxSize = 0);
uint8_t writeTempDegC(int16_t temp, boxSize = 0);
uint8_t writeTempDegF(int16_t temp, boxSize = 0);
void clear();
void clearToEnd();
};
}
An instance of TemperatureWriter
is created like this:
PatternWriter<LedModule> patternWriter(ledModule);
NumberWriter<LedModule> numberWriter(patternWriter);
TemperatureWriter<LedModule> temperatureWriter(numberWriter);
<a name="CharWriter"></a>
CharWriter
It is possible to represent many of the ASCII characters in the range [0,127]
on a seven-segment LED display, although some of the characters will necessarily
be crude given the limited number of segments. The CharWriter
contains a
mapping of ASCII characters
to seven-segment bit patterns. On platforms that support it (AVR and
ESP8266), the bit pattern array is stored in flash memory to conserve static
memory.
The public methods of this class look like this:
namespace ace_segment {
const uint8_t kPatternUnknown = 0b00000000;
const uint8_t kNumCharPatterns = 128;
extern const uint8_t kCharPatterns[kNumCharPatterns];
template <typename T_LED_MODULE>
class CharWriter {
public:
explicit CharWriter(
PatternWriter<T_LED_MODULE>& patternWriter,
const uint8_t charPatterns[] = kCharPatterns,
uint8_t numChars = kNumChars
);
T_LED_MODULE& ledModule();
PatternWriter<T_LED_MODULE>& patternWriter();
uint8_t getNumChars() const;
uint8_t getPattern(char c) const;
uint8_t size() const;
void home();
void writeChar(char c);
void clear();
void clearToEnd();
};
}
An instance of CharWriter
is created like this:
PatternWriter<LedModule> patternWriter(ledModule);
CharWriter<LedModule> charWriter(patternWriter);
You can use a custom font by providing an array of segment bit patterns
patterns[]
in the constructor of CharWriter
.
<a name="StringWriter"></a>
StringWriter
A StringWriter
is a class that builds on top of the CharWriter
. It knows how
to write entire strings into the LED display. The public methods look like:
template <typename T_LED_MODULE>
class StringWriter {
public:
explicit StringWriter(CharWriter<T_LED_MODULE>& charWriter);
T_LED_MODULE& ledModule();
PatternWriter<T_LED_MODULE>& patternWriter();
CharWriter<T_LED_MODULE>& charWriter();
uint8_t size() const;
void home();
uint8_t writeString(const char* cs, uint8_t numChar = 255);
uint8_t writeString(const __FlashStringHelper* fs, uint8_t numChar = 255);
void clear();
void clearToEnd();
};
The implementation of writeString()
is straightforward except for the
handling of a decimal point. A seven segment LED digit contains a small LED for
the decimal point. Instead of taking up an entire digit for a single '.'
character, we can collapse the '.' character into the decimal point indicator of
the previous character on the left.
The optional numChar
parameter limits the number of characters in the string
to write. The default value is 255 which is expected to be larger than the
largest LED module that will be used with the AceSegment and AceSegmentWriter
libraries, so the default value will print the entire string.
The actual number of LED digits written is returned by writeString()
. For
example, writing "1.2"
returns 2 because the decimal point was merged into the
previous digit and only 2 digits are written.
The clearToEnd()
method clears the LED display from the current pos
to the
end of the display.
An instance of StringWriter
is created like this:
PatternWriter<LedModule> patternWriter(ledModule);
CharWriter<LedModule> charWriter(patternWriter);
StringWriter<LedModule> stringWriter(charWriter);
The following will write the given string and clear all digits after the end of the string:
stringWriter.writeString(s);
stringWriter.clearToEnd();
<a name="LevelWriter"></a>
LevelWriter
A LevelWriter
writes a specified number of vertical bars (2 vertical
bar per digit) to the LED display, emulating a level meter LED module.
namespace ace_segment {
const uint8_t kPatternLevelLeft = 0b00110000;
const uint8_t kPatternLevelRight = 0b00000110;
template <typename T_LED_MODULE>
class LevelWriter {
public:
explicit LevelWriter(PatternWriter<T_LED_MODULE>& patternWriter);
T_LED_MODULE& ledModule();
PatternWriter<T_LED_MODULE>& patternWriter();
uint8_t getMaxLevel() const;
void writeLevel(uint8_t level);
};
}
An instance of LevelWriter
is created like this:
PatternWriter<LedModule> patternWriter(ledModule);
LevelWriter<LedModule> levelWriter(patternWriter);
There are 2 vertical bars available per per digit. So the maximum level supported by a 4-digit LED module is 8, and an 8-digit LED module supports a maximum level of 16.
<a name="StringScroller"></a>
StringScroller
A StringScroller
is a class that builds on top of the CharWriter
. It can
scroll strings to the left and right. The public methods look like:
namespace ace_segment {
template <typename T_LED_MODULE>
class StringScroller {
public:
explicit StringScroller(CharWriter<T_LED_MODULE>& charWriter);
T_LED_MODULE& ledModule();
PatternWriter<T_LED_MODULE>& patternWriter();
CharWriter<T_LED_MODULE>& charWriter();
uint8_t size() const;
void initScrollLeft(const char* s);
void initScrollLeft(const __FlashStringHelper* s);
bool scrollLeft();
void initScrollRight(const char* s);
void initScrollRight(const __FlashStringHelper* s);
bool scrollRight();
};
}
An instance of StringScroller
is built from its underlying classes like this:
PatternWriter<LedModule> patternWriter(ledModule);
CharWriter<LedModule> charWriter(patternWriter);
StringScroller<LedModule> stringScroller(charWriter);
To scroll a string to the left, initialize the string using initScrollLeft()
,
then call scrollLeft()
to shift one position to the left. The string scrolls
into the first digit on the right. When the scrolling is finished, the display
becomes blank, and the scrollLeft()
method returns true
to indicate
isDone
.
Similarly to scroll to the right, initialize the string using
initScrollRight()
, then call scrollRight()
to shift to the right. The string
scrolls into the first digit on the left. When the scrolling is finished, the
display becomes blank, and the scrollRight()
method returns true
to indicate
isDone
.
<a name="ResourceConsumption"></a>
Resource Consumption
<a name="FlashAndStaticMemory"></a>
Flash And Static Memory
For the most part, the user pays only for the feature that is being used. For
example, if the CharWriter
(which consumes about 300 bytes of flash on AVR) is
not used, it is not loaded into the program.
The full details are given in examples/MemoryBenchmark. Here are 2 samples of the flash and static memory consumptions.
Arduino Nano (ATmega328)
+--------------------------------------------------------------+
| functionality | flash/ ram | delta |
|---------------------------------+--------------+-------------|
| baseline | 470/ 11 | 0/ 0 |
|---------------------------------+--------------+-------------|
| PatternWriter | 574/ 19 | 104/ 8 |
| NumberWriter | 758/ 21 | 288/ 10 |
| NumberWriter::writeFloat() | 2476/ 45 | 2006/ 34 |
| ClockWriter | 834/ 24 | 364/ 13 |
| TemperatureWriter | 954/ 23 | 484/ 12 |
| CharWriter | 768/ 24 | 298/ 13 |
| StringWriter | 864/ 26 | 394/ 15 |
| StringScroller | 980/ 32 | 510/ 21 |
| LevelWriter | 678/ 21 | 208/ 10 |
+--------------------------------------------------------------+
ESP8266
+--------------------------------------------------------------+
| functionality | flash/ ram | delta |
|---------------------------------+--------------+-------------|
| baseline | 260121/27900 | 0/ 0 |
|---------------------------------+--------------+-------------|
| PatternWriter | 260173/27912 | 52/ 12 |
| NumberWriter | 260397/27920 | 276/ 20 |
| NumberWriter::writeFloat() | 261741/27920 | 1620/ 20 |
| ClockWriter | 260477/27928 | 356/ 28 |
| TemperatureWriter | 260541/27920 | 420/ 20 |
| CharWriter | 260365/27928 | 244/ 28 |
| StringWriter | 260501/27928 | 380/ 28 |
| StringScroller | 260533/27936 | 412/ 36 |
| LevelWriter | 260253/27920 | 132/ 20 |
+--------------------------------------------------------------+
<a name="SystemRequirements"></a>
System Requirements
<a name="Hardware"></a>
Hardware
Tier 1: Fully Supported
- Arduino Nano (16 MHz ATmega328P)
- SparkFun Pro Micro (16 MHz ATmega32U4)
- STM32 Blue Pill (STM32F103C8, 72 MHz ARM Cortex-M3)
- NodeMCU 1.0 (ESP-12E module, 80MHz ESP8266)
- WeMos D1 Mini (ESP-12E module, 80 MHz ESP8266)
- ESP32 dev board (ESP-WROOM-32 module, 240 MHz dual core Tensilica LX6)
- Teensy 3.2 (72 MHz ARM Cortex-M4)
Tier 2: Should work
These boards should work but I don't test them as often:
- ATtiny85 (8 MHz ATtiny85)
- Arduino Pro Mini (16 MHz ATmega328P)
- Teensy LC (48 MHz ARM Cortex-M0+)
- Mini Mega 2560 (Arduino Mega 2560 compatible, 16 MHz ATmega2560)
Tier 3: May work, but not supported
- SAMD21 M0 Mini (48 MHz ARM Cortex-M0+)
- Arduino-branded SAMD21 boards use the ArduinoCore-API, so are explicitly blacklisted. See below.
- Other 3rd party SAMD21 boards may work using the SparkFun SAMD core.
- However, as of SparkFun SAMD Core v1.8.6 and Arduino IDE 1.8.19, I can no longer upload binaries to these 3rd party boards due to errors.
- Therefore, third party SAMD21 boards are now in this new Tier 3 category.
- This library may work on these boards, but I can no longer support them.
Tier Blacklisted
The following boards are not supported and are explicitly blacklisted to allow the compiler to print useful error messages instead of hundreds of lines of compiler errors:
- Any platform using the ArduinoCore-API
(https://github.com/arduino/ArduinoCore-api).
- For example, Nano Every, MKRZero, and Raspberry Pi Pico RP2040.
<a name="ToolChain"></a>
Tool Chain
- Arduino IDE 1.8.19
- Arduino CLI 0.31.0
- SpenceKonde ATTinyCore 1.5.2
- Arduino AVR Boards 1.8.5
- Arduino SAMD Boards 1.8.9
- SparkFun AVR Boards 1.1.13
- SparkFun SAMD Boards 1.8.6
- STM32duino 2.4.0
- ESP8266 Arduino 3.0.2
- ESP32 Arduino 2.0.7
- Teensyduino 1.57
This library is not compatible with:
- Any platform using the ArduinoCore-API, for example:
It should work with PlatformIO but I have not tested it.
The library can be compiled under Linux or MacOS (using both g++ and clang++ compilers) using the EpoxyDuino (https://github.com/bxparks/EpoxyDuino) emulation layer.
<a name="OperatingSystem"></a>
Operating System
I use Ubuntu 20.04 for the vast majority of my development. I expect that the library will work fine under MacOS and Windows, but I have not explicitly tested them.
<a name="BugsAndLimitations"></a>
Bugs and Limitations
- The
NumberWriter
class supports limited functionality for floating numbers.- It reuses the algorithm implemented by
Print::print(double x, int digits = 2)
which prints a number to 2 decimal places after the decimal point by default. print()
does not support scientific notation (e.g. "1.3e-7".print()
underflows small numbers to "0.00".print()
overflows for numbers larger than about2^32
(but not exactly). It returns the stringovf
, which is printed as 3 spaces on an LED module.- Different applications will want to handle overflow errors in different
ways (e.g. print "---", "err", or print nothing), so the application
should check for overflows before calling
NumberWriter::printFloat()
.
- It reuses the algorithm implemented by
<a name="AlternativeLibraries"></a>
Alternative Libraries
Tracked using AceSegment Wiki.
<a name="License"></a>
License
<a name="FeedbackAndSupport"></a>
Feedback and Support
If you have any questions, comments, or feature requests for this library, please use the GitHub Discussions for this project. If you have bug reports, please file a ticket in GitHub Issues. Feature requests should go into Discussions first because they often have alternative solutions which are useful to remain visible, instead of disappearing from the default view of the Issue tracker after the ticket is closed.
Please refrain from emailing me directly unless the content is sensitive. The problem with email is that I cannot reference the email conversation when other people ask similar questions later.
<a name="Authors"></a>
Authors
Created by Brian T. Park (brian@xparks.net).