Skip to content

Controller board

maehw edited this page Nov 1, 2022 · 32 revisions

The self-o-mat kits provided by x-tech UG include a controller board.

The Arduino-based board

  • connects the arcade button and the LED ring (with 16 LEDs as default; other number of LEDs can be used and configured in the web-app) to a Raspberry Pi single board computer and
  • can be used to power the screen and the Raspberry Pi and connects the on/off switch.

The communication interface between the Arduino and the Raspberry Pi is a serial interface, see details below.

Hardware

The original board is based on an ATmega328 MCU based Arduino Nano.

Wiring

Here it the pinout used by the firmware:

Pin Alias Function Input/Output Connection
2 PIN_BUTTON Trigger Button Input Connect trigger button with a pull-up resistor
3 PIN_SWITCH ON/OFF Switch Input Connect ON/OFF switch with a pull-up or pull-down resistor. Pin is active low: connection to GND will switch on, connection to 5V will switch off. If not needed, connect to GND for always enabled.
4 PIN_LED NeoPixel data pin Output To NeoPixel data input
7 PIN_FLASH_CAM_TRIGGER Camera flash trigger Input Flash trigger from camera (probably only for older revisions)
8 PIN_ON POWER Output Can be used to control PC/screen power. Connect PC/screen via relay or leave open if unused
9 PIN_LED_OFF NeoPixel dummy data pin? not configured Set as NeoPixel pin in OffState
11 PIN_FLASH_ON Flash enable signal Output GPIO pin to switch on Flash on custom PCB (probably only for older revisions), initialized to LOW
19 PIN_LEVEL_SHIFTER_OE Output
20 PIN_STATUS Output

In custom setups it is required to connect at least PIN_BUTTON and PIN_SWITCH and also recommended (due to user experience) to also connect PIN_LED. All other pins are optional in such a setup.

The pin definitions can be found in globals.h.

Please take care when changing these as there may be dependencies on PCBs/hard-wiring!

Please also note that the Fritzing schematic shows resistors with a value of 220 Ohms (red-red-brown color coding). Please choose a higher value for those pull-up/down resistors (around 10kOhms should be ok).

Serial interface

The serial interface uses a baudrate of 38400.

Serial protocol

The communication between the Arduino and the Raspberry Pi is encoded with Consistent Overhead Byte Stuffing (COBS). The null/zero byte (0x00) cannot be used as delimiter because of issues with the boot loader. This is why the space character (0x20) has been chosen. For packet decoding and encoding the PacketSerial Arduino library is used. The implementation uses Arduino's default Serial stream. All Arduino boards have at least one serial port. On Uno, Nano, Mini, and Mega, pins 0 and 1 are used for communication with the computer (in this case the Raspberry Pi SBC).

Serial commands

Basically each sent packet starts with a command byte (see the list below) and optionally some data bytes. The receiver reads the first byte and then decides how many data bytes are needed as an argument (for many commands no data is needed). Then it checks if enough data is present and reads the data.

For example the "accept agreement" command simply consists of the command 'a' followed by a space character ' '.

List of commands, command arguments and expected responses:

  • identification: send 'i' (encodes as "\2i "), expect 'b' as response
  • heartbeat: send '.'
  • enable/disable watchdog: send '!' and one argument byte (enable/disable)
  • signal picture taken: send 'k'
  • trigger flash: '#'
  • signal update mode: 'f', expect 'F' as immediate response and finally 'a'
  • signal print in progress: 'p'; may receive 'c' when button has been pressed to cancel print
  • signal agreement is shown: 'a' (no command arguments), expect 'A' as immediate response and finally 'a'
  • enable/disable stress test: send 'S'/'s' (not supported by firmware, is it?)
  • signal remote trigger: 't', do not expect any response
  • query settings from board: send '?', expect settings as response (prefixed with '$') or "E1"/"E2"/"E3" on error
  • write settings to board: send '$' followed by settings sequence, expect 'k' as response
  • move LED ring light offset to the right: send '>', expect current settings as response (prefixed with '$')
  • move LED ring light offset to the left: send '<', expect current settings as response (prefixed with '$')

Settings structure

Settings relevant for using the controller board (i.e. hardware related settings, see list below) are stored in and read from the Arduino's EEPROM using Arduino's EEPROM Library.

The "write settings" command consists of a '$' byte and is followed by sizeof(settings) bytes of data. The settings data type is a struct which holds all settings of the self-o-mat controller board. The last two bytes of the struct are used as CRC16 checksum ("false CCITT") - and calculated using Frank Bösing's FastCRC library. Finally a space character ' ' needs to be sent in order to finalize the packet.

#pragma pack(push, 1)
            struct settings {
                uint8_t ledTypeIndex;
                uint8_t ledCount;
                uint8_t ledOffset;
                uint16_t countDownMillis;
                uint32_t flashDurationMicros;
                uint8_t flashMode;
                uint8_t maxLedBrightness;
                uint16_t crcChecksum;
            } __attribute__((packed)) settings;
#pragma pack(pop)

Two instances of type settings are declared and initialized inside of Arduino/SelfomatController/globals.cpp:

struct settings settings = {0};

struct settings default_settings = {
  .ledTypeIndex = 0, // RGB
  .ledCount = 16, // Default for our box
  .ledOffset = 0, // We can't know this
  .countDownMillis = 3000, // Seems reasonable
  .flashDurationMicros = 10000,
  .flashMode = 0,
  .maxLedBrightness = 255,
  .crcChecksum = 0
};

Firmware

The firmware is located in ./Arduino.

The firmware basically implements a finite state machine. It reacts on different inputs (button press, ON/OFF switch level, the camera's flash trigger, inputs via the serial interface) and controls different outputs (mainly the LED ring light, an optional PCB flash, replies via the serial interface).

State machine

(Note: The state diagram is WIP; it is documented as PlantUML diagram and will be part of the repository.)

Building the firmware

In order to build the Arduino sketch, an installation of the Arduino IDE is required.

Known issues

Building the Arduino sketch yields the following error message:

globals.h:4:10: fatal error: Adafruit_NeoPixel.h: No such file or directory
 #include <Adafruit_NeoPixel.h>
          ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
exit status 1

Adafruit_NeoPixel.h: No such file or directory

You forgot to add the Adafruit NeoPixel library. Select Tools > Manage Libraries... from the menu. Search for "Adafruit NeoPixel", select the correct library and click the Install button.

Building the Arduino sketch yields the following error message:

BusyState.cpp:4:10: fatal error: PinChangeInterrupt.h: No such file or directory
 #include "PinChangeInterrupt.h"
          ^~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
exit status 1
PinChangeInterrupt.h: No such file or directory

You forgot to add the PinChangeInterrupt library by NicoHood. Select Tools > Manage Libraries... from the menu. Search for "PinChangeInterrupt", select the correct library and click the Install button. (See also: https://github.com/NicoHood/PinChangeInterrupt)