热度 24
2016-3-19 17:28
1227 次阅读|
0 个评论
In line with my Caveman Diorama project, we've nowcome to the stage where we need to consider how to implement the fire around which a miniature version of yours truly and his cavemen companions will be relaxing, mulling over the events of the day, and commenting on the quality of the mammoth burgers we'll doubtless be munching. I've actually been pondering this poser in the back of my mind for the past couple of months, but now it's time to leap into action with gusto and abandon. It probably won't surprise you to learn that I'm currently planning on using an Arduino microcontroller and a bunch of Adafruit's NeoPixels as the basis for my fire effect. One reason for this is that I happen to have quantities of both of these little rascals close to hand here in my office. Having said this, I may change direction if it turns out we cannot achieve sufficient realism, but we'll see how we go. We'll consider the actuall nitty-gritty details of the fire implementation in a future column. For the moment, one thing we know we're going to need is a good random (or pseudo-random) number generator upon which to base our fabulously flickering effects. One way to create random numbers is to build a hardware random number generator (HRNG) -- also known as a true random number generator (TRNG) -- that is based on some physical process that generates low-level, statistically-random "noise" signals, such as thermal noise, the photoelectric effect, and other quantum phenomena. The HRNG/TRNG level of super-randomness is great for applications like cryptography, but it's probably overkill for what I'm doing, not the least that I don't want to spend the time building one. Of course, the Arduino does come equipped with a handy-dandy random() function, which is just what I need... assuming that this little scamp does indeed generate random numbers. Call me an old fuddy-duddy if you will, but this is the sort of thing that is easy to take for granted, only to be unpleasantly surprised somewhere down the line. Suppose, for example, that I wish the various NeoPixel elements forming my fire to randomly switch between red, orange, and yellow (we'll also want to vary their brightness and duration, but let's not get ahead of ourselves). Let's further suppose that we want to weight things such that red is the predominant color, followed by orange, followed by yellow. One way to do this would be to generate a series of random numbers between say 1 and 1,000, and to then say that any number from 1 to 500 equates to red, any number from 501 to 800 equates to orange, and any number from 801 to 1000 equates to yellow. The idea being that (over time and using these values) each LED will spend 50% of its time red, 30% of its time orange, and 20% of its time yellow. But this only works if the random() function is truly -- or, at least, reasonably -- random. We'd all feel slightly silly if we ended up seeing only a tiny amount of yellow, and we subsequently discovered that the vast majority of our "random" (1 to 1,000) numbers actually resided predominantly in the 300 to 700 range. In order to test this, I threw a simple program together that loops around creating 1000 X-Y pairs where each X and Y value is a randomly generated integer between 1 and 1,000. The core of this code is as follows: for (int i = 0; i 1000; i++) { x = random(0, 1001); y = random(0, 1001); Serial.print(x); Serial.print(","); Serial.println(y); } You can Click Here to see the full code (such as it is). If you do, you might care to note that I'm trying to follow the guidelines espoused in the Embedded C Coding Standard by Michael Barr (or, at least, the guidelines I find to be most applicable to what I'm doing). I then copied my 1,000 comma-separated X-Y pairs out of the Arduino IDE's Serial Monitor window and saved them in a NotePad *.txt file. You can Click Here to access these values if you want to play with them yourself (see also the discussions below). So, now that I have my 1,000 comma-separated X-Y pairs, what do I want to do with them? Well, the obvious first-pass option is to generate a scatter plot and observe the result. What we would like to see would be an arbitrary distribution that is relatively evenly distributed across our 1000 x 1000 canvas. What we don't want to see is something that looks like the following, for example: (Source: Max Maxfield / Embedded.com) Actually, even the above would be (fractionally) better than seeing something like the following, which would tend to indicate that our random number generator is outputting different sub-sets of values into our 'x' and 'y' variables, which would certainly make our poor old noggins ache. (Source: Max Maxfield / Embedded.com) Of course, my next consideration was performing the actual plot itself. I had a quick Google (while no one was looking) and ended up using an online tool called plotly ( https://plot.ly ). Although the user interface ended up being a tad less intuitive than one might hope, I was certainly happy with the first-pass results, as illustrated below: ( Click Here to see a larger image. Source: Max Maxfield / Embedded.com) Well, I must admit that this is looking rather encouraging. Having said this, my chum Ivan (the "Moustache of Knowledge") just wandered into my office and observed that it might be worth examining the temporal and spatial relationships between the X-Y pairs in more detail. For example, is the average distance between the members of medium-sized groups of X-Y pairs constant across the whole canvas? Also, if we were to consider medium-sized groups of X-Y pairs whose members are generated close to each other in time, then are the members of those groups also distributed spatially across the whole canvas, or are they clustered and clumped together? Remember that you can Click Here to access my 1,000 X-Y pairs. What we need is someone who has a clue what they are doing access to sophisticated plotting and analysis software and knows how to use it. Are you that person?