Neopixel Ring Roulette Wheel.

by Damage on Sat Sep 07, 2013 11:45 pm

Hey All, I wrote a little code that simulates a roulette wheel on a neopixel ring. The code isn't perfect aesthetically, but it is functional. Wire up 1 neopixel ring and let me know what you think! :)

Here is the code...

Code: Select all
/*
Neopixel Ring Roulette wheel sketch.
"Spins" a roulette wheel and lands on a random value.
I am not 100% satisfied with the aesthetic, but it's as close as I can get.
I would prefer a more realistic spinning to a slow effect with the final numbers slowly dropping onto a value
similar to the price is right money wheel.
I tried several approaches, but I can not seem to nail it.
A linear increment of a delay does not look right

If anyone can improve upon it,  I would love to see what results they come up with.
If you make it improve it, let me know at tom[at]damage[dot]cc
It would be rad to build a full 36+2 position American style roulette wheel out of neopixels!


Code is based on the adafruit neopixel 'strandtest' code.
*/


#include <Adafruit_NeoPixel.h>
long randNumber;  //variable to hold random number value
int pos;          //used to track position of lit segment


//──────────────────────┤         User Variables          ├────────────────────────────

#define PIN 6     //data pin used in for neopixel
int spins = 6;        //how many times to 'spin before starting to slow down and settle
#define dir 1  //set to 1 for clockwise rotation, 0 for counter clockwise.

//───────────────────────────────────────────────────────────────────────


// Parameter 1 = number of pixels in strip, value at 16 for NeoPixel Ring.
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);


//──────────────────────┤       SETUP Function       ├────────────────────────────

void setup() {
  randomSeed(analogRead(1+2+3+4+5));  //initialize floating pin (analog pins 1-5) as the seed for the RNG
  strip.begin();
  clr();  //clear the display for good measure.
  strip.show(); // Initialize all pixels to 'off'
}


//──────────────────────┤         Main Loop          ├────────────────────────────

void loop() {

  randNumber=random(0,16);  //fetch a random number between 1-16

  //call the wheel
           //color used for for odd segments, even segments, and for '0'
  roulette(strip.Color(16,0,0),strip.Color(0,0,16),strip.Color(0,16,0));   
}


//──────────────────────┤  Roulette Wheel Function   ├────────────────────────────

void roulette(uint32_t c,uint32_t d,uint32_t e) {

    //spin the number of times (variable 'spin') at full speed
      for (int i=0; i<16*spins; i++){
           advanceOne(c,d,e, 4);
      }   
     
      //slow down and 'settle' on final number
      for (int i=0; i<(16*6)+randNumber; i++){
           advanceOne(c,d,e, (i*.25)+4);
      }

//optional press reset button to spin. 
//while(1);    //wait indefinitely,  press reset button on Arduino to spin again.
  delay(2000);  //reset spins automatically.

} //end 'roulette' function


//──────────────────────┤ Advance One Position Function ├────────────────────────────

//every time this function is called, the led is advanced 1 position on the wheel
void advanceOne(uint32_t c,uint32_t d,uint32_t e, uint16_t wait) {


            clr();//Clear the display

              if ((pos & 0x01) == 0) {    //check to see if position is an even number
                    strip.setPixelColor(pos, c); //turn on the pixel at position 'pos'
               } else  //else it is odd
                 {strip.setPixelColor(pos, d);
               }
 
              if (pos == 0) { //or check to see if it is '0'
                 strip.setPixelColor(pos, e);
               }

            strip.show(); 
            delay(wait);

            if (dir){    //if direction var is set to clockwise
                  pos--;  //decrement the position
                  if(pos<0)  {pos=15;}  //resets running count if < 0}
            }
                else{
                  pos++;  //increment the position
                  if(pos>15)  {pos=0;}  //resets running count if > 15}
            }

}//end advanceOne function


//──────────────────────┤ Clear all Pixels Function ├────────────────────────────

//clears the display
void clr(){
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, 0);
    strip.show();
  } 
}


Regards
Damage
 
Posts: 11
Joined: Sun Sep 26, 2010 12:22 pm
Location: Baltimore

Re: Neopixel Ring Roulette Wheel.

by EternalCore on Sun Sep 08, 2013 3:54 am

Hi,
Cool. Can you upload a video of it in action?
User avatar
EternalCore
 
Posts: 239
Joined: Tue Jul 30, 2013 2:57 pm
Location: Canada

Re: Neopixel Ring Roulette Wheel.

by Damage on Sun Sep 08, 2013 12:48 pm

Ask an you shall receive...

http://youtu.be/KEJIe9AqgqY
Damage
 
Posts: 11
Joined: Sun Sep 26, 2010 12:22 pm
Location: Baltimore

Re: Neopixel Ring Roulette Wheel.

