Go Down

Topic: (not a ) switch case question (anymore...) (Read 3 times) previous topic - next topic

Neight

Jan 08, 2013, 09:18 pm Last Edit: Jan 12, 2013, 08:17 pm by Neight Reason: 1
Ok, I have a quick question about using switch cases.

Is it possible to use a switch case within a switch case?

my goal here is to make a 7 segment display dice roller.  I have already successfully made a shake-to-roll 6 sided dice (shake the breadboard and the 7seg will display 1-6 "randomly")
Now as a personal challenge, I am trying to make one 7seg display work as many different kinds of dice.
2 sided (coin flip), 4 sided, 6 sided, 8 sided.... so on, up to a 20 sided dice.
this would basically be a whole set of gaming dice in one little unit, fully controlled with the Arduino, no ICs.

I am doing this by using a press button to switch between dice modes (how many sides)
and using a tilt switch to trigger the shake-to-roll function, which will give a result on the 7seg that will be limited by which dice mode you are in.

I hope I am not being confusing...

here is an example -

default mode will be 0
mode 0 is a 2 sided coin flip or yes/no
button press
now it is mode 1 which is a 4 sided dice.
so on and so on up to mode 7 which is 20 sided, and then reset to default  mode 0

I am not to the point of posting the code and asking specific questions yet, I am trying to work this out on my own.  I am very new to writing code and micro controllers, and I am trying to learn, which I do best while problem solving.  
All I really need to know for the moment is if you can use a switch case to change dice modes, and use a sub-switch case? to give the results also.

sorry for being so long, but I really wanted to be clear, because I am also still learning how to communicate with the Arduino crowd :P
absence of proof is not proof of absence

billroy

Yes, you can use a switch within a switch case.

-br

HazardsMind

#2
Jan 08, 2013, 09:29 pm Last Edit: Jan 08, 2013, 09:31 pm by HazardsMind Reason: 1
4 sided dice? I thought dice had 6 sides, you must be confusing those weird 4 sided pyramid dice things.

As for a case within a case, not sure, I dont have my laptop to do any tests on my end.

Edit: I guess you can.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

Neight

excellent!
thank you both for the quick replies!

I had this idea last night, then changed my mind when I started writing the code.  I got about halfway through the code as I was writing it last night, and decided to test it.  At first it would just run the first step in a loop, regardless of any buttons or switches.  I managed to fix that, but then it wouldn't change modes, I was stuck at mode 0(2 sided).  Not to mention it was getting quite long and complicated.

Today I have decided to scrap that, and go with my original idea, because I think it will write up much more cleanly.
errr, I hope ;)


@HazardsMind Yes, this would be the pyramid dice.  My inspiration for this project is a digital set of D&D dice, so those are the modes I am using.
I only have one 7seg display at the moment, so I am using the dot at the bottom to indicate double digit numbers.

it's been an educational project, and really builds on many of the tutorials I have done so far :)
absence of proof is not proof of absence

Jimmy60

Yes you can but I don't see why you'd need to in this case.

It sounds to me like you select a mode once, then roll as often as you want.  You could use an array to store how many sides each mode represents then use the mode as the index. I don't really see a need for a switch statement at all but you must have another idea.

Code: [Select]

// I see it like this
int mode = 0;
int dice[] = {2, 4, 6, 8, 10, 12, 20}; // or whatever your dice are

void loop(){

// Check the button and increment mode with rollover (0..6)

// if the device is shaken call the random function (I'll assume it's seeded)

int rollResult = random(dice[mode]); // you may want to add one to this

// display roll result

}

// there is quite a bit of code assumed in these comments I was really just demonstrating my logic


PeterH

I don't see why you'd want to use a switch statement at all, for that problem. It seems to me that all you need is:

A constant array of integers holding the size of each die you're supporting.
A state variable which is an index into that array, identifying the currently-selected die.
Some event handling code to increment the selected die variable modulo the number of dice.
Some event handling code to generate a random number within the range of the currently-selected die and pass it to a display function.
A display function that renders a specified value on your display.

I'm not clear how you'd display any value over 9 on a seven-segment display, but presumably you have a scheme in mind.

ETA: Or in other words, I agree with Jimmy60. :)
I only provide help via the forum - please do not contact me for private consultancy.

Neight


Yes you can but I don't see why you'd need to in this case.

It sounds to me like you select a mode once, then roll as often as you want.  You could use an array to store how many sides each mode represents then use the mode as the index. I don't really see a need for a switch statement at all but you must have another idea.

Code: [Select]

// I see it like this
int mode = 0;
int dice[] = {2, 4, 6, 8, 10, 12, 20}; // or whatever your dice are

void loop(){

// Check the button and increment mode with rollover (0..6)

// if the device is shaken call the random function (I'll assume it's seeded)

int rollResult = random(dice[mode]); // you may want to add one to this

// display roll result

}

// there is quite a bit of code assumed in these comments I was really just demonstrating my logic




lol, you actually jumped ahead of me a bit :p
right now, I am trying to work this out step by step.  Then once I have it working and I know why it works the way it does, I was planning on implementing an array to shorten it and learn some short cuts in the code.
I did this with my last project (sonar distance sensor with LED bar graph and Piezzo buzzer tones) and felt like I learned much more by figuring out two totally different ways to "skin this cat"

I have a lot of plans on things I want to build with the Arduino, and I am trying to focus on making projects that teach me code that I can use later for some of these bigger projects.
makes toys now to learn off of, and when I know better what I am doing, start working on bigger more complicated projects for my home :)
working on getting "off grid" step by step, and I can see many ways in which Arduino will make this much easier!
Plus I am a tinker-er at heart, and thoroughly enjoy the process.

Thanks for the advice, and when I get this one working today, I am sure I will be back to work out how to work in arrays and lose the switches :)
absence of proof is not proof of absence

Neight

#7
Jan 08, 2013, 10:50 pm Last Edit: Jan 08, 2013, 10:55 pm by Neight Reason: 1

I don't see why you'd want to use a switch statement at all, for that problem. It seems to me that all you need is:

A constant array of integers holding the size of each die you're supporting.
A state variable which is an index into that array, identifying the currently-selected die.
Some event handling code to increment the selected die variable modulo the number of dice.
Some event handling code to generate a random number within the range of the currently-selected die and pass it to a display function.
A display function that renders a specified value on your display.

I'm not clear how you'd display any value over 9 on a seven-segment display, but presumably you have a scheme in mind.

ETA: Or in other words, I agree with Jimmy60. :)


Thanks for the reply Peter!
since I will not need to display any number higher than 20, I am using the dot to indicate double digits.
1-9 are normal,
now for 10, you would see a 0 and the dot on the bottom lit up
like this - 0.
then 11 = 1.
12 = 2.
continue up to 19 = 9.
for 20 it will display what will look like l l.  (both sides lit up, all middle segments off and the dot on.  it's supposed to be the roman numeral II, best idea I could come up with) 

its a personal challenge, to learn as much as I can from each project by doing it two different ways.

edit:  plus, the random number generating method I am using here uses randomSeed(analogRead(0)) to generate the random number, then the switch case to light up the right segments of the display.
it was the easiest way I found to make the 6 sided I made last night.
when that worked out so well, I went for the bigger challenge of multiple dice modes.
absence of proof is not proof of absence

Neight

well, I got it done, and it works great!

I worked it out both ways, though the first way I did it was buggy and clumsy, but it worked.
I am quite sure I can improve upon it, and might try someday :)

I also took the advice I was given on this forum and make a v2.0
It took a bit longer to finish than I was hoping for, but it's a pretty slick little device, if you don't mind translating a single digit display into a two digit answer...
but no ICs are used off the board, and it has a dice range of 2, 4, 6, 8, 10, 12, and 20
will post the code for review and possible suggestions for improvement, cause I love to learn, and there seem to be many ways to do about anything with the Arduino, and some are much easier than others :P

Quote

/*  this is a sketch to use a single 7 segment display as many different kinds of dice.
    the choices of dice value are 2, 4, 6, 8, 10, 12, and 20, based around a complete set of D&D dice values
    it uses a button press to select and display which mode of dice you are using
    and a tilt switch for shake-to-roll activation of random number generator.
    no external ICs were harmed (or used) in the making of this sketch */

