-
Mostly done! *Victory Fanfare*
09/26/2025 at 07:50 • 0 commentsThis is just a quick late night/early morning update.
I've successfully completed the project. It's currently 12:46 AM and I am pretty tired. A few adjustments were made with the logic in my code. For example, I realized that my seed value was only getting generated once because it was outside of my for loop. A silly mistake that I can work towards improving over time. That being said, conceptually, I feel like this project gave me a better understanding of how PRNGs are generated and that understanding will take me quite a long way with my future projects. Here is an uncommented, rough draft of my working code. I plan on cleaning things up and optimizing at a later date.
const int BUZZER_PIN = 3; //Input for Red Button PIN const int RED_BUTTON_PIN = 5; const int GREEN_BUTTON_PIN = 4; const int YELLOW_BUTTON_PIN = 6; //External output for Red LED const int RED_LED_PIN = 11; const int GREEN_LED_PIN = 12; const int YELLOW_LED_PIN = 13; void setup() { // initialize output pins pinMode(RED_LED_PIN, OUTPUT); pinMode(GREEN_LED_PIN, OUTPUT); pinMode(YELLOW_LED_PIN, OUTPUT); pinMode(BUZZER_PIN, OUTPUT); // initialize input pins pinMode(RED_BUTTON_PIN, INPUT); pinMode(GREEN_BUTTON_PIN, INPUT); pinMode(YELLOW_BUTTON_PIN, INPUT); //Initialize Serial Baud rate to 9600 Serial.begin(9600); } int XORShift(int x){ x ^= x << 13; x ^= x >> 17; x ^= x << 5; return x; } void VictoryFanfare(){ digitalWrite(RED_LED_PIN, HIGH); tone(BUZZER_PIN, 523.25, 133); delay(133); digitalWrite(GREEN_LED_PIN, HIGH); tone(BUZZER_PIN, 523.25, 133); delay(133); digitalWrite(YELLOW_LED_PIN, HIGH); tone(BUZZER_PIN, 523.25, 133); delay(133); tone(BUZZER_PIN, 523.25, 400); delay(400); tone(BUZZER_PIN, 415.30, 400); delay(400); tone(BUZZER_PIN, 466.16, 400); delay(400); digitalWrite(YELLOW_LED_PIN, LOW); digitalWrite(GREEN_LED_PIN, LOW); digitalWrite(RED_LED_PIN, LOW); tone(BUZZER_PIN, 523.25, 133); delay(133); delay(133); tone(BUZZER_PIN, 466.16, 133); delay(133); tone(BUZZER_PIN, 523.25, 1200); delay(1200); } // the loop function runs over and over again forever void loop() { const int maxLen = 4; int simonOutput[maxLen]; int simonInput[maxLen]; bool nextTurn; bool match = false; int i, j, k; Serial.println("-----output start-----");\ for (i = 0; i < maxLen; i++) { int randomNum = XORShift(analogRead(A0)) % 3; switch(randomNum){ //Red = 0 case 0: simonOutput[i] = randomNum; digitalWrite(RED_LED_PIN, HIGH); tone(BUZZER_PIN, 310); Serial.print(simonOutput[i]); delay(150); noTone(BUZZER_PIN); digitalWrite(RED_LED_PIN, LOW); delay(250); break; case 1: simonOutput[i] = randomNum; digitalWrite(GREEN_LED_PIN, HIGH); tone(BUZZER_PIN, 415); Serial.print(simonOutput[i]); delay(150); noTone(BUZZER_PIN); digitalWrite(GREEN_LED_PIN, LOW); delay(250); break; case 2: simonOutput[i] = randomNum; digitalWrite(YELLOW_LED_PIN, HIGH); tone(BUZZER_PIN, 252); Serial.print(simonOutput[i]); delay(150); noTone(BUZZER_PIN); digitalWrite(YELLOW_LED_PIN, LOW); delay(250); break; } } Serial.println("-----output end-----"); Serial.println("-----input start-----"); for(j = 0; j < maxLen; j++){ nextTurn = false; while (nextTurn == false){ if(digitalRead(RED_BUTTON_PIN) == HIGH){ simonInput[j] = 0; Serial.print(simonInput[j]); digitalWrite(RED_LED_PIN, HIGH); tone(BUZZER_PIN, 310); delay(150); noTone(BUZZER_PIN); digitalWrite(RED_LED_PIN, LOW); delay(300); nextTurn = true; } if(digitalRead(GREEN_BUTTON_PIN) == HIGH){ simonInput[j] = 1; Serial.print(simonInput[j]); digitalWrite(GREEN_LED_PIN, HIGH); tone(BUZZER_PIN, 415); delay(150); noTone(BUZZER_PIN); digitalWrite(GREEN_LED_PIN, LOW); delay(300); nextTurn = true; } if(digitalRead(YELLOW_BUTTON_PIN) == HIGH){ simonInput[j] = 2; Serial.print(simonInput[j]); digitalWrite(YELLOW_LED_PIN, HIGH); tone(BUZZER_PIN, 252); delay(150); noTone(BUZZER_PIN); digitalWrite(YELLOW_LED_PIN, LOW); delay(300); nextTurn = true; } } } Serial.println("-----input end-----"); for(k = 0; k < maxLen; k++){ if (simonOutput[k] == simonInput[k]){ match = true; } else{ match = false; break; } } if (match == false){ Serial.println("SORRY, INCORRECT MATCH"); tone(BUZZER_PIN, 44); delay(1000); } else{ Serial.println("CORRECT MATCH! YOU WIN!"); // Phrase 1 tone(BUZZER_PIN, 523.25, 133); VictoryFanfare(); } } -
New bread board, feeling happy
09/19/2025 at 02:42 • 0 commentsHello all!
Just a brief update here. Success!
As I suspected, my breadboard that came as part of my original ELEGOO package was faulty. I went ahead and purchased quite a few new things, the most important being a brand new Bread Board. It cost $13 on Amazon but the price was absolutely worth it because all of my LEDs are functioning as expected!It is slightly shorter than my original board, but replicating my original circuits was simple enough. Now that I have a reliable bread board, I can finally focus my efforts on less trivial things such as developing logic for my game and troubleshooting actual circuit issues.
My next step is to add the third LED and begin working on developing a better PRNG for my game.Figure A: My exact same circuit working as expected thanks to my new bread board.
![]()
-
[9/11/25] Game Logic and a Broken Bread Board!
09/12/2025 at 07:10 • 0 commentsMurphy's Law is a funny thing. As someone who whose career revolves around troubleshooting issues in production environments, I've learned quickly that even when dealing with seemingly simple systems, things can and usually will go wrong.
While building my second circuit for my button, I've discovered that my bread board is either damaged or just really cheap. There seems to be an issue with the left/center side of the board where even the slightest pressure on the board causes frantic activation of any GPIO port connected to that part of the board. I discovered this by re-creating my circuit on a different part of the board. This worked without any issue.
Unfortunately, this means I have to wait until the 19th before my new bread board gets here. In positive news, I've been working on the logic for my game! I am incredibly happy with it so far. Again, I've opted in using absolutely no libraries to simulate developing with resource constraints in mind. Cheers to an awesome start!:
//Simon Says for the Arduino R4. //Input for Buttons. const int RED_BUTTON_PIN = 5; const int GREEN_BUTTON_PIN = 4; //External output for LEDs const int RED_LED_PIN = 11; const int GREEN_LED_PIN = 12; int simonOutput[4]; void setup() { // initialize output pins pinMode(RED_LED_PIN, OUTPUT); pinMode(GREEN_LED_PIN, OUTPUT); // initialize input pins pinMode(RED_BUTTON_PIN, INPUT); pinMode(GREEN_BUTTON_PIN, INPUT); //Initialize Serial Baud rate to 9600 Serial.begin(9600); } void loop() { int i; for (i = 0; i< 4; i++){ //Find modulo 3 to represent/oputput 3 possible colors. int randomNum = (analogRead(A0)) % 3; simonOutput[i] = randomNum; } //Print tests to confirm values are, indeed, random! Serial.println("Simon says: "); Serial.println(simonOutput[0]); delay(500); Serial.println("Simon says: "); Serial.println(simonOutput[1]); delay(500); Serial.println("Simon says: "); Serial.println(simonOutput[2]); delay(500); Serial.println("Simon says: "); Serial.println(simonOutput[3]); delay(500); //Just testing button press logic. Ignore for now. if (digitalRead(RED_BUTTON_PIN)){ Serial.println("Red button pressed"); digitalWrite(RED_LED_PIN, HIGH); delay(100); } if (digitalRead(GREEN_BUTTON_PIN)){ Serial.println("Green button pressed"); digitalWrite(GREEN_LED_PIN, HIGH); delay(100); } else { digitalWrite(RED_LED_PIN, LOW); digitalWrite(GREEN_LED_PIN, LOW); } }- Eric Byrd
-
[9/9/25] Developing a Seed value for my PRNG
09/11/2025 at 06:12 • 0 commentsI can't think of anything more boring than playing a game of Simon Says that repeats the same pattern over and over again. Baseball might be a close second (sorry, baseball fans).
Typically, in order to implement randomness into a game's pattern, I would do something like this in C++:
-
Import a standard library
-
Slap
rand()into my code with a range of 0–2 -
Assign 0, 1, and 2 to specific colors in my game
-
Call it a day
However, because we're dealing with embedded systems, I needed to think at a deeper level. How would I achieve this if I had limited heap space and had to deal with the typical constraints that embedded software engineers face?
This led me to research how random numbers are generated by computers. Typically, something called a seed value is used. This is a seemingly random number sourced from some external or unpredictable input. A deterministic algorithm (meaning 100% predictable given the same input) then uses this seed to produce a seemingly random value. I say "seemingly random" because, unless the source of the seed is truly random (see Cloudflare's wall of lava lamps), we can only say the result is pseudo-random.
We're building a game of Simon Says — not encryption for the NSA!
Awesome — so conceptually, all I had to do was find a seed value! After working my way through this problem, a quick internet search revealed that I could actually pull electrical noise from an uninitialized pin and generate a seed value that way!
How this works is as follows:
-
I identify a pin on my board that is uninitialized — meaning the pin is left floating with no circuit actively driving it.
-
I use
analogRead()in my loop to read the electrical noise from the uninitialized pin. This serves as a sufficiently random seed value. Then, the value modulo 3 is used to output values between 0–2 (perfect for assigning three colors). It looks something like this:
randomInt = analogRead(A0) % 3;
With that, I now have a PRNG (pseudo-random number generator) without the use of any libraries! To be fair, I did use
analogRead(). However, now that I have a proof of concept, I might be interested in exploring reading from a pin without the use of theanalogRead()method.Until next time!
- Eric Byrd
-
Eric Byrd