An Amusement Machine using LEDs

I am hoping to make a simple LED analogue of a mechanical slot machine reel. My question is this: Can I run a sequence of numbers that can be stopped at an instant and keep the last number? On a poker machine reel there maybe 25 symbols of 8 different kinds. So with 8 Arduino pins I can activate an LED for each different symbol and I can use integers from 1 to 25 to reproduce the distribution of symbols spinning on a reel. The sequence can repeat but the fun is had when the reel stops at random... How to interrupt the coding sequence and keep that last LED alive? I am hoping to use a simple switch to turn the sequence on and off. Switch on - numbers run, switch off - numbers stop and last number remains alive, and an LED illuminated till the switch is reactivated.

Make three of these units and I can open a casino! (just kidding, seriously I know I could locked up)

Perhaps this is a standard challenge that has been done a million times before?

Can I run a sequence of numbers that can be stopped at an instant and keep the last number

Yes

How to interrupt the coding sequence and keep that last LED alive

Nothing special just stop outputting the sequence and the LEDs will stay at the last pattern you outputted.

Thanks Grumpy Mike. There are two ways to output a random result - run a series of random numbers and stop it after a given interval, or the more old school way of having a set series of numbers that loops around until it is stopped at some random point. I am trying the second approach because I am interested in recreating the odds distribution of ye olde slot machines. I want to take the symbols off old reels and feed them into my program, so I am trying to set up my coding accordingly. Reel position 1 may be a cherry, so it lights up LED1, position 2 is a lemon so it lights up LED2, but position 3 is also cherry and it lights up LED1, and so on. 25 bits of exact code which can be stopped at any point. My hesitation is knowing how to interrupt the sequence in real time without having it run-on to completion.

You put your sequence of numbers / symbols into an array. In your main loop you increment a counter that goes from zero to the number of elements in your array. You use this as an index into the array to get your pattern. You keep on doing this for as long as the switch is pressed. When the switch is not pressed you stop doing this, and the last outputted pattern is shown on your LEDs.

Grumpy_Mike:
You put your sequence of numbers / symbols into an array. In your main loop you increment a counter that goes from zero to the number of elements in your array.

Should it not be "from zero to the number of elements in your array - 1" ?

Should it not be "from zero to the number of elements in your array - 1" ?

Depends where you wrap it round.

But I was trying not to overwhelm the OP at the moment with too complicated detail that can always be sorted out later on the second code iteration.

So I am tinkering with some existing code that I might be able to adapt to my needs… this code was written by Chagrin back in 2012 and it allows dimming of the LEDs and acceleration of the rate of change between outputs, so in theory the lights can be made to speed up, slow down, and dim up and down - whatever. Which would make for a pretty cool reel spin simulation. I have set up an initial small sequence of symbol commands, each flashing at full brightness at 100 millisecond intervals. As it is the sequence will only run once. I need to loop this sequence and make it stop mid stream on a ground lift/switch/timer… Given my tiny programming skill set this seemed like a way forward, but I do see that it is not what you are suggesting Mike, and I apologise in advance.

/*
Fade up and down on multiple pins
Code adopted from Chagrin August 2012
*/

#define LED1 2 // Cherries
#define LED2 3 // Orange
#define LED3 4 // Lemon
#define LED4 5 // Plums
#define LED5 6 // Bell
#define LED6 7 // Bar

#define MAXPINNUMBER 7 // LED6 is the highest pin number -- number 7

#define MILLISPERDIMSTEP 100 // LED dimming is recalculated every X millis

// Group LED commands into a structure (struct)
struct command {
  byte pin;          // 0 to 255
  unsigned int time; // 0 to 65535
  byte brightness;   // 0 to 255
  char dimrate;      // -127 to 128
};

// The stored state of each LED; holds state of dimming.
struct state {
  unsigned int time;
  byte brightness;
  byte dimrate;
};

// Create the reel spin which is an array of "command" structs
struct command scene[] = {

