Im working on a device for a dance project that uses body-mounted IMUs to feed information to a processing sketch over bluetooth serial.
-There are three 3.3v Pro Minis (https://www.sparkfun.com/products/11114), each communicating with two IMUs over IC2.
-These feed data over Serial into a 3.3v Mega (https://www.sparkfun.com/products/10744). Each one goes into its own serial port on the Mega (Serial1, Serial2, Serial3).
-The Mega gets data from each Mini every time through loop(), and then when Processing asks for it, sends data in nine-byte chunks to a Processing sketch through Serial via a bluetooth module (https://www.sparkfun.com/products/12580).
-The Processing sketch reads the incoming data and moves stuff around on screen corresponding to input coming from the sensors.
-The Mega also monitors battery voltage levels over I2C using a Lipo Fuel Gauge (https://www.sparkfun.com/products/10617)
Everything above works perfectly. No problems anywhere. Problems begin below:
I want to have an SD card logging the sensor data on-board in case the Bluetooth connection craps-out during a recording (and as a backup), and I want to use an RTC to give the data context in time. I want to prompt the data-logging to start and stop from Processing.
I have tested the RTC (https://www.sparkfun.com/products/10160) and the SD card (http://www.adafruit.com/products/254). Both use SPI. Both work great with the Mega by themselves, and I did a test of logging the RTC data to the SD card each time through loop(), and that worked great too.
The problem is when I bring it all together. Just introducing the RTC works fine. I can send the time and date to Processing along with the IMU data. BUT: when I try to use the SD card, the info coming in to Processing FREAKS OUT! That is, I can move my IMUs around and see smooth changes on screen, and then when I enable logging to SD, everything starts moving randomly.
My code is below. Is there anything I’m missing? I have tried both the included SD.h library as well as the SdFat.h library. Below is the code for logging the actual data, but even if I change it to just write a constant variable to the SD card it still messes with the info going to processing.
Help?
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>
#include <RTC_DS3234.h>
#include "MAX17043.h"
MAX17043 fuelGauge(20,10);
File myFile;
// Avoid spurious warnings //This is from RTC Example code. Might not need it?
#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))
#undef PSTR
#define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); &__c[0];}))
// Create an RTC instance, using the chip select pin it's connected to
RTC_DS3234 RTC(53);
char armR[8] = {0,0,0,0,0,0,0,0};
char armL[8] = {0,0,0,0,0,0,0,0};
char legs[8] = {0,0,0,0,0,0,0,0};
int led = 13;
int battStatus = 1;
boolean logging = false;
void setup() {
pinMode(led, OUTPUT); //LED setting
pinMode(A7, OUTPUT); //Mini 1 RST
pinMode(A6, OUTPUT); //Mini 2 RST
pinMode(A5, OUTPUT); //Mini 3 RST
pinMode(10, INPUT); //Fuel Gauge
pinMode(A8, OUTPUT); //SD Card
digitalWrite(A7, HIGH);
digitalWrite(A6, HIGH);
digitalWrite(A5, HIGH);
SPI.begin();
RTC.begin();
SPI.setDataMode(SPI_MODE0);
// initialize all serial ports:
Serial.begin(38400);
Serial1.begin(38400);
Serial2.begin(38400);
Serial3.begin(38400);
fuelGauge.begin();
fuelGauge.setAlertThreshold(3);
if (!SD.begin(A8)) {
//Serial.println("initialization failed!"); //Indicate SD init error
return;
}
}
void loop() {
const int len = 32;
static char buf[len];
DateTime now = RTC.now();
SPI.setDataMode(SPI_MODE0);
battStatus = digitalRead(10);
//Serial.print(battStatus);
if (battStatus==0) {
//Battery Alert here
}
Serial1.write(1); //Get data from ProMinis
if (Serial1.available()) {
int starter = (int)Serial1.read();
if (starter==201) {
Serial1.readBytes(armR, 8);
}
}
Serial2.write(1);
if (Serial2.available()) {
int starter = (int)Serial2.read();
if (starter==202) {
Serial2.readBytes(armL, 8);
}
}
Serial3.write(1);
if (Serial3.available()) {
int starter = (int)Serial3.read();
if (starter==203) {
Serial3.readBytes(legs, 8);
}
}
if (logging) { //logging the data to the SD card
myFile = SD.open("dance1.txt", FILE_WRITE);
now.toString(buf,len);
//Serial.println(buf[0]);
if (myFile) {
//myFile.println(now.toString(buf,len));
for (int i=12; i < 20; i++){
myFile.print(buf[i]);
}
myFile.print("-");
myFile.print("A:");
for (int i = 0; i < 8; i++) {
myFile.print((byte)armR[i]);
myFile.print(",");
}
myFile.print("B:");
for (int i = 0; i < 8; i++) {
myFile.print((byte)armL[i]);
myFile.print(",");
}
myFile.print("C:");
for (int i = 0; i < 8; i++) {
myFile.print((byte)legs[i]);
myFile.print(",");
}
myFile.println("#");
myFile.close();
} else {
//Serial.println("error opening file"); //Was there an SD error?
logging = false;
Serial.write(223);
for (int i = 0; i < 8; i++) {
Serial.write(1);
}
}
}
//Inout from Processing
if (Serial.available()) {
int recd = Serial.read();
if (recd==49) { //received a "1" ---> send position data!
Serial.write(201);
for (int i = 0; i < 8; i++) {
Serial.write((byte)armR[i]);
}
Serial.write(202);
for (int i = 0; i < 8; i++) {
Serial.write((byte)armL[i]);
}
Serial.write(203);
for (int i = 0; i < 8; i++) {
Serial.write((byte)legs[i]);
}
} else if(recd==91) { //received a "[" ---> reset first mini
digitalWrite(A7, LOW);
delay(1000);
digitalWrite(A7, HIGH);
} else if(recd==113) { //received a "q" ---> check battery level and report
float batt = fuelGauge.getBatteryPercentage();
//gaugeOutput();
/*
Serial.print((int) floor(batt));
Serial.print(".");
int frac = (batt - int(batt)) * 100;
Serial.println(frac);
//*/
///*
Serial.write(220);
Serial.write((byte) floor(batt));
Serial.write(46);
int frac = (batt - int(batt)) * 100;
Serial.write((byte) frac);
for (int i = 0; i < 5; i++) {
Serial.write(1);
}
//*/
if (batt<=3.00) {
//Do emergency stuff here
}
} else if(recd==32) { //received a SPACEBAR ---> start/stop logging!
logging = !logging;
if (logging) {
Serial.write(221);
for (int i = 0; i < 8; i++) {
Serial.write(1);
}
} else if (!logging) {
Serial.write(222);
for (int i = 0; i < 8; i++) {
Serial.write(1);
}
}
}
}
//delay(1000);
}
void gaugeOutput() {
Serial.print("Version: ");
Serial.println(fuelGauge.getVersion());
Serial.print("Alert Threshold: ");
Serial.println(fuelGauge.getAlertThreshold());
Serial.print("Alert Threshold Register Version: ");
Serial.println(fuelGauge.getAlertThresholdRegister());
Serial.print("Battery Voltage: ");
Serial.println(fuelGauge.getBatteryVoltage());
Serial.print("Battery Percentage: ");
Serial.println(fuelGauge.getBatteryPercentage());
Serial.print("Is Alerting? ");
Serial.println(fuelGauge.isAlerting());
Serial.print("Is Sleeping? ");
Serial.println(fuelGauge.isSleeping());
Serial.print("Is Sleeping Register Version? ");
Serial.println(fuelGauge.isSleepingRegister());
Serial.println("");
}