0

modified Ampli-Tie Plus LED Pack eyes
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

modified Ampli-Tie Plus LED Pack eyes

by swiftjames on Mon Nov 10, 2014 3:22 am

I'm currently working on a big project that's being broken down into a bunch of smaller projects. And currently I'm having a bit of difficulty with one part in particular.
In this part, the Pro-Trinket 5v is supposed to run a constant animation loop on some 8x8 LED packs, while at the same time monitor a microphone and use its level to drive a NeoPixel Strip as a VU meter.

I've had to move the wires around a bit from how my drawing has them due to some concerns with interference, but this is the basic jist of it:
http://tinyurl.com/kwb4xwn

I have it all wired up and the code pieces work separately, but when combined I'm getting a weird effect....
the strip of LEDs used for the VU meter is refreshing veeeeeeery slowly and seems to be based entirely on the cycle of the animation for the 8x8 LED packs.
As such, the VU meter hardly responds at all.
http://tinyurl.com/qcqfhwq

Code: Select all | TOGGLE FULL SIZE
/* LED "Color Organ" for Adafruit Trinket and NeoPixel LEDs.

Hardware requirements:
 - Adafruit Trinket or Gemma mini microcontroller (ATTiny85).
 - Adafruit Electret Microphone Amplifier (ID: 1063)
 - Several Neopixels, you can mix and match
   o Adafruit Flora RGB Smart Pixels (ID: 1260)
   o Adafruit NeoPixel Digital LED strip (ID: 1138)
   o Adafruit Neopixel Ring (ID: 1463)

Software requirements:
 - Adafruit NeoPixel library

Connections:
 - 5 V to mic amp +
 - GND to mic amp -
 - Analog pinto microphone output (configurable below)
 - Digital pin to LED data input (configurable below)

Written by Adafruit Industries.  Distributed under the BSD license.
This paragraph must be included in any redistribution.
*/
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

//define for LED pack info
Adafruit_8x8matrix matrixleft = Adafruit_8x8matrix();
Adafruit_8x8matrix matrixright = Adafruit_8x8matrix();

//define for headfin
#define N_PIXELS  10  // Number of pixels you are using
#define MIC_PIN    A0  // Microphone is attached to Trinket GPIO #2/Gemma D2 (A1)
#define LED_PIN    4  // NeoPixel LED strand is connected to GPIO #0 / D0
#define DC_OFFSET  0  // DC offset in mic signal - if unusure, leave 0
#define NOISE     200  // Noise/hum/interference in mic signal
#define SAMPLES   70  // Length of buffer for dynamic level adjustment
#define TOP       (N_PIXELS +1) // Allow dot to go slightly off scale
// Comment out the next line if you do not want brightness control or have a Gemma
//#define POT_PIN    3  // if defined, a potentiometer is on GPIO #3 (A3, Trinket only)

byte
  peak      = 0,      // Used for falling dot
  dotCount  = 0,      // Frame counter for delaying dot-falling speed
  volCount  = 0;      // Frame counter for storing past volume data
 
int
  vol[SAMPLES],       // Collection of prior volume samples
  lvl       = 30,     // Current "dampened" audio level
  minLvlAvg = 0,      // For dynamic adjustment of graph low & high
  maxLvlAvg = 512;

Adafruit_NeoPixel  strip = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  memset(vol, 0, sizeof(vol));
  strip.begin();
 
    Serial.begin(9600);
  Serial.println("8x8 LED Matrix Test");
 
  matrixleft.begin(0x70);  // pass in the address
  matrixright.begin(0x71);
 
}


