Gen 1 Software

STINGR
Part of the HONEY Architecture series
& the HABEES series
Stingr.png
Chief Designer Kirill Safin
Technology Line Balloons Core Software
Version Generation I
Name STINGR
Acronym Stack Transmission & Inter-Nodal Gesture Repository
General
HONEY Standards Venom Breakout Fang Breakout Board Naming
Core Software
STINGR
Core Avionics
The Count
Core Power
Biscuit
Core Peripherals
Cobra Viper ProtoBee
Core Radio
Macaw
Test & Prototype
QueenBee
Guides
Making a HONEY Board Using STINGR Using QueenBee Making a Prototype
VE

STINGR (Stack Transmission & Inter-Nodal Gesture Repository) is the primary software suite used within the HONEY architecture for communication between boards in a HONEY flight stack.

STINGR allows boards in the flight stack to do a number of critical operations and provides a large number of utilities for FTC's, providing an easy-to-use interface that masks the complexity of CAN Bus transmissions from developers. The STINGR library is primarily comprised of operations called Gestures -- any request or response on the CAN Bus is referred to as a Gesture. Gestures are comprised of a series of frames, which provide the following information for each transmission: Type (Request/Response), Source Identifier, Destination Identifier, Data, State Flags, and Checksum.

Gesture Specification

The following is STINGR Gesture Specification II, which replaces the theoretical, but never implemented, STINGR Gesture Specification I.The STINGR Gesture Specification II was designed by Kirill Safin, Kai Marshland, Theo Diamandis, Ella Hofmann-Coyle, and Davy Ragland.

As mentioned above, a Gesture consists of a series of CAN Packets -- these packets specify the source and destination of a gesture, some auxiliary data, and the primary data payload. STINGR manages CAN Packets, which are hidden from the end-user, and managed entirely by STINGR.

More explicitly, a Gesture looks is comprised of an initialization CAN Packet, followed by up to 256 additional CAN Packets, each comprised of a 1 byte header and 7 byte data payload, for a total possible data length of 255 * 7 = 1,792 + 4 bytes (255 packets, plus 4 bytes of data in the initialization packet). The initialization CAN Packet consists of the standard header, 3 bytes of additional information, and 4 bytes of data payload. Subsequent CAN Packets consist of the 1 byte header and up to 7 bytes of data. The general structure of this format is as such:

Initialization Packet (8 bytes) Data Packets (up to 256)

The following is the general structure of a generic CAN Packet -- specifically, the 1 byte header and 7 byte data payload sections.

Source (0 - 16) (4 bit)

IsInit (1 bit)

Parity (1 bit)

Message ID (2 bit)

Data (7 bytes)

The following is the initialization CAN Packet -- the first packet sent to begin a gesture transmission. It consists of a standard header followed by a two-byte auxiliary information frame, and a 1 byte gesture-type specification frame.

Header (1 byte)

Destination Identifier (4 bits)

Flags (4 bits)

