(not a ) switch case question (anymore...)

you just solved my last problem!
I was trying to work out a way to keep track of the dice mode, but I only have two pins left. using a push button is perfect, and comes with more options than a few regular LEDs to indicate level or something else that I might have thought up.
Great idea

Thanks for the suggestion!
much more simple than what I was thinking!

Neight:
actually, I ran into that very problem and this is how I fixed it. I originally had "0" at the top of the list, but that was displaying the dice result from 0-Xdice mode instead of 1-Xdice mode. I put "0" at the end, which screwed up my code to display which dice mode you were in, by saying "d1" instead of "d2" or "d9" instead of "d0." (for d10). To fix that, I used the "sevenSegWrite(dValue[state] - 1)" and everything worked out just right.
I could have just of easily used sevenSegWrite(Result + 1) but I didn't see that at the time. Once I had it working, I was fairly timid to try and change it again.

I suspect the problem you're describing is the result of code that does not separate out the abstraction of the dice from the abstraction of the display.

I suggest you should aim to implement a function that displays a given number, and call it with an argument which contains the number generated from your virtual 'dice'. The display logic should not depend at all on which dice you're using or how you 'roll' them or anything like that - it should just receive a number to be displayed.

In your current solution you will support the display of values in the range 1 .. 20 plus blank. Since these numbers correspond to positions 0 .. 20 in the display array, you would need to subtract one from the value when you access the array. My suggestion was that you should put the definition for '0' at the front of the array, even though you never expect to need to display a zero in this application, so that you can use the number directly as an index into the array without any need for offsetting it. This also means that the display function would handle zero correctly, which (IMO) makes it safer and easier to reuse for other projects.

@PeterH

I am sure you are correct.
I haven't wrote my own function without working directly from an example before, but I am sure with a little digging, I can figure it out.

I actually have some idea of how I would do that, though it will take some testing to find out.
Thank you for the suggestion!
This is my goal, to figure out how to get my idea working on my own, then get help from others to learn where I can make it better.
many more things that get talked about on this forum are making sense, and I always enjoy the process!

Ok, I seem to have hit a wall today...

I have re-designed my digital dice project.
I am now trying to use two 7 segment displays to show the dice roll results.
I am trying to multiplex them without external ICs.
they are both common cathode displays, and I have the segments for both wired together, and the cathodes wired through 2n2222a transistors to perform the multiplexing.
I have the segments mapped out correctly, and have already tested that.
I am having trouble getting the results to display.
basically, I don't have a clue how to take the double digit result of the random function, and correctly display them on the two displays.

Looking for any guidance or links that would show me how to do this. There are loads of tutorials and examples of how to use the 7seg, and how to multiplex them, but they all seem to have some pre-packaged message to scroll or display, and not how to display numbers that the arduino comes up with internally.

sorry if my description is unclear, and if anyone has any questions on my project, I am more than happy to answer them.

If you're using multiplexing then each LED is controlled by a combination of output pin states. When your dice handling code provides a value for display, you need to translate that into a set of LEDs that need to be illuminated. One way to do that is to use the display number as an index into an array of ints, and have each bit of the int associated with a given LED. This lets you do a simple lookup to get from the dice value to the bit-mask telling you which LEDs need to be on.

Then you need some code that runs repeatedly at a fairly short interval, which flashes each of the 'on' segments in turn by switching the appropriate combination of output pins to turn it on and then off. The length of time that each LED is flashed for, and the interval between flashes, needs to be consistent for all LEDs and for all displayed numbers.

I don't have a clue how to take the double digit result of the random function, and correctly display them on the two displays.

  1. Once a random number is generated, load the corresponding segment information into a two-byte buffer called LRAM[2]: LRAM[0] is the tenth digit and LRAM[1] is the single digit.
  2. in your display function, keep track of the current digit to be displayed (using a digit counter)
  3. (optional) turn off all digits.
  4. send the segment information of the current digit to the segments.
  5. turn on the current digit.
  6. advance the digit counter to the next digit.
  7. exit the display function.

All you need to do is to implement the above steps with your code.

Once you have that done, write a timer isr and call the display function from the timer isr periodically.

With that approach, the displaying is done in the background, without user intervention (other than loading up the segment information into the buffer).

ok, couple of quick (hopefully) easy questions.