static const uint8_t PROGMEM
  lefteye_img[] =
 { B00000011,
   B00000111,
   B00011111,
   B01011111,
   B11011111,
   B11011111,
   B11111100,
   B11100000 },

  leftblink1[] =
 { B00000000,
   B00000001,
   B00000111,
   B00011111,
   B11011111,
   B11011111,
   B11111100,
   B11100000 },

  leftblink2[] =
 { B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000011,
   B11011111,
   B11111100,
   B11100000 },

  leftblink3[] =
 { B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000001,
   B00111100,
   B11100000 },

  leftblink4[] =
 { B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000 },

   righteye_img[] =
 { B11000000,
   B11100000,
   B11111000,
   B11111010,
   B11111011,
   B11111011,
   B00111111,
   B00000111 },

  rightblink1[] =
 { B00000000,
   B10000000,
   B11100000,
   B11111000,
   B11111011,
   B11111011,
   B00111111,
   B00000111 },

  rightblink2[] =
 { B00000000,
   B00000000,
   B00000000,
   B00000000,
   B11000000,
   B11111011,
   B00111111,
   B00000111 },

  rightblink3[] =
 { B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B10000000,
   B00111100,
   B00000111 },

  rightblink4[] =
 { B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000,
   B00000000 };

void loop() {
  uint8_t  i;
  uint16_t minLvl, maxLvl;
  int      n, height;
  n   = analogRead(MIC_PIN);                 // Raw reading from mic
  n   = abs(n - 512 - DC_OFFSET);            // Center on zero
  n   = (n <= NOISE) ? 0 : (n - NOISE);      // Remove noise/hum
  lvl = ((lvl * 7) + n) >> 3;    // "Dampened" reading (else looks twitchy)
 
  // Calculate bar height based on dynamic min/max levels (fixed point):
  height = 1.0 * TOP * (lvl - minLvlAvg) / (long)(maxLvlAvg - minLvlAvg);

  if(height < 0L)       height = 0;      // Clip output
  else if(height > TOP) height = TOP;
  if(height > peak)     peak   = height; // Keep 'peak' dot at top

// if POT_PIN is defined, we have a potentiometer on GPIO #3 on a Trinket
//    (Gemma doesn't have this pin)
  uint8_t bright = 100;   
//#ifdef POT_PIN           
//   bright = analogRead(POT_PIN);  // Read pin (0-255) (adjust potentiometer
                                  //   to give 0 to Vcc volts
//#endif
//  strip.setBrightness(bright);    // Set LED brightness (if POT_PIN at top
                                  //  define commented out, will be full)
  // Color pixels based on rainbow gradient
  for(i=0; i<N_PIXELS; i++) { 
    if(i >= height)               
       strip.setPixelColor(i,   0,   0, 0);
    else
       //strip.setPixelColor(i,Wheel(map(i,0,strip.numPixels()-1,30,150)));
       strip.setPixelColor(i, 5, 250, 200); // sets the color to a nice sharp blue rather than rainbow.

    }

   strip.show(); // Update strip

  vol[volCount] = n;                      // Save sample for dynamic leveling
  if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter

  // Get volume range of prior frames
  minLvl = maxLvl = vol[0];
  for(i=1; i<SAMPLES; i++) {
    if(vol[i] < minLvl)      minLvl = vol[i];
    else if(vol[i] > maxLvl) maxLvl = vol[i];
  }
  // minLvl and maxLvl indicate the volume range over prior frames, used
  // for vertically scaling the output graph (so it looks interesting
  // regardless of volume level).  If they're too close together though
  // (e.g. at very low volume levels) the graph becomes super coarse
  // and 'jumpy'...so keep some minimum distance between them (this
  // also lets the graph go to zero when no sound is playing):
  if((maxLvl - minLvl) < TOP) maxLvl = minLvl + TOP;
  minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
  maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
 
 
 
  //eyes test start

//Eyes Open
matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, lefteye_img, 8, 8, LED_ON);
  matrixleft.writeDisplay();
    matrixright.clear();
  matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, righteye_img, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(5000);
 
//Eyes Blink 
matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, leftblink1, 8, 8, LED_ON);
  matrixleft.writeDisplay();
  matrixright.clear();
  matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, rightblink1, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(25); 
 
matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, leftblink2, 8, 8, LED_ON);
  matrixleft.writeDisplay();
  matrixright.clear();
matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, rightblink2, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(25);

matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, leftblink3, 8, 8, LED_ON);
  matrixleft.writeDisplay();
  matrixright.clear();
matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, rightblink3, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(25);
 
matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, leftblink4, 8, 8, LED_ON);
  matrixleft.writeDisplay();
  matrixright.clear();
matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, rightblink4, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(25); 
 
matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, leftblink3, 8, 8, LED_ON);
  matrixleft.writeDisplay();
  matrixright.clear();
matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, rightblink3, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(25); 
 
matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, leftblink2, 8, 8, LED_ON);
  matrixleft.writeDisplay();
  matrixright.clear();
matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, rightblink2, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(25);

matrixleft.clear();
matrixleft.setRotation(3);
  matrixleft.drawBitmap(0, 0, leftblink1, 8, 8, LED_ON);
  matrixleft.writeDisplay();
  matrixright.clear();
matrixright.setRotation(3);
  matrixright.drawBitmap(0, 0, rightblink1, 8, 8, LED_ON);
  matrixright.writeDisplay();
  delay(25); 
 
// eyes test end
 

  matrixleft.setRotation(0);
  matrixright.setRotation(0);
}

// Input a value 0 to 255 to get a color value.
// The colors are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}


AND on a slightly separate note, the VU meter goes nuts with noise when it's just hooked up on its own with the mic, I was following this guide here:
https://learn.adafruit.com/trinket-soun ... n?view=all
which didn't make use of 3.3v for the Microphone, but I'm thinking I might need to, and if that's the case, how do I get a 3.3v reference that'll satisfy this little snippet of code right there:
Code: Select all | TOGGLE FULL SIZE
 // This is only needed on 5V Arduinos (Uno, Leonardo, etc.).
// Connect 3.3V to mic AND TO AREF ON ARDUINO and enable this
// line. Audio samples are 'cleaner' at 3.3V.
// COMMENT OUT THIS LINE FOR 3.3V ARDUINOS (FLORA, ETC.):
// analogReference(EXTERNAL);


would really love some help on these, please. :)

swiftjames
 
Posts: 19
Joined: Sat Aug 30, 2014 5:44 pm

Re: modified Ampli-Tie Plus LED Pack eyes

by adafruit_support_bill on Mon Nov 10, 2014 7:06 am

The problem is that the eye code uses delay() for timing. Making it work in parallel with other code requires some re-structuring. Here is the first of a series of tutorials on the subject: https://learn.adafruit.com/multi-taskin ... 1/overview

adafruit_support_bill
 
Posts: 74659
Joined: Sat Feb 07, 2009 10:11 am

Re: modified Ampli-Tie Plus LED Pack eyes

by swiftjames on Mon Nov 10, 2014 1:48 pm

Excellent, thank you Bill!
That guide helps a lot and I'm already working to restructure the code for the blink animation on the 8x8 matrices.
I'd still like to know if I am going to need to reference a 3.3volt for the Mic on the VU meter though. I've been trying to find ways to eliminate as much noise as possible, but I think it's possibly going to come down to having a 3.3volt reference. How can I get that for my 5volt Pro-Trinket, any ideas?
I thought about using a Line-Level shifter from 5v>3.3volts like this one:
https://www.adafruit.com/products/1875

I might be able to pull the 3volts as reference from a neighboring Arduino Uno that I'm using at the same time in this project that runs the Voice changer.
I was originally going to have the Uno output its volume level for the Pro-Trinket to just monitor a serial line, but I'm having such a hard time finding any code snippets for just simply sending the volume level to the TX pin on the Uno. I feel like I may be missing something obvious with it. Any suggestions on this might be great as well.
Thanks all in advance!

swiftjames
 
Posts: 19
Joined: Sat Aug 30, 2014 5:44 pm

Re: modified Ampli-Tie Plus LED Pack eyes

by adafruit_support_bill on Mon Nov 10, 2014 2:26 pm

How about using one of our new precision voltage reference breakouts: https://www.adafruit.com/product/2200

adafruit_support_bill
 
Posts: 74659
Joined: Sat Feb 07, 2009 10:11 am

Re: modified Ampli-Tie Plus LED Pack eyes

by swiftjames on Mon Nov 10, 2014 2:59 pm