 {LED1,0,255,0},
{LED2,0,0,0},
{LED3,0,0,0},
{LED4,0,0,0},
{LED5,0,0,0},
{LED6,0,0,0},

{LED1,100,0,0},

\{LED1,100,0,0},

{LED2,100,255,0},
{LED2,200,0,0},

{LED3,200,255,0},
{LED3,300,0,0},

{LED4,300,225,0},
{LED4,400,0,0},

{LED5,400,255,0},
{LED5,500,0,0},

{LED6,500,255,0},
{LED6,600,0,0},





};

// Initialize the LED states to off. Note 0 to MAXPINNUMBER is (MAXPINNUMBER + 1) states.
struct state ledState[MAXPINNUMBER + 1] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},};

void setup(){
}

void loop(){
  static unsigned long kickoff = 0;
  static unsigned int sceneCtr = 0;
  byte ledCtr = 0;

  // wait for a button press here to kick off the scene if desired

  // Check the scene to see if we have a new command
  if (sceneCtr < sizeof(scene) / sizeof(command)) {
    if (scene[sceneCtr].time <= millis() - kickoff) {
      analogWrite(scene[sceneCtr].pin, scene[sceneCtr].brightness);
      if (scene[sceneCtr].dimrate != 0) {
        // It dims; we have to add this to our ledState array and keep track of it.
        ledState[scene[sceneCtr].pin].time = scene[sceneCtr].time + MILLISPERDIMSTEP;
        ledState[scene[sceneCtr].pin].brightness = scene[sceneCtr].brightness;
        ledState[scene[sceneCtr].pin].dimrate = scene[sceneCtr].dimrate;         
      }
      sceneCtr += 1;
    }
  }
  
  // Here we process through all the LEDs in a dimming state
  for (ledCtr = 0; ledCtr < MAXPINNUMBER + 1; ledCtr++) {
    if (ledState[ledCtr].dimrate != 0) { // only LEDs with a dimming are messed with.
      if (ledState[ledCtr].time <= millis() - kickoff) {
        if (ledState[ledCtr].brightness + (char) ledState[ledCtr].dimrate >= 0 &&
            ledState[ledCtr].brightness + (char) ledState[ledCtr].dimrate <= 255) {
          ledState[ledCtr].brightness += (char) ledState[ledCtr].dimrate;
          ledState[ledCtr].time += MILLISPERDIMSTEP; // mark the time of next LED adjustment
        } else if (ledState[ledCtr].brightness + (char) ledState[ledCtr].dimrate < 0) {
          // need to stop at zero and not a negative number.
          ledState[ledCtr].brightness = 0;
          ledState[ledCtr].dimrate = 0; // zero dimrate so we stop dimming it
        } else {
          // need to stop at 255.
          ledState[ledCtr].brightness = 255;
          ledState[ledCtr].dimrate = 0; // zero dimrate.
        }
        analogWrite(ledCtr, ledState[ledCtr].brightness);
      } 
    }
  }
  
  // Have 60 seconds elapsed? We need to restart if so.
  if (millis() - kickoff > 600000) {
    kickoff = millis();
    sceneCtr = 0;
  }
}

Given my tiny programming skill set this seemed like a way forward, but I do see that it is not what you are suggesting

That is because that code does not do what you said you wanted to do. It is a state machine although I don’t see any need for one.

The problem with trying to adapt other people’s code is it carries other people’s baggage. What you want to do is simple enough in itself and extras like variable brightness and speed are easily added.

Yes, I take your point Grumpy Mike. I have been happily using the code I posted above in an expanded form for a different application and never quite understanding how it works. I know how to plug in values and make it work it for me, but I don’t really know how the architecture of the code works, which means I am still a clueless programmer. So, your observation that this code is a “state machine” is interesting to me and I shall google accordingly…

So after googling I come to the basic fork in the road of using either the delay function, which uses the clock to measure time approaching, or the millis function to measure time elapsed (the state machine?). This is kind of mind blowing; time passing vs time passed, looking forward vs looking back. You can use either approach to control an array of LEDs, the delay function effectively halting procedure until an interval elapses while the millis function is open to change within the active time period. I think possibly the millis function works better with the fine tuning of PWM fading of different LEDs - but that is a dim memory from 2012...

, but I don't really know how the architecture of the code works

The word should be structure, the word architecture is used in a zoomed out view of the differences between groups of computer languages.

