Biologists can learn a lot about animals by understanding more about their movements. To do this, they can use a small accelerometer and data logger to collect animal movement data. Commercially-available accelerometers can be quite expensive, and DIY accelerometers are often too bulky or have too short of a battery life to undertake meaningful research on small animals. The goal of this project is to develop a very small, very light-weight, low-power, low-cost accelerometer for small animal research. It has the following features:
- Weight (without battery or case): < 3grams
- Weight (with 300 mAh battery and case): 10 - 15 g
- Dimensions (without battery or case): 20mm x 20mm x 8mm
- Battery life: 2 weeks - 1 month
- Cost: < 60 USD
It is made using easily purchased commercially-available parts from TinyCircuits, and can be customized using the Arduino ecosystem. We have tested it both in the laboratory and in the field on small turtles, and have collected a data set over the course of more than two weeks.
ConstructionThe accelerometer requires four parts. All parts can be purchased from TinyCircuits or any of their retailers, except for the standard micro-SD card. The parts are:
1) TinyZero processor board with accelerometer. There are two versions of this board available. It is important that you purchase the version of this board that includes the accelerometer, as this is what we will use to collect the data. This is an Arduino-compatible microcontroller with a SAMD21 processor.
2) TinyCircuits MircoSD shield. This allows us to conveniently save data to a MircoSD card.
3) Lithium polymer battery. TinyCircuits sells batteries with the appropriate connector on their website. You can purchase any size that fits your purpose, but there is a trade-off between battery capacity and weight. We found a good balance to be the 290mAh battery from TinyCircuits. It provided more than 2 weeks of battery life.
4) Micro SD card. With a large, high quality SD card, such as a 64 Gb card, you are unlikely to be limited by storage space in your data collection.
Once you have the parts, assembly is straight-forward. The MicroSD shield fits on top of the TinyZero processor board through the white connectors on each board. The battery plugs into the corresponding battery connector on the TinyZero processor board. The SD Card fits into the SD slot on the MicroSD shield.
Putting the accelerometer on turtles meant it needed to be made waterproof. To do this, we first wrapped the boards and batteries in a thin layer of plastic. A small zip-close bag or plastic wrap works for this. We then covered the entire assembly in A+B epoxy and used this to fix it directly to the turtle shell. The hardened epoxy also helps against sharp rocks and other objects the turtle may encounter.
For this step, you will need a computer set up with the Arduino IDE. Follow Step 1 and Step 2 in the TinyZero Setup Tutorial. You will need to install the Arduino program on your computer, install the TinyZero board profiles in the Arduino IDE, and select the TinyZero board for use.
Once you have the Arduino IDE installed and configured with the Tiny Zero boards, we can download the code.
Install the libraries1) From the "Code" section at the bottom of this page, download the "sdlogger.ino" and open it in the Arduino editor.
2) The four other ZIP files in the "Code" section are Arduino libraries. Click on "Download ZIP" for each file to download them.
3) In the Arduino editor, go to "Sketch -> Include Library -> Include.ZIP library" and choose the ZIP files you just downloaded. Repeat this for each library.
Upload the software1) Using a micro USB cable, plug the TinyZero board into your computer. Use the small power switch on the side of the TinyZero to turn it on.
2) In the Arduino editor, under."Tools-> Board" select "TinyZero".
3) Under "Tools->Port" select the port to which your TinyZero is connected. If it does not show up, ensure that your TinyZero is powered on, and you are using a microUSB cable that transmits data.
4) Click the "right arrow" symbol in the top menu to upload the code.
5) If the code does not upload in step 4, ensure you have the proper board and port selected under "Tools". If this does not work, you may need to place the board into "Bootloader" mode. To do this, turn the power switch to off. Find the small button on the bottom of the TinyZero board. Press and hold the button as you move the power switch to the on-position. The board should now be available to the Arduino editor.
Operating the data loggerOnce the code is uploaded, you are ready to collect data! Whenever the power switch is in the "on" position, the accelerometer will be collecting data or sleeping, based on the parameters.
To retrieve the data, turn the power switch off, remove the SD card and insert it in a computer with an SD card reader. There should be a file called "logfile.csv" (or the name you set in "filename"). This can be read with any program that reads CSV files.
Note that if the data logger has operated for a time shorter than the SAVE_INTERVAL parameter, the data will not be saved on the card.
Code explanationLibraries#include <Wire.h>
#include <BMA250.h>
#include <RTCZero.h> // Can only go into sleep on second intervals
// Does not have power down flash or SYSTICK modifications
#include <Adafruit_SleepyDog.h> //Has power down flash correct, but not SYSTICK
//Allows you to do millisecond sleep, but limited to WDT limit ~18s
#include <SdFat.h>
#include <SPI.h>
#include <ArduinoLowPower.h> //Use RTC library for timing, therefore can only sleep in second intervals
//Has power down flash and SYSTICK correct
The first part of the code accesses the needed libraries:
Wire.h and BMA250.h -> used to access the accelerometerRTCZero.h -> Used to keep time with the Real Time Clock and to do the initial sleep periodAdafruit_SleepyDog.h -> Used to sleep between each accelerometer sampleSDFat.h and SPI.h -> Used to access the SD cardArduinoLowPower.h -> Used to sleep between recording intervals
You may notice that the RTCZero, Adafruit_SleepyDog and ArduinoLowPower libraries all have sleep functions, but they differ in how they are implemented that changes their use. To make this code easy to use and accessible, we elected to stick to common libraries rather than make our own library, and use each library where appropriate.
RTCZero library: uses the Real Time Clock, and therefore can only do sleep periods on intervals of one second. In addition, it has not fixed a well known bug (Google "SAMD21 systick" for more information) that can cause the processor to not wake up after sleeping. Therefore we do not use it to sleep and only use it to keep time with the Real Time Clock.
Adafruit_SleepDog library: This library uses the watchdog timer, which allows you to sleep for much shorter durations, so we use it to sleep between each data point. It can not sleep for longer than 18 seconds since it is based on the Watchdog timer. It suffers from the same bug that has not been fixed at the source, so we include a fixed version.
ArduinoLowPower: This library does not have the well known bugs of the other library, but like the RTCZero library it uses the Real Time Clock to sleep, and can only do sleep periods in intervals of one second. Therefore we only use it to sleep between recording intervals.
Parameters#define INITIAL_SLEEP_TIME 240 //hours; How long to sleep on power, allows to delay start of recording to save power
#define RECORD_INTERVAL 15 //seconds; How long to collect data for during each recording interval
#define SLEEP_BETWEEN_INTERVAL 900 //seconds; How long to sleep between recording intervals
#define SAVE_INTERVAL 14400 //seconds; How long to delay between SD card saves. Each save uses a lot of power, so we only save occasionally
#define SLEEP_BETWEEN_SAMPLES 60 //milliseconds; Time between samples, determined by data rate of accelerometer
#define TIME_BETWEEN_SAMPLES 64 //milliseconds; Adjustment factor to keep timestamp accurate after sleep
#define DATA_COUNT 4 //Number of data fields you are collecting. For x,y,z accelerations + temperature -> DATA_COUNT=4
To understand the parameters, it is helpful to know how the data logger works. It alternates between three activities: sleep, data collection and saving data. The logger collects data in intervals with a length determined by the parameter RECORD_INTERVAL. It then goes to sleep for a length of time of SLEEP_BETWEEN_INTERVAL. It then wakes up and collects data again. To save power, it only saves data occasionally, after a length of time equal to the parameter SAVE_INTERVAL.
In addition, the first sleep period after the power switch is turned on can be different from all the other sleep periods. This is determined by the INITIAL_SLEEP_TIME parameter.
In the example above, once the power switch is turned on, the data logger sleeps for 240 hours (or 10 days) as specified by INITIAL_SLEEP_TIME. It then wakes up and collects data for 15 seconds, as determined by RECORD_INTERVAL. Then it sleeps again for 900 seconds, as determined by SLEEP_BETWEEN_INTERVAL. It repeats this cycle of record-sleep-record-sleep as long as the battery is alive. Every 4 hours (14400 seconds) it will save all the data collected to the SD card.
To change the recording and sleep behavior of the data logger, you can adjust the parameters above. Just be aware the more frequency recording, longer recording intervals and more frequent saves will use more battery life.
Setupvoid setup() {
//If SD initialization fails, light LED
if (!sd.begin(CHIP_SELECT, SD_SCK_MHZ(50))) {
SPI.end();
lightLED();
}
//If file creation fails light LED
if (!file.open(fileName, O_WRONLY | O_CREAT | O_APPEND)) {
SPI.end();
lightLED();
}
detectReset(); //Checks reason for reset, for debugging
file.sync();
//Initialize RTC
rtc.begin();
rtc.setEpoch(0);
//Initialize Sensor
Wire.begin();
accelSensor.begin(BMA250_range_2g, BMA250_update_time_64ms);
//Set alarm for initial sleep - allows for to delay recording
rtc.setAlarmEpoch(rtc.getEpoch() + INITIAL_SLEEP_TIME * SECONDS_IN_HOUR);
rtc.enableAlarm(rtc.MATCH_YYMMDDHHMMSS);
LowPower.sleep();
// Record time at wakeup, record initial timestamp time
wakeupTime = rtc.getEpoch();
prevTime = rtc.getEpoch() - EPOCH_OFFSET;
}
The setup section sets up the SD Card, sets up the real time clock, and sets up the accelerometer. Lastly it sets up the initial sleep time. This allows you to delay the beginning of data collection and keep the data logger in a very low power sleep mode. The data logger goes to sleep when it hits the "LowPower.sleep();" line. It wakes up when after the alarm period. Upon wake up it records the time from the real time clock to being tracking the time for time stamps for the data.
Loopvoid loop() {
// Data array
double data[DATA_COUNT];
//Get data
getAccel(data);
//Create timestamp
String timeStampNow = getTimestamp(&prevTime);
//Record timestamp and data
writeData(timeStampNow, data);
// Sleep bewteen samples
Watchdog.sleep(SLEEP_BETWEEN_SAMPLES);
int currentTime = rtc.getEpoch();
//If current recording time interval is over, go to sleep for sleep period
if (currentTime - wakeupTime > RECORD_INTERVAL) {
//If data has not been saved to SD card recently, save the data
if (currentTime - lastSave > SAVE_INTERVAL) {
lastSave = currentTime;
file.sync();
}
rtc.setAlarmEpoch(currentTime + SLEEP_BETWEEN_INTERVAL); //Set alarm SLEEP_BETWEEN_INTERVAL seconds from now
rtc.enableAlarm(rtc.MATCH_YYMMDDHHMMSS);
LowPower.sleep();
wakeupTime = rtc.getEpoch();
}
}
The loop process is as follows:1) Collects one sample from the accelerometer. 2) Record data to the SD card3) Sleep before taking the next sample4) Upon waking up, check the time. If the recording interval is not over, collect data again.5) If this recording interval is over, check if it is time to save data permanently to the SD card ("sync"). This requires a lot of power so we only do it periodically. Then set an alarm to sleep until the next recording interval begins.
Future workWaterproofing - The waterproof enclosure currently works well, but it adds more mass and volume to the assembly than we would prefer. We are always looking for more compact solutions for the waterproof enclosure.
Low power library - As mentioned in the code description above, this project currently uses three libraries to handle sleep due to the various advantages and disadvantages of the various low power libraries out there. We would love to assemble a custom library for handling sleep to make it easier for everyone to upload and manage the code.
Comments