mbedni
Published © GPL3+

The Dicer

Have some fun using this handy box with shuffle and counting abilities, supported by 8-bit sound effects.

IntermediateShowcase (no instructions)2,526
The Dicer

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
Shift Register 74HC595
×5
Resistor 10k ohm
Resistor 10k ohm
×40
Resistor 1k ohm
Resistor 1k ohm
×6
Resistor 2.7k ohm
×3
Resistor 3.3k ohm
×3
Resistor 5.1k ohm
×3
Resistor 100 ohm
Resistor 100 ohm
×1
Diode Led White 5mm
×35
Diode Led Red 5mm
×5
Lever arch switch
×5
Momentary button
×2
On/off button
×2
Passive Buzzer
×1

Hand tools and fabrication machines

Soldering Station
Drill

Story

Read more

Schematics

Dicer Schematic

Describes used connections

Code

Control Four Switches non-exclusive with just one analog pin

Arduino
Right use of 5 resistors combinantion allow you to detect four switches non-exclusive. Assuming you are using 3 sets of such setting covers up to 12 switches which is more than enough for this project.

Each of 3 sets works as below:
- we put positive "+" current (5V) to each resistors: 1k ohm, 2.7k ohm, 3.3k ohm and 5.1k ohm.
- each resistor is connected to switch (on/off or momentary)
- after switches we are merging all 4 lines into resistor 1k ohm
- before 1k ohm resistor we take line into analog input
- after 1k ohm resistor we put it to the ground (GND)

Pressing buttons is changing resistances in this parallel scheme in non-random way so the result can be extraced as 4-bit value.
byte fourValues[3]; //results from 3 analog pins from 0-1023 as 0-15
byte switches[12]; //easy way to access state on 12 buttons
	
//reads analog values with specified resistors set
byte analogToDecimal(int value) {
  
//those values of 0-1023 are enough unique to proper read resistance of 4 channels / switches non-exclusive.
  int data[] = {83, 202, 256, 307, 354, 390, 443, 493, 534, 567, 585, 602, 619, 632, 653, 9999};
  
  //below there is no mistake in order of 1,2,4,3 and 10,12,11,13... it's just how resistance works in this set
  int result[] = {0, 1, 2, 4, 3, 5, 6, 7, 8, 9, 10, 12, 11, 13, 14, 15};
  for (byte i = 0; i < 16; i++) if (value < data[i]) return result[i];
}

void setSwitches(byte n, byte swA, byte swB, byte swC, byte swD) {
  switches[(n - 1) * 4] = swA;
  switches[(n - 1) * 4 + 1] = swB;
  switches[(n - 1) * 4 + 2] = swC;
  switches[(n - 1) * 4 + 3] = swD;
}

void updateAnalog() {
	fourValues[0] = analogToDecimal(analogRead(buttonAnalogPin1));
	fourValues[1] = analogToDecimal(analogRead(buttonAnalogPin2));
	fourValues[2] = analogToDecimal(analogRead(buttonAnalogPin3));
		
	// 3 decimal into 12 binary
	for (int i = 1; i <= 3; i++) {
		if (fourValues[i - 1] == 0) setSwitches(i, 0, 0, 0, 0);
		if (fourValues[i - 1] == 1) setSwitches(i, 0, 0, 0, 1);
		if (fourValues[i - 1] == 2) setSwitches(i, 0, 0, 1, 0);
		if (fourValues[i - 1] == 3) setSwitches(i, 0, 0, 1, 1);
		if (fourValues[i - 1] == 4) setSwitches(i, 0, 1, 0, 0);
		if (fourValues[i - 1] == 5) setSwitches(i, 0, 1, 0, 1);
		if (fourValues[i - 1] == 6) setSwitches(i, 0, 1, 1, 0);
		if (fourValues[i - 1] == 7) setSwitches(i, 0, 1, 1, 1);
		if (fourValues[i - 1] == 8) setSwitches(i, 1, 0, 0, 0);
		if (fourValues[i - 1] == 9) setSwitches(i, 1, 0, 0, 1);
		if (fourValues[i - 1] == 10) setSwitches(i, 1, 0, 1, 0);
		if (fourValues[i - 1] == 11) setSwitches(i, 1, 0, 1, 1);
		if (fourValues[i - 1] == 12) setSwitches(i, 1, 1, 0, 0);
		if (fourValues[i - 1] == 13) setSwitches(i, 1, 1, 0, 1);
		if (fourValues[i - 1] == 14) setSwitches(i, 1, 1, 1, 0);
		if (fourValues[i - 1] == 15) setSwitches(i, 1, 1, 1, 1);
	}
		
}

