(Topic ID: 118048)

A Uno based Williams System 3 to 6 display controller


By uncivil_engineer

5 years ago



Topic Stats

  • 13 posts
  • 4 Pinsiders participating
  • Latest reply 5 years ago by Snux
  • Topic is favorited by 3 Pinsiders

You

Linked Games

No games have been linked to this topic.

    Topic Gallery

    There have been 5 images uploaded to this topic. (View topic image gallery).

    IMG_2701.JPG
    IMG_2699.JPG
    IMG_2612.jpg
    IMG_2689.jpg
    IMG_2692.JPG

    #1 5 years ago

    Ive been posting this in the Early Solid State section, but I have been told you guys might appreciate it more over here in the mod section.

    So here is the problem I started with: If I convert an early solid state William machine to a P-roc system, what would I use to control the displays? Now I don't actually have my hands on the P-roc boards yet, and it does have some capability to control a display, but it is not set up for system 3. I have been told I could possibly re-write the drivers to drive the System 3 master display board, and I may eventually do that once I get a P-roc.

    However, I decided to try to get it to run on an Arduino Uno. I had one from an earlier project, and it seemed the perfect candidate to take serial input off the USB, and generate the signals needed to run the master display board.

    I used a cheap usb oscilloscope to figure out exactly what signals the old Williams system 3 master board was using for inputs. It turns out it was a fairly simple arrangement where each digit in the displays would get 'strobed' at a rate of about 60hz. When the display was strobed, a pair of BCD chips were used to send the the number to the display.

    The Arduino Uno could re-create both signals, but there was one problem. The Uno was limited to about 18 usable outputs, and to drive the display board, I would need 25 outputs. So enter the 74HC595 register shift chip. These chips will take an input byte using three inputs pins, and output to 8 outputs, and as a bonus, you could daisy chain them together to create as many outputs as you need.

    In my final design, I ended up using 2 74HC595 chips, and they drove all 16 of my strobe inputs.

    After building a prototype that did nothing but light up LEDs on my benchtop, I went ahead and bought a screw shield to solder up a prototype. A screw sheild is a board that sits on top of the Uno, and can be used to connect wires to the outputs. You can also use the center area to put components in.
    The benchtop prototype
    building the final prototype on a screw shield

    I also got a wiring harness off ebay from another early Williams solid state pin that I used to create a harness to connect my Uno to my Flash pinball machine.

    The software that drives the board is written in C, using special libraries especially developed for the Uno. I anyone would be interested, I can post the code I used. The software takes a serial input from the USB that is wrapped in <>. It then looks at the first three characters of the input to decide which display the score goes into. So if I send it <P1333333>, it puts all threes in the player 1 display. I also implemented using 'B' for blank spaces, and having a <G> turn on all the displays, and <B> turn them all off.

    Honestly, I was really surprised when it mostly worked when I plugged it in for the first time. I had a few minor software bugs to work out, but now it works like a champ!
    The final board
    Driving numbers
    IMG_2701.JPG

    #2 5 years ago

    Nice. Looking forward to seeing how this comes together when you get the Sys11 board, the P-ROC and really start tinkering.

    Do you post your sketch code anywhere? I have an Arduino (Nano in my case) running in my machine controlling the dozen or so RGB inserts, and that talks to the controller PC via USB. Would like to compare notes sometime

    #3 5 years ago

    I have not posted the code before, so here it is:


    //Stream Code V0.3
    //by Uncivil_Engineer
    //Copywrite 2015
    //can only be used for personal use, not for commercial sale.

    //The purpose of this sketch is to allow an Adruino Uno to take serial input
    //over usb, and display it on Williams system 3 to 6 displays. All input
    //must be wrapped in < > to be valid.
    //Player 1 score format is: <P1XXXXXX>
    //Player 2 score format is: <P2XXXXXX> and so on.
    //the displays on the main driver board are referred to as
    // displays M1 and M2 in this code.
    //where XXXXXXX is the score to be displayed. 'B' can be sent in place of
    //a character to create a blank display.
    //Also, invalid input will be displayed as a Blank space.
    //refer to the system 3 wiring diagram and schematics for an explenation
    // of the outputs for the board.
    //To start the board, a <G> must be sent to enable the displays.
    //All displays can be disabled by sending <B> over the USB.
    //a word of caution on using Serial.println statments, they severly
    //slow the board down, and should only be left on for debugging.

    //output assignments for the BCD generators, reffered to as
    //IC 5 and IC7 in the System 3 schematics of the main display driver
    //These are pin assignments for Adruino Uno
    const int ic5_aPin = 2;
    const int ic5_bPin = 3;
    const int ic5_cPin = 4;
    const int ic5_dPin = 5;

    const int ic7_aPin = 7;
    const int ic7_bPin = 8;
    const int ic7_cPin = 9;
    const int ic7_dPin = 10;

    //Output for blanking
    const int blanking = 6;

    const int latchPin = 12;//Pin connected to ST_CP of 74HC595 No. 1
    const int clockPin = 13;//Pin connected to SH_CP of 74HC595 No. 1
    const int dataPin = 11; //Pin connected to DS of 74HC595 N0. 1

    //setup the variable used to store incoming data until it is parsed
    //out to the indiviual variable for each display

    const byte numChars = 50;
    char receivedChars[numChars];

    //used in the recvWithStartEndMarkers() function
    boolean newData = false;

    //here are the character inputs for each display digit
    char p1_units = '0';
    char p1_tens = '0';
    char p1_hundreds = '0';
    char p1_thousands = '0';
    char p1_10thousands = '0';
    char p1_100thousands = '0';

    char p2_units = '0';
    char p2_tens = '0';
    char p2_hundreds = '0';
    char p2_thousands = '0';
    char p2_10thousands = '0';
    char p2_100thousands = '0';

    char p3_units = '0';
    char p3_tens = '0';
    char p3_hundreds = '0';
    char p3_thousands = '0';
    char p3_10thousands = '0';
    char p3_100thousands = '0';

    char p4_units = '0';
    char p4_tens = '0';
    char p4_hundreds = '0';
    char p4_thousands = '0';
    char p4_10thousands = '0';
    char p4_100thousands = '0';

    char m1_units = '0';
    char m1_tens = '0';
    char m2_units = '0';
    char m2_tens = '0';

    //needed to keep the code running at 60 hz. without the delay, the
    //board runs at about 200 hertz
    unsigned long msDelay = 700;

    //master flag for display on or off
    boolean displayOn = false;

    void setup(){
    //initialize the Serial Port
    Serial.begin(9600);

    // inputString.reserve(200);
    //setup the output pins

    pinMode(ic5_aPin, OUTPUT);
    pinMode(ic5_bPin, OUTPUT);
    pinMode(ic5_cPin, OUTPUT);
    pinMode(ic5_dPin, OUTPUT);

    pinMode(ic7_aPin, OUTPUT);
    pinMode(ic7_bPin, OUTPUT);
    pinMode(ic7_cPin, OUTPUT);
    pinMode(ic7_dPin, OUTPUT);

    pinMode(dataPin, OUTPUT);
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);

    pinMode(blanking, OUTPUT);
    digitalWrite(blanking, LOW);// Start out with displays off

    //make sure all strobes start out as low
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);
    digitalWrite(latchPin, HIGH);

    Serial.println("Setup Complete");
    }

    //the main loop
    void loop(){

    //First we check for new serial stream data
    recvWithStartEndMarkers();

    //check to see if displays are active
    //if so we start the strobes
    if(displayOn){

    ///TAKE STROBE 1 LOW VIA REGISTER SHIFT
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);//this byte goes to register shift 2
    shiftOut(dataPin, clockPin, MSBFIRST, 254);//this byte goes to register shift 1
    digitalWrite(latchPin, HIGH);

    //write out player 1 100thousands
    IC5output(p1_100thousands);

    //write out player 3 100thousands
    IC7output(p3_100thousands);
    //we need a delay to keep the uno from outrunning the old hardware
    delayMicroseconds(msDelay);

    //TAKE STROBE 1 HIGH, AND SET 2 STROBE LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    shiftOut(dataPin, clockPin, MSBFIRST, 253);
    digitalWrite(latchPin, HIGH);

    //next write P1 10thoutsands
    IC5output(p1_10thousands);
    //write out player 3 101thousands
    IC7output(p3_10thousands);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 2 HIGH, AND SET STROBE 3 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    shiftOut(dataPin, clockPin, MSBFIRST, 251);
    digitalWrite(latchPin, HIGH);

    //next write P1 thoutsands
    IC5output(p1_thousands);
    //write out player 3 1thousands
    IC7output(p3_thousands);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 3 HIGH, AND SET STROBE 4 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    shiftOut(dataPin, clockPin, MSBFIRST, 247);
    digitalWrite(latchPin, HIGH);

    //next write P1 hundreds
    IC5output(p1_hundreds);
    //write out player 3 hundreds
    IC7output(p3_hundreds);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 4 HIGH, AND SET STROBE 5 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    shiftOut(dataPin, clockPin, MSBFIRST, 239);
    digitalWrite(latchPin, HIGH);

    //next write P1 tens
    IC5output(p1_tens);
    //write out player 3 tens
    IC7output(p3_tens);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 5 HIGH, AND SET STROBE 6 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    shiftOut(dataPin, clockPin, MSBFIRST, 223);
    digitalWrite(latchPin, HIGH);

    //next write P1 units
    IC5output(p1_units);
    //write out player 3 units
    IC7output(p3_units);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 6 HIGH, AND SET STROBE 7 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    shiftOut(dataPin, clockPin, MSBFIRST, 191);
    digitalWrite(latchPin, HIGH);

    // write M2 tens
    IC5output(m2_tens);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 7 HIGH, AND SET STROBE 8 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    shiftOut(dataPin, clockPin, MSBFIRST, 127);
    digitalWrite(latchPin, HIGH);

    // write M2 units
    IC5output(m2_units);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 8 HIGH, AND SET STROBE 9 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 254);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //next write P2 100thousands
    IC5output(p2_100thousands);
    //write out player 4 100thousands
    IC7output(p4_100thousands);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 9 HIGH, AND SET STROBE 10 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 253);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //next write P2 10thousands
    IC5output(p2_10thousands);
    //write out player 4 10thousands
    IC7output(p4_10thousands);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 10 HIGH, AND SET STROBE 11 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 251);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //next write P2 thousands
    IC5output(p2_thousands);
    //write out player 4 thousands
    IC7output(p4_thousands);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 11 HIGH, AND SET STROBE 12 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 247);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //next write P2 hundreds
    IC5output(p2_hundreds);
    //write out player 4 thousands
    IC7output(p4_hundreds);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 12 HIGH, AND SET STROBE 13 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 239);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //next write P2 tens
    IC5output(p2_tens);
    //write out player 4 tens
    IC7output(p4_tens);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 13 HIGH, AND SET STROBE 14 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 223);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //next write P2 units
    IC5output(p2_units);
    //write out player 4 units
    IC7output(p4_units);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 14 HIGH, AND SET STROBE 15 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 191);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //write master 1 tens
    IC5output(m1_tens);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //TAKE STROBE 15 HIGH, AND SET STROBE 16 LOW
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 127);
    shiftOut(dataPin, clockPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);

    //write master 1 units
    IC5output(m1_units);

    delayMicroseconds(msDelay); // delay added to get timing correct

    //end of ouput updates

    }// end of display on loop

    }//end of main loop

    //This is the routine that gets the input from the USB bus
    void recvWithStartEndMarkers(){
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    if (Serial.available() > 0) {

    //Serial.println("Serial called");
    rc = Serial.read();
    //are we adding to the existing string?
    if (recvInProgress == true) {
    //if so, look for the end marker
    if (rc != endMarker) {
    receivedChars[ndx] = rc;
    ndx++;
    //is the string too long (over 50 characters)
    if (ndx >= numChars) {
    ndx = numChars - 1;
    }
    }//end of look for end marker

    // if you get an end marker, it terminate the string....
    else {
    receivedChars[ndx] = ''; // terminate the string
    recvInProgress = false;
    ndx = 0;
    newData = true;
    }//end of else statement

    }//end of recieved in progress true?

    else if (rc == startMarker) {
    recvInProgress = true;
    }

    }//end of serial avalaible

    //check to see if input data came through

    if(newData){// So we now have new data to parse

    //debugging lines
    //Serial.print("Data Recieved :");
    // Serial.println(receivedChars);

    //Player 1 score parser
    if(receivedChars[0] == 'P' && receivedChars[1] == '1'){
    p1_100thousands = receivedChars[2];
    p1_10thousands = receivedChars[3];
    p1_thousands = receivedChars[4];
    p1_hundreds = receivedChars[5];
    p1_tens = receivedChars[6];
    p1_units = receivedChars[7];

    newData = false;

    }//end of P1 parcer

    //Player 2 score parser
    else if(receivedChars[0] == 'P' && receivedChars[1] == '2'){
    p2_100thousands = receivedChars[2];
    p2_10thousands = receivedChars[3];
    p2_thousands = receivedChars[4];
    p2_hundreds = receivedChars[5];
    p2_tens = receivedChars[6];
    p2_units = receivedChars[7];

    newData = false;

    }//end of P2 Parcer

    //Player 3 score parser
    else if(receivedChars[0] == 'P' && receivedChars[1] == '3'){
    p3_100thousands = receivedChars[2];
    p3_10thousands = receivedChars[3];
    p3_thousands = receivedChars[4];
    p3_hundreds = receivedChars[5];
    p3_tens = receivedChars[6];
    p3_units = receivedChars[7];

    newData = false;

    }//end of P3 Parcer

    //player 4 score parser
    else if(receivedChars[0] == 'P' && receivedChars[1] == '4'){
    p4_100thousands = receivedChars[2];
    p4_10thousands = receivedChars[3];
    p4_thousands = receivedChars[4];
    p4_hundreds = receivedChars[5];
    p4_tens = receivedChars[6];
    p4_units = receivedChars[7];

    newData = false;
    }//end of P4 Parcer

    //Master display 1 parser
    else if(receivedChars[0] == 'M' && receivedChars[1] == '1'){
    m1_tens = receivedChars[2];
    m1_units = receivedChars[3];

    newData = false;

    } // end of Master 1

    //Master display 2 parser
    else if(receivedChars[0] == 'M' && receivedChars[1] == '2'){
    m2_tens = receivedChars[2];
    m2_units = receivedChars[3];

    newData = false;
    }//end of master 2

    //This signal needs to come first to activate the displays
    else if(receivedChars[0] == 'G'){
    // Serial.println("All Displays on called");
    digitalWrite(blanking, HIGH);//Blanking has to be high for the displays to run
    newData = false;
    displayOn = true;
    }
    //shutsdown all displays

    else if(receivedChars[0] == 'B'){
    Serial.println("All displays down called");
    digitalWrite(blanking, LOW);
    newData = false;
    displayOn = false;

    // pulls all strobes low
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);
    shiftOut(dataPin, clockPin, MSBFIRST, 0);
    digitalWrite(latchPin, HIGH);

    }

    //this is a catchall for bad data.
    else{
    Serial.print("Bad data received :");
    Serial.println(receivedChars);
    newData = false;
    }

    }//end of newData check

    }// end of recvStartEndMark function

    //This function sets the BCD inputs based on the digit recieved. There are tow
    //funcitons, one for input to IC 5, and one for IC 7.
    void IC5output(char inputNumber){

    // Serial.println("IC5output called");
    //Serial.println("inputNumber is:");
    //Serial.println(inputNumber);
    switch (inputNumber){

    case 'B': //creates a blank unit in the display
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, HIGH);
    break;

    case '0':
    digitalWrite(ic5_aPin, LOW);
    digitalWrite(ic5_bPin, LOW);
    digitalWrite(ic5_cPin, LOW);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '1':
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, LOW);
    digitalWrite(ic5_cPin, LOW);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '2':
    digitalWrite(ic5_aPin, LOW);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, LOW);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '3':
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, LOW);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '4':
    digitalWrite(ic5_aPin, LOW);
    digitalWrite(ic5_bPin, LOW);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '5':
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, LOW);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '6':
    digitalWrite(ic5_aPin, LOW);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '7':
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, LOW);
    break;

    case '8':
    digitalWrite(ic5_aPin, LOW);
    digitalWrite(ic5_bPin, LOW);
    digitalWrite(ic5_cPin, LOW);
    digitalWrite(ic5_dPin, HIGH);
    break;

    case '9':
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, LOW);
    digitalWrite(ic5_cPin, LOW);
    digitalWrite(ic5_dPin, HIGH);
    break;

    default: // if bad input gets through, it will put up a blank
    // Serial.println("error in ic5 routine");
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, HIGH);
    break;
    }// end of switch statement

    }// end of function

    //the routine for lighting up IC7 based on the number given
    void IC7output(char inputNumber){
    //Serial.println("IC7output called");
    //Serial.println("inputNumber is:");
    //Serial.println(inputNumber);

    switch (inputNumber){

    case 'B':
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, HIGH);
    break;

    case '0':
    digitalWrite(ic7_aPin, LOW);
    digitalWrite(ic7_bPin, LOW);
    digitalWrite(ic7_cPin, LOW);
    digitalWrite(ic7_dPin, LOW);
    break;

    case'1':
    digitalWrite(ic7_aPin, HIGH);
    digitalWrite(ic7_bPin, LOW);
    digitalWrite(ic7_cPin, LOW);
    digitalWrite(ic7_dPin, LOW);
    break;

    case '2':
    digitalWrite(ic7_aPin, LOW);
    digitalWrite(ic7_bPin, HIGH);
    digitalWrite(ic7_cPin, LOW);
    digitalWrite(ic7_dPin, LOW);
    break;

    case '3':
    digitalWrite(ic7_aPin, HIGH);
    digitalWrite(ic7_bPin, HIGH);
    digitalWrite(ic7_cPin, LOW);
    digitalWrite(ic7_dPin, LOW);
    break;

    case '4':
    digitalWrite(ic7_aPin, LOW);
    digitalWrite(ic7_bPin, LOW);
    digitalWrite(ic7_cPin, HIGH);
    digitalWrite(ic7_dPin, LOW);
    break;
    case '5':
    digitalWrite(ic7_aPin, HIGH);
    digitalWrite(ic7_bPin, LOW);
    digitalWrite(ic7_cPin, HIGH);
    digitalWrite(ic7_dPin, LOW);
    break;

    case '6':
    digitalWrite(ic7_aPin, LOW);
    digitalWrite(ic7_bPin, HIGH);
    digitalWrite(ic7_cPin, HIGH);
    digitalWrite(ic7_dPin, LOW);
    break;

    case '7':
    digitalWrite(ic7_aPin, HIGH);
    digitalWrite(ic7_bPin, HIGH);
    digitalWrite(ic7_cPin, HIGH);
    digitalWrite(ic7_dPin, LOW);
    break;

    case '8':
    digitalWrite(ic7_aPin, LOW);
    digitalWrite(ic7_bPin, LOW);
    digitalWrite(ic7_cPin, LOW);
    digitalWrite(ic7_dPin, HIGH);
    break;

    case '9':
    digitalWrite(ic7_aPin, HIGH);
    digitalWrite(ic7_bPin, LOW);
    digitalWrite(ic7_cPin, LOW);
    digitalWrite(ic7_dPin, HIGH);
    break;

    default:
    //Serial.println("error in ic7 routine");
    digitalWrite(ic5_aPin, HIGH);
    digitalWrite(ic5_bPin, HIGH);
    digitalWrite(ic5_cPin, HIGH);
    digitalWrite(ic5_dPin, HIGH);
    break;
    }// end of switch statement

    }// end of ic7 function

    #4 5 years ago

    This is very cool.

    So are you going to try to use the System11 P-ROC board in a System 3-6 game? (looks like the game is Flash, system 4)

    #5 5 years ago

    That is the plan right now, unless I can find a more suitable donor machine. One has been offered to me, but I can't get away to make the 8 hour round trip to pick it up

    My P-roc is on order, and my System 11 board is making it's way across the pond to me right now as well. I may have to make some adapter cables, but I think I can make it work out.

    1 week later
    #6 5 years ago

    Ive spent some quality time with my score controller over the past few days and have made a few discoveries about it.

    The input buffer is only 64k, now that sounds like a lot, but it fills up fast. I have found that I can only send a score only at a maximum of 10 times per second, and have the Uno keep up. Otherwise the buffer overflows, and it pretty much stops working.

    The other thing I have found is that the old Pinball machine hardware will run at much higher speeds than the 60Hz the original cpu put out. However, the faster you run it, the more digits tend to fade out. However, running it faster forces the code to clear out the buffer more often. I think the happy medium is right around 100hz.

    #7 5 years ago

    There are simple ways to optimize the code if you're worried about your buffer filling up. The most obvious would be to move the serial read into a function and call it during each of the places you're currently doing the delays. Feel free to contact me if you want help with that.

    #8 5 years ago

    That would be an easy change to make. The serial read is already in it's own function recvWithStartEndMarkers() , so adding more calls in the place of the delays can easily be done. I may try that tonight.

    Right now if I send the board an unrestricted flow of information from my host computer from a for loop, it locks up pretty quickly.
    --C. Alan

    #9 5 years ago

    Even easier would be to put a loop around the serial receive and process all the incoming characters in the serial buffer each time in the function, if you did that you could probably leave everything else as it currently is.

    i.e.

    while (Serial.available()) {
    // do all the serial code in here
    }

    It would be a little clunky, but that probably isn't an issue

    #10 5 years ago

    so I added the following statement in place of the delay statements:

    if (Serial.available() > 0) {
    recvWithStartEndMarkers();
    }
    else{delayMicroseconds(msDelay);}

    Now I can run input a full computer speeds, and the buffer doesn't fill up. It works much better.

    #11 5 years ago
    Quoted from ecurtz:

    Even easier would be to put a loop around the serial receive and process all the incoming characters in the serial buffer each time in the function, if you did that you could probably leave everything else as it currently is.
    i.e.
    while (Serial.available()) {
    // do all the serial code in here
    }
    It would be a little clunky, but that probably isn't an issue

    right now it goes to the buffer, and gets the first valid value it finds, then writes that one out to the score variables. Doing it this way means it never misses a score, but when you continually send it numbers, it filled up too quick.

    #12 5 years ago
    Quoted from uncivil_engineer:

    so I added the following statement in place of the delay statements:
    if (Serial.available() > 0) {
    recvWithStartEndMarkers();
    }
    else{delayMicroseconds(msDelay);}
    Now I can run input a full computer speeds, and the buffer doesn't fill up. It works much better.

    Great. If you want to get fancy you could time the recvWithStartEndMarkers(); call and do a shortened delay, but if it's working fine now it probably isn't necessary.

    #13 5 years ago

    I push serial data from a PC out to an Arduino to control the RGB LED inserts in my F14 project. The commands coming in are always 6 bytes long. I use the same technique, my main loop in the Arduino code has

    if (Serial.available() >= 6) {
    // Grab the first 6 bytes and do something.
    }

    Promoted items from the Pinside Marketplace
    $ 86.95
    Cabinet - Shooter Rods
    Super Skill Shot Shop
    $ 29.50
    Playfield - Plastics
    Pinball Haus
    $ 29.99
    Cabinet - Sound/Speakers
    Lighted Pinball Mods
    € 22.00
    Cabinet - Other
    YOYOKOPTER MODS
    $ 59.00
    Playfield - Toys/Add-ons
    Sparky Pinball
    $ 22.00
    Cabinet - Sound/Speakers
    ModFather Pinball Mods
    $ 5,899.99
    Pinball Machine
    Pinball Pro
    $ 9.95
    $ 21.00
    $ 34.94
    Playfield - Plastics
    Plastic 9 for Pin-Bot Out of stock
    Pinball-Mods.com
    $ 69.99
    Playfield - Toys/Add-ons
    Lighted Pinball Mods
    $ 249.00
    Lighting - Led
    PinballBulbs
    $ 399.00
    Gameroom - Decorations
    Bent Mods
    $ 25.00
    From: $ 18.00
    Apparel - Men
    Pinside Shop
    From: $ 119.99
    Lighting - Backbox
    Rock Custom Pinball
    $ 999.00
    Flipper Parts
    Mircoplayfields
    $ 48.00
    Cabinet - Other
    ModFather Pinball Mods
    $ 20.00
    Various Novelties
    GC Pinball
    $ 11.95
    Playfield - Toys/Add-ons
    ULEKstore
    $ 49.99
    Playfield - Toys/Add-ons
    Lighted Pinball Mods
    $ 16.95
    Playfield - Toys/Add-ons
    pinballmod
    $ 89.99
    Lighting - Led
    Lighted Pinball Mods
    $ 999.00
    Pinball Machine
    Mircoplayfields

    Hey there! Got a moment?

    Great to see you're enjoying Pinside! Did you know Pinside is able to run thanks to donations from our visitors? Please donate to Pinside, support the site and get anext to your username to show for it! Donate to Pinside