0

So my program fails to run because there is not enough room for my variables as well as the Arduino Core and Stack. I can't find any more ways to optimize my program so I'm thinking about just rewriting it in C.

However, I'm not sure if that will actually help me. For example I know that in C my program will run faster because things like digitalWrite() and analogRead() have a bunch of "extras" that make it go slower, but I don't know if this will affect RAM.

So can any of the experts on here tell me if writing my code will help before I waste time doing so?

Here is my code:

#include <SoftwareSerial.h>
#include <avr/pgmspace.h>

#define FASTADC 1

// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

SoftwareSerial mySerial(0,1) PROGMEM;

byte i;

byte pixelsArray1[128];   //Array to hold the values of the individual pixles.
byte pixelsArray2[128];   //Array to hold the values of the individual pixles.
byte pixelsArray3[128];   //Array to hold the values of the individual pixles.

void setup() 
{
  #if FASTADC
   // set prescale to 16
   sbi(ADCSRA,ADPS2);
   cbi(ADCSRA,ADPS1);
   cbi(ADCSRA,ADPS0);
  #endif

  pinMode(1,OUTPUT);        //Setting the 1 pin to be used for output 
  pinMode(0,OUTPUT);        //Setting the 0 pin to be used for output
  pinMode(A3,INPUT);        //Input for Camera 3
  pinMode(A2,INPUT);        //Input for Camera 2
  pinMode(A1,INPUT);        //Input for Camera 1

  mySerial.begin(9600);     //Setting the data transfer rate
}

Notes:

  • I'm programming on the ATtiny85
  • I'm running Windows 10
  • I've never programmed in Arduino before
  • What does your RAM usage currently look like? – Ignacio Vazquez-Abrams Jun 14 '16 at 17:49
  • The three arrays, SoftwareSerial, and byte variable use 432 of the total 512 bytes of RAM on the ATtiny. Leaving the remaining 128 for the Core and Stack which I'm assuming is not enough because when I upload the program it fails to run. However when I reduce the size of the arrays the program runs just fine. – sgmm Jun 14 '16 at 17:53
  • Personally I would look at ditching SoftwareSerial and running the USI by hand, but have you tried the code on a larger device yet? – Ignacio Vazquez-Abrams Jun 14 '16 at 17:59
  • Yes it work just fine on my Mega. But doesn't SoftwareSerial not affect the memory in my code since I'm using PROGMEM to store it in flash? Also can you expand on what you mean by "running the USI by hand". – sgmm Jun 14 '16 at 18:03
  • SoftwareSerial has a buffer that takes up RAM regardless of where the object itself is located. AVR307 – Ignacio Vazquez-Abrams Jun 14 '16 at 18:07
4

The simplest approach to reducing RAM usage of the program shown is to get rid of the three 128-byte pixel arrays. They are not needed for the program to function.

Instead of writing

pixelsArray1[i]=analogRead(A1)/4;
pixelsArray2[i]=analogRead(A2)/4;
pixelsArray3[i]=analogRead(A3)/4;

write

if (analogRead(A1)/4 == 0 && analogRead(A2)/4 == 0 && analogRead(A3)/4 == 0) ++foundZero;

where foundZero is initialized to zero before the loop. After the loop, you say something like

while (foundZero--) {
  digitalWrite(1, HIGH);
  delay(2000);
  digitalWrite(1, LOW);
  delay(2000);
}

to toggle pin 1 as many times as there were three zero pixels.

Note, the timing of the if (...) ++foundZero; statement may differ from pixel to pixel because the && evaluation may short circuit. If the timing matters, save data in temporary variables, or check if the sum of the three is zero, etc.

| improve this answer | |
  • Thanks but eventually I will need all three arrays to do some calculations once the project nears completion. I need the three arrays and can't do without them. – sgmm Jun 14 '16 at 18:26
  • 1
    If timing of reading pixels isn't critical, just do those other calculations online also. If possible. Or if your later processing needs some context but not the whole array, keep a dozen or two of pixels in a circular buffer. Or just reread all the pixels when you need to work with them. – James Waldby - jwpat7 Jun 14 '16 at 18:31
0

I don't believe that rewriting it in C is going to help you much: the framework is pretty tight already, and you'd only get the C library's versions of the various drivers' buffers etc.

I do think your only solution (apart from getting larger hardware!) is to 'optimise' the pixelArrays. To do that, could you consider the following questions:

  1. What is the worst value resolution that you'll get away with? You're currently compressing each camera feeds' pixel to the range 0-255, to store them into their individual bytes. What about 0-31? (See why below)
  2. Will you always be comparing each feed's individual pixels against the same pixel in another feed? If so, perhaps you could pack all three values into one 16-bit quantity:
    X 11111 22222 33333
    where each quintet of bits is that feed's value compressed down. The X is cute: before compressing, you could compare all three values with each other, or zero, or something, and if true set the X bit to 1. That then means that you can later test for that exact condition in the triple-pixel with a <0 check - the sign bit will be set, so the condition will be true.
  3. Or, if compressing down to 0-31 is too extreme, what about storing a 'master' copy of the pixel, and then two (scaled) differences from there: 11111111 2222 3333 where the master 1 value is unscaled (other than /4), while the other values are from the following table:

    0000 - Identical pixel value
    0001 - Within +2
    1111 - Within -2
    0010 - Within +4
    1110 - Within -4
    0011 - Within +8
    1101 - Within -8
    0100 - Within +16
    1100 - Within -16
    0101 - Within +32
    1011 - Within -32
    0110 - Within +64
    1010 - Within -64
    0111 - Within +128
    1001 - Within -128
    1000 - More than ±128

  4. Even more radical: could you do all the tests when you read the data (do you have time???), and then simply store a one-bit result for each pixel? Such a packed-bit array is VERY efficient - if you can boil down your decision to yes/no...

I'd be happy to help write (reasonably) efficient C code to implement the TriplePixel functions - or even attempt it in assembly...

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.