by 1chicagodave on Sun Sep 08, 2013 1:14 pm

Ahh...ok.

Pretty cool. Now I know what you meant about wanting a Price-is-Right type of effect. I think that was what I was actually picturing in my head before the video.

Nice effect though! What issues did you have when you tried to "spin the entire wheel" so to speak?
Please forgive my hyperanthropomorphization.
Every answer reveals new questions.
And, yes... there's always a better way to 'do that'.
User avatar
1chicagodave
 
Posts: 564
Joined: Wed Jun 19, 2013 2:35 am
Location: Chicago

Re: Neopixel Ring Roulette Wheel.

by EternalCore on Sun Sep 08, 2013 5:06 pm

Damage wrote:Ask an you shall receive...

http://youtu.be/KEJIe9AqgqY


Nice, but it stops too abruptly and at too far of random spots away from where the spinner led is; So If you fix that it'll be awesome, Good work though I look forward to see more updates of it. :)
Things I've Made Here:
1.[101-Help]~12v -> 5v 1.5A Regulated Power For NeoPixels.: http://goo.gl/uMXuk7
2.[Example]NeoPixel Strip Scrolling Cylon Eye!: http://goo.gl/4RzWQQ
User avatar
EternalCore
 
Posts: 239
Joined: Tue Jul 30, 2013 2:57 pm
Location: Canada

Re: Neopixel Ring Roulette Wheel.

by Damage on Sun Sep 08, 2013 6:30 pm

1chicagodave: I apologize, I may have used a bad example leading to the wrong impression. My comparisons to the Price is right wheel were relating entirely to the speed & deceleration of the spinning animation, not so much the look of the wheel graphically. To your question, I have not tried to implement a spinning wheel per say. It should be somewhat easy to modify the existing code to accomplish that effect. It would be similar to the fading rainbow effect that the example code uses, except instead of a continuous fade of colors, there would be x number of discrete colors. I hadn't thought of that prior to you mentioning it, but your post inspires me to give it a shot!

EternalCore: I agree 100%, it stops too abruptly. This is precisely where I am stuck, I don't really know how to solve that problem. This is what I meant by the price is right money wheel thing. I want the speed/slowdown to somewhat emulate the speed and slowdown of it. I tried linear slowdowns... exponential slowdowns, etc. Nothing I have come up with 'feels' right. Emulating an actual roulette wheel's speed/decel would be a bad idea as the wheel itself practically spins forever (massive wheel, high quality bearings, etc.)
Damage
 
Posts: 11
Joined: Sun Sep 26, 2010 12:22 pm
Location: Baltimore

Re: Neopixel Ring Roulette Wheel.

by 1chicagodave on Sun Sep 08, 2013 7:54 pm

.....I've had another thought after my last post. I'm thinking the "full wheel" just mentioned 'spinning' at one speed, and the single "ball" (similar to video you posted) spinning at separately defined speed - all at same time. First the wheel slows to a stop, then the ball slows to a stop.

Since the colors don't get sent out to the pixels until the strip.show() ...it shouldn't be too difficult to combine the two codes. Just define the single ball after the wheel so it's set 'on top'. :D

It'd be (almost) like a real roulette table.

*I like using using "quotes"....
Please forgive my hyperanthropomorphization.
Every answer reveals new questions.
And, yes... there's always a better way to 'do that'.
User avatar
1chicagodave
 
Posts: 564
Joined: Wed Jun 19, 2013 2:35 am
Location: Chicago

Re: Neopixel Ring Roulette Wheel.

by EternalCore on Sun Sep 08, 2013 8:06 pm

Damage wrote:EternalCore: I agree 100%, it stops too abruptly. This is precisely where I am stuck, I don't really know how to solve that problem. This is what I meant by the price is right money wheel thing. I want the speed/slowdown to somewhat emulate the speed and slowdown of it. I tried linear slowdowns... exponential slowdowns, etc. Nothing I have come up with 'feels' right. Emulating an actual roulette wheel's speed/decel would be a bad idea as the wheel itself practically spins forever (massive wheel, high quality bearings, etc.)

You could use a while loop to increase the delay time until it slows down enough for it to stop. ;)
Example:
Code: Select all
int delaytime=1000; //1second
while {
//led blah blah code...
if (delaytime>4000) {
break; //breaks from the loop if the delay time reaches 5 seconds
}
delay(delaytime);
delaytime+1000;
}
//etc...


Of course it would be a lot more complex then that but this just gives you an idea.
Things I've Made Here:
1.[101-Help]~12v -> 5v 1.5A Regulated Power For NeoPixels.: http://goo.gl/uMXuk7
2.[Example]NeoPixel Strip Scrolling Cylon Eye!: http://goo.gl/4RzWQQ
User avatar
EternalCore
 