should I write the array to define the answer as 0-9 or as 0-20.
My highest dice value will be 20, but that can be broken down into 2 and 0 on the display.
I am not sure if I need to write a byte value for 10-20, and if so, how would I do that.

It seems to me it would be easier to write the array 0-9 and call up the proper byte for each digit on each display.

At this point, I am absolutely convinced I am over-thinking this issue, but I have looked at so many different ways of handling a two digit 7 segment display, I think I am getting lost in the options.

second, what exactly is a timing isr?
I know that is probably a dumb question, but it is a term I haven't run into yet, so I am just trying to make sure I look up the right thing :slight_smile:

should I write the array to define the answer as 0-9 or as 0-20.

Doesn't matter.

At this point, I am absolutely convinced I am over-thinking this issue,

More importantly, you are under-doing it: sit in front of your arduino / ide and start coding one step at a time.

At this point, I am absolutely convinced I am over-thinking this issue,

More importantly, you are under-doing it: sit in front of your arduino / ide and start coding one step at a time.

Thanks for the reply!
actually, I have tried writing this up several ways, but haven't even been able to get both displays to work yet.
I have had all kinds of odd results (the right character showing up on the wrong display, and only half brightness, both characters showing on one display one after the other, things like that, but most of the time, I get no result.)

I have been scribbling code on paper all day trying to get this straight in my head. Not sure why I am having so much trouble honestly. everything else I have tried on the arduino has ended up being pretty cut and dry, and worked. At most I have maybe had to scratch my head for an hour or so, until I stumbled on a sample code that I could use correctly to do the job.
I have even had this project working perfectly with a single seven segment display, but wanted to expand it as a challenge to myself, and to learn about multiplexing.
I figured all I would have to do is merge my working code with some example multiplexing code and viola, working digital dice that could be used in a multitude of dice games.
as a matter of fact, once I had this working with my basic setup, I am even looking to add a few more modes, that would allow each display to show results for a single die, allowing for a person to roll two dice at once, and skip having to see one result for three seconds, then roll again to get a second result.

For the overall project I have a long way to go, but I am trying to teach myself the code step by step and increase the complexity as I get one part working.

