Spinning LED Display – The Big Picture

This project dealt with timing, frequency, and the phenomenon of persistence of vision. The project required a platform for spinning the display, the display, and the code to run the display.

The base platform is made from sections of 2×4 which provide a sturdy mounting point for the rest of the apparatus. The motor used to spin the LED’s platform is mounted on the wood base. Two ATMega328P boards are used, one for the motor and one for the LEDs. The LEDs are mounted in a breadboard on a separate section of light wood. The light wood and attached components all spin with an external battery allowing for two separate sections of the project.

Successfully getting the persistence of vision words displaying correctly required significant tuning to get the right timing. Another challenge was balancing the spinning section which was solved with weights on the opposite end. The complete product works and demonstrates the fascinating nature of persistence of vision.

An application was also made in the Unity Engine to help generate the necessary characters in a reasonable amount of time.

Spinning LED Display – Schematics

To create our spinning LED display we needed to create a way for the board to communicate with each LED individually. It was important to use an odd number of LEDs so that we could create letters and numbers with a center arm, like E, H, and A. We decided to use 7 LEDs because this number creates a nice height for each letter, and makes the display readable at a distance. The LED display was constructed by creating a ground bus on one side of the breadboard and connecting the cathode of each LED to it. The anode of each LED was then connected to a 100Ω resistor, which in turn connected to a wire which led to the input pin that would control the LED. (refer to schematic below) In this way we were able to send information to each individual LED.

We also needed a simple way to turn the motor on and off, we decided on a slide switch to meet that need. This was created by connecting the positive wire from the motor to ground and the negative end to the center pin of the slide switch. The leftmost pin of this switch was connected to ground while the rightmost pin was connected to 5V. For a bit of fun we created an on/off LED, which was accomplished by running a resistor from the center pin of the switch to the anode of the LED and the cathode was connect to ground. We would advise caution not supply the ground and 5V required to run this circuit from your microcontroller as this practice permanently disabled one of our boards. Rather use some other source of power and ground, like the large breadboards supplied in the lab.

 

 

 

Spinning LED Display – Supplemental Application Code

Since our project had to be able to display various characters (A-Z, a-z, 0-9, , ., ?, !), it was obvious that individually defining each character through its five frames would be time consuming. Thus, a supplementary application was created in Unity to provide the team with a easy-to-use interface that allowed us to “draw” each character and receive a binary/hexadecimal equivalent that would be stored in the code.

‘Bit’ Class:

This object was attached to each of the buttons in the scene. It kept track of whether a button has been enabled or disabled and dynamically updates the color of the button depending on its state (this allows the user to draw the image).

// ‘Bit’ Class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Bit : MonoBehaviour
{
    private bool isSet;
    // Use this for initialization
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
           if (isSet)
           {
                  this.GetComponent<Image>().color = Color.black;
           }
           else
           {
                  this.GetComponent<Image>().color = Color.white;
           }
    }
    // Set the bit in memory
    public void Set()
    {
           if (isSet)
           {
                  isSet = false;
           }
           else
           {
                  isSet = true;
           }
    }
    // Get the value of the bit
    public int getBit()
    {
           if (isSet)
           {
                  return 1;
           }
           else
           {
                  return 0;
           }
    }
}

‘Exit’ Class:

This object, once attached to a button, closes the application when pressed.

// ‘Exit’ Class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Exit : MonoBehaviour
{
    // Exit the program
    public void exit()
    {
           Application.Quit();
    }
}

‘TextHandler’ Class:

This object continuously communicated with each of the ‘bits’ on the screen and translated them into binary and hexadecimal before updating the text boxes present on the application.

// ‘TextHandler’ Class
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TextHandler : MonoBehaviour
{
    //Binary Text Holders
    public Text b0;
    public Text b1;
    public Text b2;
    public Text b3;
    public Text b4;
    //Hex Text Holders
    public Text h0;
    public Text h1;
    public Text h2;
    public Text h3;
    public Text h4;
    //Binary Holder
    public List<Bit> bits;
    // Use this for initialization
    void Start()
    {
    }
    // Update is called once per frame
    void Update()
    {
           b0.text = bits[30].getBit() + "" + bits[25].getBit() + "" + bits[20].getBit() + "" + bits[15].getBit() + "" + bits[10].getBit() + "" + bits[5].getBit() + "" + bits[0].getBit();
           b1.text = bits[31].getBit() + "" + bits[26].getBit() + "" + bits[21].getBit() + "" + bits[16].getBit() + "" + bits[11].getBit() + "" + bits[6].getBit() + "" + bits[1].getBit();
           b2.text = bits[32].getBit() + "" + bits[27].getBit() + "" + bits[22].getBit() + "" + bits[17].getBit() + "" + bits[12].getBit() + "" + bits[7].getBit() + "" + bits[2].getBit();
           b3.text = bits[33].getBit() + "" + bits[28].getBit() + "" + bits[23].getBit() + "" + bits[18].getBit() + "" + bits[13].getBit() + "" + bits[8].getBit() + "" + bits[3].getBit();
           b4.text = bits[34].getBit() + "" + bits[29].getBit() + "" + bits[24].getBit() + "" + bits[19].getBit() + "" + bits[14].getBit() + "" + bits[9].getBit() + "" + bits[4].getBit();
           h0.text = binToHex(b0.text);
           h1.text = binToHex(b1.text);
           h2.text = binToHex(b2.text);
           h3.text = binToHex(b3.text);
           h4.text = binToHex(b4.text);
    }
    // Convert the binary value to hex
    string binToHex(string binary)
    {
           int total = 0;
           // Find the decimal equivalence
           for (int i = 0; i < 7; i++)
           {
                  total += int.Parse(binary.Substring(i, 1)) * (int)   (Mathf.Pow(2, 6 - i));
           }
           // Convert it to hex
           int firstValue = total / 16;
           int secondValue = total % 16;
           return getHexChar(firstValue) + getHexChar(secondValue);
    }
    // Return the correct hex character
    string getHexChar(int d)
    {
           const string hex = "0123456789ABCDEF";
           return hex.Substring(d, 1);
    }
}

The code is located here (https://github.com/ahuynh15/IconToBinary) and can be compiled and built into a standalone application.