Project showcase
DIP/DIL Switch-Based 8-Byte ROM via Daisy-Chained 4051 MUXs

DIP/DIL Switch-Based 8-Byte ROM via Daisy-Chained 4051 MUXs © GPL3+

Switches as bits, a 4051 daisy chain as bytes, and a small 8-byte ROM for Arduino is made! A tribute to AGC's core rope memory of 1960s!

  • 2,243 views
  • 4 comments
  • 11 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
4051 multiplexer 8-channel IC
×9
Dip Switch package (4 lines)
×16
10 kOhm bussed resistive network (4 or 5 lines + common)
×16

About this project

Full story and pictures here: http://www.cesarebrizio.it/Arduino/DIP_Switch_ROM.html

Originally conceived as a tribute to the hand-sewn core rope memories of the Apollo Guidance Computer, my idea was successively simplified to “find a way to store a short character string in a series of DIP switches, then retrieve and display that text via an Arduino UNO."

I was inspired by (or better: I plagiarized) the project by PaulRM described here: https://forum.arduino.cc/index.php?topic=446780.0 : the prototype is based on a very simple circuit and nine 8-channel multiplexers in a “MUX daisy chain” arrangement (one multiplexer drives the other eight).

Considering that each 4051 IC can manage up to 8 lines, the total number of bits in the ROM will be 64 (8 Byte), with each bit set independently via its own dip switch. A separate 4051 multiplexer reads one by one the bits in each Byte, the remaining one selects which Byte to read.

The ROM will be tested by storing 8 Byte of text as ASCII characters, that will be displayed by Arduino on a 2 line LCD display.

For each byte, two banks of 4-bit DIP switches are provided. The choice of 4-switch packages has been dictated only by economic convenience (...a sale).

Although I expected that - to allow correct voltage reading by non-sinking IC’s - the ROM banks should be independently powered by a separate 5V DC supply, it became apparent that equally successful readings can be obtained by powering the inner ROM circuit and the outer circuit with multiplexers, by two independent +5V/GND pins on the same Arduino.

To make wiring easier, bussed 10KΩ resistive network (5 pins +common, also a bargain: in fact, I would have needed just 4 pins+common) have been used.

Code

Arduino sketch to read the 8-Byte ROM and show its content on an LCD displayArduino
/*
 
DIP/DIL Switch-based 8-Byte ROM via daisy-chained 4051 multiplexers and Arduino

Circuit and comments: 
See http://www.cesarebrizio.it/Arduino/DIP_Switch_ROM.html
Circuit is as illustrated here:http://www.cesarebrizio.it/Arduino/Final%20Fritzing%20Schema.jpg
 
 created 03 Feb 2019
 by Cesare Brizio
 modified ----

This example code is in the public domain.

Originally conceived as a tribute to the hand-sewn Core Rope memories of the Apollo Guidance Computer, 
my idea was successively simplified to “find a way to store a short character string in a series of 
DIP switches, then retrieve and display that text via an Arduino UNO”.

I was inspired by (or better: I plagiarized) the schematics by PaulRB and the project described here: 
https://forum.arduino.cc/index.php?topic=446780.0 

I have 64 DIP switches, each one capable of storing a bit of information, in eaght groups of eight switches
(closed = non-null voltage reading = binary 1 - opened = null voltage reading = binary 0) 

Each group of eight switches, that I will call a "Byte", is connected to the eight I/O channels of a 
separate "slave" 4051. 

The three address lines S0/S1/S2 of all the slave multiplexers are common: one S0, one S1, and one S2 address all
the slave multiplexers simultaneously

I am using a master multiplexer 4051 whose I/O channels are connected to the com out/in of each slave multiplexer
Thus, by a two-step process:
a) select the "byte" (=slave multiplexer) to read via the S0/S1/S2 of the master 4051
b) select which "bit" to read from each slave via the common S0/S1/S2 of the slave 4051's
I can access one switch at a time and make individual reading.

As each byte is meant to store an 8-bit ASCII character, I compose the bytes by the successive readings from
their bits, and translate them into ASCII values, that are added to the string.

The string obtained is displayed on an LCD display driven by Arduino.

By changing the open/closed DIP switch configuration, I can vary the displayed string in real time.


  ==========================
  The circuit for LCD board:
  ==========================
 * LCD RS pin to digital pin 15
 * LCD Enable pin to digital pin 14
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

*/
// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// "Slave" 4051 ADDRESS PINS :
int slave_S0 = 2;
int slave_S1 = 3;
int slave_S2 = 4;

// "Master" 4051 ADDRESS PINS :
int master_S0 = 5;
int master_S1 = 6;
int master_S2 = 7;

//
int analogPin = A0;

int ReadVolt = 0;

int bitValue;

int asciiCode;

char asciiChar ="";

int powerOfTwo = 0;

char asciiString[8];



void setup() {
    // set up the LCD's number of columns and rows:
    lcd.begin(16, 2);
    // Print a message to the LCD.
    lcd.print("8-bit ROM says: ");
    // CONFIGURE ADDRESS PINS
    pinMode(master_S0, OUTPUT);
    pinMode(master_S1, OUTPUT);
    pinMode(master_S2, OUTPUT);
    pinMode(slave_S0, OUTPUT);
    pinMode(slave_S1, OUTPUT);
    pinMode(slave_S2, OUTPUT);
    
  Serial.begin(9600);   
  
}


void loop() {

    for( int x = 0; x < 8;  ++x )
          asciiString[x] = (char)0;

 
    // For each "Byte" 
    for (int i = 0; i < 8; i++) {
        
        // Select current Byte
        cycle4051('M',i);
        
        delay(5);
        
        //Serial.print("Byte ");
        //Serial.print(i);
        //Serial.println(" readings:");
        //Serial.print(">"); 

        asciiCode=0;

        for (int j = 7; j >=0; j--) {
        
            // Select current bit  
            cycle4051('S',j);   

            delay(5);
    
            ReadVolt = analogRead(analogPin); 
            
            if(ReadVolt>500) // check if current is running
            {
                bitValue=1; // Switch closed, bit high
                asciiCode = asciiCode + powerOfTwo;
            }
            else
            {
                bitValue=0; // Switch open, bit low
            }  
            
            //Serial.print(bitValue); 
            //Serial.print(ReadVolt); 
            //Serial.print("|"); 

        }

        //Serial.print(asciiCode); 
        //Serial.println("|");
        asciiString[i]=asciiCode;

    
    }
    //Serial.println("--- End series");    
    //Serial.println(asciiString);   

    for( int z = 0; z < 8;  ++z )
        {
        // (note: line 1 is the second row, since counting begins with 0):
        lcd.setCursor(z, 1);
        // print on the LCD the current character from the string:
        lcd.print(asciiString[z]);
        // print it also on the Serial Monitor
        Serial.print(asciiString[z]);
        }      
    Serial.println("");
    delay(10);
}


void cycle4051(char master_slave, int stepNumber) {
     // It's very obvious that this subprogram could have been written in
     // a much more compact form. I prefer to use a more verbose style
     // for clarity, readability and ease of maintenance.
     // I do know that there are may valid alternatives to the stratagem of 
     // using the powerOfTwo variable - the native POW() exponentiation function
     // that I could well have used has its drawbacks.
     switch (master_slave) {
        case 'M':
            //Next "Byte" (= next slave 4051)
            //Select the next slave 4051, connected to one of the channels of the master 4051 
            switch (stepNumber) {
               case 0:
                   //Select Channel 0 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, LOW);
                   break;
               case 1:
                   //Select Channel 1 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, HIGH);
                   break;
               case 2:
                   //Select Channel 2 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, LOW);
                   break;
               case 3:
                   //Select Channel 3 of the master 4051
                   digitalWrite(master_S2, LOW);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, HIGH);
                   break;
               case 4:
                   //Select Channel 4 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, LOW);
                   break;
               case 5:
                   //Select Channel 5 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, LOW);
                   digitalWrite(master_S0, HIGH);
                   break;
               case 6:
                   //Select Channel 6 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, LOW);
                   break;
               case 7:
                   //Select Channel 7 of the master 4051
                   digitalWrite(master_S2, HIGH);
                   digitalWrite(master_S1, HIGH);
                   digitalWrite(master_S0, HIGH);
                   break;
            }
            break;
        case 'S':
            //Next "bit" (= next channel in the currently selected slave 4051)
            //Select the next channel of the slave 4051, connected to one of the dip switches 
            switch (stepNumber) {
               case 0:
                   //Select Channel 0 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=1;
                   break;
               case 1:
                   //Select Channel 1 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=2;                   
                   break;
               case 2:
                   //Select Channel 2 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=4;                   
                   break;
               case 3:
                   //Select Channel 3 of the slave 4051
                   digitalWrite(slave_S2, LOW);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=8;                   
                   break;
               case 4:
                   //Select Channel 4 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=16;                   
                   break;
               case 5:
                   //Select Channel 5 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, LOW);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=32;                   
                   break;
               case 6:
                   //Select Channel 6 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, LOW);
                   powerOfTwo=64;                   
                   break;
               case 7:
                   //Select Channel 7 of the slave 4051
                   digitalWrite(slave_S2, HIGH);
                   digitalWrite(slave_S1, HIGH);
                   digitalWrite(slave_S0, HIGH);
                   powerOfTwo=128;                   
                   break;
            }
            break;
    }


}

Schematics

Fritzing schematics (with only one 4051 attached to its 8 switches)
A full overview of the project, but with many obvious connections omitted for clarity
big_board_con_4051_e_un_4051_connesso_agli_switch_55dx4xVVft.fzz

Comments

Similar projects you might like

Where's my stuff?? - Find your misplaced things with Alexa!

Project in progress by Team Crakers

  • 1,873 views
  • 0 comments
  • 7 respects

Arduino-Based Pressure Cooker Whistle Indicator

Project tutorial by sourav344

  • 870 views
  • 3 comments
  • 7 respects

Arduino Based Mini CNC 2D Plotter

Project showcase by Mrinnovative

  • 79,795 views
  • 14 comments
  • 195 respects

Water Quality Monitoring and Notification System

Project showcase by emmanuel ani

  • 52,617 views
  • 40 comments
  • 120 respects

Homotica - a simple, cost-effective home control system

Project showcase by Davide Vertuani

  • 44,889 views
  • 16 comments
  • 137 respects

RFID Based Automatic Door System

Project showcase by Robodia Technology

  • 37,264 views
  • 21 comments
  • 101 respects
Add projectSign up / Login