I really appreciate the advice and patients I am getting with this. I have only been working with electronics for less than two years, and only learned how to use ICs about 6 months ago (555 timer aside, it's hard to learn electronics without running into some good 555 timer projects)
I have had my Arduino for maybe two weeks, and have learned more on how to use it in the last two weeks than I have basic electronics in the last two years.
Much that is discussed on forums such as this one are a bit over my head with the abbreviations and terms I am not familiar with, and I usually just look things up as I run into new information. Usually this process works well for me, but today has been one of those "can't quick wrap my head around it" kind of days...

I am sure I will get it, it will just take some time, and a little tweaking of my current learning curve :stuck_out_tongue:

Neight:
should I write the array to define the answer as 0-9 or as 0-20.
My highest dice value will be 20, but that can be broken down into 2 and 0 on the display.
I am not sure if I need to write a byte value for 10-20, and if so, how would I do that.

It seems to me it would be easier to write the array 0-9 and call up the proper byte for each digit on each display.

Either way could be made to work.

If you have got your LEDs arranged in a single multiplexed matrix then the simplest way to get it working would be to conceptually treat all the segments in both digits as being part of a single display which can display any number from "00" to "20" (or however far you want to go).

If you ever wanted to be able to change the physical arrangement of LED segments (and the wiring to the Arduino, and Arduino pin-outs etc), vary the number of digits you can display, support multiple sets of multiplexed outputs then you could abstract out the concept of an LED segment display than can display a single digit, and the logic used to control each segment via the multiplexed output. This would reduce the amount of code you needed to rewrite when you do similar types of thing in other projects. However, I suggest that, at least at first, you start with the simplest approach and get that working. Unless you plan to implement a lot of different projects using this type of hardware I would doubt that it is worth your time to generalise the software. In any case you can take that decision in future if you get fed up with copying and pasting this code between projects and are confident enough to deal with extra complexity.

It is fairly simple. For example, this would be my implementation, high-level:

void led2_display(void) {
  static unsigned char current_dig=0; //current digit to be displayed. 0=tenth digit, 1=sigle digit

  //turn off all digits, optional
  //DIG_OFF(DIG_0); DIG_OFF(DIG_1);
  switch (current_dig) {
    case DIG_0: DIG_OFF(DIG_1); SEG_OUT(LRAM[DIG_0]); DIG_ON(DIG_0); current_dig=DIG_1; break; //turn off the previous digit, send data to segments, and turn on the current digit, advance to the next digit
    case DIG_1: DIG_OFF(DIG_0); SEG_OUT(LRAM[DIG_1]); DIG_ON(DIG_1); current_dig=DIG_0; break; //turn off the previous digit, send data to segments, and turn on the current digit, advance to the next digit
    default: continue; //do nothing for invalid input
  }
}

Each time led2_display() is called, it shows the next digit (from display buffer LRAM[]). If you call it fast enough, it appears to show both.

You just need to figure out how to implement DIG_ON/OFF() and SEG_OUT() based on your hardware.

Soooo, here we go, totally revised v4.o

I finally threw in the towel on making a dual 7seg display, even with some code I simply copied and pasted, it wasn't quite working right. (the code I copied was for a 4 digit display, while I only had two digits, had to mod it a little, and lost something in the translation...) it would not scroll the message properly, so I got pretty frustrated after a whole weekend spent on it, and went to radio shack and picked up a simple LCD display...

I really like this option for my project, and I think it works better anyway. Now I can always display on the screen which dice mode you are in, and I am now starting to think of ways to add more dice to the mix. that way you can roll multiple dice at the same time. probably going to use a toggle switch and some basic digitalRead arguments to tell the arduino to display 2 or maybe even 3 random results of the current dice mode. Really increase the functionality of this thing.

So far, everything is working nearly perfect. Only glitch is, when I have cycled through all the dice modes, my default D2 mode (coin flip) is called D1 instead of D2. When it first comes on, it shows D2, then D4, D6, D8, D10, D12 and D20 as you cycle through the modes. One more button push should cycle back to D2, but instead reads D1.

here is my code...

#include <LiquidCrystal.h>

LiquidCrystal lcd(2,3,4,5,6,7);

const int mButton = 9;
int mode = 0;
int oldMode = 0;
const int Tilt = 8;
int val = 0;
int oldVal = 0;
int state = 0;

int dValue[] =
{2,4,6,8,10,12,20};

long result;


void setup()
{
  Serial.begin(9600);
  pinMode(Tilt, INPUT);
  pinMode(mButton, INPUT);
  
  lcd.begin(16,2);
  lcd.print("DigiDice - D");
  lcd.print(dValue[state]);
  
  randomSeed(analogRead(0));
}

void loop()
{
  {
    mode = digitalRead(mButton);
    if ((mode == HIGH) && (oldMode == LOW))
    {
      state++;
      {
        lcd.begin(16,2);
        lcd.print("DigiDice - D");
        lcd.print(dValue[state]);
      }
    }
    if (state > 6)
    {
      state = 0;
      delay(10);
    }
    oldMode = mode;
  }
      
  val = digitalRead(Tilt);
  if ((val == HIGH) && (oldVal == LOW))
  {
    result = random(1, dValue[state] + 1);
    lcd.setCursor(0, 1);
    lcd.print("Result = ");
    lcd.print(result);
    lcd.print("       ");
    delay(3000);
  } else
  {
    lcd.setCursor(0,1);
    lcd.print("Give Me A Shake");
    
  }
  Serial.println(result);
}

sorry for the lack of comments, I honestly just threw this together on the fly, and it worked nearly out of the box. I haven't taken the time to comment it yet, but will before I am all done.
pretty basic code, and the LiquidCrystal library is great! Made this a snap.
if anyone could let me know why my dice mode is displaying wrong (I still get the correct expected results, no false numbers outside the dice range) and maybe point me to a fix, I would greatly appreciate it!

This has been a very twisty, educational project for me, and I cannot express how much I have appreciated everyone who took the time to try and walk me through this.

You do have some unnecessary curly braces in there (they aren't hurting anything) and your style differs a bit from mine :slight_smile: but I don't see any obvious reason this should ever print "D1". Quick question - if you press that button again, does it go to D2 or D4 (or something else)?

I am having trouble pinning it down also.
if you push the button again, it goes to D4 like it is supposed to.
The only mode that doesn't display correctly, no matter how many times you cycle through, is D2.

I have tried adding and subtracting 1 at various points in the code where the display is called, but that only seems to effect my dice results, or limits my results by one.
I am honestly stumped, but for the moment it is a minor issue, and I have moved on.
When I get the rest of the functions I am trying to work out done and working correctly, I will probably go back and see if I can fix it.
If it can't be fixed, then so be it, I could have done worse in my opinions :stuck_out_tongue:

Out of curiosity, do you mind explaining how you would have handled it?
I am always interested in learning other ways to do things with the Arduino. The more ways you can do one things, the more tools you have in the toolbox :slight_smile:

I seem to be nutty for curly brackets, I always end up with many of them :stuck_out_tongue:

This bit of code does things in the wrong order:

      state++;
      {
        lcd.begin(16,2);
        lcd.print("DigiDice - D");
        lcd.print(dValue[state]);
      }
    }
    if (state > 6)

You print the new dice value before you do the 'if(state > 6)' check to reset it to zero. The '1' you're seeing on the display is just whatever happens to be in the memory location after the last dice.

A better way to do this would be like this:

      // DICE_COUNT is the number of elements in the dValue array
      state = (state+1) % DICE_COUNT;
      lcd.begin(16,2);
      lcd.print("DigiDice - D");
      lcd.print(dValue[state]);

PeterH:
This bit of code does things in the wrong order:

      state++;

{
       lcd.begin(16,2);
       lcd.print("DigiDice - D");
       lcd.print(dValue[state]);
     }
   }
   if (state > 6)