byte Display[23][8] =  //define 7seg digit patern
{
  {0,1,1,0,0,0,0,0},  // "1"
  {1,1,0,1,1,0,1,0},  // "2"
  {1,1,1,1,0,0,1,0},  // "3"
  {0,1,1,0,0,1,1,0},  // "4"
  {1,0,1,1,0,1,1,0},  // "5"
  {1,0,1,1,1,1,1,0},  // "6"
  {1,1,1,0,0,0,0,0},  // "7"
  {1,1,1,1,1,1,1,0},  // "8"
  {1,1,1,0,0,1,1,0},  // "9"
  {1,1,1,1,1,1,0,1},  // "10"
  {0,1,1,0,0,0,0,1},  // "11"
  {1,1,0,1,1,0,1,1},  // "12"
  {1,1,1,1,0,0,1,1},  // "13"
  {0,1,1,0,0,1,1,1},  // "14"
  {1,0,1,1,0,1,1,1},  // "15"
  {1,0,1,1,1,1,1,1},  // "16"
  {1,1,1,0,0,0,0,0},  // "17"
  {1,1,1,1,1,1,1,1},  // "18"
  {1,1,1,0,0,1,1,1},  // "19"
  {0,1,1,0,1,1,0,1},  // "20"
  {1,1,1,1,1,1,0,0},  // "0"
  {0,1,1,1,1,0,1,0},  // "d"
  {0,0,0,0,0,0,0,0},  // off
};

int dValue[] =  //define dice value array
{2, 4, 6, 8, 10, 12, 20};

const int Button = 12;  //assign push button to pin 12
const int Tilt = 11;  //assign tilt switch to pin 11
int mode = 0;  //assign variable mode, and store
int oldMode = 0;  //assign variable old mode, and store
int val = 0;   //assign variable val, and store
int oldVal = 0;  //assign variable old val and store
int state = 0;   //assign variable state, and store

void setup()
{
  pinMode(Button, INPUT);  //assign each pin used as input or output
  pinMode(Tilt, INPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(13, OUTPUT);
  writeDot(0);  //start with "dot" off
 
  randomSeed(analogRead(0));  //read analog pin 0 to seed random number
}

void writeDot(byte dot)  //assign function writeDot as a byte named "dot"
{
  digitalWrite(9, dot);  //write dot to pin 9
}

void sevenSegWrite(byte digit)  //assign function sevenSegWrite to byte "digit"
{
  byte pin = 2;  //start writing sevenSegWrite at pin 2
  for (byte segCount = 0; segCount < 8; ++segCount)  // increpent segCount up by one
  {
    digitalWrite(pin, Display[digit][segCount]);  //Write "pin" 1 or 0 according to the defined array
    ++pin;  //advance to next pin
  }
}

void loop()
{
  {
    mode = digitalRead(Button);  //read push button
    if ((mode == HIGH) && (oldMode == LOW))  //check button state
    {
      state++;  //if button mode has changed, increment state up by one
      {
        sevenSegWrite(21);  //if state has gone up, display "d" on 7seg
        delay(500);      //delay .5 second
        sevenSegWrite(22);  //turn 7seg off
        delay(250);      // delay .25 second
        sevenSegWrite(dValue[state] - 1);  //display the dice value currently selected
        delay(500);     //delay .5 second
        sevenSegWrite(22);  //turn off 7seg
      }
    }
    if (state > 6)  //if state is greater than 6 roll back to 0 then delay 10mS
    {
      state = 0;
      delay(10);
    }
    oldMode = mode;  //old mode is now the mode
  }
 
  val = digitalRead(Tilt);  //read tilt switch
  if ((val == HIGH) && (oldVal== LOW))  //check for switch state change
  {
    {
      digitalWrite(9, HIGH);            //displays a . . . on 7 seg
      delay(250);                       //before showing dice result
      digitalWrite(9,LOW);              //did this for dice rolling effect
      delay(250);                       //dramatic pause kind of thing
      digitalWrite(9, HIGH);
      delay(250);
      digitalWrite(9,LOW);
      delay(250);
      digitalWrite(9, HIGH);
      delay(250);
      digitalWrite(9,LOW);
      delay(250);
    }
    {
      byte Result = random(dValue[state]);  //assign variable Result and set it equal to the random seed related to the state count as a upper limit
      sevenSegWrite(Result);  //display the result on 7seg
      delay(3000);  //delay 3 seconds
      sevenSegWrite(22);  //turn off 7seg
    }
  }
  digitalWrite(13, HIGH);  //turn on led @ pin 13 as "on" indicator light
}



let me know what you think!
absence of proof is not proof of absence

AWOL

Quote
let me know what you think!

Code: [Select]
byte Display[23][8]
I think you're using eight times as much RAM as you need to.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Neight

@AWOL

thanks for the reply :)