Posts: 239
Joined: Tue Jul 30, 2013 2:57 pm
Location: Canada

Re: Neopixel Ring Roulette Wheel.

by EternalCore on Sun Sep 08, 2013 9:29 pm

Also you can use random() To generate a random start speed. ;)
Things I've Made Here:
1.[101-Help]~12v -> 5v 1.5A Regulated Power For NeoPixels.: http://goo.gl/uMXuk7
2.[Example]NeoPixel Strip Scrolling Cylon Eye!: http://goo.gl/4RzWQQ
User avatar
EternalCore
 
Posts: 239
Joined: Tue Jul 30, 2013 2:57 pm
Location: Canada

Re: Neopixel Ring Roulette Wheel.

by 1chicagodave on Mon Sep 09, 2013 2:09 am

I played with the code a little. (I'll post changes tomorrow.). But, here's a little video to summarize —

http://www.youtube.com/watch?v=oF0ysjE_1dQ

**EDIT:

As promised, here's my (sloppy) code! :o

Code: Select all
#include <Adafruit_NeoPixel.h>


long randNumber;
int pos;
#define PIN 6
int spins = 6;
#define dir 1
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);

void setup()
{
  randomSeed(analogRead(1 + 2 + 3 + 4 + 5));

  strip.begin();
  colorWipe(0,0);  // Initialize all pixels to 'off'
  strip.show();
}    /***************end setup****************/

void loop()

{

  randNumber = random(0,16);    // Generate random number

  roulette(strip.Color(16,0,0),strip.Color(0,0,16),strip.Color(0,16,0));


}   /*****************END VOID*******************/


void roulette(uint32_t c, uint32_t d, uint32_t e)
{
  float waitTime = 4.0;    // long variable for adjustable dealy/wait time

  // Full speed spins
  for (int i = 0; i<16; i++)
  {
    advanceOne(c,d,e, waitTime);

  }
  //    Slow spins & stop
  for ( int i = 0; i <(16*6)+randNumber; i++)
  {
    advanceOne(c,d,e, waitTime);
    waitTime = (waitTime * 1.05);    // SLOWLY increase waitTime, and thus delay(), each time through the for loop
  }
  delay(100);

  int winner = (pos +1);
  if (winner>15) winner = 0;
 
  uint32_t win = strip.getPixelColor(winner);

strip.setPixelColor(winner, (c+d+e));
strip.show();
delay(100);
strip.setPixelColor(winner, win);
strip.show();
delay(200);
strip.setPixelColor(winner, (c+d+e));
strip.show();
delay(100);
strip.setPixelColor(winner, win);
strip.show();

  delay(2000);
}    /******************END ROULETTE*****************/

void blinkWinner()

{
  uint32_t win = strip.getPixelColor(pos);
 
  delay(100);
  colorWipe(0,0);
  strip.show();
  delay(100);
  strip.setPixelColor(pos, win);
  strip.show();
  delay(200); 
  colorWipe(0,0);
  strip.show();
  delay(100);
  strip.setPixelColor(pos, win);
  strip.show();
  delay(200);

}    /*****************END BlinkWinner ******************/



void advanceOne(uint32_t c, uint32_t d, uint32_t e, float wait)
{
  colorWipe(0,0);
 
  if ((pos & 0x01) == 0)     // it's even
  {
    strip.setPixelColor(pos,c);

  }
  else    // it's odd
  {
    strip.setPixelColor(pos,d);

  }
  if (pos == 0) strip.setPixelColor(pos,e);    // or it's "0"

  strip.show();
  delay(wait);

  if (dir)
  {
    pos--;
    if(pos<0) pos=15;

  }
  else
  {
    pos++;
    if(pos>15) pos=0;

  }
}    /*************** END AdvanceOne ********************/

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}    /**************END colorWipe *********************/



Last edited by 1chicagodave on Tue Sep 10, 2013 5:52 pm, edited 1 time in total.
Please forgive my hyperanthropomorphization.
Every answer reveals new questions.
And, yes... there's always a better way to 'do that'.
User avatar
1chicagodave
 
Posts: 564
Joined: Wed Jun 19, 2013 2:35 am
Location: Chicago

Re: Neopixel Ring Roulette Wheel.

by EternalCore on Mon Sep 09, 2013 2:23 am

1chicagodave wrote:I played with the code a little. (I'll post changes tomorrow.). But, here's a little video to summarize —

http://www.youtube.com/watch?v=oF0ysjE_1dQ

yep that's more like what I had in mind too. ;) If I had the ring I would of played with the code too, but I only have the strips and it would look messed up if I used it.
User avatar
EternalCore
 
Posts: 239
Joined: Tue Jul 30, 2013 2:57 pm
Location: Canada