void update() {
		updateAnalog();
}

5 Shift registers daisy chained to control 40 Leds.

Arduino
By using 5 shift registers 74HC595 we can control 40 outputs with just 3 pins on arduino board.
When we will understand the mechanics behind it, it is very simple to reuse with another projects
#define SHIFT_REGISTERS 5
#define REGISTER_OUTPUT_PINS 8
#define SLOTS 40

byte shifterLatchPin = 8; //latch pin used to daisy chain shift registers
byte shifterClockPin = 12; //clock pin used to daisy chain shift registers
byte shifterDataPin 11; //data pin used to daisy chain shift registers

byte slots[SLOTS]; //outputs from shift registers daisy chained
	//0 - disabled
	//1 - enabled

void updateSlots() {
		
	digitalWrite(shifterLatchPin, LOW);
	for (int i = SHIFT_REGISTERS - 1; i >= 0; i--) {
		byte n = 0; //value 0-255 to send into shifter
		byte m = 1; //multiplication of 2
    
		for (byte j = 0; j < REGISTER_OUTPUT_PINS; j++) {
			byte slotValue = slots[i * 8 + j];
			if (slotValue == 1) {
				n += m;
			}
			m = m * 2;
		}
			
		shiftOut(shifterDataPin, shifterClockPin, MSBFIRST, n);
	}
	digitalWrite(shifterLatchPin, HIGH);
}

void setup() {
		pinMode(shifterLatchPin, OUTPUT);
		pinMode(shifterClockPin, OUTPUT);
		pinMode(shifterDataPin, OUTPUT);
}

void update() {
  
  //at some points we will change slots array with zeros & ones to light proper LEDs.
  for (byte i=0; i<40; i++) slots[i] = random(2); //0 or 1
  
  //after that we will update slots.
  updateSlots();
}

Blinking Leds with no delay() function

Arduino
With just simple mod (%) operator we can take millis() into action and specify if this is the right time ON state, or OFF state.
//state ON for 500ms, state OFF for 500ms, repeat.
int blinkSlowInterval = 500; 

//state ON for 100ms, state OFF for 100ms, repeat.
int blinkFastInterval = 100;

//state ON for 1900ms, state OFF for 100ms, repeat.
int blinkAstillInterval = 1000;
	
bool blinkSlow;
bool blinkFast;
bool blinkAstill;

void updateBlinks() {
	unsigned long t = millis();
	blinkSlow = (t % (blinkSlowInterval * 2) < blinkSlowInterval) ? true : false;
	blinkFast = (t % (blinkFastInterval * 2) < blinkFastInterval) ? true : false;
	blinkAstill = (t % (blinkAstillInterval * 2) < (int)(blinkAstillInterval * 1.9)) ? true : false;
}

void update() {
  updateBlinks();
}

Play melody on your buzzer

Arduino
I have barely used this function here to emulate menu clicks but can be exhanced to give more length to it.

The idea is to create array of 2 values : note & duration.

The note represents C4-C7 frequnecy, while duration tell us for how long this should sound.
#define MAX_MELODY_LENGTH 100

byte buzzerPin = 7;

unsigned long melodyStartTime;
unsigned long melodyCurrentTime;
bool melodyStarted;
byte melodyPosition;
byte lastMelodyPosition;

int notes[37]; //stores all notes frequency from C4 to C7 inclusive
	
//current frequnecy
int buzzerFreq;

//each member of array contains two values: note & duration
int melody[MAX_MELODY_LENGTH][2];

//clear melody data
void readyMelody() {
	for(int i=0; i<MAX_MELODY_LENGTH; i++) {
		melody[i][0] = 0;
		melody[i][1] = 0;
	}
	melodyPosition = 1;
	lastMelodyPosition = -1;
}

void updateMelody() {
		if(melodyStarted == true) {
			
			melodyCurrentTime = millis();
			unsigned long elapsedTime = melodyCurrentTime - melodyStartTime;
			
			if(ENABLE_SERIAL == true) {
				Serial.print("Elapsed: ");
				Serial.println(elapsedTime);
			}
			
			int intervalStart;
			int intervalEnd;
			
			for(byte i=0; i<MAX_MELODY_LENGTH; i++) {
				if(i == 0) {
					intervalStart = 0;
					intervalEnd = melody[i][1];
				}
				else {
					intervalStart = melody[i-1][1] + 1;
					intervalEnd = melody[i][1];
				}
				
				if(melody[i][1] == 0) {
					//melody has ended
					melodyStarted = false;
					noSound();
					if(ENABLE_SERIAL == true) {
						Serial.println("Melody Finished!");
					}
					busy = false;
					break;
				}
				else {
					if(elapsedTime >= intervalStart && elapsedTime <= intervalEnd) {
						melodyPosition = i+1;
						if(lastMelodyPosition == -1 || melodyPosition != lastMelodyPosition) {
							
							if(ENABLE_SERIAL == true) {
								Serial.print("Curr Interval (");
								Serial.print(i+1);
								Serial.print("): ");
								Serial.print(intervalStart);
								Serial.print("-");
								Serial.println(intervalEnd);
							}
							
							//handle melody here
							if(melody[i][0] > 0) { //play note
							  tone(buzzerPin, getFrequncyById(melody[i][0]));
							}
							else { //play silence
								noTone(buzzerPin);
							}
							
							lastMelodyPosition = melodyPosition;
						}
						break;
					}
				}
				
				
			}
			
			
		}
	}

//filling global melody variable with predefined set of notes and it's durations {note, duration}
// if note equal 0 its stands as silence
// if duration equal 0 it's a sign to end melody
void playMelody() {
		if(melodyStarted == false) {
			readyMelody();
			int sum = 0;
			
			//yellow menu click
				int m[][2] = {
					{25, 100}, {0, 50}, {25, 100}, {0, 50}, {32, 100}
				};
				
				byte msize = sizeof(m) / sizeof(int);
				for(byte i=0; i < (int)(msize / 2); i++) { 
					melody[i][0] = m[i][0]; 
					sum += m[i][1]; 
					melody[i][1] = sum; 
				}
			}
			
			melodyStartTime = millis();
			melodyStarted = true;
		}
	}

void update() {
  updateMelody(); 
  
  
  //at some point you will want to play you melody
  //...
  playMelody();
  
  
}

void setup() {
  
  pinMode(buzzerPin, OUTPUT);
  
  notes[0] = 262; // 1 C4
  notes[1] = 277; // 2 C#4
  notes[2] = 294; // 3 D4
  notes[3] = 311; // 4 D#4
  notes[4] = 330; // 5 E4
  notes[5] = 349; // 6 F4
  notes[6] = 370; // 7 F#4
  notes[7] = 392; // 8 G4
  notes[8] = 415; // 9 G#4
  notes[9] = 440; // 10 A4
  notes[10] = 466; // 11 A#4
  notes[11] = 494; // 12 H4
  notes[12] = 523; // 13 C5
  notes[13] = 554; // 14 C#5
  notes[14] = 587; // 15 D5
  notes[15] = 622; // 16 D#5
  notes[16] = 659; // 17 E5
  notes[17] = 698; // 18 F5
  notes[18] = 740; // 19 F#5
  notes[19] = 784; // 20 G5
  notes[20] = 831; // 21 G#5
  notes[21] = 880; // 22 A5
  notes[22] = 932; // 23 A#5
  notes[23] = 988; // 24 H5
  notes[24] = 1047; // 25 C6
  notes[25] = 1109; // 26 C#6
  notes[26] = 1175; // 27 D6
  notes[27] = 1245; // 28 D#6
  notes[28] = 1319; // 29 E6
  notes[29] = 1397; // 30 F6
  notes[30] = 1480; // 31 F#6
  notes[31] = 1568; // 32 G6
  notes[32] = 1661; // 33 G#6
  notes[33] = 1760; // 34 A6
  notes[34] = 1865; // 35 A#6
  notes[35] = 1976; // 36 H6
  notes[36] = 2093; // 37 C7
  
  currNote = 13; //1-37
	buzzerFreq = getFrequncyById(currNote);
}

int getFrequncyById(byte id) {
	return notes[id-1];
}

Credits

mbedni

mbedni

0 projects • 1 follower

Comments