TBH I have only had my arduino for less than two weeks, and haven't wrote a sketch large enough to even begin wondering how much is "too much".  (at least not as far as I know.  haven't "hit the wall" yet and had to figure out why)

If you don't mind, could you explain how it is too much, and maybe give me a clue as to how to start making it more efficient.

I do notice that your estimate of how much I am over-using RAM matches the [8] at the end of the quote, I am guessing there is a relationship?

The bit of code I learned that array function from was very sparsely commented, and I had to figure out what much of it meant by trial and error.
If I made a change that didn't work with my sketch, I would go back and change something else until I got closer to what I wanted.
There are even a few lines in there that I am not completely clear on what they are doing.  (which you may have guessed at by the vagueness of my own commenting)

Also, the original sketch where that line came from was made to just count down from 9 and start over automatically, with no control input.  I adapted it for what I wanted, the best I know how so far.  I assumed that the way it was wrote simply told the arduino how many digit to look for to define each byte that was displayed on the 7seg.

Thank you for the honest reply.  I know sometimes people don't want to crit someone else' work, but I am here to learn, and that means doing it wrong until I know how to do it right....

any suggestions for improvement, or a point in the right direction is greatly appreciated!
absence of proof is not proof of absence

AWOL

Can you see that :
Code: [Select]
byte Display[23][8] =  //define 7seg digit patern
{
  {0,1,1,0,0,0,0,0},  // "1"
  {1,1,0,1,1,0,1,0},  // "2"
  {1,1,1,1,0,0,1,0},  // "3"
  {0,1,1,0,0,1,1,0},  // "4"
  {1,0,1,1,0,1,1,0},  // "5"
  {1,0,1,1,1,1,1,0},  // "6"
  {1,1,1,0,0,0,0,0},  // "7"
  {1,1,1,1,1,1,1,0},  // "8"
  {1,1,1,0,0,1,1,0},  // "9"
  {1,1,1,1,1,1,0,1},  // "10"
  {0,1,1,0,0,0,0,1},  // "11"
  {1,1,0,1,1,0,1,1},  // "12"
  {1,1,1,1,0,0,1,1},  // "13"
  {0,1,1,0,0,1,1,1},  // "14"
  {1,0,1,1,0,1,1,1},  // "15"
  {1,0,1,1,1,1,1,1},  // "16"
  {1,1,1,0,0,0,0,0},  // "17"
  {1,1,1,1,1,1,1,1},  // "18"
  {1,1,1,0,0,1,1,1},  // "19"
  {0,1,1,0,1,1,0,1},  // "20"
  {1,1,1,1,1,1,0,0},  // "0"
  {0,1,1,1,1,0,1,0},  // "d"
  {0,0,0,0,0,0,0,0},  // off
};

could be written
Code: [Select]
byte Display[23] =  //define 7seg digit pattern
{
  0b01100000,  // "1"
  0b11011010,  // "2"
  0b11110010,  // "3"
  0b01100110,  // "4"
//and so on until
  0  // off
};
?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

AWOL

Quote
I wonder If you can save a little more RAM if you make the display digits in HEX instead of binary.

You're joking, right?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

HazardsMind

#13
Jan 09, 2013, 02:21 pm Last Edit: Jan 09, 2013, 02:32 pm by HazardsMind Reason: 1
@AWOL
I know they are the same representation,-_- but does it take the lenght into consideration too or just what it represents?
I dont know whats easier on the compiler, even though in the end, it is still 1s and 0s.

Edit: I answered my own question, and no change.
My GitHub:
https://github.com/AndrewMascolo?tab=repositories

Neight

Quote from: AWOL link=topic=141626.msg1064083#msg1064083 date=1357736627/

could be written
Code: [Select]
byte Display[23] =  //define 7seg digit pattern
{
  0b01100000,  // "1"
  0b11011010,  // "2"
  0b11110010,  // "3"
  0b01100110,  // "4"
//and so on until
  0  // off
};
?



OK, I think I see where you are going with this :)
the way I wrote it, it has to remember every char each time the display is activated, where as the way you wrote it, cherry-picks the line requested and leaves out the rest?
at least that is the best way I can come up with to explain it, sorry communication isn't my strong suit...

forgive me for asking, but what exactly does the "0b" do at the beginning (starting to think I am answering my own question here) of each line.
My first thought on that would be, the "0" sets the start point, and "b" tells the arduino where to begin reading each line.  It digitalWrites each pin I/0 until it hits the next "0b" where it stops.
absence of proof is not proof of absence

Go Up