Hello smart people. I am stuck I need help.
I am creating a "Battleship" Game that uses custom Pegs that light up to show hits, and the ships themselves have built in LEDs to show hits as well.
It will be running on an Arduino Mega.
When I first came up with the project, after lots of thinking, I landed on using Mono Headphone Jacks with LEDs soldered between sleeve and tip for the Pegs (I also have a prototype that uses DC power jacks in the same way - both work the same way, I might use one for the ships and one for the hit/miss pegs).
Anyway, for the game boards themselves, my original plan was to use a matrix of resistors at each node (soldered across female audio jack or DC jack). The player would plug in the jack, and effectively short the resistor, pulling it low, thus allowing me to "scan" the matrix and know where the peg and/or ships are.
I started with TinkerCad and got a working 3x3 version that did everything I needed it to (place a peg, press 'fire' and if the array of pre-determined ship positions shows that coordinate was occupied, it registers a hit and lights the LED inside the peg).
Check the code below, but put simply, cathode columns set to input_pullup then set each row one at a time to high and do a digitalRead on the columns one at a time, and if it has pulled low (or high depending on the setup) then there is a peg at that intersection)After the online prototype worked, I moved to hardware and built the same 3x3 prototype. This also worked and gave me the confidence to move forward with the full sized 10x10 grid.
And this is where things fall down.
My oringal matrix used 1k resistors that, at 10x10, all of the extra paths, there it so much leackage, that it only shows very low resistance across each intersection node (about 190ohm, where as my 3x3 matrix of 1K's showed about 555ohm) - This affected the ability to detect pegs. As in, the same pegs did not register at all.
I tried using external pulldowns, pullups and reversing the logic (peg pulls high instead of low). I managed to get a version with a modified Peg with a 68ohm resistor in parallel with the LED to work, but only 1 or 2 pegs would detect. More than than that and it would begin interfere with other pegs and they would not register.
I also tried using the 3rd pin on a TRS audio jack. So when the peg is inserted it physically disconnects the resistor and only flows through peg. But I think this meant I had floating pins and caused inconsistent readings and I could not even get a small scale 3x3 board to work for that method. Even with stronger external pulldown, I was getting some strange results. So I gave that up.
I have also tried putting different combinations of Diodes and resistors
inside the peg, in both Parallel and in series - and in combination with external pullups/pulldowns on the matrix, but alas, to no avail.
I even managed to create a weird scenario where I was reversing the current at one point- dont ask, I dont know how I did that....
Finally, it hit me! A traditional matrix of LEDs works without these issues, and LEDs are just diodes! So instead of resistors at the intersections, I tried diodes, in series with a resistor - The empty nodes read, High, then when Peg is plugged in (with a smaller resistor with the LED) it would pull it LOW and I could detect it!
But this is where I have hit yet another wall - I only had enough Schottky Diodes to do a small 2x2 matrix for a test. And at first it seemed to work flawlessly... until I realised it was showing the peg one row 'offset' from its actual position (if the peg was on row 0, it would show row 1, if it was in row 1 it would show row 0) - And even 2 pegs at once in the same column would only show one row no matter what! (I did register 2 pegs at once, as long as they were on different columns, but would still show as offset to the wrong row)
I checked everything to troubleshoot!!! - Solder connections, shorts, diode the right way around, my code, the Array was correct, I had the pins in the right order. Also tried plugging pegs in each point and just individually setting their anode/cathodes to high/low to light them up one by one. It all worked fine! But no matter what, my 'scanning' code says the peg is plugged in on the wrong row! - as if somehow its "passing" the short along to the next row!
Anyway, I am at my wits end - I was sure the Matrix of Diodes would be the answer, but this new quirk is kicking me in the guts.
Things I still want to try:- I am going to try scaling up the 10x10 resistor matrix to 4.7k on each node- My calculations (Ok, ChatGPT's calculations) show me that it will be about 900ish ohms once all wired up. And Since my 3x3 with 1k's worked so well, I am hoping the same method with bigger resistors is the answer - its just risky since its takes me SO long to solder 100 DC jacks or Audio jacks into a matrix, and there is no guarantee it will even work
- The other thing is, I have this odd feeling that the 2x2 diode matrix is just doing something quirky, and that I should at least give it the full 3x3 test to make sure. I just need to buy some more diodes.
I am going to attach pictures and some of my test code for those that are interested.
I know schematics would be helpful, but I dont have them. I can say though that is literally just like a standard LED matrix. All Anodes are rows and all cathodes are columns. The Diode version has a 1k resistor in series so that it goes
Anode -> 1k -> diode -> cathode. But the resistor version is literally just
Anode -> 1K -> CathodeAs for the pins, I have tried many versions, but the one I am using the most is an LED and resistor in parallel (I found a combination that can pull the node low and still light the LED) - I have also tried in series, but cant go too high since I need it to be less than the board's resistance.
Oh and if you are wondering, I am handling all these pins with Shift registers for the Anodes (just need high and low) but to be able to
read the Cathode columns, they are all going directly to their own Pin on the Arduino - Hence the Mega - ( I need 40 cathode pins - 10 for player 1's target board, 10 for their fleet board, and the same again for player 2)
Specific Questions:- If anyone has any thoughts on a different method on how I can not just light up a 10x10 matrix but actually "read" when something changes at a node, then Im open to suggestions...
- What is up with my 2x2 diode matrix detecting the wrong row?
- Would just simply going bigger 4.7k resistors work? the 3x3 works so well! Or am I just wasting my time?
Here is a Tinker cad setup of my diode dilemma:
https://www.tinkercad.com/things/9lRQKs6wZvs-battleship-rndThis is a simplified version of some code, I'm not turning on the LEDs here, because I can get that working, its just the scanning that is killing me:
// Pin Definitions
const int cathodePins[] = {6,7}; // Columns
const int anodePins[] = {8,9}; // Rows
const int numRows = 2;
const int numCols = 2;
// Stores detected pegs
bool detectedState[numRows][numCols] = {{false}};
void setup() {
Serial.begin(9600);
// Initialize all anode pins as OUTPUT and set LOW
for (int i = 0; i < numRows; i++) {
pinMode(anodePins[i], OUTPUT);
digitalWrite(anodePins[i], LOW);
}
// Initialize all cathode pins as INPUT_PULLUP
for (int i = 0; i < numCols; i++) {
pinMode(cathodePins[i], INPUT_PULLUP);
}
Serial.println("Matrix Peg Detection Ready...");
scanMatrix();
}
void loop() {
}
void scanMatrix() {
Serial.println("Scanning Matrix...");
for (int row = 0; row < numRows; row++) {
digitalWrite(anodePins[row], HIGH); // Activate the current row for scanning
delayMicroseconds(200); // Stabilization delay
Serial.print("Row ");
Serial.print(row);
Serial.print(": ");
// Scan current row
for (int col = 0; col < numCols; col++) {
pinMode(cathodePins[col], INPUT_PULLUP); // Ensure it's in pull-up mode
int pegState = digitalRead(cathodePins[col]);
detectedState[row][col] = (pegState == HIGH); // Peg detected if HIGH
// Print the raw read value
Serial.print(pegState ? "1 " : "0 ");
}
Serial.println(); // New line for each row
// Reset row after scanning
digitalWrite(anodePins[row], LOW);
}
Serial.println("Scan Complete!\n");
}