Breaking News
View Comments: Threaded | Newest First | Oldest First
DrMark0
User Rank
Rookie
An object, not a function
DrMark0   4/22/2014 6:42:41 PM
NO RATINGS
Hi Max,

In C (and in C++) it is important to always keep straight the difference between an object and a pointer to an object.  Consider the following code:

Adafruit_NeoPixel strip = Adafruit_NeoPixel(16,1); /* creates an OBJECT */
Adafruit_NeoPixel* strip_pointer = &strip; /* creates a POINTER to the object */

Now, you need to decide if you want to have an array of OBJECTS or an array of POINTERS to objects.  Let's assume you want to have an array of OBJECTS:

Adafruit_NeoPixel strip[16];

We need to initialize the objects by calling Adafruit_NeoPixel():

for (int i=0; i < 16; i++) {
    strip[i] = Adafruit_NeoPixel(16, i);
}

Now, you can define your lightStrip() function to be passed a POINTER to the strip you want it to light:

void lightStrip(Adafruit_NeoPixel* strip, int value) {
    strip->setPixelColir(value, R, G, B); /* use -> not . because strip is a POINTER */
    strip->show();
}

You would call lightStrip() using the & operator to turn your strip OBJECT into a POINTER so that you can pass it to lightStrip():

for (int i=0; i < 16; i++) {
    light_strip(&(strip[i]), value);
}

Because I don't have access to the Adafruit library, I can't compile the above code, so there might be a typo in there, but hopefully it will give you the hint you need to get going on this problem.

Good Luck!

--Mark

JVISOSKY000
User Rank
Rookie
Re: An object, not a function
JVISOSKY000   4/23/2014 12:21:42 AM
NO RATINGS
Mark,

In your code, the line:

    strip[i] = Adafruit_NeoPixel(16, i);

is making use of an implicitly defined assignment operator, which I believe will only do a shallow copy.  (There is a temporary Adafruit_NeoPixel created on the stack, which is then copied into the Adafruit_NeoPixel at strip[i].)

I'm assuming that the Adafruit_NeoPixel is the one defined here:

https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.h

which may have problems with shallow copies because the class includes a couple of pointers (like 'pixels').

Better would be to declare the strip array as pointers, and use the 'new' operator:

Adafruit_NeoPixel* strip[16];

for (int i=0; i < 16; i++) {
    strip[i] = new Adafruit_NeoPixel(16, i);
}

Then just use the pointers in the loop:

for (int i=0; i < 16; i++) {
    light_strip(strip[i], value);
}

My C++ may be a little rusty, but I believe the above is correct.

JV



Max The Magnificent
User Rank
Blogger
Re: An object, not a function
Max The Magnificent   4/23/2014 10:32:36 AM
NO RATINGS
@JVISOSKY000: Better would be to declare the strip array as pointers, and use the 'new' operator...

There's a 'new' operator? I really do need to learn more (well, some/any) C++. Having said this, I understand what your code is doing -- I will try this to see what happens when I compile it.

Max The Magnificent
User Rank
Blogger
Re: An object, not a function
Max The Magnificent   4/23/2014 9:55:31 AM
NO RATINGS
@DrMark: Consider the following code...

I can barely wrap by brain around C, let alone C++, but I think I see what you are doing. I will try writing something based on thsi and see if it compiles.

JeffL_2
User Rank
CEO
Here's a few other "pointers"
JeffL_2   4/22/2014 11:20:57 PM
NO RATINGS
Max,