Message Length (in # Packets) (8 bits)

Gesture Type (8 bits)

Data (4 bytes)

Header

The Header is a 1 byte frame that precedes the 7 byte data frame of each CAN Packet. This header provides critical data used by STINGR to re-assemble a fragmented conglomeration of CAN Packets back into one gesture. The Header is defined as mentioned above:

Source (0 - 16) (4 bit)

IsInit (1 bit)

Parity (1 bit)

Message ID (2 bit)

Data (7 bytes)

The Source field is a 4-bit field identifying the origin board of a message. Each board in the flight stack is given a unique identifier, 0-15, which serves to identify it to other boards during transmissions. The Avionics reserves the '0' identifier, and the '15' identifier is reserved for broadcast messages (further down on this page). This leaves 14 possible identifiers, allowing for a flight stack featuring 15 boards total. The identifiers for each board are established during boot-up of the flight stack by the avionics, and distributed to the boards. This "source identifier", while unique to a given flight stack configuration from boot-up, does not permeate between flights or flight stack configurations. That is to say, if a flight stack consists of an Avionics Board, BMS, and Radio board, their unique identifiers might respectively be assigned as 0, 1, and 2 on boot-up, but, on power cycle, could reset to 0, 2, 1. The source identifiers only exist in perpetuity while a flight stack remains powered.

The IsInit field is a 1-bit field identifying whether this message is an initialization message. If HIGH, STINGR will inspect the following 2 bytes for initialization information. If LOW, STINGR will consider the following two bytes to be part of the data payload.

The Parity field is an even parity bit used by STINGR to verify proper message transmission.

The Message ID field is a 2-bit field that indicates the ID of a given message -- that is, it uniquely identifies the gesture. If a board, say, the BMS, transmitted three gestures one after another, they would be given consecutive Message ID's of X, X+1, X+2, all mod 4, where X is the initial message ID. The first message by a board has a message ID of 0, the second 1, the fourth 0, and so on. The primary purpose of this field is to allow STINGR to request a re-transmit of a specific gesture if it was corrupted during transmission. If a gesture from the BMS with Message ID 2 was improperly received by the Avionics, it can request the BMS re-send the Gesture with Message ID 2. However, STINGR only stores the previous four messages that were transmitted (since the Message ID field only fits four values). Hence, if a board has transmitted four messages since the corrupted one, and then the corrupted one is re-requested, STINGR will respond with a re-transmit fault, and the corrupted transmit message will not be transmitted.

The Data field is a 7 byte frame that contains actual data specifying the gesture. This field can contain any information for generic messages, which are generally encoded with simple characters. However, if this is an initialization message, the first two bytes of the data frame will contain information needed by STINGR to re-assemble the gesture.

Initialization Packet

The initialization packet is the first packet sent out by a board to fully define the gesture it is about to transmit, allowing all other boards to re-construct the gesture once all CAN Packets are fully transmitted. The initialization packet looks as so:

Header (1 byte)

Destination Identifier (4 bits)

Flags (4 bits)

Message Length (in # Packets) (8 bits)

Gesture Type (8 bits)

Data (4 bytes)

The Header is defined in the previous section. For the initialization packet, most fields in the Header remain standard -- source is the 4-bit identifier of the sending board, the parity bit is even parity, the message ID is the message ID of the current gesture. The only thing that explicitly changes in the header for the initialization packet is the IsInit bit, which is HIGH for the initialization packet.

Following the header, the initialization packet provides three bytes of information as part of the data frame. This data is organized as such:

Destination (4 bits)

Flags (4 bits)

Length (8 bits)

Gesture Type (8 bits)

Data (4 bytes)

The reader should recognize that it is the first four frames -- Destination, Flags, Length, and Gesture Type -- that are considered the initialization data, and that the subsequent 4 bytes of data are the beginning of the gesture data.

The Destination field is a 4-bit field that uniquely identifies the destination board. This is akin to the source identifier, in that you would specify the same identifier. For example, if the BMS transmitted a gesture, and it's identifier was 2, it would specify a source identifier of 2. Likewise, if the avionics were to send a message to the BMS, it would specify a destination identifier of 2. It should be noted that the identifier of "15" is reserved as the Broadcast Identifier. A destination of 15 specifies that the entire flight-stack is the recipient of a gesture, rather than any specific board.

The Flags field is a 4-bit field that consists of four unique flags that carry some auxiliary data pertinent to the message; they are as such:

High Priority Type No Override Request ACK

The High Priority Flag, if HIGH, indicates that the receiving board should respond to the gesture immediately or at next possible opportunity, as it is a high priority gesture. The Type Flag, if HIGH, indicates that the gesture is a REQUEST, while a LOW bit indicates that the message is a RESPONSE. The No Override Flag, if HIGH, indicates that a receiving board cannot override the received gesture. This flag is carefully managed by STINGR, and typically reserved for Avionics messages. The Request ACK Flag, if HIGH, indicates that a receiving board should respond to the transmitting board with an ACK to indicate that it has successfully received and acknowledged a gesture.

The Length field is an 8-bit field that defines the number of subsequent CAN Packets, all of which define the current transmitting gesture. This field is used by STINGR to carefully monitor all incoming CAN traffic and reassemble gestures.

The Gesture Type field is an 8-bit field that defines the type of gesture being transmitted. This field allows STINGR to optimize performance by performing up to 256 standardized gesture in one CAN Packet instead of using multiple packets. The following table shows the current list of Gesture Types.

Custom 00000000
Beacon 00000001
Silence 00000010
Unsilence 00000011
Request Re-Transmit 00000100
ACK 00000101
Disable 00000110
Enable 00000111
Get Altitude 00001000
Get Pressure Altitude 00001001
Get GPS Altitude 00001010
Get Pressure 00001011
Get Latitude 00001100
Get Longitude 00001101
Get Internal Temp 00001110
Get External Temp 00001111
Get Stability Index 00010000
Get Flight State 00010001
Get Ascent Rate 00010010
Get Voltage 00010011
Get Current 00010100
Get Capacity 00010101

The blanket "0" type is for non-standardized gestures, which constitute a large part of board-to-board gestures. The rest of the Gesture Types specify standardized data requests or responses.

Source & Destination Identifiers

The Source & Destination Identifiers merit some specific discussion. Boards each have an 8-bit unique Identifier that fully defines that board, and cannot be shared between boards. This allows for a possible 256 HONEY-compliant boards to be used within the STINGR suite. This 8-bit identifier is known as the Absolute Board Identifier (ABI).

When a flight stack is constructed and assembled, it ends up being comprised of a series of boards each with one of these unique, enumerated identifiers. It should be noted that a flight stack cannot exceed 15 boards total (3U). Upon boot-up, the Avionics receives a variety of messages from STINGR identifying all boards in the flight stack, and re-labels the identifiers to the Flight Stack Identifiers (FSI) format, whereby all 8-bit identifiers are re-categorized and re-assigned into 4-bit stack-relative addresses.

As of August 10th, 2017, HONEY boards now also have an associated Board Serial Number (BSN). This number starts at 0 for the first of a given board to be made, and increases by one for each additional version of the same board made. The BSN was introduced to allow multiple versions of the same board to exist in the same flight stack -- IE, having two Cobra's in a stack would not permit a unique identifier for each, as their ABI is the same. By adding a BSN, the ABI and BSN are enough to uniquely identify each board in the stack.

Boards designed & fabricated prior to August 10, 2017, do not have a BSN. This includes The Count, Biscuit, and Macaw. For The Count and Biscuit, this is OK -- as there cannot be more than one BMS or Avionics in a flight stack. Macaw has no BSN, and only one Macaw can be flown in a flight stack.

More details about the re-assignment process can be found in the operations section of STINGR, below on this page.

The following are the current ABI's, as of August 10, 2017).

The Count (Gen 4 Avionics) 00000000
Biscuit (Gen 2 BMS) 00000001
Macaw (Gen 1 Radio) 00000010
Cobra (Gen 1 Expander) 00000011
Viper (Gen 1 Breakout) 00000100
QueenBee (Gen 1 TestBench) 00000101
ProtoBee (Gen 1 Payload Board) 00000110

Operation

The following operations are defined by STINGR Gesture Specification II -- for legacy operations defined by STINGR Gesture Specification I, visit its page. STINGR has a specific control flow that must be strictly followed to ensure proper operation. Luckily, most of this is handled within the STINGR internal code. It is described here in full detail, however, for posterity, debugging purposes, and for context in the following section, which enumerates specific methods and their purposes/parameters.

Initialization

Each board using STINGR must initialize the suite in order to properly utilize it. This initialization routine allows proper communication between boards in the stack, as well as gives vital information to each board about the actual structure of the stack, which isn't formally known unless hardcoded (a poor choice).

When a board initializes STINGR, it must provide its ABI (Absolute Board Identifier). Once STINGR obtains the unique identifier of a board, it will send a broadcast gesture on the CAN Bus -- this signal has a destination identifier of 15 -- that is, it is sent to all boards in the flight stack. This is the first gesture sent out by a board, and its definition is as follows:

Header (Source = 15, IsInit = 1, Parity, Message ID = 0)

Destination (15 -- Broadcast)

Flags - (0000)

Length - (00000000)

Gesture Type - (00000001)

Data -- Absolute Board Identifier (1 byte)

Data -- Board Serial Number (1 byte)

0 Padded (3 bytes)

This particular gesture definition is reserved, and is known as the beacon gesture. It is defined by Source & Destination Identifiers of 15 (broadcast), 0 Flags, 0 Length, a Gesture Type of 1, and a data frame consisting only a 1 byte ABI and a 1 byte Serial Number, zero padded.

The beacon gesture is transmitted to the entirety of the stack, and uniquely identifies a given board as being present in the flight stack. In the initialization phase, each board transmits the beacon gesture every 2 seconds. The Avionics waits 5 seconds to receive all beacon gestures, then re-assigns the received ABI's into FSI's. The FSI's are then provided to STINGR, which provides the FSI's to all other boards in the stack. Once the FSI's have been re-assigned and re-distributed, the initialization phase is over.

Once the FSI's have been distributed, all boards in the flight stack are now "live" and are able to send and receive messages via STINGR. Until the FSI's are distributed, a board is not live, and STINGR will not allow any messages to be transmitted or received by the given board.

The initialization routine is limited to 5 seconds -- the time that the avionics waits to receive all beacon gestures.

Standard Mode

Once STINGR passes initialization, it enters Standard Mode. In Standard Mode, a board is able to send and receive gestures via the CAN Bus through STINGR. A board may send a message as frequently or infrequently as desired in Standard Mode. The other defining characteristic of Standard Mode is that, in Standard Mode, STINGR will transmit the beacon gesture every 60 seconds. This is known as the heartbeat gesture, and allows boards in the stack to continue to acknowledge the presence of a board, as well as register a boards presence if they hadn't already registered it.

Silent Mode

Silent Mode can be triggered by the Silence Gesture, a gesture reserved for the avionics board. Silent Mode can be triggered for a specific board in the flight stack, or for the entirety of the flight stack.

To put a board into Silent Mode, the avionics transmits a reserved gesture that has a gesture type of 2. The Avionics can request a specific board to enter silent mode by specifying a destination identifier, or it can request all boards to enter silent mode by using the broadcast identifier.

Silence Gesture:

Header

Destination

Flags

Length - (00000000)

Gesture Type - (00000010)

Data -- Empty

There is, additionally, a gesture to reverse this, and put a board back into Standard Mode -- this is the Unsilence Gesture, which is identical to the Silence Gesture, except the Gesture Type is 3, as shown below. Unsilence Gesture:

Header

Destination

Flags

Length - (00000000)

Gesture Type - (00000011)

Data -- Empty

Disabled Mode

Disabled Mode forces a board to disable all of its standard operations, except STINGR. That is, the board pauses all of its standard operations and only leaves STINGR operating, and listening -- allowing it to be re-enabled at a later time.

Disabled Mode can be triggered by the Disable Gesture, a gesture reserved for the avionics board. Disable Mode can be triggered for a specific board in the flight stack, or for the entirety of the flight stack.

To put a board into Disabled Mode, the avionics transmits a reserved gesture that has a gesture type of 6. The Avionics can request a specific board to enter disabled mode by specifying a destination identifier, or it can request all boards to enter disabled mode by using the broadcast identifier.

Disable Gesture:

Header

Destination

Flags

Length - (00000000)

Gesture Type - (00000110)

Data -- Empty

There is, additionally, a gesture to reverse this, and put a board back into Standard Mode -- this is the Enable Gesture, which is identical to the Disable Gesture, except the Gesture Type is 7, as shown below. Enable Gesture:

Header

Destination

Flags

Length - (00000000)

Gesture Type - (00000111)

Data -- Empty

Core Functions

The STINGR library features a large array of core functions that allow boards to send, receive, and interpret gestures. There also exist standardized gestures for often-used gestures, and a wide array of utilities. The following sections show some of these functions.

Initialization Functions

stingr myStingr = getSTINGR(byte identifier);
The getSTINGR method returns an instance of STINGR, paired with the given identifier, which should be the identifier of the calling board.

boolean isInit = myStingr.initSTINGR();
The initSTINGR method conducts the initialization routine by sending out a beacon gesture, and returns the success of the operation. You should not utilize STINGR if the result of this operation is false -- it should return false only in the case of hardware failure.

myStringr.attachConsole(Serial);
The attachConsole method allows one to attach STINGR output to a Serial stream, permitting STINGR to output status messages. This particular function outputs high-level output.

myStingr.attachDebugConsole(Serial);
The attachDebugConsole method allows one to attach STINGR low-level debug output to the Serial stream, providing a large array of information for debugging possible communication problems.

Utility Functions

boolean mode = myStingr.isStandard();
The isStandard() method returns a boolean value asserting whether a board is currently in standard mode. If it is, the boolean mode is true. If it is in silence mode, the returned value is false.

byte[] stack = myStingr.getFlightStack();
This method returns a byte array of identifiers indicating what boards are present in the flight stack, including the identifier of the calling board. This byte array fully defines the flight stack.

char[] source = myStingr.getSource(struct gesture gest)
Returns a string indicating the source board of the specified gesture -- i.e., a gesture with a source identifier of 00000000 would return "The Count".

char[] source = myStingr.getBoard(byte identifier)
Returns a string indicating the board of the specified identifier -- like getSource, but required explicitly passing the identifier byte.

Gesture Functions

Gestures are defined by a struct known as the Gesture struct, which looks as so:
struct gesture {

byte type;
byte flags;
byte destination;
char[] data;

};
The struct omits the source identifier and checksum, which are inserted automatically by STINGR. It should be noted that the data field of the struct is only the payload -- STINGR inserts the start and end designators itself.

bool myStingr.gesture(struct gesture gest);
The gesture(struct gesture gest) is the primary means of sending data using STINGR. The method takes a valid gesture struct, formats it appropriately, parses it, and sends it through the flight stack over CAN. The method returns a boolean success flag -- true in the case of successful transmission, and false in the case of either failed transmission or invalid struct.

bool myStingr.gesture(byte type, byte flags, byte dest, char[] data);
This method is equivalent to the primary gesture method, but accepts the individual parameters as opposed to a filled-out struct.

Handlers

The STINGR handlers are interrupt-driven handlers that are called when a gesture is received that is either targeted at your board, or is a broadcast gesture. It should be noted that heartbeat gestures (the gestures send every 60 seconds by a board identifying its presence, do not trigger these interrupt handlers).

myStingr.attachBroadcastHandler();
This method attaches the broadcast handler, which will call broadcastHandler(struct gesture gest) -- a callback that you must implement in your code, whenever a broadcast gesture is identified.

myStingr.attachRequestHandler();
This method attaches a request handler, which will call gestRequestHandler(struct gesture gest) -- a callback that you must implement in your code, whenever a request gesture targeting your board is identified.

myStingr.attachResponseHandler();
This method attaches a response handler, which will call gestResponseHandler(struct gesture gest) -- a callback that you must implement in your code, whenever a response gesture targeting your board is identified.

myStingr.attachGenericHandler();
This method attaches a generic handler, which will call gestGeneralHandler(struct gesture gest) -- a callback that you must implement in your code, whenever any gesture is identified targeting your board, whether it is a request, response, or broadcast gesture.

State Functions

State Functions are a set of functions deemed very standardized and useful to all boards that describe the state of the payload, as reported by the avionics and BMS. These functions allow boards to very easily request simple data from the avionics, without setting up and transmitting a gesture -- the entire gesture is created, send, and interpreted by STINGR, which simply returns the desired information.

int alt = myStingr.getAltitude();
Returns integer altitude, in meters, as indicated by the Core Avionics.

int alt = myStingr.getPressureAltitude();
Returns integer altitude, only based on barometric pressure, in meters, as indicated by the Core Avionics.

int alt = myStingr.getGPSAltitude();
Returns integer GPS altitude, in meters, as indicated by the Core Avionics.

double alt = myStingr.getBarometricPressure();
Returns double pressure, in Pa, as indicated by the Core Avionics.

double lat = myStingr.getLatitude();
Returns double GPS latitude as indicated by the Core Avionics.

double long = myStingr.getLongitude();
Returns double GPS longitude as indicated by the Core Avionics.

double tmp = myStingr.getInternalTemp();
Returns double internal temperature, in degrees celsius, as indicated by the Core Avionics.

double tmp = myStingr.getExternalTemp();
Returns double external temperature, in degrees celsius, as indicated by the Core Avionics.

int stabIndex = myStingr.getStabilityIndex();
Returns integer stability index, from 0-100, as determined by the Core Avionics.

byte state = myStingr.getFlightState();
Returns flight state (0 - Ground, 1 - Ascent, 2 - Descent by Pop, 3 - Descent by Cutdown, 4 - Land), as indicated by the Core Avionics.

int stabIndex = myStingr.getAscentRate();
Returns ascent rate, in meters per second, as determined by the Core Avionics.

float volt = myStingr.getVoltage();
Returns battery pack voltage, in volts, as determined by the Core Avionics.

float current = myStingr.getCurrent();
Returns flight stack current draw, in mA, as determined by the Core BMS.

float capacity = myStingr.getCapacity();
Returns battery pack capacity (0-1000), as determined by the Core BMS.

Avionics Functions

These are STINGR functions reserved to the avionics, and will not be processed if called by any board that isn't the avionics (this is verified by comparing the source identifier to the internal list of identifiers).

myStringr.setSilent(byte identifier);
Sets the specified board to silent mode.

myStringr.setStandard(byte identifier);
Sets the specified board to standard mode.

myStringr.setAllSilent();
Sets all boards to silent mode.

myStringr.setAllStandard();
Sets all boards to standard mode.

myStringr.disable(byte identifier);
Sends a specialty gesture to the specified board to cease all operations, except STINGR response handling.

myStringr.enable(byte identifier);
Sends a speciality gesture to the specified board to resume all operations.

myStringr.disableAll();
Sends a speciality gesture to all boards to cease all operations, except STINGR response handling.

myStringr.enableAll();
Sends a speciality gesture to all boards to resume all operations.