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
sgmm
  • 175
  • 1
  • 7

2 Answers2

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.

James Waldby - jwpat7
  • 8,920
  • 3
  • 21
  • 33
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...

John Burger
  • 1,885
  • 1
  • 14
  • 23