The Ardusat Sensor SDK is a software package designed to make interacting with the sensors found in the Ardusat Space Kit as easy as possible, while also providing a powerful unified interface to use the same code to interact with ground-based sensors as well as satellite systems. It builds on top of popular open source libraries provided by Adafruit and others.
The first step to getting going is to install the Arduino Integrated Development Environment (IDE). Downloads for all major OS versions can be found at http://arduino.cc/en/Main/Software.
Once you have the IDE, installing the SDK is easy - it works like any other third party Arduino library. Just download the SDK or clone this repository to your hard drive, then open the Arduino IDE, go to 'Sketch -> Import Library -> Add Library' and navigate to your download (zip file or the directory cloned with Git). You now should be able to use the SDK in your sketches.
If you're interested in using the SDK for logging data to an SD card, you'll need to do this same thing with our other Ardusat Logging SDK Library
If you want to use the latest SDK and you have existing Arduino sketches (from before June 20, 2016) that you would like to keep using, take a look at the Transition Documentation for how to update your sketches to work with the latest SDK.
The first step to using the SDK is to include it into your sketch. This can be done with a simple include statement:
#include <ArdusatSDK.h>
After the SDK is included, the basic I/O functions and sensor drivers should be available.
Every Sensor in the SDK is accessible with a Sensor class that helps wrap up internal functionality. Each Sensor Class supports reading data from one or more physical sensors.
Sensor Class | Sensors | Required Constructor Arguments |
---|---|---|
Acceleration | LSM303 (9DOF breakout) | None |
Gyro | L3GD20 (9DOF breakout) | None |
Luminosity | TCS34725 | None |
Magnetic | LSM303 (9DOF breakout) | None |
Orientation | Derived from Acceleration and Magnetic | Acceleration & accel, Magnetic & mag (Existing Accel and Mag objects) |
Pressure | BMP180 | None |
RGBLight | TCS34725 (Default) | None |
RGBLightTCS | TCS34725 | None |
RGBLightISL | ISL29125 | None |
Temperature | TMP102 (Default) | None |
TemperatureTMP | TMP102 | None |
TemperatureMLX | MLX90614 (IR) | None |
UVLight | ML8511 (Default) | None |
UVLightML | ML8511 | None |
UVLightSI | SI1132 | None |
UVLight uv; // --> uv is now a sensor object that reads from the ML8511 Sensor
UVLightML uv; // --> uv is now a sensor object that reads from the ML8511 Sensor
UVLightSI uv; // --> uv is now a sensor object that reads from the SI1132 Sensor
Note that the Orientation object is not technically a sensor, but rather a value derived from readings from the Acceleration and Magnetic Sensors. Therefore, you must provide existing Acceleration and Magnetic objects when constructing the Orientation object. It is used in the following way:
Acceleration accel;
Magnetic mag;
Orientation orient(accel, mag); // --> orient uses existing Acceleration and Magnetic objects
orient.read(); // --> orient calls accel's and mag's read and then derives a value
Every Sensor in the SDK has the following functions that can be used to initialize, read, and print data:
Available Functions | Required Parameters | Description
--- | --- | --- | ---
begin()
| None | Initializes sensors with any optional advanced configurations
read()
| None | Takes a reading from the sensor
readToCSV()
| const char * sensorName
| Takes a reading and prints it in a CSV format
readToJSON()
| const char * sensorName
| Takes a reading and prints it in a JSON format
toCSV()
| const char * sensorName
| Prints the last reading taken in a CSV format
toJSON()
| const char * sensorName
| Prints the last reading taken in a JSON format
- CSV format:
timestamp,sensorName,values,...,checksum
- JSON format:
~{"sensorName": "NAME", "unit": "UNIT", "value": 123.4, "cs": 123}|
NOTE: The toCSV
functions will not guarantee that you are outputting data in a format that is acceptable for
importing CSV logs into the Ardusat Experiment Platform. These functions
are for live STREAMING data into the Experiment Platform.
If you are calling the toCSV
functions on exactly one type of Sensor Class per sketch, this is fine for
STREAMING data and LOGGING data to be imported.
If you are calling the toCSV
functions on more than one type of Sensor Class per sketch, this is fine for
only STREAMING data, LOGGING data to be important will not be formatted correctly. If you want to LOG more
than one type of Sensor Class, see the CSV Logging Example with valuesToCSV
.
There is a full example in the CSV Examples of how to use valuesToCSV
, but this function is available to make
it easier to format data properly:
const char * valuesToCSV(const char *sensorName, unsigned long timestamp, int numValues, float values...);
const char * valueToCSV(const char *sensorName, float value, unsigned long timestamp); // if timestamp == 0, it will just calculate a timestamp using millis()
There is a similar function for formatting arbitrary values in the JSON format called valuesToJSON
:
const char * valuesToJSON(const char *sensorName, unsigned char unit, int numValues, float values...);
const char * valueToJSON(const char *sensorName, unsigned char unit, float value);
This is an overview of the sensor specific fields and advanced configuration parameters
Sensor Class | Data Fields | Optional Constructor Parameters (for advanced configuration) |
---|---|---|
Acceleration | float x , float y , float z |
lsm303_accel_gain_e gGain |
Gyro | float x , float y , float z |
uint8_t range |
Luminosity | float lux |
tcs34725IntegrationTime_t intTime , tcs34725Gain_t gain |
Magnetic | float x , float y , float z |
lsm303_mag_scale_e gaussScale |
Orientation | float roll , float pitch , float heading |
None |
Pressure | float pressure |
bmp085_mode_t mode |
RGBLight | float red , float green , float blue |
None |
RGBLightTCS | float red , float green , float blue |
tcs34725IntegrationTime_t it , tcs34725Gain_t gain |
RGBLightISL | float red , float green , float blue |
uint8_t islIntensity |
Temperature | float t |
None |
TemperatureTMP | float t |
None |
TemperatureMLX | float t |
None |
UVLight | float uvindex |
None |
UVLightML | float uvindex |
int pin |
UVLightSI | float uvindex |
None |
These are the specific values avaliable for each of the advanced configurations
Constructor Configuration Parameter Type | Acceptable Values | Sensor Class |
---|---|---|
lsm303_accel_gain_e gGain |
LSM303_ACCEL_GAIN2G , LSM303_ACCEL_GAIN4G , LSM303_ACCEL_GAIN6G , LSM303_ACCEL_GAIN8G (Default), LSM303_ACCEL_GAIN16G |
Acceleration |
uint8_t range |
0x00 (SENSITIVITY_250DPS), 0x10 (SENSITIVITY_500DPS), 0x20 (SENSITIVITY_2000DPS) (Default) |
Gyro |
tcs34725IntegrationTime_t intTime |
TCS34725_INTEGRATIONTIME_2_4MS , TCS34725_INTEGRATIONTIME_24MS (Default), TCS34725_INTEGRATIONTIME_50MS , TCS34725_INTEGRATIONTIME_101MS , TCS34725_INTEGRATIONTIME_154MS , TCS34725_INTEGRATIONTIME_700MS |
Luminosity |
tcs34725Gain_t gain |
TCS34725_GAIN_1X , TCS34725_GAIN_4X , TCS34725_GAIN_16X (Default), TCS34725_GAIN_60X |
Luminosity |
lsm303_mag_scale_e gaussScale |
LSM303_MAG_SCALE1_3GAUSS , LSM303_MAG_SCALE2GAUSS , LSM303_MAG_SCALE2_5GAUSS , LSM303_MAG_SCALE4GAUSS (Default), LSM303_MAG_SCALE4_7GAUSS , LSM303_MAG_SCALE5_6GAUSS , LSM303_MAG_SCALE8GAUSS , LSM303_MAG_SCALE12GAUSS |
Magnetic |
bmp085_mode_t mode |
BMP085_MODE_ULTRALOWPOWER , BMP085_MODE_STANDARD , BMP085_MODE_HIGHRES , BMP085_MODE_ULTRAHIGHRES (Default) |
Pressure |
tcs34725IntegrationTime_t it |
TCS34725_INTEGRATIONTIME_2_4MS , TCS34725_INTEGRATIONTIME_24MS , TCS34725_INTEGRATIONTIME_50MS , TCS34725_INTEGRATIONTIME_101MS , TCS34725_INTEGRATIONTIME_154MS (Default), TCS34725_INTEGRATIONTIME_700MS |
RGBLightTCS |
tcs34725Gain_t gain |
TCS34725_GAIN_1X (Default), TCS34725_GAIN_4X , TCS34725_GAIN_16X , TCS34725_GAIN_60X |
RGBLightTCS |
uint8_t islIntensity |
CFG1_375LUX , CFG1_10KLUX (Default) |
RGBLightISL |
int pin |
DRIVER_ML8511_UV_PIN (A0) (Default), or any other Arduino Pin |
UVLightML |
Sensor Class | Unit Type | Unit String |
---|---|---|
Acceleration | DATA_UNIT_METER_PER_SECONDSQUARED | "m/s^2" |
Gyro | DATA_UNIT_RADIAN_PER_SECOND | "rad/s" |
Luminosity | DATA_UNIT_LUX | "lux" |
Magnetic | DATA_UNIT_MICROTESLA | "uT" |
Orientation | DATA_UNIT_DEGREES | "deg" |
Pressure | DATA_UNIT_HECTOPASCAL | "hPa" |
RGBLight | DATA_UNIT_LUX | "lux" |
Temperature | DATA_UNIT_DEGREES_CELSIUS | "C" |
UVLight | DATA_UNIT_MILLIWATT_PER_CMSQUARED | "mW/cm^2" |
None | DATA_UNIT_NONE | "" |
The Barometric Pressure sensor has two additional convenience functions to calculate altitude (which requires knowing the current sea level barometric pressure, a value that's easily available from weather observation data), or current sea level barometric pressure (which requires knowing the current altitude). For these convenience functions, altitude should be provided in meters, and pressure values should be provided in hPa.
float Pressure::altitudeFromSeaLevelPressure(float seaLevelPressure);
float Pressure::seaLevelPressureFromAltitude(float altitude);
To translate meters to feet, multiply the meter value by 3.28084
. To translate feet to meters,
multiply the feet value by 0.3084
.
Allows the user to manually decide in an Arduino sketch if the SDK should dynamically check if the SpaceBoard is being used or not. Defaults to false
boolean MANUAL_CONFIG;
Used when dynamically checking if the SpaceBoard is being used or not. If the SpaceBoard is being used, different addresses might be used for each sensor.
boolean ARDUSAT_SPACEBOARD;
Example Usage
...
void setup(void) {
MANUAL_CONFIG = true;
ARDUSAT_SPACEBOARD = false;
...
}
...
You will likely never need to use these, unless you are interested in building your own hardware setup with new sensors, or are curious to see what will happen.
#include <ArdusatSDK.h>
Luminosity lum;
void setup(void) {
Serial.begin(9600);
lum.begin();
}
void loop(void) {
Serial.println(lum.readToJSON("Luminosity")); // >> ~{"sensorName": "Luminosity", "unit": "lux", "value": 123.5, "cs": 43}|
Serial.println(lum.readToJSON("lum2")); // >> ~{"sensorName": "lum2", "unit": "lux", "value": 121.9, "cs": 30}|
Serial.println(lum.readToCSV("Luminosity")); // >> 243,Luminosity,128.2,49
Serial.println(lum.readToCSV("lum4")); // >> 311,lum4,124.6,29
Serial.println(lum.lux); // >> 124.6
Serial.println(lum.lux); // >> 124.6
lum.read();
Serial.println(lum.lux); // >> 127.5
}
#include <ArdusatSDK.h>
RGBLightISL rgb(CFG1_375LUX);
void setup(void) {
Serial.begin(9600);
rgb.begin();
}
void loop(void) {
Serial.println(rgb.readToJSON("RGBLight")); // >> ~{"sensorName": "RGBLight", "unit": "lux", "red": 89.2, "green": 177.9, "blue": 183.2, "cs": 83}|
}
As mentioned in the NOTE in "Sensor Overview and Reference", the Experiment Platform reads reads two different types of CSV
formats. The toCSV
family of functions work fine on multiple types of Sensor Classes at a time when you want to STREAM data,
but if you want to LOG data to be imported, you need to have properly formatted data.
####CSV STREAMING example:
#include <ArdusatSDK.h>
Magnetic mag;
Luminosity lum;
void setup(void) {
Serial.begin(9600);
mag.begin();
lum.begin();
}
void loop(void) {
Serial.println(mag.readToCSV("Magnetic"));
Serial.println(lum.readToCSV("Luminosity"));
}
Output: (not proper CSV format) Will fail to be imported to Experiment Platform However, this is fine if you're streaming CSV data to the Experiment PLatform.
89,Magnetic,0.78,9.11,0.02,123
123,Luminosity,128.2,234
145,Magnetic,0.74,9.01,0.03,234
168,Luminosity,126.7,423
...
####CSV LOGGING example:
#include <ArdusatSDK.h>
Acceleration accel;
Temperature temp;
void setup(void) {
Serial.begin(9600);
accel.begin();
temp.begin();
// CSV Headers to print once at the top of the data
Serial.print("timestamp (millis), name, ");
Serial.print("temperature (C), x acceleration (m/s^2), y acceleration (m/s^2), z acceleration (m/s^2), ");
Serial.println("checksum");
}
void loop(void) {
accel.read();
temp.read();
//Log Name, Time Stamp, Number of Values, Temp, Accel X, Accel Y, Accel Z
Serial.println(valuesToCSV("reading", accel.header.timestamp, 4, temp.t, accel.x, accel.y, accel.z));
}
Output: Proper CSV format. This will be successfully imported into the Experiment Platform However, this will not work if you're streaming CSV data to the Experiment PLatform.
timestamp (millis), name, temperature (C), x acceleration (m/s^2), y acceleration (m/s^2), z acceleration (m/s^2), checksum
89,reading,27.3,9.11,0.02,0.78,123
123,reading,27.2,9.10,0.08,0.73,120
145,reading,27.3,9.02,0.11,0.88,121
198,reading,27.2,9.08,0.03,0.80,128
211,reading,27.3,9.13,0.08,0.75,119
229,reading,27.5,9.19,0.01,0.78,127
...
The Ardusat SDK can output sensor data in both JSON and CSV format to allow interfacing with
external systems such as the Ardusat Experiment Platform. To use these functions,
call the toJSON
or toCSV
family of functions:
Both JSON and CSV output formats optionally include checksum values to verify that the data remains
uncorrupted through transmission. This is an integer value that is calculated when the data packet
is first written in a known way. The client receiving the data packet can then re-calculate the
checksum using the same algorithm, then verify that the calculated value matches the transmitted
checksum. The algorithm used to calculate the checksum sums the characters in the sensorName
field
as integers, then rounds the value (s) and adds this to the sum of the name characters.
Example checksum calculation:
int calculate_checksum(const char *sensorName, float value) {
int checksum = 0;
int i, len;
len = strlen(sensorName);
for (i = 0; i < len; ++i) {
checksum += sensorName[i];
}
checksum += lroundf(value);
return checksum;
}
The regular Arduino Serial
library works fine with the SDK. However, sometimes when connecting to
XBee or other wireless modules, it is useful to be able to wire serial connections that leave the
main Arduino USB Serial free for programming. To do this, the SDK leverages the SoftwareSerial
library in a new class called ArdusatSerial
. This class has the same interface as both Serial
and SoftwareSerial
, but can be configured to output on hardware serial (Serial
), software
serial, or both.
If a software serial mode is selected, the ArdusatSerial
constructor must be supplied with
arguments for softwareReceivePin
and softwareTransmitPin
:
ArdusatSerial(serialMode mode, unsigned char softwareReceivePin, unsigned char softwareTransmitPin);
Usage:
ArdusatSerial serialConnection(SERIAL_MODE_HARDWARE_AND_SOFTWARE, 10, 11);
Temperature temp;
void setup(void) {
serialConnection.begin(9600);
temp.begin();
serialConnection.println("This message will go out on hardware serial and software serial!");
}
void loop(void) {
temp.read();
serialConnection.println("The recorded temperature is ");
serialConnection.println(temp.t);
}
Name | Description |
---|---|
SERIAL_MODE_HARDWARE | Output serial data on built-in USB hardware serial |
SERIAL_MODE_SOFTWARE | Output serial data on software serial (must specify transmit and receive pins in the constructor, see arguments in example above) |
SERIAL_MODE_HARDWARE_AND_SOFTWARE | Output to both hardware and software serial interfaces |
SoftwareSerial does not appear to work reliably above 57600 baud.
If you're having trouble running the examples, chances are something is messed up with the external library locations in your Arduino IDE. Double check that the ArdusatSDK library is included into your Arduino libraries (Sketch -> Import Libraries -> Contributed). If the sketches are compiling and uploading but not behaving as expected, make sure you double check your wiring, it's always easy to accidentally plug something in wrong!
If you get really stuck, feel free to reach out at [email protected], or the "Issues" section of this repository.
This SDK leverages some really excellent code already written by Adafruit, SparkFun, and Pololu. They have all provided really great sensor drivers and Arduino Libraries, so please support them in thanks for their efforts!