Close
0%
0%

Electronic Mancala++

Updated version of my Electronic Mancala Board that uses a ATtiny3224 microcontroller

Similar projects worth following
490 views
0 followers
This update to the original project adds support for a USB interface (to perhaps maybe interact with a future software application), adds a computer player, and upgrades the MCU to an ATtiny3224.

Changes from the original Mancala game include:

  • Change from 5mm through-hole LEDs to SMD-0805 LEDs
  • Addition of a USB interface (via FT230X) to allow future interoperability between the board and a potential PC application
    • Maybe allow the use of a high-performance CPU player running on a host PC?
  • Button interface solution has swapped from a scan-matrix to a TCA9535 I2C I/O expander
  • MCU has been switched from a PIC18LF2420 to an ATtiny3224.
  • Smaller footprint PCB with 4-40 threaded holes to allow for more flexible mounting solutions
  • Addition of a 4-position DIP switch to allow for potential of different game modes.

This project is based on an earlier project and retains all its features, including a two-player mancala game featuring the full rule set and game parameters, the ability to alter the brightness of the LEDs through a TLC59116 LED driver, and the 16-LED/16-button interface of the original design.

The board is a 4-layer design fabricated and assembled by JLCPCB. Firmware for the ATtiny3224 is developed using MPLAB X and the avr-gcc compiler. A PICkit 5 is used to program and debug the MCU over UPDI.

src-2-3-25.zip

C source files for ATtiny3224 MCU Electronic Mancala++, compiled with avr-gcc

Zip Archive - 12.49 kB - 02/03/2025 at 23:42

Download

src-random.zip

C source files for ATtiny3224 MCU build implementing electronic mancala with a random computer player, compiled with avr-gcc

Zip Archive - 11.67 kB - 01/31/2025 at 01:45

Download

src.zip

C source files for ATtiny3224 MCU debugging build for electronic mancala, compiled with avr-gcc

Zip Archive - 10.42 kB - 01/28/2025 at 01:50

Download

gerbers.zip

Manufacturing files for PCB fabrication

Zip Archive - 466.86 kB - 01/22/2025 at 00:01

Download

EMancala2.pdf

Electronic schematic for Electronic Mancala++

Adobe Portable Document Format - 741.57 kB - 01/12/2025 at 15:56

Preview

  • Update: code optimization

    Zachary Murtishi02/03/2025 at 23:42 0 comments

    I went and optimized some of the code to remove some unnecessary memory usage from the code + changed some of the code around to be less dependent on global variables. In a few functions, I had the game table global variable hardcoded - this has since been changed to the function taking the gameTable as a pointer and operating on its addresses that way. I removed the need for having to generate new arrays to run the isEmpty and sum functions - instead, I just add an offset to the game state's address and provide a manual length calculation for each. So far, it looks like it works.

  • Update: USB interface, moving forward with "smart" computer player

    Zachary Murtishi02/02/2025 at 19:46 0 comments

    I've went and added a software interface for a host PC to control game actions from a USB VCOM interface. It is a simple 9600 baud, 8N1 interface using the FT230X to bridge the ATtiny3224 USART port with a USB host. The game state can be polled as a 15-byte vector: 14 bytes containing the number of stones per pot with the current player's turn as the last byte. Bytes corresponding to a valid move (pots 0-5, 7-12) can be input to the board to make a move, provided it is the right player's turn for that move to be made. If an invalid input/move out of turn is input/illegal move (no stones in pot) is received, an appropriate error message is sent (ERROR!/WRONG TURN!/EMPTY!).

    This interface will allow an external mancala game engine to control one of the players on the board. A "smart" mancala engine based on expensive recursion probably can't run very smoothly on the ATtiny3224, but it most likely will be able to on my Mac. Right now, I will work on modifying one of the many Python-based mancala game engine programs out there to serve as a second player for this board. It shouldn't be too difficult, given that the software and hardware are there on the board side. I just have to configure an existing project to output its move choice to this board in the proper way. I imagine I will have to do something like this:

    1. Integrate Pyserial read/write functions into the mancala engine
    2. Change interface for the mancala engine to read the game state
      1. Instead of reading from a Python object/list/other data structure, it will read a 15-byte vector over the serial interface to determine the game state.
    3. Change interface for the mancala engine to cast a move
      1. Instead of writing to a Python object/list/data structure, it will send a one-byte move over the serial interface to make a move

  • Update: Minimax, serial port

    Zachary Murtishi02/02/2025 at 12:07 0 comments

    I've attempted and failed to implement a computer player based on the minimax algorithm. I was right when I thought recursion + dynamically-allocating memory in the stack would be a terrible idea for an AVR microcontroller. I am just going to work on implementing the minimax algorithm on a Python script (running on a host PC with more RAM and computing power than an ATtiny, of course), with the host PC retrieving the game state and inputting its moves through the FT230X/USB serial port.

    I will start by implementing a serial port interface to allow data (game state, move inputs, etc.) to be exchanged through the micro USB port.

  • Update: computer player with "random" moves

    Zachary Murtishi01/31/2025 at 01:41 0 comments

    As a test, I've implemented a test computer player that makes all its moves based on a PRNG value. The PRNG is generated by a 16-bit Fibonacci linear feedback shift register with taps at bits 15, 13, 12, and 5 that is cycled three times per 1ms system tick to generate a "random" 3-bit number to apply a modulo 6 to. This isn't perfect, but it works enough for testing. This mode can be selected by moving SW0 to the OFF position; regular two-player mode may be selected by placing SW0 in the ON position. The debug LED will light in the case that the computer player is selected. I've uploaded the source for a test build.

  • Update: computer player

    Zachary Murtishi01/29/2025 at 22:44 0 comments

    I haven't used much of the RAM or program memory on the ATtiny3224, so I'm thinking about filling it up by adding a computer player functionality. At the moment, I want to test this out by developing a computer player that simply picks from legal moves at random, but I'd like to implement a minimax search function with a shallow depth in the future.

  • Update: basic game code and sleep mode functionality (notes on unexpected behavior)

    Zachary Murtishi01/27/2025 at 22:18 0 comments

    I went in and ported the crude game code running on the PIC18LF2420 to the ATtiny3224. That code is quite frankly very messy and uses a ton of global variables, which is something I'd like to clean up here. I went through it, changed the interfaces between the game code and hardware (to be honest, most of it was migrating from a button matrix to an I2C port expander) and did a small amount of housekeeping to make the code more digestible and now the board is capable of running mancala, as it was intended to.

    I still have a lot of code to clean up, but it's looking good so far.

    I implemented a very basic USART function for debugging the game - I send a character from "0" to "F" and it sends me the number of stones in the pot corresponding to that number. This lets me do real-time debugging without having to use my PICKit 5 and UPDI, which is honestly very valuable. I should probably do something a little more sophisticated for debugging with USART, but that is TBD. So far, I am using a 9600 baud, 8N1 communication scheme and it works well with Screen on my Mac.

    I implemented a feature that will put the ATtiny into sleep mode when two minutes have passed - but I am encountering unexpected behaviors. First, I was able to configure the ATtiny's sleep control register to place the MCU into a power-down mode whenever two minutes have passed without a button press. This power-down mode is combined with an I2C command to clear all the LEDs on the board to save as much power as possible. I set it so that the INT signal (indicating that a button has been pressed) from the TCA9535 will wake the ATtiny from sleep and resume normal operation (by setting the pin it interfaces with to a low-level interrupt). This seems to work well, but I experienced an unexpected behavior when trying out the idle sleep mode.

    When I put the ATtiny into idle mode, I notice that I am unable to wake the MCU from sleep no matter what I do. I personally find this odd as idle is the mode in which all peripherals are still active - so my level-based interrupt on the I/O port should wake the MCU from sleep. This does not happen and I am very confused: I am able to place the MCU into the other sleep modes (standby and power-down) and wake them with the INT signal from the TCA9535. Stumped, I fired up my PICkit 5 and started debugging through UPDI to see if the sleep control register was receiving the right bits for the idle mode - indeed, it was.

    I have found nothing in the ATtiny3224 datasheet or errata to explain this behavior, but it is okay because I didn't want to use idle mode anyway. Power-down mode is what I want because it lets me disable all of the ATtiny peripherals and go to sleep; I don't want the MCU to do anything except to go to sleep and wait for a level-based interrupt to come from the TCA9535.

    How much does sleep mode reduce power? Quite a bit. Below is an image of my multimeter measuring current through VDD when the ATtiny has not executed the sleep instruction and all LEDs are off

    Below is my multimeter after the ATtiny has executed a sleep instruction to place itself into the power-down sleep mode:

    500 uA might seem like a drop in the bucket here given that the other ICs on the board are certainly drawing most of the ~20mA load in this application, but it would be a huge deal if this device were running on battery.

  • Update: basic interface code complete

    Zachary Murtishi01/26/2025 at 03:18 0 comments

    I went ahead and soldered the THT components of the boards. I left off the piezo as I didn't really have a use for it. Everything seems to work pretty well.

    I noticed that an 0805 capacitor was accidentally specified in place of an 0603 part for the 100nf decoupling capacitors. It might not be compliant with IPC-A-610, but 0805s definitely can fit on an 0603 landing. I should probably update the BOM to reflect an 0603 part number later, but this is just a hobby project and I can verify that the part is soldered to the pad. Below is a picture of one of these 0805 100nf decoupling caps - this one is for the TLC59116 LED driver I'm using:

    Before I work to port the game code to the ATtiny3224, I went and developed the interfaces required first:

    1. Got an I2C driver working. At first, I wrote my own TWI library and was able to talk to the TLC59116 after porting a library I wrote for the PIC18LF2420 to work with the ATtiny3224 TWI interface. I was able to implement 1-way I2C commands (write), but my attempts at a receive library were not as successful. I ended up consulting this ATtiny 1-series TWI library by bitbanging for help - I discovered I was being overly cautious with my implementation with all my checks of various TWI flags. I ended up importing their TWI library and tweaking some of the write functions to allow repeated writes with only the send byte function (it did not work out of the box so I added checks for both the receive/write complete flags as well as the bus state). I now have a 100 KHz I2C interface that is capable of communicating with both the TLC59116 LED driver and TCA9535 I/O expander.
    2. My code wasn't running how exactly I wanted to - for some reason, a for loop was not iterating over all 16 LEDs when I was trying to get them to light during debugging. I disabled avr-gcc's optimization after some extended debugging. Disabling compiler optimization seemed to do the trick; something about it was causing the last iteration of the for loop to not make it into the assembled code.
    3. Wrote a quick USART implementation to allow data exchange through the FT230X. Thankfully, USART wasn't very difficult to get going and I quickly wrote a library for simple I/O over the ATtiny3224 USART interface. As usual, I set it up for a 9600 baud, 8N1 serial scheme. I ended up setting up the receive complete interrupt to allow my debugging to not interfere with the main program loop - that is, I can send messages at any time during program execution and get a reply. Much better than my prototypes where I had blocking USART receive code in the while(1) loop. I'm glad to know that both my FT230X and level shifter implementation work in this application. I have to see what I want to do with this interface, but I'm likely just going to use it for debugging right now.
    4. I realized a little too late that the ATtiny3224 has a default divide-by-6 prescaler for the peripheral clock and wondered why my I2C bus was so slow compared to the value I thought I set (assuming a 20 MHz peripheral clock). Using the ccp_write_io function In the background, my test LED is being toggled every ~1s to test the system tick.provided in the cpufunc header, I was able to reconfigure the main prescaler to divide the main clock by 10 for a clean 2 MHz value to serve as my peripheral clock - sure it's slower than 3.3 MHz, but I like working with a clean number like 2 MHz more.
    5. I set up a simple 1 ms system tick with a Type B timer - the 2 MHz system clock is fed into a divide-by-16 prescaler and compared to a value of 125 to generate this 1ms tick. I will be using this for anything requiring a timing source going forward.
    6. I ended up removing the TCA9535 from the main program loop and moving it to an ISR triggered by the port interrupt vector - the TCA9535 has a pin that is pulled low upon change of its input port to indicate state changes to an MCU. Naturally, I tied this pin to an interrupt on PORTA. Instead of having this I/O expander periodically polled, it is only...
    Read more »

  • Update: received PCBs

    Zachary Murtishi01/22/2025 at 00:00 0 comments

    I've received the PCBs and I'm pleased with the product. So far, everything appears to function. I'm able to detect the FT230X from my ThinkPad and my PICkit 5 can detect the ATtiny3224 through UPDI using MPLAB IPE. I'll start development on the software when I decide that it's a good time to go through the PIC18 code for the original mancala board and port it to this application.

  • Update: Schematic finalized

    Zachary Murtishi01/08/2025 at 01:10 0 comments

    After checking product availability, I made some changes to the schematic:

    • The MCU is now an ATtiny3224. I don't need a lot of GPIO as I am using I2C components to interface with the buttons and LEDs.
    • I've added a piezo and a 2N7002 driver FET for sound effects. I'm going to allow this to be disabled through a rocker switch
    • I've switched the CP2102 to a FT230X. I tend to prefer FTDI's product portfolio and application notes.
    • After some consideration, I've decided to switch everything to run off of 5V (as all chips on this board are 5V-compatible).
      • As a result, I've had to add a 74AHCT1G125 buffer as a level shifter to ensure that the 3.3V UART output from the FT230X can be read by the ATtiny (the ATtiny's Vih is 3.5V @ 5V, which requires level shifting).
    • I've decided to remove the graphic display from the design. I thought it would take away from the goal of the game - to be a simplistic version of electronic mancala.

  • Update: MCU change

    Zachary Murtishi01/05/2025 at 22:00 0 comments

    I decided to downgrade the MCU for this project from a SAM device to an ATtiny3217. I realized I wouldn't need all that much computing power for my effort - after all, I plan on using I2C devices for I/O (buttons, LED, etc.) anyway, so I don't really need a crazy fast CPU.

    Still working on the PCB design for this effort. I'm throwing in a SiLabs CP2102 USB-to-UART bridge to allow for some real-time debugging as the ATtiny3217 does not have native USB support.


View all 10 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates