World Conquest Chronicles

World Conquest Chronicles

Robot 7-segment Display, v1.1.0

The library for controlling a 7-segment display.

Implementing controlling a multiplexed display.

Change Log

  • structures:
    • the Character structure:
      • support transformation to the same character with a decimal point;
      • increase usability;
    • the DisplaySelector structure controls a multiplexed display by switching its sub-displays, and keeps a set of pins using for this;
  • perform refactoring.

Features

  • possibilities:
    • controlling a single display;
    • controlling a multiplexed display;
  • structures:
    • the Character structure represents a character and keeps a set of specific segments that should be active for displaying this character:
      • supports transformation to the same character with a decimal point;
    • the Display structure represents a single display and keeps mapping between segments and pins to which they are connected;
    • the DisplaySelector structure controls a multiplexed display by switching its sub-displays, and keeps a set of pins using for this.

Examples

A multiplexed display stopwatch:

#include <Character.h>
#include <Display.h>
#include <PinForSegment.h>
#include <DisplaySelector.h>
#include <stdint.h>

using namespace irenica_ideas::robot_7_segment_display;

constexpr auto DISPLAY_QUANTITY = 4;
constexpr auto DECIMAL_POINT_INDEX = 1;
constexpr auto COUNTER_UPDATE_DELAY_IN_MS = 100;
constexpr auto DISPLAY_SELECTION_DELAY_IN_MS = 2;

const Character digits[] = {
  Character(0x7e), // digit 0
  Character(0x30), // digit 1
  Character(0x6d), // digit 2
  Character(0x79), // digit 3
  Character(0x33), // digit 4
  Character(0x5b), // digit 5
  Character(0x5f), // digit 6
  Character(0x70), // digit 7
  Character(0x7f), // digit 8
  Character(0x7b)  // digit 9
};

// TODO: specify your own pin for every segment.
const auto display = Display(
  PinForSegment<'a'>{2},
  PinForSegment<'b'>{3},
  PinForSegment<'c'>{5},
  PinForSegment<'d'>{7},
  PinForSegment<'e'>{11},
  PinForSegment<'f'>{13},
  PinForSegment<'g'>{17},
  PinForSegment<'p'>{19}
);
// TODO: specify your own pin for every sub-display.
const auto selector = makeDisplaySelector(23, 29, 31, 37);

auto previousTime = 0ul;
uint8_t counterDigits[DISPLAY_QUANTITY] = {};

void setup() {
  display.initialize();
  selector.initialize();
}

void loop() {
  // update the counter; about creating timers through the `millis()` function
  // see: https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay
  const auto currentTime = millis();
  const auto elapsedTime = currentTime - previousTime;
  if (elapsedTime > COUNTER_UPDATE_DELAY_IN_MS) {
    auto willBeOverflowed = true;
    for (
      auto index = 0;
      index < DISPLAY_QUANTITY && willBeOverflowed;
      ++index
    ) {
      willBeOverflowed = counterDigits[index] == 9;
      counterDigits[index] = willBeOverflowed ? 0 : counterDigits[index] + 1;
    }

    previousTime = currentTime;
  }

  // perform single update of the whole multiplexed display
  for (auto index = 0; index < DISPLAY_QUANTITY; ++index) {
    selector.selectDisplay(index);

    // show the first character on the first sub-display, the second character
    // on the second sub-display, etc.
    auto digit = digits[counterDigits[index]];
    if (index == DECIMAL_POINT_INDEX) {
      digit = digit.withDecimalPoint();
    }
    digit.show(display);

    delay(DISPLAY_SELECTION_DELAY_IN_MS);
  }
}

Videos