Regarding the general direction of the project, it looks as if you're trying to display the audio frequency spectrum by dividing it into 16 equal bands. Actually that's kind of a bizarre selection, it's typically looked on as 30 or 31 1/3-octave bands, or 10 one-octave bands. If you divide it into 16 bands then I suppose they could be 2/3-octave wide each, of course you CAN do it that way (and digital filters can be created that are just that wide) but it kind of guarantees that the display won't be terribly "relevant" or meaningful (not that it has to be). And I guess this will just be the monophonic combination of left and right? Is the processing just going to send any and all filtered data to the display (more or less "peak-reading") or will there be peak-holding or even sample averaging? (There's a popular type of display that holds and illuminates peaks WHILE the instantaneous values dance beneath them, that actually has some utility as well.) Also I imagine you'll want to make this display logarithmic, with each LED representing 2 or 3 decibels higher level, and maybe even make the lower LEDs represent larger values (so the display comes closer to handling the much larger dynamic range that the ear responds to than just 32 or 48 decibels)? Will there be a provision to "calibrate" this so it can read actual sound levels? How about a "master level" channel to one side to show the unfiltered level? (You ought to think about whether you keep the lowest position always "on" as a kind of visual "anchor", it's commonly done that way anyway.) How is color going to be applied, there's a convention that "acceptable" levels at the bottom are green, levels above that are yellow, even higher are red, will you "go conventional" or do something out of the ordinary? These are all the kind of decisions you ought to think about before taking this to the next stage. (Then again maybe I'm just a LITTLE obsessive about this stuff since I used to design audio gear for sale to pros, back in another lifetime and maybe another universe, I can't really recall right now...)

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 9:59:48 AM
NO RATINGS
@JeffL: Regarding the general direction of the project, it looks as if you're trying to display the audio frequency spectrum by dividing it into 16 equal bands.

First let me remind you that if you go back to the beginning of this project, I did say that I don't really have a clue what I'm doing on the audio side -- I'm learning (or making it up) as I go along.

One of my early questions was whether the frequency spectrum (think horizontal axis) should be divided in a linear (equal bands) or logarithmic manner.

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 10:03:37 AM
NO RATINGS
@JeffL: If you divide it into 16 bands then I suppose they could be 2/3-octave wide each, of course you CAN do it that way (and digital filters can be created that are just that wide) but it kind of guarantees that the display won't be terribly "relevant" or meaningful (not that it has to be).

I'm not so worried about the display being "relevant" as "looking pretty" -- what I really need is for someone who knows what they are talking about to say something like "OK Max, it's obvious you don't have a clue -- let's say the bottom frequency 'bucket' includes 50Hz and below, the top 'bucket' encompases 16KHz and above, and this is the way you should partition the rest of the spectrum into your remaining 14 'buckets'"

JeffL_2
User Rank
CEO
Re: Here's a few other "pointers"
JeffL_2   4/23/2014 10:59:07 AM
NO RATINGS
Here's a link to a fairly small "freebie" analyzer program that has a 1/3-octave mode that you can install on your PC and have a look to get some ideas:

http://download.cnet.com/AudioAnalyser/3000-2170_4-10781338.html

(CAREFUL! If you install from this link don't "agree" to anything EXCEPT the download itself, or you may find yourself installing some rather vicious "adware" you probably DON'T want on your system.)

"Back in the day" these types of programs were called "real-time analyzers" (RTAs) and they were fairly routinely utilized to "set up" the "house" equalizers for studio monitor loudspeakers, movie or stage theater, stadium, church or concert sound applications. The "sound guy" would rig the speakers to output a "pink noise" source, then hook up a microphone on a LONG extension cord and locate it in various areas, you'd use it to "aim the horns" and such as well. I remember when the first (analog-hardware-based) handheld 1/3-octave RTA came out (I don't think the early ones even had a simple display "freeze" mode, let alone memory!), everyone was amazed you could "integrate" that much into a battery-operated small unit - now of course it would hardly be worth mentioning as a smartphone app!

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 1:32:41 PM
NO RATINGS
@JeffL: Here's a link to a fairly small "freebie" analyzer program that has a 1/3-octave mode that you can install on your PC and have a look to get some ideas...

Wonderful -- thanks for sharing this

JeffL_2
User Rank
CEO
Warning, Conduit adware alert!!
JeffL_2   4/23/2014 9:14:20 PM
NO RATINGS
Max,

I just noticed something kind of horrifying. After I installed the program I linked you (which is everything I said it was), I tried doing a Google search and discovered that the "Conduit" search engine hijacker had been installed on my machine (even though I had in fact agreed to NOTHING other than the download itself)! Now "Conduit" itself is sort of nasty but it is after all just a kind of adware, so I did a search on the removal process and was able to get rid of it in a few short steps, and the instructions that I found online (the ones that invoke adwcleaner) worked rather well and I believe they removed the problem completely. What I wanted to say first is that this download site is owned by Cnet which I understand is itself owned by the CBS network, and it is the very height of corporate irresponsibility AND GREED that they feel they can maintain this site as a paid mechanism for infecting other PCs with unwelcome adware as a means of monetizing the website, and I think a wholesale boycott of CBS products would not be out of the question. It's probably also possible to download the program directly fron the developer's website, I haven't looked for it yet but if I find it I'll leave that as the download link. Anyway I feel just TERRIBLE about the distress that I may have caused some of you, and I wanted to get this warning out as soon as possible, thanks to all of you for your patience and understanding!

JeffL

Max The Magnificent
User Rank
Blogger
Re: Warning, Conduit adware alert!!
Max The Magnificent   4/24/2014 9:53:52 AM
NO RATINGS
@JeffL: ...Anyway I feel just TERRIBLE about the distress that I may have caused some of you...

No worries on my part -- I hadn't got around to doing anything yet (struggling to keep my nose above the waterline) -- thanks for alerting us to the problem.

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 10:09:21 AM
NO RATINGS
@JeffL: I guess this will just be the monophonic combination of left and right?

I'm intending to drive this from my iPad. I plan on feeding the stereo signal in. I plan on having several modes. One will be mono (I was thinking of sampling both channels, adding them together, and dividing by two) -- in which case the entire horizontal axis could be used to display the spectrum data from this mono channel.

I would also like to play with stereo displays. One way would be to split the horizontal axis into two 8-channel bands. Another way would be to keep the 16 bands, but display the left channel "growing up from the bottom" (to a max of 8 pixels tall) and the right channel "growing down from the top)" (to a max of 8 pixels).

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 10:19:40 AM
NO RATINGS
@JeffL: Is the processing just going to send any and all filtered data to the display (more or less "peak-reading") or will there be peak-holding or even sample averaging? (There's a popular type of display that holds and illuminates peaks WHILE the instantaneous values dance beneath them, that actually has some utility as well.)

I was planning with the "any and all" approach to start off with. But then start playing with some more interesting effects like holding and illuminating the peaks -- and then having them gradually fall -- with the instantaneous values "dancing" below. (I wouldn't know "sample averaging" if it crawled up my leg and bit me in an unfortunate place).

Check out my earlier blogs on this BADASS Display tracing my thoughts (including some videos I saw on YouTube) and you will see just how little of a clue I have (Part 1, Part 2, Part3, and Part 4).

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 10:21:44 AM
NO RATINGS
@JeffL: Also I imagine you'll want to make this display logarithmic, with each LED representing 2 or 3 decibels higher level, and maybe even make the lower LEDs represent larger values (so the display comes closer to handling the much larger dynamic range that the ear responds to than just 32 or 48 decibels)?

I had planned on making it logarithmic on the vertical axis -- but I hadn't thought much beyond that. Any advice you can provide woudl be very gratefully accepted (my email is max.maxfield@ubm.com).

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 10:24:49 AM
NO RATINGS
@JeffL: Will there be a provision to "calibrate" this so it can read actual sound levels?

I will need some way to calibrate it -- I haven't thought how yet.

 

How about a "master level" channel to one side to show the unfiltered level?

I guess I could use one of the channels for this -- the great thing about this sort of display is that you can do pretty much anything...

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 10:27:49 AM
NO RATINGS
@JeffL: How is color going to be applied, there's a convention that "acceptable" levels at the bottom are green, levels above that are yellow, even higher are red, will you "go conventional" or do something out of the ordinary?

Check out my earlier blogs (including the videos) -- I want to experiment with lots of different schemes -- that's one of the things the control panel at the bottom of the display will be used for (see Part 4) -- to switch between different display modes.

Max The Magnificent
User Rank
Blogger
Re: Here's a few other "pointers"
Max The Magnificent   4/23/2014 10:29:52 AM
NO RATINGS
@JeffL: Then again maybe I'm just a LITTLE obsessive about this stuff...

Don't be silly -- you aren't obsessive at all (LOL) -- if you have the time to chat further about this, email me at max.maxfield@ubm.com and we can set up a call.

djohns
User Rank
Rookie
Addresses and objects
djohns   4/23/2014 7:59:34 AM
NO RATINGS
Perhaps an analogy might help with the pointer mystery:


Consider two ways you could get a package delivered to your house.  The normal way: you give UPS your address and they send a cheerful driver in a brown truck to plunk the package down on your porch.


To save your poor driver some time, you could instead make a duplicate of your house, hire a house mover to move the house to the local UPS office where they put the package on the porch and have the mover bring the house back to you.  The mover demolishes your original house and replaces it with the house that has your package which you open only to discover it's the wrong color and you have to ship it back....


Passing pointers instead of the whole object is more efficient.  Of course there are some down sides to this.  Giving your address to some hoodlums who come over and have a huge party and trash the place is not good.  In that case, making a duplicate of the house that they can do what they want to with is a good option.  You could also lock up certain parts of the house and post big signs that say "PRIVATE KEEP OUT" in those critical areas. Let them do what they want in the tornado shelter, just keep them out of the room with all the expensive antiques.


Pointer to a function? Same idea except now the memory pointed to contains code instead of data.  It's like the address of your lawn mower.  So you tell your son to work on his homework and every time he finishes one assignment to start the mower and mow one section of the lawn.  You also tell him where the mower is in case he forgot. You sit in the garage watching the mower and every time you see it start up you know that another assignment was finished.

 

Max The Magnificent
User Rank
Blogger
Re: Addresses and objects
Max The Magnificent   4/23/2014 10:35:43 AM
NO RATINGS
@djohns: Perhaps an analogy might help with the pointer mystery...

Good analogy -- I think I understand the main concepts involved with regard to thinks like passing pointers to functions -- but I always say that just before things crash and burn LOL

djohns
User Rank
Rookie
Re: Addresses and objects
djohns   4/23/2014 12:04:33 PM
NO RATINGS
(another long post, sorry)

It is usually better to put a little abstraction between the logic of your main code and the actual hardware.  What happens if you decide to make an HD version of the display and want 24 columns instead of 16? Or the neo pixs are no longer available or a hot new type becomes available, if you have built the program around a specific display you have more work changing it over. You could create a separate .cpp file for the hardware like this:

 

// pixels.cpp

#include "pixels.h"


#include "Adafruit_neopixels.h"

 


#define PixelsPerStrip 16
#define StripsPerDisplay 16;

Adafruit_NeoPixel strips[StripsPerDisplay]; // make this global to this .cpp file,but no one else!

 

int InitPixels(int& numrows,int& numcols)
{
 int Success = 0;
// init the strips here. If something goes wrong set Success to an error code


 numcols = StripsPerDisplay; // pass back parameters of the current display
 numrows = PixelsPerStrip; // assume strips are vertical and row and col are relative to the top left corner of display
 
 return Success;
}

void LightUpPixelBuffer(int row, int col, int red, int green, int blue)
{
 // map row and col to the appropriate strip and pixel in the strip and set it

}

void ShowDisplay()
{
 // signal all the strips to display their new states
 // i.e. loop through all the strips and call show() on them
}

 

in your main routine include "pixels.h" in which you declare the three routines above. Call InitPixels once at the beginning of your main routine and pass it two variables, numRows, and numCols, which it returns to you with the geometry of your display. Determine row and col from your analysis of the waveform.  You call LightUpPixelBuffer() to set the display value of a pixel.  Since it looks like neopix lets you set a bunch of them and then show them all at once, you could do the same and call ShowDisplay() after you have set all the pixels for one time frame.  When calculating which pixels to turn on, use the variables numRows, and numCols instead of hard coding in 16.


This way you could create a display of any size and not have to change the main code.  Get a new display technology? just create a new .cpp file for it and implement the three routines and you're good to go. 


One more thought, you might want a main loop that you go through at set time intervals, ie. a refresh rate,  for example, 30 times per second.  For each pass you could do your waveform calculations, set your pixels, and refresh your display, wait until time for the next loop, and repeat. 

This would let you do animations on the leds. If you kept a current value of a pixel and a target value, by changing the current value in steps until it reaches the target value, you could fade the pixels to a new color. If you define a pixel class like this it could help keep track of things better:
class Pixel
{
private:
 int thispixelsRow, thispixelsCol; // used to map to the hardware display
 int target_r, target_g, target_b;
 int current_r, current_g, current_b;
 int r_step, g_step, b_step;
public:
 SetTargetValue(int r, int g, int b, ...); // set new target value, and calculate how big the steps need to be to go from the current colors to the new target colors. Example if you calculate the step size to be one 15th of the difference between the current value and the target value, and you step 30 times a second, you get a half second dissolve


 Animate(); // call this once everytime through the main timing loop. It adds the step value to the current pixel value until current pixel is same as target

 DrawPixel(...); // draw current pixel to the device using its row and col values
};

 


In the main routine you declare an array of these Pixel classes numCols * numRows long and map it by ndx = curRow * NumCols + curCol;

Now, call set targetValue for each pixel based on your wave form, then loop through the array, call Animate() and DrawPixel().  Finally, call ShowDisplay() to blast it to the display.

Max The Magnificent
User Rank
Blogger
Re: Addresses and objects
Max The Magnificent   4/23/2014 1:35:38 PM
NO RATINGS
@djohns: ...another long post, sorry...

Don't appologise! I'm tremendously grateful for all the help I can get

Max The Magnificent
User Rank
Blogger
Re: Addresses and objects
Max The Magnificent   4/23/2014 1:37:26 PM
NO RATINGS
@djohns: ... Now, call set targetValue for each pixel based on your wave form, then loop through the array, call Animate() and DrawPixel().  Finally, call ShowDisplay() to blast it to the display.

It all sounds so easy when you say it quickly ... when can you come round to my house to get this working in the real world LOL

djohns
User Rank
Rookie
Re: Addresses and objects
djohns   4/23/2014 2:11:33 PM
NO RATINGS
Haha. Let's see if I had the pointer to your house I could access it...

Really, though, this is a fun concept. Maybe I'll write a little program that does a simulation on a PC and send you the source.

Max The Magnificent
User Rank
Blogger
Re: Addresses and objects
Max The Magnificent   4/23/2014 2:16:59 PM
NO RATINGS
@djohns: Maybe I'll write a little program that does a simulation on a PC and send you the source.

I hate to eat into your time like that (I know how precious time is), but I would love to see that program LOL

stwomey0
User Rank
Rookie
Goertzel verses FFT
stwomey0   4/23/2014 9:08:32 AM
NO RATINGS
If you are still pondering about frequency detection you might conceder using the Goertzel algorithm to detect the energy in the 16 bins.  The algorithm is more efficient then an FFT when measuring the energy at specific frequencies.

Max The Magnificent
User Rank
Blogger
Re: Goertzel verses FFT
Max The Magnificent   4/23/2014 10:39:57 AM
NO RATINGS
@stwomey: If you are still pondering about frequency detection you might conceder using the Goertzel algorithm to detect the energy in the 16 bins.

I've never even heard of this. According to the Wikipedia: "For covering a full spectrum, the Goertzel algorithm has a higher order of complexity than Fast Fourier Transform (FFT) algorithms; but for computing a small number of selected frequency components, it is more numerically efficient."

But don't I want to cover the entire spectrum, in which case thsi is more complex?

But then the Wikipedia goes on to say: "The simple structure of the Goertzel algorithm makes it well suited to small processors and embedded applications."


My head hurts LOL

dyson_
User Rank
Rookie
Pointers are just addresses
dyson_   4/23/2014 1:29:50 PM
NO RATINGS
Max,

Looks like you are getting some excellent help from other posters but I thought I would just chip in with my hardware oriented thoughts.

Someone may have pointed (sic) this out already but pointers in C/C++ are just memory addresses.  A pointer to a function is the address of that function in memory.  Granted, the syntax for decalring a pointer to a function can be a bit mystifying but, hey thats just syntax.

You can make a pointer point at any bit of memory (there is even a generic pointer type: void* ) That said, things can go wrong in strange ways if you mess up your pointer and read/write memory you did not intend to. (data changing unexpectedly, the dreaded segmentation voilation, etc)

If ptr is decalres as a pointer to type T you read by "dereferencing":

x = *ptr;

where x is a variable of type T

You write the memory like this:

*ptr = x; // write to memory at where "ptr" points

You set the value of the pointer (i.e. the memory address) by assigned to it like any other variable:

int *ptr; 

ptr = (int *)0x1234; // some arbitrary address that is unlikely to be vaild!

The (int *) is a "cast" which makes the expression 0x1234 be of the type int * , a pointer to int

Often harware peripherals will be mapped into the memory space so you write to their control registers by pointing to the approprate address with a pointer fo a type of the same size as the peripheral register (more correclty the space it takes up in the memory map) and writing to the memory with *ptr = <some expression>;

I could go on but I suspect the books express it better...

 - Dyson 

Max The Magnificent
User Rank
Blogger
Re: Pointers are just addresses
Max The Magnificent   4/23/2014 1:39:42 PM
NO RATINGS
@Dyson: I thought I would just chip in with my hardware oriented thoughts.

Chip away old friend LOL. I know what you mean -- the only way I can wrap my brain around any of this stuff is to have a good visualization as to what's actually happening in the underlying hardware.

djohns
User Rank
Rookie
Pixel Fader Simulation
djohns   4/24/2014 9:51:09 AM
NO RATINGS
Hi, here is link to some stuff I put together for fun illustrating fading pixels on and off and abstracting from the hardware.  It turned out to be very flexible.  The first thing I did was just select pixels at random and give them a random rgb color.  If the same pixel was randomly selected later and given a new color, it would fade from the one color to the other.  Then I changed it to draw light the pixels as a vertical bar from the bottom to the selected pixel and fade the bar out over time.  Then I added some gravity effects so that the bar would fade out from the top down.  Then I decided to stop playing and go to bed...

https://copy.com/oWNxl7MqjKLE

 

Max The Magnificent
User Rank
Blogger
Re: Pixel Fader Simulation
Max The Magnificent   4/24/2014 10:04:52 AM
NO RATINGS
@djohns: The first thing I did was just [...] Then I changed it to [...] Then I added some [...] Then I decided to stop playing and go to bed...

LOL This is WONDERFUL -- thank you so much -- I am snowed under with work at the moment -- fighting my way toward the weekend -- but I cannot wait to root through all of this and see what you did.

Also, I hjave to say that this ha sinspired me to "pull my finger out" and actually start constructing the display so I can start playing with these effects on the real display.

FYI Keep your eyes open for a follow-up blog later today on MUC Designline in which I will be pondering whether to use I2C or create a custom interface to link two MCUs (as part of my BADASS Display, of course)

Flash Poll
Radio
LATEST ARCHIVED BROADCAST
EE Times editor Junko Yoshida grills two executives --Rick Walker, senior product marketing manager for IoT and home automation for CSR, and Jim Reich, CTO and co-founder at Palatehome.
Like Us on Facebook

Datasheets.com Parts Search

185 million searchable parts
(please enter a part number or hit search to begin)
EE Times on Twitter
EE Times Twitter Feed
Top Comments of the Week