RAM RAM I need more RAM!!

I really like my Arduino uno and have great fun making it do things. But.. the 2K of RAM is driving me nuts! What options are out there that program like the Arduino but have more RAM to play with?

Thanks!

-jim lee

http://ruggedcircuits.com/html/quadram.html

The 2K of RAM is one of the things that makes Arduino fun!

Mind you the Apollo 11 got to the moon with less RAM and you are complaining? :wink:

What kind of application do you make that needs more RAM?

Sounds like you need one of these:
1284 thruhole, Duemilanove style boards!
Prices shipped to US locations:
1-lot $4.50
2-lot $6.75
3-lot $9.25
5-lot $17.00
10-lot $28.25

I ordered 50 of them, sent out about 1/2 so far.

I'll see if I can get one asssembled & a picture posted.

Thanks!
Robert

(Rats - I don't have regulators. Knew I forgot to order something when I last ordered stuff from anyone.)

http://www.pjrc.com/store/teensypp.html
http://www.pjrc.com/store/teensypp_pins.html

outside of audio and video I find 2k to be quite spacious, but I spend time nitpicking details (ie not using a 16 bit integer for a variable that counts to 12)

I usually use arduino with tiny chips which boast 512 BYTES of ram and dont run out, heck even did some graphics with one

so, what are you doing that really requires ram? and is it just crap that could be shoved to other storage medium (such as strings or whatnot) and never be changed? or is are you doing some seriously complex stuff that really requires it to be in volatile memory?

Please give more details.
I find most people that have problems with ram have large static arrays that can be put in PROGMEM.

smeezekitty:
Please give more details.
I find most people that have problems with ram have large static arrays that can be put in PROGMEM.

bingo

Just as a starter here is something that I use to reduce RAM requirements:

void serialPrint_P(const prog_char* s){
char* p = (char*)alloca(strlen_P(s) + 1);
strcpy_P(p, s);
Serial.print(p);
}

void lcdPrint_P(const prog_char* s){
char* p = (char*)alloca(strlen_P(s) + 1);
strcpy_P(p, s);
lcd.print(p);
}

in sketch:

serialPrint_P(PSTR("This text is going to be going to the serial port. If I used the normal Serial.print command it would go there via RAM wasting lots of space in the process. The lcdPrint_P function does the same thing for LCDs. Have a nice day."));

.. for example there is an external ramdisk (currently 4Mbytes) connected via 11 wires only. R/W speed on pic32 is 7MBytes/sec (with bitbanging).
See Home · RetroBSD/retrobsd Wiki · GitHub
You may try with SPI serial FRAM (made by Ramtron) or MRAM (made by Everspin). On arduino connected via SPI you may
get few hundred kBytes/sec. P.
PS: for Apollo AGC ram spec see Apollo Guidance Computer - Wikipedia :slight_smile:

Sorry, been away.

I'm running 18 R/C servos on three different time functions. The functions are loaded via the serial port point by point into RAM. Then I use liner scaling to interpolate between the entered points in time. To coordinate this I have time objects that "go off" at prescribed times to tell the servos its time to recalculate positions and send out the next set of position info.

I'd got it all going for a single servo, tested all the bits. Worked wonderful. But, when expanding up to 18 times the size.. Well, it went bananas. I figured; "I doubt this'll fit in 2k, maybe I should look for more headroom?"

I come from the c++ application world so I have no RAM usage discipline at all.

-jim lee

If you'd like help...

Hahah!

Ok but I'm going to be out of town for a week. Next week I'll post it.

-jim lee

Maybe use external serial RAM IC.

Main program..

#include "antThorax.h"
#include "blinker.h"

#define buttonPin 2

blinker  aBlinker;
antThorax thorax;

char command[20];
byte index;


void setup() { 

  pinMode(buttonPin, INPUT);
  index = 0;
  Serial.begin(9600);            // Set up for commands as default.
  Serial.setTimeout(100);
  aBlinker.init();
  
  // Skip doing this through the serial port.. Lets hardcode it for now..
  thorax.addMapperPoint( 0, 0, 0);
  thorax.addMapperPoint( 0, 5, 0.66);
  thorax.addMapperPoint( 0, 20, 1);
  thorax.addMapperPoint( 0, 25, 1);
  thorax.addMapperPoint( 0, 45, 0.66);
  thorax.addMapperPoint( 0, 55, -0.66);
  thorax.addMapperPoint( 0, 75, -1);
  thorax.addMapperPoint( 0, 95, -0.66);
  thorax.addMapperPoint( 0, 100, 0);

  thorax.addMapperPoint( 1, 15, -1);
  thorax.addMapperPoint( 1, 20, 0.33);
  thorax.addMapperPoint( 1, 25, 0.5);
  thorax.addMapperPoint( 1, 75, 0.5);
  thorax.addMapperPoint( 1, 77.5, -.5);
  thorax.addMapperPoint( 1, 85, -1);

  thorax.addMapperPoint( 2, 15, -1);
  thorax.addMapperPoint( 2, 20, .25);
  thorax.addMapperPoint( 2, 25, 0.5);
  thorax.addMapperPoint( 2, 75, 0.5);
  thorax.addMapperPoint( 2, 77.5, -0.5);
  thorax.addMapperPoint( 2, 85, -1);
}


void commandCheck(void) {

  int  value1;
  float value2, value3;
  byte inByte;

  if (Serial.available() > 0) {
    inByte = Serial.read();
    if (isalpha(inByte)) {
      command[index] = inByte;
      index++;
    } 
    else if (index>0) {
      command[index] = '\0';
      index = 0;
      if (!strcmp("add",command)) {
        value1 = Serial.parseInt();
        value2 = Serial.parseFloat();
        value3 = Serial.parseFloat();
        thorax.addMapperPoint(value1,value2,value3);
        Serial.print("Added point : ");
        Serial.print(value2);
        Serial.print(", ");
        Serial.print(value3);
        Serial.print(" to mapper ");
        Serial.println(value1);
      } 
      else if (!strcmp("view",command)) {
        value1 = Serial.parseInt();
        thorax.mapperPointsToSerial(value1);
      }  
      else if (!strcmp("map",command)) {
        value1 = Serial.parseInt();
        value2 = Serial.parseFloat();
        value3 = thorax.mapPoint(value1,value2);
        Serial.print("Mapping : ");
        Serial.print(value2);
        Serial.print(" to : ");
        Serial.print(value3);
        Serial.print(" with mapper ");
        Serial.println(value1);

      }
      else if (!strcmp("dump",command)) {
        value1 = Serial.parseInt();
        Serial.print("Data for mapper : ");
        Serial.print(value1);
        Serial.println(" as (Time, value)");
        thorax.dumpMapperToSerial(value1);
      } 
      else if (!strcmp("clear",command)) {
        value1 = Serial.parseInt();
        thorax.clearMapper(value1);  
      } 
      else {
        Serial.println(command);
        Serial.println("add m x y adds point to mapper m.");
        Serial.println("view m lists mapper m");
        Serial.println("map m x returns a mapped point from mapper m.");
        Serial.println("clear m empties mapper m.");
        Serial.println("dump m returns the curve for mapper m.");
      }
    }
  }
}


void loop() {

  aBlinker.idle();
  if (!digitalRead(buttonPin)) {
    if (thorax.stepState != walkingFwd
      && thorax.stepState != startingToWalk) {    // If we are not walking..
      Serial.end();                          // kill the serial port.
      thorax.startSerial();                  // Let the thorax have the port..
    }
    thorax.walkFwd();
  } 
  else {
    if (thorax.stepState == walkingFwd) {
      thorax.park();
      thorax.stopSerial();            // Done with servos for now..
      Serial.begin(9600);            // Set up for commands.
      Serial.setTimeout(100);
    } 
    else
      commandCheck();
  }
}

thorax.h

#ifndef antThorax_h
#define antThorax_h

#include "multiMap.h"
#include "miniSSC.h"
#include "timeObj.h"

/*
                                   Front
   0           1
    \        /
     \  () /
       O  O
 2 --- O  O --- 3
       O  O
      /    \
     /       \ 
    4         5 
 
 Group A = 0,3,4
 Group B = 1,2,5
 
 */
#define swivel 0
#define lift   1
#define knee   2

#define swivel0 16
#define lift0   16
#define knee0   16

#define swivel1 5
#define lift1   6
#define knee1   7

#define swivel2 16
#define lift2   16
#define knee2   16

#define swivel3 0
#define lift3   1
#define knee3   2

#define swivel4 16
#define lift4   16
#define knee4   16

#define swivel5 16
#define lift5   16
#define knee5   16

#define swivleFwd  1
#define swivleBack -1
#define swivlePark 0

#define liftUp -1
#define liftDwn .5
#define liftPark -1

#define kneeExtend 1
#define kneeRetract -1
#define kneePark -1

#define NUM_LEGS   6                     // Duh! Its an ANT!
#define NUM_JOINTS 3

#define CYCLE_TIME 40000.0               // Time to complete one step
#define SLICES 50.0                      // How many times to update position per step.
#define STEP_SET_WAIT CYCLE_TIME/2
#define NUM_MAPPERS NUM_JOINTS

enum stepStateType { unknown, parked, startingToWalk, walkingFwd };

class antThorax;

class antLeg {

public:
  antLeg(antThorax* inThorax, byte inLegNum, byte inSwivel, byte inLift, byte inKnee);

  void walkFwd(void);
  void park(void);

private :
  antThorax*    thorax;       // Our thorax..
  byte          legNum;     
  byte          swivelPin;    // Output here..
  byte          liftPin;      // and here..
  byte          kneePin;      // and here..
  int           timeSlice;    // Where are we in our step?
  timeObj*      legTimer;     // How long between updates?
  
  float         swivelVal;    // Calculated values to send out to the servos.
  float         liftVal;
  float         kneeVal;
  stepStateType legState;

};


// **************************************************



class antThorax {

public :
  antThorax(void);

  void startSerial(void);
  void stopSerial(void);
  void park(void);
  void walkFwd(void);

  boolean checkMapperNum(int mapperNum);
  void addMapperPoint(int legMapperNum, double x, double y);
  double mapPoint(int legMapperNum, double x);
  double legsMapPoint(int legNum, int jointNum, double x);
  void clearMapper(int LegMapper);
  void mapperPointsToSerial(int LegMapper);
  void dumpMapperToSerial(int LegMapper);
  double mapTime(double timeSlice);                           // Acess the slice mapper..

  stepStateType stepState;
  miniSSC  theSSC;                                            // Used to make servos go..
  
private: 
  antLeg*  legList[NUM_LEGS];                                 // just the leg list
  mapper*  sliceMapper;                                       // Mapps from slice number to data scaled to %.
  multiMap legMapper[NUM_MAPPERS];                            // The joint position mappers.
  timeObj* waitTimer;    // We need to wait before doing something.
};


#endif

thorax.cpp

#include "antThorax.h"

// Start with leg code..

antLeg::antLeg(antThorax* inThorax, byte inLegNum, byte inSwivel, byte inLift, byte inKnee) {

  thorax = inThorax;
  legNum = inLegNum;
  swivelPin = inSwivel;
  liftPin = inLift;
  kneePin = inKnee;
  legTimer = new timeObj(CYCLE_TIME/SLICES);
  legState = unknown;
}


void antLeg::walkFwd() {

  float mappedTime;

  switch (legState) {
  case walkingFwd :
    if (legTimer->ding()) {
      legTimer->stepTime();                  // reset the timer..

      // send step data.
      thorax->theSSC.setServo(swivelPin,swivelVal);    // Send out the data.
      thorax->theSSC.setServo(liftPin,liftVal);
      thorax->theSSC.setServo(kneePin,kneeVal);

      timeSlice++;                          // calculate next step.
      if (timeSlice>SLICES)                 // Overrun number of slices?
        timeSlice = 0;                      // reset the silly thing.
      mappedTime = thorax->mapTime(timeSlice);
      swivelVal = thorax->legsMapPoint(legNum,swivel,mappedTime);
      liftVal = thorax->legsMapPoint(legNum,lift,mappedTime);
      kneeVal = thorax->legsMapPoint(legNum,knee,mappedTime);
    }
    break;
  default :
    timeSlice = 0;
    mappedTime = thorax->mapTime(timeSlice);
    swivelVal = thorax->legsMapPoint(legNum,swivel,mappedTime);
    liftVal = thorax->legsMapPoint(legNum,lift,mappedTime);
    kneeVal = thorax->legsMapPoint(legNum,knee,mappedTime);
    legState = walkingFwd;
    break;
  } 
}


void antLeg::park(void) {

  if (!(legState == parked)) {
    thorax->theSSC.setServo(swivelPin,swivlePark);
    delay(100);
    thorax->theSSC.setServo(liftPin,liftPark);
    delay(100);
    thorax->theSSC.setServo(kneePin,kneePark);
    legState = parked;
    delay(100);
  }
}



// ***********************************************
// antThorax code below


antThorax::antThorax(void) {

  legList[0] = new antLeg(this,0,swivel0,lift0,knee0);
  legList[1] = new antLeg(this,1,swivel1,lift1,knee1);
  legList[2] = new antLeg(this,2,swivel2,lift2,knee2); 
  legList[3] = new antLeg(this,3,swivel3,lift3,knee3);
  legList[4] = new antLeg(this,4,swivel4,lift4,knee4);
  legList[5] = new antLeg(this,5,swivel5,lift5,knee5);
  sliceMapper = new mapper(0,SLICES,0,100);
  waitTimer = new timeObj(STEP_SET_WAIT);
  stepState = unknown;
}


void antThorax::startSerial(void) {

  theSSC.initSSC(true);           // Grab the serial port for ourselves.
}


void antThorax::stopSerial(void) {

  Serial.end();
  stepState = unknown;
}


void antThorax::park() {

  int i;

  delay(200);
  for (i=0;i<NUM_LEGS;i++) {
    if (legList[i]!=NULL)
      legList[i]->park();
  }
  stepState = parked;
}



void antThorax::walkFwd() {

  byte i;

  switch (stepState) {
  case walkingFwd :
    for (i=0;i<=NUM_LEGS;i++) {
      legList[i]->walkFwd();
    }
    break;
  case startingToWalk :
    legList[0]->walkFwd();
    legList[3]->walkFwd();
    legList[4]->walkFwd();
    if (waitTimer->ding()) {
      legList[1]->walkFwd();
      legList[2]->walkFwd();
      legList[5]->walkFwd();
      stepState = walkingFwd;
    }
    break;
  default :
    waitTimer->start();
    legList[0]->walkFwd();
    legList[3]->walkFwd();
    legList[4]->walkFwd();
    stepState = startingToWalk;
    break;
  }
}


boolean antThorax::checkMapperNum(int mapperNum) {

  return mapperNum>=0 && mapperNum <= NUM_MAPPERS;
}


void antThorax::addMapperPoint(int legMapperNum, double x, double y) {

  if (checkMapperNum(legMapperNum)) {
    legMapper[legMapperNum].addPoint(x,y);
  }
}


double antThorax::mapPoint(int legMapperNum, double x) {

  if (checkMapperNum(legMapperNum)) {
    return legMapper[legMapperNum].Map(x);
  } 
  else
    return 0;
}

// This is where the logic like turning, opposite sides etc. happens. 
// The leg gives us the joint & time, we have the mapper and other 
// information to bundle up into where we want that joint to be set.
// No this bit isn't complete. Only legs 1 & 3 have been built.
double antThorax::legsMapPoint(int legNum, int jointNum, double x) {

  switch(legNum) {
  case 0 :
    switch(jointNum) {
    case swivel :
      return legMapper[swivel].Map(x);
      break;
    case lift :
      return legMapper[lift].Map(x);
      break;
    case knee :
      return legMapper[knee].Map(x);
      break;
    }
    break;
  case 1 :
    switch(jointNum) {
    case swivel :
      return legMapper[swivel].Map(x);
      break;
    case lift :
      return legMapper[lift].Map(x);
      break;
    case knee :
      return legMapper[knee].Map(x);
      break;
    }
    break; 
  case 2 :
    switch(jointNum) {
    case swivel :
      return legMapper[swivel].Map(x);
      break;
    case lift :
      return legMapper[lift].Map(x);
      break;
    case knee :
      return legMapper[knee].Map(x);
      break;
    }
    break; 
  case 3 :
    switch(jointNum) {
    case swivel :
      return legMapper[swivel].Map(x);
      break;
    case lift :
      return legMapper[lift].Map(x);
      break;
    case knee :
      return legMapper[knee].Map(x);
      break;
    }
    break; 
  case 4 :
    switch(jointNum) {
    case swivel :
      return legMapper[swivel].Map(x);
      break;
    case lift :
      return legMapper[lift].Map(x);
      break;
    case knee :
      return legMapper[knee].Map(x);
      break;
    }
    break; 
  case 5 :
    switch(jointNum) {
    case swivel :
      return legMapper[swivel].Map(x);
      break;
    case lift :
      return legMapper[lift].Map(x);
      break;
    case knee :
      return legMapper[knee].Map(x);
      break;
    }
    break; 
  }
}


void antThorax::clearMapper(int legMapperNum) {

  if (checkMapperNum(legMapperNum))
    legMapper[legMapperNum].clearMap();
}



void antThorax::mapperPointsToSerial(int legMapperNum) {

  if (checkMapperNum(legMapperNum))
    legMapper[legMapperNum].outputList();
}



void antThorax::dumpMapperToSerial(int LegMapper) {

  int timeSlice;
  float value;

  timeSlice = 0;
  while (timeSlice<=SLICES) {
    value = legMapper[LegMapper].Map(timeSlice);
    Serial.print(timeSlice);
    Serial.print(", ");
    Serial.println(value);
    timeSlice++;
  }
}


double antThorax::mapTime(double timeSlice) {

  return sliceMapper->Map(timeSlice);
}

multiMap.h

#ifndef multiMap_h
#define multiMap_h


class mapItem {

public :
  mapItem(double inX, double inY);
  ~mapItem(void);

  void setValues(void);
  bool linkIn(mapItem* itemPtr);
  double Map(double inVal);
  double doMap(double inVal);
  void outputItem(void);

  double x;
  double y;
  double slope;
  double intercept;
  mapItem* lessItem;
  mapItem* greaterItem;
};


class multiMap {

public:
  multiMap(void);
  ~multiMap(void);

  void addPoint(double x, double y);
  void clearMap(void);
  double Map(double inVal);
  void outputList(void);

private :

  mapItem* itemList;
};


#endif

multiMap.cpp

#include "multiMap.h"
#include "mapper.h"

mapper mapItemMppr(1,2,1,2);


mapItem::mapItem(double inX, double inY) {

  x = inX;
  y = inY;
  lessItem = NULL;
  greaterItem = NULL;
}

mapItem::~mapItem(void) {     // Time to die. If your in a list, remove yourself.

  if (lessItem!=NULL) // Have a "less" item.
    lessItem->greaterItem = greaterItem;
  if (greaterItem!=NULL) // Have a greater item.
    greaterItem->lessItem = lessItem;
  lessItem = NULL;
  greaterItem = NULL;
  // Our work is done here..
}


void mapItem::setValues() {

  if (lessItem!=NULL) {
    mapItemMppr.setValues(lessItem->x,x,lessItem->y,y);
    slope = mapItemMppr.getSlope();
    intercept = mapItemMppr.getIntercept();
  }
}


bool mapItem::linkIn(mapItem* itemPtr) {

  if (itemPtr==NULL)                         // Sanity, is there a list?
    return false;
  if (itemPtr->x == x)                       // Duplicates are NOT allowed!
    return false;
  if (itemPtr->x < x) {                      // Ok, we belong on the greater side..
    if (itemPtr->greaterItem!=NULL) {        // There is a greater one..
      return linkIn(itemPtr->greaterItem);   // Do the recursive jump.
    }
    else {                                   // There is no one on greater side..
      lessItem = itemPtr;                    // Link in to end of list here.
      lessItem->greaterItem = this;
      setValues();
      return true;
    }
  } 
  else {                                     // We belong on the less side..
    if (itemPtr->lessItem!=NULL) {           // There is a lesser one..
      if (itemPtr->lessItem->x<x) {          // This is our spot!
        lessItem = itemPtr->lessItem;
        greaterItem = itemPtr;
        lessItem->greaterItem = this;
        greaterItem->lessItem = this;
        setValues();
        greaterItem->setValues();
        return true;
      } 
      else                                  // We are NOT greater than the less item..
      return linkIn(itemPtr->lessItem);     // Do the recursive jump down.
    } 
    else {                                  // There is no lesser one. And we are smaller..
      greaterItem = itemPtr;
      itemPtr->lessItem = this;
      setValues();
      greaterItem->setValues();
      return true;
    }
  }
}


double mapItem::Map(double inVal) {  // We need to find the correct mapper and map this value.

  if (inVal == x)                      // Hey its us!
    return (y);                        // Pass back our y value.
  if (inVal>x) {                       // inVal is greater than us.
    if (greaterItem!=NULL)             // Fine, if there's a greaterItem -
      return greaterItem->Map(inVal);  // Pass it up the line.
    else                               // Oh! We are the top of the line..
    return(y);                         // Again, pass back our y value.
  } 
  else {                               // inVal is less than us..
    if (lessItem==NULL)                // We are the smallest and inVal's smaller?
      return(y);                       // Again, pass back our y value.
    else {                             // inVal's less than us, and there is someone down there..
      if (lessItem->x>inVal)            // inVal is less than the smaller guy -
        return lessItem->Map(inVal);      // Pass it down the line.
      else {                            // inVal is less than us but not less than the smaller guy?
        return doMap(inVal);             // This one we can map!       
      }
    }
  }
}   


double mapItem::doMap(double inVal) {  // We have been choosen to map this value.

  if (inVal < lessItem->x)
    inVal = lessItem->x;
  else if (inVal > x)
    inVal = x;
  return(slope*inVal+intercept);
}


void mapItem::outputItem() {

  Serial.print("x = ");
  Serial.print(x);
  Serial.print(", y = ");
  Serial.println(y);
}

// ***********************

multiMap::multiMap() {

  itemList  = NULL;
}


multiMap::~multiMap(void) {

  clearMap();
}


void multiMap::addPoint(double x, double y) {

  mapItem* newItem;

  newItem = new mapItem(x,y);          // Whip up a fresh item.
  if (itemList == NULL) {             // Look its the first one!
    itemList = newItem;  
  } 
  else {
    if (newItem->linkIn(itemList)) {  // We were successful at linking this in?
      while(itemList->lessItem!=NULL)  // Make sure we point at the smaller end.
        itemList = itemList->lessItem;
    } 
    else {
      delete(newItem);                // Not succesfull at linkin in the new item? Recycle it.
    }
  }
}


void multiMap::clearMap(void) {

  Serial.println("I'm being cleared!!");
  if (itemList!=NULL) {
    while(itemList->greaterItem!=NULL)
      delete(itemList->greaterItem);
    while(itemList->lessItem!=NULL)
      delete(itemList->lessItem);
    delete(itemList);
    itemList = NULL;
  } 
}


double multiMap::Map(double inVal) {

  if (itemList!=NULL)              // If we have mappers..
    return itemList->Map(inVal);   // Map that item!
  else                             // What the heck? We have no mappers at all?
  return 0;                      // I guess zero is the best we can do here.
}

void multiMap::outputList(void) {

  mapItem* trace;

  if (itemList!=NULL) {           // If we have mappers..
    trace = itemList;
    while(trace!=NULL) {
      trace->outputItem();
      trace = trace->greaterItem;
    } 
  } 
  else  {                           // What the heck? We have no mappers at all?
    Serial.println("Empty");
  }
}

mapper.h

#ifndef mapper_h
#define mapper_h

#include <Arduino.h>

class mapper {
public:
  mapper(double x1,double x2,double y1,double y2);

  double Map(double inNum);

  // This stuff is for using the mapper as a liner calculator.
  void setValues(double x1,double x2,double y1,double y2);
  double getSlope(void);
  double getMinX(void);
  double getMaxX(void);
  double getIntercept(void);

private:
  double minX;
  double maxX;
  double slope;
  double intercept;
};

#endif

mapper.cpp

#include "mapper.h"

mapper::mapper(double x1,double x2,double y1,double y2) {

  setValues(x1,x2,y1,y2);
}


void mapper::setValues(double x1,double x2,double y1,double y2) {
  maxX = max(x1,x2);
  minX = min(x1,x2);
  slope = (y1-y2)/(x1-x2);
  intercept = y1 - slope*x1;
}


double mapper::getSlope(void) { 
  return slope; 
}


double mapper::getMinX(void) { 
  return minX; 
}


double mapper::getMaxX(void) { 
  return maxX; 
}


double mapper::getIntercept(void) { 
  return intercept; 
}


double mapper::Map(double inNum) {

  if (inNum < minX)
    inNum = minX;
  else if (inNum > maxX)
    inNum = maxX;
  return(slope*inNum+intercept);
}

miniSSC.h

#ifndef miniSSC_h
#define miniSSC_h

#include <Arduino.h>
#include "mapper.h"

#define miniSSCMinVal -1
#define miniSSCMaxVal 1

class miniSSC  {

public:
  miniSSC(void);

  void initSSC(bool fast=false);
  void setServo(byte servoNum,float inVal);  // Value ranged from -1.0 ... 1.0
private :
  
  byte buff[3];
  byte lastVal[255];
};

#endif

miniSSC.cpp

#include "miniSSC.h"

mapper SSCMapper(miniSSCMinVal,miniSSCMaxVal,0,254);

miniSSC::miniSSC() {

  byte i;
  buff[0] = 255;
  for(i=0;i<=254;i++)
    lastVal[i] = 255;
}


void miniSSC::initSSC(bool fast) {

  if (fast)
    Serial.begin(9600);
  else
    Serial.begin(2400);
}


void miniSSC::setServo(byte servoNum,float inVal) {

  buff[1] = servoNum;                                    // Slam the servo num into the output buffer
  buff[2] = byte(SSCMapper.Map(inVal));                  // Scale the inVal to a byte and pop it in there..
  if (servoNum<255 && buff[2] != lastVal[servoNum]) {    // Now before spending time to write it out, sanity check all this.
    Serial.flush();                                      // Maybe we need to wait 'till its done?
    Serial.write(buff,3);                                // Everything's ok, write the buffer out.
    lastVal[servoNum] = buff[2];                         // update our last position for this servo.
  }
}

timeObj.h

#ifndef timeObj_h
#define timeObj_h


class timeObj {

public:
  timeObj(float inMs);

  void setTime(float inMs,bool startNow=true);    // Change the time duration for next start..
  void start(void);                               // Start the timer "now".
  void stepTime(void);                            // Restart the timer from last end time.
  bool ding(void);                                // Timer has expired.

private:
  unsigned long waitTime;
  unsigned long startTime;
  unsigned long endTime;
  bool crossing;
};

#endif

timeObj.cpp

#include "timeObj.h"
#include <arduino.h>

timeObj::timeObj(float inMs) {

  setTime(inMs);
  startTime = 0;
  endTime = 0;
  crossing = false;
}


void timeObj::setTime(float inMs,bool startNow) {

  waitTime = 1000 * inMs;
  if (startNow) start();
}


void timeObj::start(void) {

  startTime = micros();
  endTime = startTime + waitTime;
  crossing = endTime < startTime;
}


void timeObj::stepTime(void) {

  startTime = startTime + waitTime;
  endTime = startTime + waitTime;
  crossing = endTime < startTime;
}


bool timeObj::ding(void) {
  
  unsigned long now;

  now = micros();
  if (crossing)
    return (now < startTime) && (now >= endTime);
  else
    return now >= endTime;
}