this code is a "state machine" is interesting to me and I shall google accordingly

Two good examples are my
http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html
Or Robin2's several things at once

Perfect! Thanks for the inspiration Mike (but will my brain follow my ambition)..."Rather than trawl the net looking for code to copy and paste into your project, how about using a bit of effort and try and understand what is going on. This shows you how to take that next step from beginner to expert, as you start writing code that is a bit beyond the plodding."

If you want help with sorting out that code then we can help here. What you need to do is to post what you have written so far, we make comments and suggestions and then you try an implement. Rinse and repeat, and you will soon start making progress and begin to understand things.

I suggest you start off by posting a schematic of your hardware, but not a Fritizing layout diagram. A photo of a hand drawn schematic will be fine.

So here is my schematic drawing of a fruit machine with 8 symbols…

Thanks for that, although your LEDs do look a bit phallic :wink:

I will tell you what to do step by step, if you don’t understand anything, first try looking it up but if you still don’t get it then please ask.

Start off by assigning PIN numbers to those outputs and input. Avoid pins 0&1 as they are used for uploading code.

Ok so start with defining an array with your pattern in it. Define the pattern to start with as the PIN number of that Led in each element. Make it a byte array.

Then in the setup function use a for loop and make those LED pins into outputs. Make the loop index run over the consecutive pin numbers you use rather than the normal 0 to N. Make the switch pin an input and enable the pull up resistor.

Then outside of any function define a byte called count and set it to zero.
Now define the loop function, start with a simple display all the symbols in your array. Set the LED’s output corresponding to the variable count’s value in the pattern array, like this

digitalWrite(pattern[count], HIGH);

Then delay for a second, and set it low.
Finally increment the count variable, then use an if test to see if it is equal to the maximum number in your pattern array and if it is set the value of count to zero.

That should run through all the patterns continuously.
Get that working and post the code and we can move on to the next bit.

Thanks a million Mike, I hope to repay your patience by doing my best to learn rather than sponge. I shall begin coding… But first I thought I better try to explain precisely what I hope to achieve. One set of symbols, but three sets of sequences corresponding to three reels and an ability to display the results of a set of three spins. Something like this:

Thanks Tommy, sorry so long in replying but I have a Maker Fair in two weeks and their is a lot to do.

The only thing that is a bit vague is how a player is going to keep track about what spin he is on. Also the pattern will start moving as soon as the timer is moved off zero not when released which would look / feel a bit better.

With any project you always implement it a small part at a time, so I think I we are on track to get there. I see no need for using a state machine for this one, so go ahead on the first stage.

Hey Mike, I'm just back from fighting bush fires this weekend, (I'm in Sydney Australia) so I've dropped the ball at my end...
Will have a crack at the code tomorrow, but please take your time with any help offered.

So it is not possible to know which spin is in play while the display sequence is in spin mode, but when the reel spin stops we enter a four second looping sequence which could compare to a piece of music of four 'bars'. After the first spin there is a tone in the first bar only, after the second spin there is a beat in the first and second bar, and after the third spin there is a beat in the first, second and third bars. The fourth bar remains empty to signal the end of the sequence. There is also a small pause at the beginning of each bar to separate the tones, in this way a pair or three of a kind will give a set of identical tones rather than one long tone. Hope that makes sense?

Agreed... releasing the timer would feel like a better place for the sequence to start... Hmm tricky.

OK so work begins on building the array. As a starting point I used a set of old reel strips and transcribed the symbols into three strings, one string for each reel (in this case the 2nd and third reels are identical). Each symbol now has a unique alphanumeric identifier.

I have drawn up a diagram as attached

You will notice that I have veered slightly off course, the reel set has 10 different symbols rather than 8 as previously promised. Am I trying to set up a byte array with a limit of 8 bits per byte and am I now exceeding the binary option and making the pattern masking option too complicated? Should I just use an easier reel set?

Am I trying to set up a byte array with a limit of 8 bits per byte and am I now exceeding the binary option and making the pattern masking option too complicated?

Not sure I follow this, why is it complex. A byte array, the smallest you can have, can store up to 256 symbols per array entry, you only need 10.