Bingo! That looks like just what I need! Thank you again. :)
I'm going to order one of those regulators and work on restructuring the code for the eye-blink animation to see if I can make it play nicely with the VU meter portion.
Hopefully this will all even out in the end and the line won't be full of so much noise either.
If it is, I might be back to see what else could be done to reduce noise.

swiftjames
 
Posts: 19
Joined: Sat Aug 30, 2014 5:44 pm

Re: modified Ampli-Tie Plus LED Pack eyes

by swiftjames on Fri Nov 14, 2014 10:10 am

Really appreciate all the help, Bill!
Thank you. I've managed to learn some things about using millis() instead of that crippling Delay(), so It's successfully running on my Arduino Uno with both the VU meter and the Animated Blinking eyes.

http://youtu.be/KdHEkTSaCFs

Just thought I should come back and show off a little of how your help allowed me to succeed on this!
I'm just waiting on the 3volt reference board to be able to move this whole project over to my Pro-Trinket and then install all this into the costume head. :)

swiftjames
 
Posts: 19
Joined: Sat Aug 30, 2014 5:44 pm

Re: modified Ampli-Tie Plus LED Pack eyes

by adafruit_support_bill on Fri Nov 14, 2014 10:23 am

Looking good! Thanks for the follow-up post.

adafruit_support_bill
 
Posts: 74659
Joined: Sat Feb 07, 2009 10:11 am

Re: modified Ampli-Tie Plus LED Pack eyes

by swiftjames on Wed Nov 19, 2014 12:14 pm

Okay, the whole project is working quite well together now on the Arduio, I'm ready to move it over to the Pro Trinket...
However I'm having some confusion about where the VCC for the mic needs to come from once I've given the Pro Trinket the reference voltage from the LM4040 board.
I've attached a quick diagram of what I understand of this external reference voltage board and how it should hook up. but I'm unclear where the new referenced voltage comes from for the devices that need to use it.

ref_voltage1.PNG
ref_voltage1.PNG (620.6 KiB) Viewed 864 times


In this case, i have:
................................5V -->VIN on the LM4040
............................GND --> GND on LM4040 and GND on Mic
..2.048 on LM4040 --> Aref pin on Pro Trinket
..............OUT on mic -->A0 on Pro trinket
..............VCC on mic --> ?
I don't know where the new 2.048 volts should be coming from for the VCC on the Mic.

I'm just not finding any solid documentation when I search for how the LM4040 alters things for the Pro Trinket.
Thank you in advance for the assist!

swiftjames
 
Posts: 19
Joined: Sat Aug 30, 2014 5:44 pm

Re: modified Ampli-Tie Plus LED Pack eyes

by adafruit_support_bill on Wed Nov 19, 2014 1:11 pm

The microphone amplifier OUT pin will put out a signal between 0 (GND) and VCC.
The Pro Trinket analog pin will measure voltages ranging from 0(GND) to AREF.
So you need to figure out how to get the microphone output to be within the range of your reference voltage.

The LM4040 is a precision reference voltage only. It is not suitable for use as a power source. You could use a voltage divider to convert the 0-5v from the Mic into 0-2v. A simple way to do this is to start with 5x 1K resistors in series (5K ohms total). Connect one end to GND and the other end to OUT. Counting up from the GND connection, connect a wire from the junction between the 2nd and 3rd resistor to your analog input. That will scale your 0-5v output to 0-2v.

adafruit_support_bill
 
Posts: 74659
Joined: Sat Feb 07, 2009 10:11 am

Re: modified Ampli-Tie Plus LED Pack eyes

by swiftjames on Thu Nov 20, 2014 1:43 pm

okay, so it sounds like I need to modify the voltage coming out of the Mic, but it'll still be receiving 5volts off the 5V line.
I've included another picture, hopefully depicting what you described for cutting the voltage from 5v down to the 2.048
ref_voltage2.PNG
ref_voltage2.PNG (649.5 KiB) Viewed 849 times


