RAM RAM I need more RAM!!

blinker.h

#ifndef blinker_h
#define blinker_h

// A simple blink class used to turn on and off blinking LEDs.
// Spawn a blinker for each pin you would like to blink an LED on.
// Its not ment to be the end all. Its just something to blink LEDs.
// It will probably crash and burn when the microsecond counter overruns.
// 
// Written by : Jim Lee @ www.LeftCoast.biz


// Some defaults in case the user just doesn't care..
#define defPin 13
#define defOnMs 50
#define defPeriodMs 400

class blinker {
	
public:
	blinker(int inPin=defPin,float inOnMs=defOnMs, float inPeriodMs=defPeriodMs);
	
	void init(bool running=true);	        // Call this in the setup function perhaps?
	void setBlink(bool onOff);		// Start or stop the blinking..
	void idle(void);			// Call this in the loop function.
	
	void setTimes(float inOnMs, float inPeriodMs);	// Want to change the blink?
	
private:
	unsigned long onTime;
	unsigned long periodTime;
	unsigned long startTime;
	bool running;
	bool pinHigh;
	int pin;
};

#endif

blinker.cpp

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

blinker::blinker(int inPin,float inOnMs, float inPeriodMs) {

   running = false;
   pinHigh = false;
   pin = inPin;
   setTimes(inOnMs,inPeriodMs);
}


void blinker::init(bool running) {

   pinMode(pin, OUTPUT);
   setBlink(running); 	
}


void blinker::setBlink(bool onOff) {

   if(onOff != running) {		// ignore if no change
      if (onOff) {			// Start blinking..
         startTime = micros();		// Starting NOW!
         digitalWrite(pin,HIGH);	// light on!
         pinHigh = true;		// set state.
         running = true;
      } 
      else {			         // Stop blinking..
         digitalWrite(pin,LOW);		// light off.
         running = false;		// set state.
         pinHigh = false;
      }
   }
}


void blinker::idle(void) {

   unsigned long now;

   if (running) {
      now = micros();				// Look at the time!
      if (pinHigh) {				// If the light is on..
         if (now >= startTime+onTime) {		// And its been on long enough!
            digitalWrite(pin,LOW);		// light off.
            pinHigh = false;			// set state
         }
      } 
      else {					// Else the light is off..
         if (now >= startTime+periodTime) {	// And its been off long enough!
            digitalWrite(pin,HIGH);		// light on!
            pinHigh = true;			// set state
            startTime = startTime + periodTime;	// Set next iteration.
         }
      }
   }
}


void blinker::setTimes(float inOnMs, float inPeriodMs) {

   onTime = round(1000*inOnMs);
   periodTime = round(1000*inPeriodMs);
}

I think that's all of it..

-jim lee

Holy cow! I can see why you are running out of ram.
But, there is room for optimizations.
First of all, some of the instructional strings in main.cpp can be stored in PROGMEM. That should gain you atleast 100 bytes.
I am also sure there are some optimizations that can be done in the "thorax" code but it makes my brain hurt to look at. :roll_eyes:

Lots of candidates for PROGMEM strings there

Hey Jim,
Really you should look into reframicating the software if only that others may use it on UNO's buuuut,

Check out the Teensy++!
Teensy USB Development Board

128k flash, 8k SRAM, 4k EEPROM.
46 I/O pins; 8 analog inputs, 9 PWM's.
USB based Atmel chip, programmable as HID/MIDI and they have libraries.
Really small. Arduino compatible, able to use the Arduino IDE.
Way more than an UNO, not sure how it rates compared to a MEGA2560.
With pins (sticks right into a breadboard), $27. Without, $24.

Or you can buy SPI-bus SRAM, 8k x 8-bit through-hole DIPs are pretty cheap @ $.70. See the 3K640-I/P:
RAM's (Random Access Memory ICs)

Not as fast as on-board SRAM but way cheaper than a new board.
The 23K256-I/P 32k x 8-bit SPI-bus SRAM are surface mount, for $1.35 they are 4x as much.

Of course either way there's a shipping charge so save up and buy enough to justify that.

And my non-disclaimer is that I have no connection to either of those companies except being a satisfied customer. PJRC (the Teensy site) shipping got to me a lot quicker but then across the US isn't as far from me than Hong Kong. But the HK shipment 'only' took between 2-3 weeks and they DO have so many different things.

There are many other good sites but those jump out at me when it comes to 'Mo RAM!'. Hey... Moe RAM, that'd be a good forum name, wouldn't it? People could say "Hey Moe!".

'1284's have 16K SRAM. '2560 only has 8K.
$5 processor vs $13 too.

miniSSC.h:
  byte lastVal[255];

ouch? I certainly hope that this only gets instantiated once. Even then, I think it's safe to say that the Arduino is NOT EVER going to support 255 simultaneous servos, so you can immediately save a couple hundred bytes here by changing this to a more realistic value... (nit: it should be a #define somewhere too, rather than a hardcoded constant.)

mapper.h:
private:
  double minX;
  double maxX;
  double slope;
  double intercept;

Since you are adding a significant number of these to each joint (?), you might want to check out just how much space the list of mappers is taking vs a simpler data structure like an array with a static maximum size.

The usual argument against C++ at my old stomping grounds was not so much that it was "inefficient", but that it could be silently and "innocently" inefficient. A small piece of normal-looking source code could inadvertently lead to runtime and/or storage problems that were otherwise unexpected. In an embedded system without much (or any) memory protection, this is particularly serious. An Arduino won't tell you that there is no space for the next "new" that your program does, it will just start failing. Sometimes in mysterious ways...

Sorry, was off the grid for a week there.

In the miniSSC file, The 255 byte array is only created once. Its just some code to run a string of SSC-ASD2 Discontinued boards. They listen on the serial port. The idea was to unload the processor from dealing with keeping the Servos alive. Currently 18 servos.

As for the mappers, I didn't create them with the 6 legs, just the single thorax. The legs go to the thorax for mapping services.

I worry about the mutiMapper code because I kinda' cheated and made them recursive.

Serial.writeLn("bla bla bla in quotes") <- I used form this a lot in the main file. Am I reading this correct that this is not a good idea memory-wise?

Actually, I've been looking at the teensy++. But really, I have no idea what RAM I need. Am I close and with a few tweaks I'll be ok? Or am I way out in left field where the extra 8k won't make any difference at all? Some sort of took to look at this would sure be nice.

One last thing, what is the difference between EEPROM and Flash memory? They seem like the same thing, but I guess they are not?

-jim lee

Serial.writeLn("bla bla bla in quotes") <- I used form this a lot in the main file. Am I reading this correct that this is not a good idea memory-wise?

Correct. Since program memory is not "normally" addressable, all C variables/objects/etc will end up being allocated in RAM, even if their value is constant. In arduino 1.0, steams (xxx.write()) understand "strings allocated in flash", which can be done by adding F("string"), ("Serial.writeln(F("bla bla bla in quotes")):wink:

Jim, when you're making structures, etc, that store and use data.. don't you count the bytes required for the data?

And if there's 18 servo boards then use [18] or a realistic maximum instead of [255] for that array.

All floating point on Arduino is 32-bit no matter float or double. If you can switch the sections that use FP to use 16 or 32-bit integer then you will gain speed and possibly save on ram. A 16-bit integer is good for +/- 4 digits or unsigned, 5 digits. Where the decimal place is makes it flexible; if I want fractions of a kilogram then I weigh -integer- grams, not -fp- .001 kg's. 16 bits for 4 or 5 places is pretty good. Back in the ages BC (Before Calculators), 3 or 4 places was deemed good for most classwork. And I see you use it on robot insect leg joints. How precise do you need?

Tables should be made in PROGMEM to hold pre-calculated values, trig, sqrt, that FP functions supplied except for integers -- table them up in PROGMEM, lookup there will be faster than using FP but slower than ram. But you have no choice unless you go to a bigger MCU.

Man, that 1284 has gotta be looking real good about now.....

"Man, that 1284 has gotta be looking real good about now....."

For sure!
I need to figure out my FTP password again so I can upload some more pictures. For now,
check #282, #287 here,
http://arduino.cc/forum/index.php/topic,80483.285.html
and PL on #313

Do I count up the bytes for structures? Never..

As for the variable sizes and stuff. 90% of this code is general purpose library files that I use all over the place. So I'd rather not create special case versions for this yet.

Now this 1284 thing. This -is- looking pretty tempting. Can I program it just like my little Uno? Tell me some more about this.

-jim lrr

I was looking at info on my Teensy++ and found that it can use 64k bytes of directly addressable external ram. It's an AT90USB1286. I am finding other AT90 chips able to use external ram and I see that the Arduino MEGA can also use external ram, Rugged Circuits has memory shields for them. Chances are that the 1284 can use it too.

Yes you should count bytes and be aware as you write your code. Even on a full PC. Fat code is why we need desktop supercomputers to run apps way slower than they should. On an MCU it's critical. Do you watch how high you hold your head in low places?

Yes you can. Install maniacbug's core files into the IDE, select Bobuino as the board type, and have more RAM, FLASH memory, IO, all ready to go.

I have 19 boards on hand still.
Reply #224 at the bottom of page 15 has the details
http://arduino.cc/forum/index.php/topic,80483.210.html

with a parts line in #313
http://arduino.cc/forum/index.php/topic,80483.300.html on page 21

Cross roads, now I'm confused..

I thought you had a board, kinda' like the Uno with more RAM & goodies for about $80-ish. And my hope was I could select a different chip with my IDE, load my program and be done.

How close am I? What is this talk about raw PC boards and what is this github thing?

And, wasting RAM doesn't make code slow. Its poor algorithms that makes code slow. Unless, of course, the OS starts swapping to disk. Then your going to be slow..

-jim lee

OS wouldn't need to swap if the OS and programs fit. 800 lb gorillas tend to take up a lot of room to themselves as it is.

And, wasting RAM doesn't make code slow.

It depends how you waste it.

You can get a MEGA2560 and a Rugged Circuits 512k Quadram shield then try and waste 8 x 64k banks.

Or you can find out if a more suited approach can make your project work on less hardware. But with your attitude I think you will be blind to over half the possibilities and never able to cut the unnecessary parts out let alone come up with shortcuts.

"I thought you had a board, kinda' like the Uno with more RAM & goodies for about $80-ish."

I have that too. You hadn't indicated any need for RTC, RS232, SD/uSD card tho.

No matter how you go '1284, you will need the maniac/github stuff for the 1284 support as the Arduino IDE does not support the 1284 as a 'native' chip yet; only the '168, '328, '1280, and '2560 I believe.

I got it working.

Clipped out the command processor with all its strings. It was for debugging anyway. Set the upper limit of the servos to 18 like you suggested.. Still crashed.

But, I noticed it always crashed at the same spot... Hmm.. Found a loop counter that was 0 to <= Some number as opposed to 0 to < some number and Vola! Everything worked!

Sorry if I came across as having a bad attitude, it wasn't meant that way. I'm just having all sorts of fun playing with this little gadget.

Yes, I do like wasting RAM.. RAM's like chocolate, never have enough!

-jim lee

jimLee:
And, wasting RAM doesn't make code slow.

It may, since accessing more ram will take more time.

Yes, I do like wasting RAM.. RAM's like chocolate, never have enough!

I don't like wasting RAM and don't like chocolate :stuck_out_tongue: