i have in mind to learn about the basics of a self-balancing robot, i probably don't have accurate enough hardware but i think it should be sufficient to work through first principles and then that wil point me to what sort of specs i should be looking at for a proper self-balancing robot/vehicle.
i have an Arduino Uno, an (MMA7361) accelerometer and a (DFRobot) motor shield running 2 x 9V DC motors, max. current 0.65A
i will also add an ultrasonic ranger - i've not attempted connecting "so many gizmos" to the Uno in one go so i'm not sure whether i will start to experience processing power limitations.
anyway, i intend to add an SD card module to log the sensor data (mainly the accelerometer) as the "robot" goes about on it's merry way, up to now it's just been tethered while i see what the sensor data looks like via the Serial Monitor.
firstly, is my assumption correct, that it's better to store the data in a variable (program space ?) rather than to continually write to the SD card as it would slow down the processing speed ?
i have assumed this method and proceeded to write some code for it like so;
const int led=13;
const int axisX=A1;
const int axisY=A2;
float avgX , avgY ;
const float setcount = 50;
int count=0;
byte storeData[638][2]; // highest possible number of pairs that can be stored
// freeRAM = 515 at 638 pairs, but how to calculate the limit ?
#define DEBUG 1
void setup() {
Serial.begin(9600);
pinMode(led,OUTPUT);
Serial.println(freeRam());
}
void loop()
{
// read the input on analog pin 1 on a moving average:
avgX = ( (avgX * ( (setcount-1) / setcount) ) + (analogRead(axisX) * ( 1/setcount) ) );
// read the input on analog pin 2 on a moving average:
avgY = ( (avgY * ( (setcount-1) / setcount) ) + (analogRead(axisY) * ( 1/setcount) ) );
#ifdef DEBUG
Serial.print(avgX);
Serial.print(",");
Serial.println(avgY);
#endif
int roundX = avgX; // typecast to int or byte even ! (<255)
int roundY = avgY; // to save prog.space on data storage
// valid range of analogRead-ings => min=280 to max=350
// extended within 8-bit resolution : 190 to 440
byte dataX = constrain (roundX, 190, 440);
byte dataY = constrain (roundY, 190, 440);
// store data to the array
byte buffer[2] = {dataX,dataY};
for (int i=0; i<2; i++)
{
storeData[count][i] = buffer[i];
}
// code for the "robot" moves will go here;
// << if falling backward, move forward >>
// << if falling forward, move backward >>
// << if balanced, stay still >>
if (count < 638)
{
count += 1 ;
}
else
{
writeDataSTOP() ; // store accumulated data and halt program
}
delay(10); // delay in between reads for stability
}
// temporary placeholder for eventual function to stop the robot and save the data to SD card
void writeDataSTOP()
{
Serial.println("limit reached, saving readings to SD card");
while(1);
}
// copied this from a tip on checking RAM usage
int freeRam ()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
secondly, the storing of the data seems rather laborious with typecasting from float to byte (which i assume is better to be able to store more readings ?) and am wondering if there's a more efficient way to do it ?
EDIT:
just realised i still need to further subtract the constrained values to be 0-255
byte dataX = (constrain (roundX, 190, 440) - 190);
byte dataY = (constrain (roundY, 190, 440) - 190);