This also begs another question as this project also has two 8x8LED packs (https://www.adafruit.com/products/1853) that currently use A4 and A5 for the clock and data. I had simplified the drawing to not include these to avoid clutter for just asking the question about the mic and the reference board.

But if I also have the two LED panels on the analog pins (A4, and A5) will this also be listening for just 2.048 volts instead of 5?
I'm wanting to make sure that the MIC is getting and using the lower voltage, but not the LED packs.

swiftjames
 
Posts: 19
Joined: Sat Aug 30, 2014 5:44 pm

Re: modified Ampli-Tie Plus LED Pack eyes

by adafruit_support_bill on Thu Nov 20, 2014 1:50 pm

I've included another picture, hopefully depicting what you described for cutting the voltage from 5v down to the 2.048

Close - but the A0 wire should connect to the resistor ladder only. Not to the direct output of the mic amplifier. Each step of the resistor ladder drops the signal voltage by 1/5. By connecting at the second rung from the ground, the signal range is 0-2v instead of 0-5v.

I also have the two LED panels on the analog pins (A4, and A5) will this also be listening for just 2.048 volts instead of 5?

No. These are being used in digital i/o mode, so they are not affected by the external AREF.

adafruit_support_bill
 
Posts: 74659
Joined: Sat Feb 07, 2009 10:11 am

Re: modified Ampli-Tie Plus LED Pack eyes

by swiftjames on Thu Nov 20, 2014 5:54 pm

Excellent, I'll check tonight to make sure I have those resisters! :)
So if I have all of this understood correctly, then my new project layout looks like the following (sorry for crudeness, only have a mouse for drawing connecting lines)

Thanks again for the assist, Bill! Much appreciated! :)

Digita_Eyes-Sound_Reactive_Headfin.PNG
Digita_Eyes-Sound_Reactive_Headfin.PNG (942.62 KiB) Viewed 834 times

swiftjames
 
Posts: 19
Joined: Sat Aug 30, 2014 5:44 pm

Re: modified Ampli-Tie Plus LED Pack eyes

by adafruit_support_bill on Thu Nov 20, 2014 6:30 pm

That all looks good!

adafruit_support_bill
 
Posts: 74659
Joined: Sat Feb 07, 2009 10:11 am

Re: modified Ampli-Tie Plus LED Pack eyes

by pburgess on Mon Nov 24, 2014 6:19 pm

Hm. I think there's some confusion going on about references voltages...this seems to be getting needlessly complex and not particularly efficient...

The Uno version of the voice changer powers the mic from a 3.3V regulator that's present on the Uno (but not Pro Trinket); the resulting mic output voltage will therefore be from 0.0 to 3.3 Volts. The same 3.3V is also fed to the AREF pin (used as a max point of reference in analog-to-digital conversions), so that analogRead() (or equivalent register-reading operations in the voice changer code) output 0 to 1023 for the 0.0 to 3.3V input. (By default the analog reference is the same as the Uno's supply voltage, i.e. 5V, so a 3.3V mic reading would only be about 0 to 675, don't want that.)

ANYWAY, I think the simplest and Most Correct way to handle this would be approximate the 3.3V regulator part of the Uno circuit. This requires just a voltage regulator like this one and two capacitors (2.2 uF, though a little more is fine). Center pin on the regulator is ground, so the two caps sort of flank it, with their - leads both going to ground, + on one on the 5V input, + on the other on the 3.3V output. The 3.3V output is then split to the mic and the AREF pin.

pburgess
 
Posts: 4038
Joined: Sun Oct 26, 2008 2:29 am

Re: modified Ampli-Tie Plus LED Pack eyes

by pburgess on Mon Nov 24, 2014 6:30 pm

Oh! Or -- since you already have an Uno in the circuit doing the voice changer -- I think you should take another look at having the boards communicate, and drop the voltage regulator/reference complexity with the second board.

If you look in the adavoice_face.pde code, there's a variable called 'oldsum' being tossed around. It gets passed to the drawMouth() function around line 325-ish...this is the average amplitude of the last batch of audio samples (like 10 milliseconds or something). Then there's some changes we could make with regards to Serial stuff in that sketch to get the two boards talking.

pburgess
 
Posts: 4038
Joined: Sun Oct 26, 2008 2:29 am

Please be positive and constructive with your questions and comments.