You print the new dice value before you do the 'if(state > 6)' check to reset it to zero. The '1' you're seeing on the display is just whatever happens to be in the memory location after the last dice.

A better way to do this would be like this:



// DICE_COUNT is the number of elements in the dValue array
     state = (state+1) % DICE_COUNT;
     lcd.begin(16,2);
     lcd.print("DigiDice - D");
     lcd.print(dValue[state]);

you are 100% correct sir!
while you posted that, I had accidentally stumbled on the answer myself, but hadn't realized it yet, or why.
I am very nearly successful at my next stage of complexity with this project.
here is what I am doing with it now....

There is a push button to select through the range of dice modes.
there is a toggle switch to select rolling one dice or two dice at a time. (both dice must be of the same value though, ex - two d6.)
I can get the LCD to display the correct dice mode all through the count now, and I can get two different results with one shake of the dice.

my only problem now is the LCD seems to be trying to display both modes at the same time, and it makes the words flicker like mad, and is a bit hard to read everything.
I am using a switch case at the moment to handle switching between one and two dice per throw. I originally wrote it as an if/else, but changed it to a switch to see if that would cure my screen flicker. It seems to have helped a bit, but it is still very much an issue.
I am working my way through the LCD examples now trying to find out how to change the number of dice, and print two completely different screen readouts, without the flicker
if that makes any sense...

here is the code as I have it wrote now...

#include <LiquidCrystal.h>

LiquidCrystal lcd(2,3,4,5,6,7);

const int nButton = 11;
const int mButton = 9;
int mode = 0;
int oldMode = 0;
const int Tilt = 8;
int val = 0;
int oldVal = 0;
int state = 0;
int number = 0;

int dValue[] =
{2,4,6,8,10,12,20};

long result;
long resultA;
long resultB;


void setup()
{
  pinMode(Tilt, INPUT);
  pinMode(mButton, INPUT);
  pinMode(nButton, INPUT);
  
  randomSeed(analogRead(0));
}

void loop()
{
  mode = digitalRead(mButton);
  if ((mode == HIGH) && (oldMode == LOW))
  {
    state++;
  }
  if (state > 6)
  {
    state = 0;
    delay(10);
  }
  oldMode = mode;
  {
    number = digitalRead(nButton);
    switch(number)
    {
      case 0:
      {
        {
          lcd.begin(16,2);
          lcd.print("DigiDice - D");
          lcd.print(dValue[state]);
        }
        val = digitalRead(Tilt);
        if ((val == HIGH) && (oldVal == LOW))
        {
          result = random(1, dValue[state] + 1);
          lcd.setCursor(0, 1);
          lcd.print("Result = ");
          lcd.print(result);
          lcd.print("       ");
          delay(3000);
        } else
        {
          lcd.setCursor(0, 1);
          lcd.print("Give Me A Shake!");
        }
      }
      break;
      case 1:
      {
        {
          lcd.begin(16,2);
          lcd.print("Roll Two - D");
          lcd.print(dValue[state]);
        }
        val = digitalRead(Tilt);
        if ((val == HIGH) && (oldVal == LOW))
          {
            resultA = random(1, dValue[state] + 1);
            resultB = random(1, dValue[state] + 1);
            lcd.setCursor(0,1);
            lcd.print("R1 = ");
            lcd.print(resultA);
            lcd.print("   R2 = ");
            lcd.print(resultB);
            lcd.print("     ");
            delay(3000);
          } else
          {
            lcd.setCursor(0, 1);
            lcd.print("C'mon...Shake Me!!");
          }
        }
        break;
      }
    }
}

I seem to be off on my curly brackets somewhere, because my indenting is messed up a bit, but I will fix that when I have the whole code in working order.

off to keep researching, but will be happy to hear any suggestions to stabilize my display :slight_smile:

ETA: I should mention that when you shake the "dice", the display does stabilize, and very clearly prints everything it is supposed to.
This makes me think I should have the mode selecting code in both cases, like the Tilt code, and maybe that will work it out.
seems very redundant to me, but this is how we learn :wink:

Again, very happy to take suggestion improvements and general criticism on the project!
be brutal if need be :slight_smile:

I don't think your lcd.print(" "); is long enough to clear the entire line in case 1, try to make it longer and see if that works.

actually, I might not even need the " " anymore.
that was there to clear the rest of the line earlier on.

I did fix the flicker problem after all.
at some point I must have deleted the line of code that initializes the screen size and positions
(lcd.begin(16,2))
without that, it was writing the data over and over on the whole screen. The only reason text was visible at all is because of the repetitiveness of the message...

Now that I have put the initialization code back in the setup, it works like a charm, and is quite beautiful if you ask me :stuck_out_tongue:

May not be the most efficient way to do it ( I am assuming it isn't anyway) but it works perfectly, and I quite enjoy it.
Now to add some effects to make it a bit more fun to watch.
trying to figure out some simple animation to represent the dice rolling for a moment before displaying the results.

Even had an idea to mount this in a project box, and make a small box inside the project box that would hold an actual dice. That way, when you shake the dice roller, there is a real dice rolling sound to go along with the shaking :slight_smile: (kind of like the sound when you shake dice in a cup while playing yatzee. Matter of fact, this kind of makes me want to make a whole new code specifically to handle dice rolling for yatzee. building the new one around a full set of yatzee dice, and being able to roll them all at once, just like in the real game.

which makes me wonder how hard it would be to write code to play actual yatzee on the arduino would be....
good lord, I am getting ahead of myself here (to be honest, I have never played yatzee, so I don't know all the rules, but I know the game is structured around dice, so it has my brain spinning)

Rather than adding physical dice, you might continue the Arduino theme and see whether you can make your Arduino output the sound of dice rolling in a cup.

You might also add an accelerometer/tilt switch so that it makes the 'rolling' sound when you shake it, and rolls the dice when you put it down.

PeterH:
Rather than adding physical dice, you might continue the Arduino theme and see whether you can make your Arduino output the sound of dice rolling in a cup.

You might also add an accelerometer/tilt switch so that it makes the 'rolling' sound when you shake it, and rolls the dice when you put it down.

sounds like another shopping trip to me :stuck_out_tongue:

First thoughts on that would be a music shield, or build my own, with an mp3 on an SD card of a dice rolling sound.

I have been wanting to pick up an accelerometer and play with it, and this is as good an excuse as any!

Great ideas BTW, and thanks for the suggestions. It would keep the project that much more compact not having to build a chamber large enough for a die to roll around in.

I also like the shake then put down to roll idea quite a bit. Anything to increase the sensation of rolling dice would be a good thing in my opinion.
thinking about an enclosure for this one, and making something permanent out of it. It's been a struggle, and it would make a fun souvenir when I get it all done. Could even have two larger modes, one for d2 - d20 for strategy gaming, and one that is just a set of multiple six sided dice for yatzee style, so you can roll both ways if you choose.
Lots of expansion could be done on this project, and this could really be a neat addition to any game where dice are involved :slight_smile:
Heck, I might even try for a third option, and come up with my own dice based game that could be played with two (or more?) players, and could be played all on the arduino with no external game mechanics involved.
Wonder how long it would take me to find the limits of the arduino with a dice rolling project?...