Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 25 of 25

Thread: Teensy audio and FastLED SPI?

  1. #1
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19

    Teensy audio and FastLED SPI?

    So here is my predicament: the project I am working on calls for about 2000 LEDS, triggered and modified by sound. Specifically it will be a wearable LED installation for burning Man. Everything starts to come nicely together, so far so good. Yesterday the audio shields arrived and so far I like it. There is a lot I can do with that. BUT there is one really nagging problem. It seems that the FastLED library and the teensy audio library are not best pals. What I mean is that if I use hardware spi to drive the LEDs (at around 5MHz) then the FFT library indicates that there is a lot of distortion, aka high frequency noise. this can be prevented by using bit-banging the LEDs, on different pins, but that of course means that the LEDs are being handled much slower, and with 2000 LEDs to handle that could be a problem. Is there anything I can do, tell the audio library to make those two peacefully co-exist on the same processor (but on different pins?)

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    Guessing from only what you've described (without posting code... the "Forum Rule"), this sounds like an analog signal problem, utterly unrelated to the libraries & software on Teensy.

    I saw the same thing happening when using OctoWS2811 with the audio lib on an ADC pin. There's a huge amount of noise at the 800 kHz output frequency. It couples to the analog input and aliases into the audio band.

    Keeping digital switching noise out of sensitive analog signals is tough. The small details of how you're powering and connecting everything matter greatly.

    Of course, the very first step would be to really figure out if there is indeed a software compatibility problem. That's unlikely, since these 2 libraries don't overlap in hardware resources, unless you use the stuff in the library which access the SPI port. Still, some tests like whether the problems change when you're driving the LEDs versus just letting the pins toggle without any wires connected would really help, and let you focus your effort on the right area (and be able to post the right soft of info here... source code vs photos & wiring diagrams).

  3. #3
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Quote Originally Posted by PaulStoffregen View Post
    Guessing from only what you've described (without posting code... the "Forum Rule"), this sounds like an analog signal problem, utterly unrelated to the libraries & software on Teensy.

    I saw the same thing happening when using OctoWS2811 with the audio lib on an ADC pin. There's a huge amount of noise at the 800 kHz output frequency. It couples to the analog input and aliases into the audio band.

    Keeping digital switching noise out of sensitive analog signals is tough. The small details of how you're powering and connecting everything matter greatly.

    Of course, the very first step would be to really figure out if there is indeed a software compatibility problem. That's unlikely, since these 2 libraries don't overlap in hardware resources, unless you use the stuff in the library which access the SPI port. Still, some tests like whether the problems change when you're driving the LEDs versus just letting the pins toggle without any wires connected would really help, and let you focus your effort on the right area (and be able to post the right soft of info here... source code vs photos & wiring diagrams).
    I highly doubt this is an analog problem since the audio comes from the mic on the audio shield, but I see your problem in deciding what it could be. I was just on the iPad yesterday evening when posting the question and did not have everything together. So this post will be a longer one, showing the whole setup and the relevant portions of the code. (There is more code, but that is not involved and if you want to I am happy to post the rest as well)

    And with that: here is the main loop

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include <FastLED.h>
    #include <RunningAverage.h>
    #include <EEPROM.h>
    #include <FastCRC.h>
    
    #include "definitions.h"
    
    #define NUM_LEDS (MatrixWidth * MatrixHeight)
    CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
    CRGB leds2_plus_safety_pixel[ NUM_LEDS + 1];
    CRGB* const leds( leds_plus_safety_pixel + 1);
    CRGB* const leds2( leds_plus_safety_pixel + 1);
    CRGBPalette16 firePalette;
    
    float mgain1 = 1.0;
    float mgain2 = 1.0;
    //static uint8_t Debug = 1;
    
    #include "AudioDefinitions.h"
    
    RunningAverage avg(255);
    
    #include "misc.h"
    #include "setup.h"
    
    #include "Effects.h"
    #include "Fire.h"
    #include "SpectrumAnalyzer.h"
    #include "DiffBase.h"
    
    typedef void (*FrameList[])();
    FrameList drawFrame = {SpectrumAnalyzer, Fire, DiffBase };
    
    #include "Effects.h"
    #include "Fire.h"
    
    void loop() { 
    //  int vol = analogRead(A1) / 20;
    //  sgtl5000.micGain(vol);   // vol is integer
    //  if (Serial) Serial.println(vol);
     drawFrame[0]();
     FastLED.show();
    }
    definitions.h:
    Code:
    #define BRIGHTNESS  64
    #define NoiseFloor  0.05
    #define TargetAVG   1.0              // Target avg for AGC
    #define GainAdjust  0.001            // AGC uses this value to increase or decrease gain each loop, bigger values make AGC react faster
    #define MAXGAIN     1.0              // AGC will not set the mixer gain higher than this
    #define MINGAIN     0.01              // AGC will not set mixer gain lower than this
    #define LogCurve    3        
    #define MatrixHeight 10
    #define MatrixWidth 10
    
    #define DATA_PIN  7
    #define CLOCK_PIN 6
    #define COLOR_ORDER BGR
    #define CHIPSET     APA102
    #define UpdateFrequencyMHZ  1
    
    #define MATRIX_CENTRE_Y 5
    #define MATRIX_CENTRE_X 5
    
    const bool  MatrixSerpentineLayout = true;
    AudioDefinitions.h:
    Code:
    // GUItool: begin automatically generated code
    AudioInputI2S            i2s1;           //xy=115,244
    AudioMixer4              mixer;          //xy=400,248
    AudioAnalyzeFFT1024      fft;            //xy=649,152
    AudioAnalyzePeak         peak;           //xy=653,380
    AudioConnection          patchCord1(i2s1, 0, mixer, 0);
    AudioConnection          patchCord2(mixer, fft);
    AudioConnection          patchCord3(mixer, peak);
    AudioControlSGTL5000     sgtl5000;       //xy=335,609
    // GUItool: end automatically generated code
    misc.h:
    Code:
    float cVal(int start, int end){
      double val = 0;                         // starting value
      double res = 0;
    
      val = fft.read(start,end);          // add 1 so that we get to the correct part of the log2 curve
      if ( val > NoiseFloor ) {
        res = ((log10(val) + 2) / 2);   // 0(Noisefloor) is at a value of approx 0.3
        return(res);
      } else {
        return((float)0.0);
      }
    }
    
    // This function will return the right 'led index number' for 
    // a given set of X and Y coordinates on your matrix.  
    // IT DOES NOT CHECK THE COORDINATE BOUNDARIES.  
    // That's up to you.  Don't pass it bogus values.
    //
    uint16_t XY( uint8_t x, uint8_t y)
    {
      uint16_t i;
      
      if( MatrixSerpentineLayout == false) {
        i = (y * MatrixWidth) + x;
      }
    
      if( MatrixSerpentineLayout == true) {
        if( y & 0x01) {
          // Odd rows run backwards
          uint8_t reverseX = (MatrixWidth - 1) - x;
          i = (y * MatrixWidth) + reverseX;
        } else {
          // Even rows run forwards
          i = (y * MatrixWidth) + x;
        }
      } 
      return i;
    }
    
    uint16_t xySave( uint8_t x, uint8_t y)
    {
      if( x >= MatrixWidth) return -1;
      if( y >= MatrixHeight) return -1;
      return XY(x,y);
    }
    
    void cLed(int band, int start, int end){
      int displayVal = 0;
      float val = cVal(start,end);
      if (val > 1) val = 1;
      val = val * 100;                  // bring into usable are
      displayVal = map((long) val, 39,100,0, MatrixHeight);  // Number of LEDs  
      for ( int i = 0; i < displayVal; i++) {
        int index = xySave(i, band);
        leds[index] = CHSV(100-i*10, 255, 200);  
      }
    }
    setup.h:
    Code:
    void setup() {
      Serial.begin(9600);
    //  while (!Serial);                    // wait for serial to start
      
      AudioMemory(10);
      sgtl5000.enable();
      sgtl5000.volume(0.5);
      sgtl5000.inputSelect(AUDIO_INPUT_MIC);
      sgtl5000.micGain(30);
      FastLED.addLeds<APA102,DATA_PIN,CLOCK_PIN,BGR,DATA_RATE_MHZ(UpdateFrequencyMHZ)>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
      FastLED.setBrightness( BRIGHTNESS );
      FastLED.setDither(0);
      FastLED.setMaxPowerInVoltsAndMilliamps(5,2000);
      for (int i = 0; i < NUM_LEDS; i++)
        leds[i] = 0x000000;
      FastLED.show();
      // Uncomment one these to try other window functions
      // fft1024_1.windowFunction(NULL);
      fft.windowFunction(AudioWindowBartlett1024);
      // fft.windowFunction(AudioWindowFlattop1024);
      avg.clear();
      mixer.gain(0, mgain1);
    //  mixer.gain(1, mgain2);
      firePalette = CRGBPalette16( CRGB::Black, CRGB::DarkOrange, CRGB::Red, CRGB::White);
      pinMode(5, OUTPUT);
    }
    and finally the piece of the code that shows the problem:
    SpectrumAnalyzer.h
    Code:
    void SpectrumAnalyzer() { 
     double val = 0;
    
      if (fft.available()) {
        blur2d( leds, MatrixWidth, MatrixHeight, 3);
        fadeToBlackBy(leds,NUM_LEDS, 30);
          
    //    cLed(0,1,1);      // 43             // too much noise in this bin
        cLed(1,2,3);      // 86
        cLed(2,3,4);      // 172
        cLed(3,5,8);      // 344  
        cLed(4,9,16);     // 688
        cLed(5,17,32);    // 1376
        cLed(6,33,64);    // 2752
        cLed(7,65,128);   // 5504
        cLed(8,129,255);  // 11008
        cLed(9,256,511);  // rest
    
        val = fft.read(2,128);
        avg.addValue(val);
        double ravg = avg.getAverage();
     
        if (ravg > TargetAVG)
          mgain1 -= GainAdjust;
        else
          mgain1 += GainAdjust;
    
        if (mgain1 > MAXGAIN)
          mgain1 = MAXGAIN;         //lets not overdo it!
        if (mgain1 < MINGAIN)
          mgain1 = MINGAIN;         // same here
        mixer.gain(0, mgain1);
      }
    }
    The way I posted the code is the way it works. bitbanging the protocol on two arbitrary pins. I will include links to some short videos that do show the problem rather clearly.

    Also, here is the code when it does not work: Everything stays the same, with the exception of
    definitions.h:
    Code:
    #define BRIGHTNESS  64
    #define NoiseFloor  0.05
    #define TargetAVG   1.0              // Target avg for AGC
    #define GainAdjust  0.001            // AGC uses this value to increase or decrease gain each loop, bigger values make AGC react faster
    #define MAXGAIN     1.0              // AGC will not set the mixer gain higher than this
    #define MINGAIN     0.01              // AGC will not set mixer gain lower than this
    #define LogCurve    3        
    #define MatrixHeight 10
    #define MatrixWidth 10
    
    #define DATA_PIN  7
    #define CLOCK_PIN 14
    #define COLOR_ORDER BGR
    #define CHIPSET     APA102
    #define UpdateFrequencyMHZ  1
    
    #define MATRIX_CENTRE_Y 5
    #define MATRIX_CENTRE_X 5
    
    const bool  MatrixSerpentineLayout = true;
    andy you can see that the only thing that changed is the clock pin moved to a pin that is really a clock pin for the UART and thus the FastLED library switches from bitbanging to using the hardware UART. The videos show this rather well. In addition, as you might be able to see from the videos the LED array has its own power supply, and the connection to the teensy is via 3 lines (GND, CLK, DATA)

    The links in the next post ....

  4. #4
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    My MacBook decided it had to reboot/update right while I was writing the post, so here is the second part with all the documentation:

    So, here is the setup that works. (The LEDs connected to 6 and 7 as per definitions.h)



    And the video that shows how it is supposed to look like when it works with sound and without.
    http://www.ple.org/TeensyAudioProblem/IMG_0029.MOV

    And the setup that doesn't work: With the LEDs connected to 7 and 14 and thus using hardware SPI)


    And the video that shows how it should not look like when it is quiet
    http://www.ple.org/TeensyAudioProblem/IMG_0032.MOV

  5. #5
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Just wondering if there are any thoughts on this problem?

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    Code:
    /home/paul/teensy/sketch/fastled_issue/fastled_issue.ino:7:28: fatal error: RunningAverage.h: No such file or directory
    #include <RunningAverage.h>
    ^
    compilation terminated.
    Edit: looks like Effects.h any others maybe also be missing. I can't run it here if stuff is missing!
    Last edited by PaulStoffregen; 02-25-2016 at 03:42 PM.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    This looks very similar to a recent question on FastLED's Google+ group.

  8. #8
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Yes, this looks similar. Because it is the other side of the equation.

    As for RunningAverage: https://github.com/RobTillaart/Ardui...RunningAverage

    Effects.h
    Code:
    /*
     * Aurora: https://github.com/pixelmatix/aurora
     * Copyright (c) 2014 Jason Coon
     *
     * Portions of this code are adapted from "Funky Clouds" by Stefan Petrick: https://gist.github.com/anonymous/876f908333cd95315c35
     * Portions of this code are adapted from "NoiseSmearing" by Stefan Petrick: https://gist.github.com/StefanPetrick/9ee2f677dbff64e3ba7a
     * Copyright (c) 2014 Stefan Petrick
     * http://www.stefan-petrick.de/wordpress_beta
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy of
     * this software and associated documentation files (the "Software"), to deal in
     * the Software without restriction, including without limitation the rights to
     * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
     * the Software, and to permit persons to whom the Software is furnished to do so,
     * subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in all
     * copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
     * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
     * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
     * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     */
    
    #ifndef Effects_H
    #define Effects_H
    
    #define MAX_COLOR_VALUE 255
    
    #define SWAPint(X,Y) { \
            int temp = X ; \
            X = Y ; \
            Y = temp ; \
        }
        
    uint8_t beatcos8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0)
    {
      uint8_t beat = beat8(beats_per_minute, timebase);
      uint8_t beatcos = cos8(beat + phase_offset);
      uint8_t rangewidth = highest - lowest;
      uint8_t scaledbeat = scale8(beatcos, rangewidth);
      uint8_t result = lowest + scaledbeat;
      return result;
    }
    
    uint8_t beattriwave8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0)
    {
      uint8_t beat = beat8(beats_per_minute, timebase);
      uint8_t beatcos = triwave8(beat + phase_offset);
      uint8_t rangewidth = highest - lowest;
      uint8_t scaledbeat = scale8(beatcos, rangewidth);
      uint8_t result = lowest + scaledbeat;
      return result;
    }
    
    uint8_t mapsin8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) {
      uint8_t beatsin = sin8(theta);
      uint8_t rangewidth = highest - lowest;
      uint8_t scaledbeat = scale8(beatsin, rangewidth);
      uint8_t result = lowest + scaledbeat;
      return result;
    }
    
    uint8_t mapcos8(uint8_t theta, uint8_t lowest = 0, uint8_t highest = 255) {
      uint8_t beatcos = cos8(theta);
      uint8_t rangewidth = highest - lowest;
      uint8_t scaledbeat = scale8(beatcos, rangewidth);
      uint8_t result = lowest + scaledbeat;
      return result;
    }
    
    // Array of temperature readings at each simulation cell
    byte heat[MatrixWidth][MatrixHeight];
    
    uint32_t noise_x;
    uint32_t noise_y;
    uint32_t noise_z;
    uint32_t noise_scale_x;
    uint32_t noise_scale_y;
    
    uint8_t noise[MatrixWidth][MatrixHeight];
    
    uint8_t noisesmoothing;
    
      // Oscillators and Emitters
    
      // the oscillators: linear ramps 0-255
      byte osci[6];
    
      // sin8(osci) swinging between 0 to MatrixWidth - 1
      byte p[6];
    
      // set the speeds (and by that ratios) of the oscillators here
      void MoveOscillators() {
        osci[0] = osci[0] + 5;
        osci[1] = osci[1] + 2;
        osci[2] = osci[2] + 3;
        osci[3] = osci[3] + 4;
        osci[4] = osci[4] + 1;
        if (osci[4] % 2 == 0)
          osci[5] = osci[5] + 1; // .5
        for (int i = 0; i < 4; i++) {
          p[i] = map8(sin8(osci[i]), 0, MatrixWidth - 1); //why? to keep the result in the range of 0-MatrixWidth (matrix size)
        }
      }
    
    
    
      // scale the brightness of the screenbuffer down
      void DimAll(byte value)
      {
        for (int i = 0; i < NUM_LEDS; i++)
        {
          leds[i].nscale8(value);
        }
      }
    
      // give it a linear tail to the right
      void StreamRight(byte scale, int fromX = 0, int toX = MatrixWidth, int fromY = 0, int toY = MatrixHeight)
      {
        for (int x = fromX + 1; x < toX; x++) {
          for (int y = fromY; y < toY; y++) {
            leds[XY(x, y)] += leds[XY(x - 1, y)];
            leds[XY(x, y)].nscale8(scale);
          }
        }
        for (int y = fromY; y < toY; y++)
          leds[XY(0, y)].nscale8(scale);
      }
    
      // give it a linear tail to the left
      void StreamLeft(byte scale, int fromX = MatrixWidth, int toX = 0, int fromY = 0, int toY = MatrixHeight)
      {
        for (int x = toX; x < fromX; x++) {
          for (int y = fromY; y < toY; y++) {
            leds[XY(x, y)] += leds[XY(x + 1, y)];
            leds[XY(x, y)].nscale8(scale);
          }
        }
        for (int y = fromY; y < toY; y++)
          leds[XY(0, y)].nscale8(scale);
      }
    
      // give it a linear tail downwards
      void StreamDown(byte scale)
      {
        for (int x = 0; x < MatrixWidth; x++) {
          for (int y = 1; y < MatrixHeight; y++) {
            leds[XY(x, y)] += leds[XY(x, y - 1)];
            leds[XY(x, y)].nscale8(scale);
          }
        }
        for (int x = 0; x < MatrixWidth; x++)
          leds[XY(x, 0)].nscale8(scale);
      }
    
      // give it a linear tail upwards
      void StreamUp(byte scale)
      {
        for (int x = 0; x < MatrixWidth; x++) {
          for (int y = MatrixHeight - 2; y >= 0; y--) {
            leds[XY(x, y)] += leds[XY(x, y + 1)];
            leds[XY(x, y)].nscale8(scale);
          }
        }
        for (int x = 0; x < MatrixWidth; x++)
          leds[XY(x, MatrixHeight - 1)].nscale8(scale);
      }
    
      // give it a linear tail up and to the left
      void StreamUpAndLeft(byte scale)
      {
        for (int x = 0; x < MatrixWidth - 1; x++) {
          for (int y = MatrixHeight - 2; y >= 0; y--) {
            leds[XY(x, y)] += leds[XY(x + 1, y + 1)];
            leds[XY(x, y)].nscale8(scale);
          }
        }
        for (int x = 0; x < MatrixWidth; x++)
          leds[XY(x, MatrixHeight - 1)].nscale8(scale);
        for (int y = 0; y < MatrixHeight; y++)
          leds[XY(MatrixWidth - 1, y)].nscale8(scale);
      }
    
      // give it a linear tail up and to the right
      void StreamUpAndRight(byte scale)
      {
        for (int x = 0; x < MatrixWidth - 1; x++) {
          for (int y = MatrixHeight - 2; y >= 0; y--) {
            leds[XY(x + 1, y)] += leds[XY(x, y + 1)];
            leds[XY(x, y)].nscale8(scale);
          }
        }
        // fade the bottom row
        for (int x = 0; x < MatrixWidth; x++)
          leds[XY(x, MatrixHeight - 1)].nscale8(scale);
    
        // fade the right column
        for (int y = 0; y < MatrixHeight; y++)
          leds[XY(MatrixWidth - 1, y)].nscale8(scale);
      }
    
      // just move everything one line down
      void MoveDown() {
        for (int y = MatrixHeight - 1; y > 0; y--) {
          for (int x = 0; x < MatrixWidth; x++) {
            leds[XY(x, y)] = leds[XY(x, y - 1)];
          }
        }
      }
    
      // just move everything one line down
      void VerticalMoveFrom(int start, int end) {
        for (int y = end; y > start; y--) {
          for (int x = 0; x < MatrixWidth; x++) {
            leds[XY(x, y)] = leds[XY(x, y - 1)];
          }
        }
      }
    
    
      void BresenhamLine(int x0, int y0, int x1, int y1, CRGB color)
      {
        int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
        int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
        int err = dx + dy, e2;
        for (;;) {
          leds[XY(x0, y0)] += color;
          if (x0 == x1 && y0 == y1) break;
          e2 = 2 * err;
          if (e2 > dy) {
            err += dy;
            x0 += sx;
          }
          if (e2 < dx) {
            err += dx;
            y0 += sy;
          }
        }
      }
    
    
      CRGB HsvToRgb(uint8_t h, uint8_t s, uint8_t v) {
        CHSV hsv = CHSV(h, s, v);
        CRGB rgb;
        hsv2rgb_spectrum(hsv, rgb);
        return rgb;
      }
    
      void NoiseVariablesSetup() {
        noisesmoothing = 200;
    
        noise_x = random16();
        noise_y = random16();
        noise_z = random16();
        noise_scale_x = 6000;
        noise_scale_y = 6000;
      }
    
      void FillNoise() {
        for (uint8_t i = 0; i < MatrixWidth; i++) {
          uint32_t ioffset = noise_scale_x * (i - MATRIX_CENTRE_Y);
    
          for (uint8_t j = 0; j < MatrixHeight; j++) {
            uint32_t joffset = noise_scale_y * (j - MATRIX_CENTRE_Y);
    
      byte data = inoise16(noise_x + ioffset, noise_y + joffset, noise_z) >> 8;
    
            uint8_t olddata = noise[i][j];
            uint8_t newdata = scale8(olddata, noisesmoothing) + scale8(data, 256 - noisesmoothing);
            data = newdata;
    
            noise[i][j] = data;
          }
        }
      }
    
      void MoveX(byte delta) {
        for (int y = 0; y < MatrixHeight; y++) {
          for (int x = 0; x < MatrixWidth - delta; x++) {
            leds2[XY(x, y)] = leds[XY(x + delta, y)];
          }
          for (int x = MatrixWidth - delta; x < MatrixWidth; x++) {
            leds2[XY(x, y)] = leds[XY(x + delta - MatrixWidth, y)];
          }
        }
    
        // write back to leds
        for (uint8_t y = 0; y < MatrixHeight; y++) {
          for (uint8_t x = 0; x < MatrixWidth; x++) {
            leds[XY(x, y)] = leds2[XY(x, y)];
          }
        }
      }
    
      void MoveY(byte delta) {
        for (int x = 0; x < MatrixWidth; x++) {
          for (int y = 0; y < MatrixHeight - delta; y++) {
            leds2[XY(x, y)] = leds[XY(x, y + delta)];
          }
          for (int y = MatrixHeight - delta; y < MatrixHeight; y++) {
            leds2[XY(x, y)] = leds[XY(x, y + delta - MatrixHeight)];
          }
        }
    
        // write back to leds
        for (uint8_t y = 0; y < MatrixHeight; y++) {
          for (uint8_t x = 0; x < MatrixWidth; x++) {
            leds[XY(x, y)] = leds2[XY(x, y)];
          }
        }
      }
    
      void MoveFractionalNoiseX(byte amt = 16) {
        // move delta pixelwise
        for (int y = 0; y < MatrixHeight; y++) {
          uint16_t amount = noise[0][y] * amt;
          byte delta = 31 - (amount / 256);
    
          for (int x = 0; x < MatrixWidth - delta; x++) {
            leds2[XY(x, y)] = leds[XY(x + delta, y)];
          }
          for (int x = MatrixWidth - delta; x < MatrixWidth; x++) {
            leds2[XY(x, y)] = leds[XY(x + delta - MatrixWidth, y)];
          }
        }
    
        //move fractions
        CRGB PixelA;
        CRGB PixelB;
    
        for (uint8_t y = 0; y < MatrixHeight; y++) {
          uint16_t amount = noise[0][y] * amt;
          byte delta = 31 - (amount / 256);
          byte fractions = amount - (delta * 256);
    
          for (uint8_t x = 1; x < MatrixWidth; x++) {
            PixelA = leds2[XY(x, y)];
            PixelB = leds2[XY(x - 1, y)];
    
            PixelA %= 255 - fractions;
            PixelB %= fractions;
    
            leds[XY(x, y)] = PixelA + PixelB;
          }
    
          PixelA = leds2[XY(0, y)];
          PixelB = leds2[XY(MatrixWidth - 1, y)];
    
          PixelA %= 255 - fractions;
          PixelB %= fractions;
    
          leds[XY(0, y)] = PixelA + PixelB;
        }
      }
    
      void MoveFractionalNoiseY(byte amt = 16) {
        // move delta pixelwise
        for (int x = 0; x < MatrixWidth; x++) {
          uint16_t amount = noise[x][0] * amt;
          byte delta = 31 - (amount / 256);
    
          for (int y = 0; y < MatrixWidth - delta; y++) {
            leds2[XY(x, y)] = leds[XY(x, y + delta)];
          }
          for (int y = MatrixWidth - delta; y < MatrixWidth; y++) {
            leds2[XY(x, y)] = leds[XY(x, y + delta - MatrixWidth)];
          }
        }
    
        //move fractions
        CRGB PixelA;
        CRGB PixelB;
    
        for (uint8_t x = 0; x < MatrixHeight; x++) {
          uint16_t amount = noise[x][0] * amt;
          byte delta = 31 - (amount / 256);
          byte fractions = amount - (delta * 256);
    
          for (uint8_t y = 1; y < MatrixWidth; y++) {
            PixelA = leds2[XY(x, y)];
            PixelB = leds2[XY(x, y - 1)];
    
            PixelA %= 255 - fractions;
            PixelB %= fractions;
    
            leds[XY(x, y)] = PixelA + PixelB;
          }
    
          PixelA = leds2[XY(x, 0)];
          PixelB = leds2[XY(x, MatrixWidth - 1)];
    
          PixelA %= 255 - fractions;
          PixelB %= fractions;
    
          leds[XY(x, 0)] = PixelA + PixelB;
        }
      }
    
      void standardNoiseSmearing() {
        noise_x += 1000;
        noise_y += 1000;
        noise_scale_x = 4000;
        noise_scale_y = 4000;
        FillNoise();
    
        MoveX(3);
        MoveFractionalNoiseY(4);
    
        MoveY(3);
        MoveFractionalNoiseX(4);
      }
    
    #endif

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    Now missing Fire.h.

    Are you going to make me keep trying and asking for the missing files one-by-one? Any chance you could just put all the files into a single ZIP file and attach it here (click "Go Advanced" to get to the message posting where you can attach a zip file).

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    Or better yet, if there really is a compatibility problem between FastLED and Teensy Audio, is there any chance you could create a small program in just a single file which reproduces the problem?

    Yeah, I know that requires some extra work. Either way, I do want to help you and I absolutely want to get to the bottom of any library conflicts. But you really could make this a little easier and less time consuming with a small, single-file example. That'd let me focus more time on help you and others too.

  11. #11
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    I apologize for the files missing, I thought the pertinent files are enough. The other files are "just" different effects.

    I did a little bit more development on the project and the volume on the audio card selects the effects. The one that shows the problem is all the dialed down (volume at or near 0)

    this one should compile, it is the whole folder as you requested, I will also work on on a single file and attach that in another post. I hope I can get this done today. But here is the whole project for now.

    Edit: The problem is visible when the data and clock pins are changed to 7 and 14 (alternative SPI PINS) Where they are right now the problem does not show, but now the CPU is bit-banging the leds

    Edit2: output is to a 10x10 APA102 Matrix
    Attached Files Attached Files
    Last edited by apleschu; 02-25-2016 at 06:27 PM.

  12. #12
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    As requested ... here is one file that shows the problem. Look for the definitions of CLOCK_PIN and DATA_PIN. if you change it to 7/14 you will see the problem in the FFT data as well as on the display (10x10 matrix), or on 0 and 1 no problem.

    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #include <FastLED.h>
    
    #define BRIGHTNESS  32
    #define NoiseFloor  0.05
    #define TargetAVG   3.0               // Target avg for AGC
    #define peakTargetAVG 0.4
    #define GainAdjust  0.0001            // AGC uses this value to increase or decrease gain each loop, bigger values make AGC react faster
    #define MAXGAIN     2.0              // AGC will not set the mixer gain higher than this
    #define MINGAIN     0.01              // AGC will not set mixer gain lower than this
    #define LogCurve    3        
    #define MatrixHeight 10
    #define MatrixWidth 10
    
    //#define DATA_PIN  1
    //#define CLOCK_PIN 0
    #define DATA_PIN 7
    #define CLOCK_PIN 14
    #define COLOR_ORDER BGR
    #define CHIPSET     APA102
    #define UpdateFrequencyMHZ  1
    
    #define MATRIX_CENTRE_Y 5
    #define MATRIX_CENTRE_X 5
    
    const bool  MatrixSerpentineLayout = true;
    
    #define NUM_LEDS (MatrixWidth * MatrixHeight)
    CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
    CRGB leds2_plus_safety_pixel[ NUM_LEDS + 1];
    CRGB* const leds( leds_plus_safety_pixel + 1);
    CRGB* const leds2( leds_plus_safety_pixel + 1);
    
    float mgain1 = 1.0;
    float mgain2 = 1.0;
    
    
    // GUItool: begin automatically generated code
    AudioInputI2S            i2s1;           //xy=115,244
    AudioMixer4              mixer;          //xy=400,248
    AudioAnalyzeFFT1024      fft;            //xy=649,152
    AudioAnalyzePeak         peak;           //xy=653,380
    AudioConnection          patchCord1(i2s1, 0, mixer, 0);
    AudioConnection          patchCord2(mixer, fft);
    AudioConnection          patchCord3(mixer, peak);
    AudioControlSGTL5000     sgtl5000;       //xy=335,609
    // GUItool: end automatically generated code
    
    
    float cVal(int start, int end){
      double val = 0;                         // starting value
      double res = 0;
    
      val = fft.read(start,end);          // add 1 so that we get to the correct part of the log2 curve
      if ( val > NoiseFloor ) {
        res = ((log10(val) + 2) / 2);   // 0(Noisefloor) is at a value of approx 0.3
        return(res);
      } else {
        return((float)0.0);
      }
    }
    
    // This function will return the right 'led index number' for 
    // a given set of X and Y coordinates on your matrix.  
    // IT DOES NOT CHECK THE COORDINATE BOUNDARIES.  
    // That's up to you.  Don't pass it bogus values.
    //
    uint16_t XY( uint8_t x, uint8_t y)
    {
      uint16_t i;
      
        if( y & 0x01) {
          // Odd rows run backwards
          uint8_t reverseX = (MatrixWidth - 1) - x;
          i = (y * MatrixWidth) + reverseX;
        } else {
          // Even rows run forwards
          i = (y * MatrixWidth) + x;
        }
     
      return i;
    }
    
    uint16_t xySave( uint8_t x, uint8_t y)
    {
      if( x >= MatrixWidth) return -1;
      if( y >= MatrixHeight) return -1;
      return XY(x,y);
    }
    
    void cLed(int band, int start, int end){
      int displayVal = 0;
      float val = cVal(start,end);
      if (val > 1) val = 1;
      val = val * 100;                  // bring into usable are
      displayVal = map((long) val, 39,100,0, MatrixHeight);  // Number of LEDs  
      for ( int i = 0; i < displayVal; i++) {
        int index = xySave(i, band);
        leds[index] = CHSV(100-i*10, 255, 200);  
      }
    }
    
    void colorLed(int i, int start, int end){
      int displayVal = 0;
      float val = fft.read(start,end); 
      if (val > 1) val = 1;
      displayVal = (int) (val *255);
      leds[i] = CHSV(255 - displayVal, 200, displayVal);
    }
    
    
    
    
    void setup() {
      Serial.begin(9600);
    //  while (!Serial);                    // wait for serial to start
      
      AudioMemory(10);
      sgtl5000.enable();
      sgtl5000.volume(0.5);
      sgtl5000.inputSelect(AUDIO_INPUT_MIC);
      sgtl5000.micGain(40);
      FastLED.addLeds<APA102,DATA_PIN,CLOCK_PIN,BGR,DATA_RATE_MHZ(UpdateFrequencyMHZ)>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
      FastLED.setBrightness( BRIGHTNESS );
      FastLED.setDither(0);
      FastLED.setMaxPowerInVoltsAndMilliamps(5,2000);
      for (int i = 0; i < NUM_LEDS; i++)
        leds[i] = 0x000000;
      FastLED.show();
      fft.windowFunction(AudioWindowBartlett1024);
      mixer.gain(0, mgain1);
    
    }
    
    
    void loop() {
       if (fft.available()) {
        blur2d( leds, MatrixWidth, MatrixHeight, 3);
        fadeToBlackBy(leds,NUM_LEDS, 30);
    
        cLed(0,1,1);      // 43             
        cLed(1,2,3);      // 86
        cLed(2,3,4);      // 172
        cLed(3,5,8);      // 344  
        cLed(4,9,16);     // 688
        cLed(5,17,32);    // 1376
        cLed(6,33,64);    // 2752
        cLed(7,65,128);   // 5504
        cLed(8,129,255);  // 11008
        cLed(9,256,511);  // rest
        
      }
      FastLED.show();
    }
    Last edited by apleschu; 02-25-2016 at 09:51 PM.

  13. #13
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    Which version of FastLED are you using?

    When I compile this, I get:

    Code:
    'class CFastLED' has no member named 'setMaxPowerInVoltsAndMilliamps'
    I have version 3.1.0.

  14. #14
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Same version. I just tested, that command is not needed in the test version. That is more preparation for the real product, when it runs on battery and I will need to limit current draw.

    That said, when I compile it uses, the version I downloaded yesterday from the FastLED.io web site:

    Code:
    multiple libraries were found for "FastLED.h"
     Used: /Users/andy/src/Arduino/libraries/FastLED
     Not used: /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/FastLED
    Since this is one of the libraries that I use in other projects where teensy is not the CPU, I rather have it in a common area.

  15. #15
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    Ok, I commented out that line and the program now compiles.

    I'm about to start actually testing on a Teensy... but every indication is you have a different version of FastLED in /Users/andy/src/Arduino/libraries/FastLED. So if I can't reproduce the problem or find anything wrong, I guess this will be wasted effort and I'll end up redoing it again.

    If you see this soon, maybe you could check which version you really have in /Users/andy/src/Arduino/libraries/FastLED? Maybe post a zip file with the *exact* copy of FastLED you're really using?

  16. #16
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Ask and ya shall receive
    Attached Files Attached Files

  17. #17
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    I'm testing now, with a strip of 144 LEDs. I edited the defines for a 12x12 size, but otherwise the code is the same. I'm using the newer copy of FastLED from #16.

    When I run it with FastLED.setMaxPowerInVoltsAndMilliamps(5,2000), almost nothing seems to happen no matter what I do.

    When I run it without the line, it appears to work. I'm getting very similar results with either pins 0/1 or 7/14. Maybe I'll see if I can shoot a very quick video clip....

  18. #18
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153

  19. #19
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    The only thing I can see that's substantially different is your test has the signals going through a cable. We're both sending the 3.3V outputs from Teensy to the 5V APA102s. Maybe the signals are just barely able to drive such a cable, and the SPI output has slightly less drive capability?

    Can you try doing your test again with relatively short wires, like I did in this video?


    EDIT: as far as hardware differences, I can tell you the normal pinMode and digitalWrite configures the pin in high drive strength mode with slow slew rate limiting enabled. SPI on pin 14 uses fast slew rate and lower drive strength. Maybe the slew rate limited edges and stronger drive, and somewhat slower speed allow pins 0/1 to drive a longer cable than 7/14 can?
    Last edited by PaulStoffregen; 02-27-2016 at 05:02 AM.

  20. #20
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Hi Paul,

    Thank you for the test ... I think I saw the problem in your video also, but it was not as pronounced as on mine, because you were talking and thus it seemed to overriding the fft ...

    Could you run that test again, with little to no noise? I think we both agree that if there is little to no noise around the FFT should not bring back any values... The problem shows best when the surroundings are quiet.

    Now as for the slew rate ... I am not sure. I have never had seen this behavior since I never had a teensy audio board before. The problem on my end also does not show when I am getting the audiosignal from an analogread rather than through the teensy audio shield

  21. #21
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    I did test in a fairly quiet room. When I wasn't talking or moving stuff around on the desk, all the LEDs were off. Hopefully that's visible in the video during the pauses when I wasn't speaking? This footage is right off my camcorder, without any editing, so the sound in the video is what the camcorder's mic heard (after Youtube's re-encoding). There wasn't any extra noise that's been edited out of the video. I could try to repeat this late at night when perhaps it's slightly quieter, but I don't have access to a studio quality room with extremely low noise level. This video is about as quiet as I can reasonably get the background noise.

    I do not understand what more I should do to test. I also disconnected all this stuff and put it away, since I have very limited workbench space... and a lot of work to do on so many things. I'm willing to set it up again and try another test, if you're convinced it'll help, but I also need to clearly understand what I'm supposed to do. Right now, I don't.

    Any chance you could try on your end first with short wires instead of a long cable?
    Last edited by PaulStoffregen; 02-28-2016 at 01:02 AM.

  22. #22
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Quote Originally Posted by PaulStoffregen View Post
    I did test in a fairly quiet room. When I wasn't talking or moving stuff around on the desk, all the LEDs were off. Hopefully that's visible in the video during the pauses when I wasn't speaking? This footage is right off my camcorder, without any editing, so the sound in the video is what the camcorder's mic heard (after Youtube's re-encoding). There wasn't any extra noise that's been edited out of the video. I could try to repeat this late at night when perhaps it's slightly quieter, but I don't have access to a studio quality room with extremely low noise level. This video is about as quiet as I can reasonably get the background noise.

    I do not understand what more I should do to test. I also disconnected all this stuff and put it away, since I have very limited workbench space... and a lot of work to do on so many things. I'm willing to set it up again and try another test, if you're convinced it'll help, but I also need to clearly understand what I'm supposed to do. Right now, I don't.

    Any chance you could try on your end first with short wires instead of a long cable?
    I'll try with shorter wires. Thank you for testing.

  23. #23
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    Any idea if the wire length/type made a difference? Might help to understand what really happened here, in case others run into similar issues.

  24. #24
    Junior Member
    Join Date
    Feb 2016
    Location
    Houston
    Posts
    19
    Quote Originally Posted by PaulStoffregen View Post
    Any idea if the wire length/type made a difference? Might help to understand what really happened here, in case others run into similar issues.
    I apologize for not responding, thank you for pinging.

    I shortened the wires to no more than 4 inches, but the effect is the same. If I use hardware spi on 7,14 I have a lot of noise in the higher bins of the FFT as shown in the beginning. If use software spi on 0,1 I don't have that noise.

    Since I need more than 1 chain anyway and I have restrict the speed, it's not so much as big deal for me, but as you said it could be a problem for somebody else.

  25. #25
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,153
    As a quick followup for anyone who finds this old thread (perhaps from the Youtube video), I'm pretty sure the problem with noise in the higher bins with fast SPI was due to this APA102 problem with fast clock speeds.

    https://www.pjrc.com/why-apa102-leds...ble-at-24-mhz/

    Back in early 2016, nobody really understood this APA102 problem. Everybody believed APA102 had superior performance, partly due to comments Adafruit published about solving software limitations most boards have with WS2812, partly due to a blog article about their faster PWM rate for POV applications.

    Now in 2018, the poor quality of APA102's signal regeneration is well known. Unlike WS2812 where the signal really is regenerated in a manner similar to digital copying, APA102 regenerates the signals similar to analog copying. After each LED, the signal quality gets slightly worse. Basically, it's a copy of a copy of a copy which loses timing margin. At higher clock speeds, those slight errors add up, causing corrupted data after 100 to 200 LEDs when using 24 MHz clock.

    Since early 2016, Daniel changed the default APA102 clock speed to only 12 MHz, which solves this problem for most projects using only a few hundred LEDs or less.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •