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

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?...

guess I am not doing as well as I hoped...

Tried rearranging the code to take out some elements I thought were redundant (like having the mode select code in both cases.)
now, the dice values displayed are not right again.
The roll results are still good, and the rate they cycle through the dice modes when you push the button is still correct also.
now, when you turn it on, it shows you are in D2 mode, which is correct, from there it goes through D4, D6, D8, D10, D12, then D20 which is also right.
Here is where it gets odd.
it hangs on 20 for two pushes, then goes to 40, 60, 80, 10, 12, 20, 20, 40, 60.... on like that.
after the first time though, it starts displaying the modes in tens, instead of single and double digits.
on the second pass, the dice modes are still right, but the name for them is wrong.
once again, I cannot see where the code is making the error, so without further ado...

#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);
  
  lcd.begin(16,2);
  
  randomSeed(analogRead(0));
}

void loop()
{
  {
    mode = digitalRead(mButton);
    if ((mode == HIGH) && (oldMode == LOW))
    {
      state++;
    }
    if (state >= 7)
    {
      state = 0;
      delay(10);
    } oldMode = mode;
  }
  {
    number = digitalRead(nButton);
    switch(number)
    {
      case 0:
      {
        {
          lcd.setCursor(0,0);
          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.setCursor(0,0);
          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;
    }
  }
}

This is where I have it at now.
The mode select part of the code seems to be working right, and I have wrote it several different ways, to test it.
The code to show the dice value isn't something I changed, and it went from working fine to not. Don't know what happened.
any help would be awesome.
it is possible I just need fresh eyes on it, and the problem is fairly obvious, but for right now, I am stumped.

Neight:
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.

Have you considered using a cup of some sort as the enclosure? Perhaps with the display in the base so that you shake it, put it down upside down, and see the rolled values displayed in the base? Just make sure nobody tries to drink out of it. :slight_smile:

PeterH:

Neight:
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.

Have you considered using a cup of some sort as the enclosure? Perhaps with the display in the base so that you shake it, put it down upside down, and see the rolled values displayed in the base? Just make sure nobody tries to drink out of it. :slight_smile:

Man, you are full of great ideas!
I have been looking into 3D printers lately, and could even design and print something that could fit the hardware and battery in nice and secure.
very cool, I really did hope this project would turn into something fun and long term, that I could actually use. I really liked the idea, and its only getting better as I move on!

Neight:
it hangs on 20 for two pushes, then goes to 40, 60, 80, 10, 12, 20, 20, 40, 60.... on like that.
after the first time though, it starts displaying the modes in tens, instead of single and double digits.

This one I know :slight_smile:

What's happening is you're overwriting the two digit number with a one digit number... with nothing to write in the second digit, the LCD continues to display what was already there. Try using sprintf to format your number. That should get rid of the unwanted 0

djjoshuad:

Neight:
it hangs on 20 for two pushes, then goes to 40, 60, 80, 10, 12, 20, 20, 40, 60.... on like that.
after the first time though, it starts displaying the modes in tens, instead of single and double digits.

This one I know :slight_smile:

What's happening is you're overwriting the two digit number with a one digit number... with nothing to write in the second digit, the LCD continues to display what was already there. Try using sprintf to format your number. That should get rid of the unwanted 0

HA! you were right :smiley:
I should have seen that, it wasn't the first time I ran into that problem, but last time it was much more obvious, I had a whole word that never left the screen.
I took the easy way out for a fix though, I just added a couple of spaces next to the result so it turns off the couple of spaces after every number.

Not sure why that started all of a sudden, but it's fixed now, and I probably just accidentally deleted something when I was rearranging the code...

Thank you so much for pointing out my error!

Now to start having fun with the display, make it a little more showy :slight_smile: