pinball project (space cadet)

oh no, i realised it would be complicated. it seemed to good to be to true. my overall design hinges on it though (probs find another way in a pinch), i'll be copy and pasting my sound board from the light and just changing the "events" while keeping the names, so hoping to share the data control to save mega pins

An array of structs you say? i think i should get reading lol

Thank you! :slight_smile:

I would solve that with a long switch/case statement.

Also keep your Serial communications short, one or two values, to keep it fast. Use constants or #define statements to replace it with human readable commands in your code.

If you have less than 255 commands you can do it in a single character on the Serial. You may even be able to do away with start/stop bytes, even faster. Just a single value, every one value has a meaning. If more than 255 you need two bytes, and start/stop bytes (use e.g. 0 or 255 for that).

So you’d get code like this in the slave:

#define BANK1_HIT 1
#define BANK1_RESET 2
#define BANK2_HIT 3
#define BANK2_RESET 4

void loop() {

  // bank 1 hit! Send notification to host.
  Serial.write(BANK1_HIT);

}

And on the receiving end:

#define BANK1_HIT 1
#define BANK1_RESET 2
#define BANK2_HIT 3
#define BANK2_RESET 4

void loop() {

  command = Serial.read();
  switch (command) {
    case 1:
      bank1_hit();
      break;

    case 2:
      bank1_reset();
      break;
  }
}

You can use a #include to keep your list of #defines in sync between the various sketches.

wvmarle:
I would solve that with a long switch/case statement.

Also keep your Serial communications short, one or two values, to keep it fast. Use constants or #define statements to replace it with human readable commands in your code.

If you have less than 255 commands you can do it in a single character on the Serial. You may even be able to do away with start/stop bytes, even faster. Just a single value, every one value has a meaning. If more than 255 you need two bytes, and start/stop bytes (use e.g. 0 or 255 for that).

So you'd get code like this in the slave:

my original thoughts where using while statements pretty much the way your describing. but in the context of your example ending each while statement with a "command = 0;" is there any reasons i'd use the case over the while? or vica versa? and thank you. I think i'm gonna go have a play with that idea :slight_smile:

wvmarle:
You can use a #include to keep your list of #defines in sync between the various sketches.

i have a dedicated file in notepad with all my header and void setups, everytime i add more features or start something new i take what a copy to my new sketc. then at the end go back update the file. in truth i wouldn't be sure how to include other sketches variables, is it the same as adding a library?

aka_daz:
is there any reasons i'd use the case over the while? or vica versa?

The while statement is a loop. The switch/case and if/else statements are selectors. Very different use case.

i have a dedicated file in notepad with all my header and void setups, everytime i add more features or start something new i take what a copy to my new sketc. then at the end go back update the file. in truth i wouldn't be sure how to include other sketches variables, is it the same as adding a library?

Pretty much like adding a library indeed - save your headers in a .h file in your libraries folder, then include that in the top of your sketch and it'll be read at compile time.

so i been making a lot of various boards and what not for lighting control and decided to have a go at the serial control:

#include <Shifty.h>


#define GAME_START 1
#define BALL_LOST 2
#define GAME_RESET 3
#define BANK2_RESET 4

Shifty shift;


// Declare pins for CLK, DTA, LTCH
int CLK = 11;
int DTA = 12;
int LTCH = 8;
int delayTime = 250;
int command = 256;

void gameStart (){
  shift.writeBit(1, HIGH);
  delay(delayTime);
  shift.writeBit(1, LOW);
  delay(delayTime);
}
void ballLost (){
  shift.writeBit(2, HIGH);
  delay(delayTime);
  shift.writeBit(2, LOW);
  delay(delayTime);
}
void setup(){
	Serial.begin(9600);
	shift.setBitCount(16);
	shift.setPins(CLK, DTA, LTCH);
}
void loop() {

  command = Serial.read();
  switch (command) {
    case 1:
      gameStart();
      break;

    case 2:
      ballLost();
      break;
  }
}

i cant get it to work… i send the command and nothing… i know how i have this set up (wiring etc) that its all working , i can start a new sketch, insert “shifty” library with the same variables and control any led. my error has come from the serial, i think i’m missing something glaringly obvious but can’t place it… the fact i’m using the serial monitor to send commands should affect it should it? (same baud rate)

You're looking for a command of character 1, which is hard to send from serial. Try 49 instead, or:

    case '1':
      gameStart();
      break;

Note single quotes.

single quotes worked, thank you!!! thats been irritating me for ages lol

aka_daz:

int command = 256;

This should probably be a single byte type, so one of:

byte command;
char command;
uint8_t command;
unsigned short int command;

256 does not fit in a single byte, by the way. 255 is the highest number allowed.

(edit: fixed bbcode)

it was deliberate. it was part of my debugging to make sure it wasn’t in a case on startup. it will all be changed by the time i get to revision 1. nicely spotted though! thanks for the warning :slight_smile:

my work for today, i am having a new issue

#define sel1 0
int sel1s = LOW;

#define sel2 1
int sel2s = LOW;

int row1[] {sel1, sel2, sel3, entry1, entry2, entry3, 6, 7};
int row1s[] {sel1s, sel2s, sel3s, entry1s, entry2s, entry3s, LOW, LOW};


void SEL1() {
  if(sel1s == LOW){
	  sel1s = HIGH;
  }
  else(){
	  sel1s = HIGH;
  }
}


void ballLost () {
  shift.writeBit(1, HIGH);
  delay(delayTime);
  shift.writeBit(1, LOW);
  delay(delayTime);
}

void setup() {
  Serial.begin(9600);
  shift.setBitCount(16);
  shift.setPins(CLK, DTA, LTCH);

  for (thisPin = 0; thisPin <= 15; thisPin ++) {
    shift.writeBit(thisPin, LOW);
  }

}
void loop() {

  command = Serial.read();
 // for (int x = 0; x <= 2; x++) {
       // thisPin=0;
        for (thisPin = 0; thisPin <= 6; thisPin++) {
          shift.writeBit(row1[thisPin], row1s[thisPin]);
          delay(5);
        }
        delay(5);
        if(thisPin=6){
          thisPin = 0;
        }
   //   }
  switch (command) {

    case '0':

      
      break;
      
      
    case '1':
      SEL1();
      command = 256;
      break;

    case '2':
      ballLost();
      break;

  }
}

that isn’t all of it so anything that looks “undefined” is actually in my code, just copied where i think the problem lies…

when i parse in a 2 sel2 (number 1 on my bitwrite) lights up and goes off as it should, when i parse in a 1 nothing happens… if i was to put the “row1s=row1s {sel1s, sel2s, sel3s, entry1s, entry2s, entry3s, LOW, LOW};” inside my for loop just before the writeBit part would that sort it? or do i require another way?

my ultimate aim is to have the incoming data modify these states so the main program is essentially just displaying everything.

You’re going to need lots of states, but: are you sure about adding delay() calls there? I thought this code is to be as responsive as possible!

When you get a '1' you call this:

void SEL1() {
  if(sel1s == LOW){
	  sel1s = HIGH;
  }
  else(){
	  sel1s = HIGH;
  }
}

That flips sel1s, but it'll have no effect on your display. I'm guessing you're expecting that when you declared this:

int row1s[] {sel1s, sel2s, sel3s, entry1s, entry2s, entry3s, LOW, LOW};

That row1s's first element will always take it's value from sel1s. It won't. It takes it when it's declared, but afterwards, changing sel1s has no effect on row1s.

You could do it with pointers, but easier is just to do it directly:

void SEL1() {
  if(row1s[0] == LOW){
	  row1s[0] = HIGH;
  }
  else(){
	  row1s[0] = HIGH;
  }
}

Better if you declare a const to use instead of a literal zero of course.

No () after else.

void SEL1() {
  if(row1s[0] == LOW){
	  row1s[0] = HIGH;
  }
  else{
	  row1s[0] = HIGH;
  }
}

@wvmarle - yes i am lmao, 64 inputs one output each so 64 states, plus i figured i could use to double up and add some lighting effects so 128 all together, which by extension means 128 functioning subroutines… that’s why i’m so keen to get the “array” (i think it’s called an array) working how i envision it

the delays need to go, i just haven’t deleted them yet, though for the time being responsiveness no issue. they where part of a failed test to see if the lack of delay was the issue… it wasn’t.

@wildbill - you summed up my expectations perfectly! lol
i was thinking that maybe the data was compiled that way… wasn’t sure of the workaround… thank you! might actually get my scale model built today :slight_smile:

@wvmarle - i always make that mistake, “else(){~~}” the IDE must hate me for it lol

Yes, arrays are the way to go.

Be careful with your types - if you use byte it's one byte per state, and of course you can store both the light and input states in a single byte if you start to run out of space (after all an input is a single bit, a light on/off is a single bit, so 128 on/off states can fit in 16 bytes.

In fact you can create 64-bit variables, you can approach them as if they are an array of 64 bools.

Though you may still consider to use a long list of defines so you can at least assign a readable name to them, and so keep track of which light or switch you're looking at.

this board doesn't actually deal with inputs per say, i gave it "virtual" inputs by having it respond to state changes instead, this is just the "graphics card". The "motherboard" my mega is what takes the readings and calculates level progress score etc and then Serial.print(appropraite instruction) to sound and the light board... though i did click on early that multiples of 8 is the way to go seeing as my main switching board consists of 595s

wvmarle:
Be careful with your types - if you use byte it's one byte per state, and of course you can store both the light and input states in a single byte if you start to run out of space (after all an input is a single bit, a light on/off is a single bit, so 128 on/off states can fit in 16 bytes.

In fact you can create 64-bit variables, you can approach them as if they are an array of 64 bools.

that mostly went straight over my head to be honest lmao. in truth, what i have done so far is pushing to the extremes of my current understanding..

i mean a bit is either 1 or 0, on or off i get that. a byte is an arrangement of 8 bits with the first one to the right (lsb) how to use that in a meaningfull way... that's why i'm using the shifty library. all i have to do is writeBit(output number, state); could you perhaps suggest some reading please? i tried the examples but they didn't help

p.s. i think whatever method i approach this with will require at least defines equating to outputs*3 in my header

Look at bitwise operations (bitwise and, or, not, xor are very useful, as are bit shifts which sometimes can take the place of multiplications: times 2 is the same as shifting one bit left):

byte x = 13;
byte y = x * 2; // multiplication; y = 26
byte z = x << 1; // bitwise left shift; z = 26

The third line takes one operation. The second line many more.

bitRead() and siblings are useful here as well.