code help - best use of sensors to switch functions

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: code help - best use of sensors to switch functions

Post by adafruit_support_bill »

With the symptoms you report, a memory issue was my first suspicion. But with 92 pixels on a Teensy 3.2, pixel memory is not going to be a problem. Do you have any other large arrays, or are you doing any dynamic memory allocation?

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

I am not sure what dynamic memory allocation is... but I looked it up and it says if I am using "new" or "delete" (or other things in just C, but this isn't C.)

I am using "new" only in the initializer of the function Solid() posted above...

Larger arrays.... i have 3 or 4 twelve color arrays (a list right?) and a bunch of colors declared at the top as main variables (not in any class or anything)

Code: Select all

//Define some colors!
uint32_t pink = StripFront.Color(127, 0, 30);
uint32_t red = StripFront.Color(127, 0, 0);
uint32_t dk_orange = StripFront.Color(127, 5, 0);
uint32_t lt_orange = StripFront.Color(120, 18, 0);
uint32_t yellow = StripFront.Color(127, 127, 0);
uint32_t faded_yellow = StripFront.Color(127, 127, 18);
uint32_t lime_green = StripFront.Color(48, 127, 0);
uint32_t green = StripFront.Color(0, 127, 0);
uint32_t sea_green = StripFront.Color(0, 110, 10);
uint32_t teal = StripFront.Color(0, 127, 45);
uint32_t cyan = StripFront.Color(0, 127, 127);
uint32_t sky_blue = StripFront.Color(0, 40, 127);
uint32_t blue = StripFront.Color(0, 0, 127);
uint32_t dk_purple = StripFront.Color(55, 0, 127);
uint32_t purple = StripFront.Color(127, 0, 127);
uint32_t white = StripFront.Color(110, 110, 110);
uint32_t black = StripFront.Color(0, 0, 0);


uint32_t colors12[] = {blue, lt_orange, purple, yellow, green, red, lime_green, dk_orange, teal, pink, cyan, dk_purple};
uint32_t twelveColors0[] = {red, faded_yellow, purple, blue, yellow, green, lime_green, dk_orange, teal, pink, cyan, dk_purple};
uint32_t twelveColors1[] = {dk_orange, black, faded_yellow, black, sea_green, black, sky_blue, black, dk_purple, black, pink, black};
uint32_t twelveBlacks[] = {dk_orange, cyan, black, black, faded_yellow, dk_purple, black, black, pink, sea_green, black, black};
uint32_t twelveSolids[] = {dk_purple, black, pink, black, sea_green, black, faded_yellow, black, dk_orange, black};

Then I also have this for fading my tails the way I like...

Code: Select all

    uint32_t fade_color(uint32_t color, int tail, int current) {
      //Decompose
      byte g = color >> 16 & 0x7f;
      byte r = color >> 8 & 0x7f;
      byte b = color & 0x7f;
      float ourDecay = 0;
      if (tail == 0) {
        float newDecay[] = {1};
        ourDecay = newDecay[current];
      }
      if (tail == 1) {
        float newDecay[] = {1, 0.2};
        ourDecay = newDecay[current];
      }
      if (tail == 2) {
        float newDecay[] = {1, 0.39, 0.08};
        ourDecay = newDecay[current];
      }
      if (tail == 3) {
        float newDecay[] = {1, 0.51, 0.2, 0.04};
        ourDecay = newDecay[current];
      }
      if (tail == 4) {
        float newDecay[] = {1, 0.6, 0.31, 0.12, 0.02};
        ourDecay = newDecay[current];
      }
      if (tail == 5) {
        float newDecay[] = {1, 0.65, 0.39, 0.20, 0.08, 0.02};
        ourDecay = newDecay[current];
      }
      if (tail == 6) {
        float newDecay[] = {1, 0.7, 0.46, 0.27, 0.14, 0.05, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 7) {
        float newDecay[] = {1, 0.73, 0.51, 0.34, 0.2, 0.1, 0.04, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 8) {
        float newDecay[] = {1, 0.76, 0.56, 0.39, 0.26, 0.15, 0.08, 0.03, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 9) {
        float newDecay[] = {1, 0.78, 0.6, 0.44, 0.31, 0.2, 0.12, 0.06, 0.03, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 10) {
        float newDecay[] = {1.00, 0.8, 0.63, 0.49, 0.36, 0.25, 0.17, 0.11, 0.06, 0.03, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 11) {
        float newDecay[] = {1.00, 0.82, 0.66, 0.52, 0.4, 0.3, 0.21, 0.14, 0.09, 0.05, 0.03, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 12) {
        float newDecay[] = {1.00, 0.83, 0.69, 0.55, 0.44, 0.33, 0.25, 0.18, 0.12, 0.07, 0.04, 0.02, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 13) {
        float newDecay[] = {1.00, 0.84, 0.71, 0.58, 0.47, 0.37, 0.28, 0.21, 0.15, 0.1, 0.06, 0.04, 0.02, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail == 14) {
        float newDecay[] = {1.00, 0.85, 0.73, 0.61, 0.50, 0.40, 0.32, 0.24, 0.18, 0.13, 0.09, 0.06, 0.03, 0.02, 0.01};
        ourDecay = newDecay[current];
      }
      if (tail >= 15) {
        float newDecay[] = {1.00, 0.86, 0.74, 0.63, 0.52, 0.43, 0.35, 0.27, 0.21, 0.16, 0.11, 0.08, 0.05, 0.03, 0.02, 0.01};
        ourDecay = newDecay[current];
      }

      //float ourDecay = pow( (((float)tail) - current) / tail, log(0.2)/log(0.5) );
      //do our math
      g = (byte) ((float) g) * ourDecay;
      r = (byte) ((float) r) * ourDecay;
      b = (byte) ((float) b) * ourDecay;

      //recompose and return
      return (g << 16) + (r << 8) + b;
    }
So there are quite a few there. That is a helper function defined inside my main class.
It used to look something like this...

Code: Select all

uint32_t fade_color(uint32_t color, int tail, int current, float BIAS) {
    //Decompose
    byte g = color >> 16 & 0x7f;
    byte r = color >> 8 & 0x7f;
    byte b = color & 0x7f;
    
    
    float newDecay[tail + 1];

    //tail += 1;
    
    float ourDecay = pow( (((float)tail) - current) / tail, log(BIAS)/log(0.5) );

    //do our math
    g = (byte) ((float) g) * ourDecay;
    r = (byte) ((float) r) * ourDecay;
    b = (byte) ((float) b) * ourDecay;

    //recompose and return
    return (g << 16) + (r << 8) + b;
}
But there was seriously noticeable lag the bigger the tail got so i thought maybe the math was making it chug... I pretty much only used a bias of 0.2, so I just set it all like in the first example of the fading tail (how I currently have it) and it was noticeably faster.




Are variables initialized in the update functions of the patterns considered dynamic memory?

if so i have those all over..

I have 8 patterns and they all look somewhat like what I already posted and here are a few more...

Code: Select all

    //----------------  Rainbow()  -------------------------------------------  <--- GOOD TO GO
    //initialize for a rainbow
    void Rainbow(uint8_t interval, direction dir = FORWARD, stripSide side = TOE) {
      ActivePattern = RAINBOW;
      Interval = interval/(nLEDs+8);
      TotalSteps = interval*(nLEDs+8);
      StripSide = side;
      Index = 0;
      Direction = dir;
    }
    //update the rainbow pattern
    void RainbowUpdate() {
      int i;
      for (i = 0; i < nLEDs; i++) {
        int newNum = map(Index,0,TotalSteps,0,128);
        setPixelColor(i, Wheel(newNum));
      }
      show();
      Increment();
    }
and

Code: Select all

    //---------------------- RippleOut()------------------------------------- <-- GOOD TO GO
    //---- initialize for a ripple outward
    void RippleOut(uint32_t c, uint32_t c2, uint8_t tail, uint8_t center, uint8_t interval, direction dir = FORWARD, stripSide side = TOE) {
      ActivePattern = RIPPLEOUT;
      Interval = interval;
      //uint16_t NumPixelsToRender = (nLEDs+8);
      TotalSteps = (abs(center - ((nLEDs + 8) / 2)) + abs((nLEDs + 8) / 2)) + tail + 1;
      Color1 = c;
      Color2 = c2;
      Index = 0;
      Tail = tail;
      Center = center;
      StripSide = side;
      Direction = dir;
    }

    void RippleOutUpdate() {
      int totalPixelNum = (nLEDs + 8);
      int x, t;
      int legF2 = 14;
      if (StripSide == HEEL) {
        legF2 = 16;
      }
      int legM2 = 32;
      for (x = 0; x < totalPixelNum; x++) {
        int erasePixel = x;
        int colorPixel = Index + Center;
        int colorPixelOpposite = Center - Index - 1;
        setPixelColor(erasePixel, 0, 0, 0);
        for (t = 0; t <= Tail; t++) {
          if (Index + Center - t >= Center) {
            if (colorPixel - t < legF2) {
              setPixelColor(colorPixel - t, fade_color(Color1, Tail + 1, t));
            }
            if (colorPixel - t >= (legF2 + 4) && colorPixel - t < legM2) {
              setPixelColor(colorPixel - t - 4, fade_color(Color1, Tail + 1, t));
            }
            if (colorPixel - t >= (legM2 + 4)) {
              setPixelColor(colorPixel - t - 8, fade_color(Color1, Tail + 1, t));
            }
            if (colorPixelOpposite + t < legF2) {
              setPixelColor(colorPixelOpposite + t, fade_color(Color2, Tail + 1, t));
            }
            if (colorPixelOpposite + t >= (legF2 + 4) && colorPixelOpposite + t < legM2) {
              setPixelColor(colorPixelOpposite + t - 4, fade_color(Color2, Tail + 1, t));
            }
            if (colorPixelOpposite + t >= legM2 + 4) {
              setPixelColor(colorPixelOpposite + t - 8, fade_color(Color2, Tail + 1, t));
            }
          }
        }
      }
      show();
      Increment();
    }
I have commented out the wrapper class for now for debugging purposes but notice no difference with or without it.

the sketch says I am using 8% of storage space.

sometimes i define an integer as just "int" (like in the update parts of the pattern functions) as opposed to like uint8_t" or the like... just because... I don't really know any better? should I not use just "int"?

Sorry for getting back in day increments... life is busy ATM.

ps. I will most likely get a few hours tonight to try debugging a little more... if I find anything, I'll post again :D

G

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

oh it also says this after compiling...

Global variables use 5080 bytes (7%) of dynamic memory, leaving 60456 bytes for local variables. Maximum is 65536 bytes.

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

ok i found something...
if i do a simple sketch just printing the analog read of the flex sensor (without it ever flexing) i get right around 715 - 740 ish...

when i plug print the analog read in my sketch with the LEDs i also get the same values... UNTIL it hits the 30th pattern loop then hits this insane number (7685) then drops to right around 685. i've never touched the flex sensor... and it does not do this in a simple print sketch.

When that happens it throws this error (which i havent seen it throw unless i am printing the sensor value)

Code: Select all

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
	at javax.swing.text.GapContent.allocateArray(GapContent.java:94)
	at javax.swing.text.GapVector.resize(GapVector.java:214)
	at javax.swing.text.GapVector.shiftEnd(GapVector.java:229)
	at javax.swing.text.GapContent.shiftEnd(GapContent.java:345)
	at javax.swing.text.GapVector.open(GapVector.java:201)
	at javax.swing.text.GapVector.replace(GapVector.java:142)
	at javax.swing.text.GapContent.insertString(GapContent.java:132)
	at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:723)
	at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:707)
and that error goes on and on....

if i hard code in a value for the sensor, it works fine.
if i change my if statement value to a lower number it works fine.

original

Code: Select all

void loop() {
  //update the strips
  
  int noseFlex = analogRead(A1);
  Serial.println(noseFlex);

  if(noseFlex>700){
    Straight();
  }else{
    NosePress();
  }
  StripFront.Update();
  StripBack.Update();
  
}
hard coded

Code: Select all

void loop() {
  //update the strips
  
  int noseFlex = 1200;//analogRead(A1);
  Serial.println(noseFlex);
  
  if(noseFlex>700){
    Straight();
  }else{
    NosePress();
  }
  StripFront.Update();
  StripBack.Update();
  
}
changed if value

Code: Select all

void loop() {
  //update the strips
  
  int noseFlex = analogRead(A1);
  Serial.println(noseFlex);
  
  if(noseFlex>600){
    Straight();
  }else{
    NosePress();
  }
  StripFront.Update();
  StripBack.Update();
  
}
the weird part though is that after it gets to the 36th pattern loop (at which point it resets to 0th pattern loop number) visually the LEDs start all over as they should. it just hangs on the 30th pattern from 30 to 36.

does this help any?

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: code help - best use of sensors to switch functions

Post by adafruit_support_bill »

I am using "new" only in the initializer of the function Solid() posted above...
How frequently is Solid() called? Looks like it allocates an array of 32 byte integers to store colors. So that would be 4 bytes times the number of colors allocated for each call.

Not sure if this code works on the Teensy, but some diagnostics to track your use of dynamic memory may be helpful here:
https://learn.adafruit.com/memories-of- ... emory#sram

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

that freeMemory thing worked great no problems. It returns 57316 always (I printed it in the loop)... even when it hangs. (it continues printing while the LEDs sit on the 30th pattern.)

I currently only call Solid() here...
the first third... when PatternIndexStraight is 0-11.

Code: Select all

void Straight() {
  if (PatternIndexStraight<12){
    
    StripFront.NumColors = 10;
    StripBack.NumColors = 10;
    StripFront.Colors = twelveSolids;
    StripBack.Colors = twelveSolids;
    StripFront.Interval = 20;
    StripBack.Interval = 20;
    StripFront.ActivePattern = SOLID;
    StripBack.ActivePattern = SOLID;
    StripFront.TotalSteps = nLEDs+8;
    StripBack.TotalSteps = nLEDs+8;

  }
  if (PatternIndexStraight >= 12&&PatternIndexStraight<24) {
    StripFront.ActivePattern = CHASE;
    StripBack.ActivePattern = CHASE;
    StripFront.Color1 = colors12[PatternIndexStraight-12];
    StripBack.Color1 = colors12[PatternIndexStraight-12];
    StripFront.Tail = 6;
    StripBack.Tail = 6;
    StripFront.TotalSteps = nLEDs + 17;
    StripBack.TotalSteps = nLEDs + 17;
    StripFront.Interval = 10;
    StripBack.Interval = 10;
  } 
  if (PatternIndexStraight >= 24) {
    StripFront.ActivePattern = WIPE;
    StripBack.ActivePattern = WIPE;
    StripFront.Color1 = twelveSolids[(PatternIndexStraight-24)];
    StripBack.Color1 = twelveSolids[(PatternIndexStraight-24)];
    StripFront.TotalSteps = nLEDs + 8;
    StripBack.TotalSteps = nLEDs + 8;


  }
  //Serial.println(PatternIndexStraight);
}
guess I'll just keep playing with it. Kinda weird. Thanks for all the help... if you have any other thoughts feel free to shout out.

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

oh wait... i call solid here in setup()

Code: Select all

void setup() {

  Serial.begin(115200); //<- is this needed?

  // Initialize the LED strips
  //Strips.begin();
  StripFront.begin();
  StripBack.begin();
  pinMode(A1,INPUT);
  // kick off a pattern
  StripFront.Solid(twelveSolids,10,20,FORWARD);
  StripBack.Solid(twelveSolids,10,20,FORWARD);

}
i guess in the Straight() funtion im just setting the ActivePattern to SOLID which technically is SolidUpdate() right?

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: code help - best use of sensors to switch functions

Post by adafruit_support_bill »

that freeMemory thing worked great no problems. It returns 57316 always (I printed it in the loop).
That rules out a memory leak problem. Another thing to look for is possible array overruns. Running off the end of an array can corrupt nearby variables and lead to strange behaviors.

Say, for example, you have something like this:

Code: Select all

uint32_t ArrayOfLongs[10];
uint16_t ArrayOfInts[10];
int JustANumber;
Both arrays have 10 elements indexed from 0 to 9. What happens if you overrun those limits?

If you do this:

Code: Select all

ArrayOfLongs[10] = 0;
You will have effectively written 0 to the first two elements of "ArrayOfInts".

And if you do this:

Code: Select all

ArrayOfInts[10] = 0;
You will have effectively set "JustANumber" to 0;

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

I have been trying to wrap my brain around your last post for a lil while now... but I am not sure I am getting it.

I have an array of longs...

Code: Select all

uint32_t twelveSolids[] = {dk_purple, black, pink, black, sea_green, black, faded_yellow, black, dk_orange, black};
(all pointing to a color)

then I was calling each of those colors here..

Code: Select all

if (PatternIndexStraight >= 24 && PatternIndexStraight < 36) {
    StripFront.ActivePattern = WIPE;
    StripFront.Color1 = twelveSolids[(PatternIndexStraight - 24)];
    StripFront.TotalSteps = nLEDs + 8;
  }
are you saying that in my code this here could be a possibility?

Code: Select all

StripFront.Color1 = twelveSolids[(13)];
which does'nt actually exist...

IF that is what you are saying, then I used to write it like this, and not sure why I had it the way above (maybe testing things..)

Code: Select all

    StripFront.Color1 = twelveSolids[(PatternIndexStraight % 12)];
  }
That way It just looped back around to the first one in the array if we went over. So I should never be looking for a long that is out of the array.

Anyhow, I had it like the second example originally... so I am assuming I had issues with that too... but I'm not entirely sure at this point.
I have reverted it back to the second example. I have been playing with it a bit... and it seems to have magically fixed itself? I've even added 8 or 10 more LEDs per strip. I have added more patterns in the Straight() function and PatternIndexStraight is a much higher number now... apart from that, it looks no different than it did before so I can't figure out why I was having problems.

I still get weirdness when I use the flex sensor in the WIPE pattern only... (a different kind of weirdness...) but i believe it is due to the fact that I am switching the direction the LEDs go in by use of the flex sensor (if I put the switching value really low the weirdness goes away) and I am on right on the turning point of the flex sensor saying whether to go in one direction or the other... (so it could be periodically switching directions for a very short time) AND the WIPE pattern is the only one that does not erase the pixels before writing the new ones, or write all the LEDs at once, it just writes only the one pixel Index is on... So I will rewrite that one to write all pixels at once and see if that fixes it.

Apart from that...
I am just now trying to make use of the gyro/accelerometer.
I purchased this one... (the other one I was looking at wasn't available at the time)
https://www.adafruit.com/product/3387
is this usable with the teensy?

I should probably have done my research before purchasing it... but I was just too excited i guess.

If it is usable with the teensy... could I be pointed in the direction of some documentation or examples of how to get it working on the teensy?
I tend to use the pjrc website for arduino items in relation to the teensy... but I seem to have a hard time over there so I'm asking here first :P
If it is NOT... is there one that is?

I still have a looong road ahead of me... but I am enjoying the adventure and learning a bunch :D

G

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: code help - best use of sensors to switch functions

Post by adafruit_support_bill »

I have reverted it back to the second example. I have been playing with it a bit... and it seems to have magically fixed itself?
If I understand correctly, you added the modulo operator "%" back into your array addressing and the problem went away? If so, that would suggest that you were having some array overruns before. These can corrupt data and cause strange behavior such as you were seeing.
I purchased this one... (the other one I was looking at wasn't available at the time)
https://www.adafruit.com/product/3387
is this usable with the teensy?
I have not tried that combination, but I would expect it should work in the Teensy. It is an i2c sensor, so just wire it to the bus the same as other i2c sensors. The main thing you need to watch out for is that there are no address conflcts with any other i2c devices you have on the bus.

This is a fairly comprehensive list of addresses for the devices we sell: https://learn.adafruit.com/i2c-addresses/the-list

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

ok i got it working. I think maybe I just had an old Wire.h library or something... as I updated that and it's good to go.

(I was getting a lot of TwoWire errors or something... not compilable on teensy 3.x...)

Thanks for all the help Bill!


Now to actually use it....

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: code help - best use of sensors to switch functions

Post by adafruit_support_bill »

Good to hear!

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

ok so i have one more issue...
I want to use some flex sensors to detect if I am doing a nose or tail press on the snowboard...
I am using these...
https://www.adafruit.com/product/182

and it works great in the code and everything... the problem is that when doing a press there is actually minimal flex in the board so I need to be able to read just a small amount of flex in the sensor... but I get a larger range of input values than I want ... it ranges from something like 490 to 570 (off the top of my head from memory) even when the flex sensor is flat. I believe it is due to different patterns running more or less LEDs at a time taking up more amps?

So... is there a way I can like neutralize the sensor to keep its input values pretty even when it isnt being flexed?

Thanks again,
G

User avatar
adafruit_support_bill
 
Posts: 88096
Joined: Sat Feb 07, 2009 10:11 am

Re: code help - best use of sensors to switch functions

Post by adafruit_support_bill »

The noise could be caused by a number of things. It could be fluctuations in the analog reference voltage or 'ground bounce' from the varying current draw from the LEDs. It could also be inductively coupled EMI from the PWM switching that takes place in the LEDs.

Not sure what processor you are using on the snowboard, but on an Arduino, you can minimize analog reference fluctuations by using the 3.3v pin as an external reference. We also have precision voltage reference breakouts. https://www.adafruit.com/product/2200

To minimize ground-bounce, you need to make sure that your sensor has its own ground path back to the processor. It should not share any part of the ground wiring for your pixels.

EMI is best dealt with by making sure that your sensor wiring is well separated from the neopixels and their wiring.

User avatar
mohawkpiper
 
Posts: 138
Joined: Sat Oct 13, 2012 3:28 am

Re: code help - best use of sensors to switch functions

Post by mohawkpiper »

Thank you so much Bill. Using the 3.3V pin works perfectly!

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”