C# LED and Music Controller

Team members: Blake Ballew, Mahvish Fatima, Alicia King, Nghi Tu

Description

C# GUI which can control music selection and LED options.

Music:

  • Plays music saved on an SD Card
  • Shuffles music
  • Displays current song information
  • Buttons for play, pause, and skip

LEDs:

  • strip of 60 individually addressable LEDs
  • several lighting modes the user can choose from
  • user can also choose a single color using RGB sliders

Parts List:

  • mbed LPC1768
  • Adafruit dotstar - LED strip
  • 5 V 5A power supply
  • PC

C# GUI

  • 9 buttons for color options
  • drop down bar to choose COM Port
  • buttons to control music
  • slider bars to control the color of the Single Color options

/media/uploads/kingalicia51/c-_gui.png

Finding and playing song files on the SD card

  • Read file names on SD card into array of strings
  • Choose a random number, play the song at that index in the array, and pass info on to GUI

Code

Our Form1.cs file, which creates the functionality of the GUI seen in the picture above, as well as playing the music

form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace LEDController
{
    public partial class Form1 : Form
    {
        //private int button;
        private byte R = 255;
        private byte G = 255;
        private byte B = 255;
        private String[] portNames;
        private String[] allFiles;
        Random rand = new Random();
        private bool play = false;
        private String pos = "";
        private String dir = "";

        private void trackBar3_ValueChanged(object sender, EventArgs e)
        {
            G = (byte)trackBar3.Value;
            label3.Text = "Green: " + G.ToString();
            
        }

        private void trackBar4_ValueChanged(object sender, EventArgs e)
        {
            B = (byte)trackBar4.Value;
            label4.Text = "Blue: " + B.ToString();
            
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L4");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L4");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L1");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L1");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L2");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L2");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L3");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L3");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L5");
            label1.Text = b.Text;
            serialPort1.Write("!L5");
        }

        private void button6_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L6");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L6");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void button7_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L7");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L7");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void button8_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L8");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L8");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void button9_Click(object sender, EventArgs e)
        {
            Button b = (Button)sender;
            label1.Text = b.Text;
            serialPort1.Write("!L9");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            serialPort1.Write("!L9");
            serialPort1.Write(new byte[] { 0x00 }, 0, 1);
        }

        private void comboBox1_SelectedValueChanged(object sender, EventArgs e)
        {
            serialPort1.PortName = comboBox1.SelectedText;
        }

        private void comboBox1_TextUpdate(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen) serialPort1.Close();
            serialPort1.PortName = comboBox1.SelectedText;
            serialPort1.Open();
        }

        private void button10_Click(object sender, EventArgs e)
        {
            String[] newNames = System.IO.Ports.SerialPort.GetPortNames();
            foreach(string s in newNames)
            {
                if (Array.IndexOf(portNames, s) == -1)
                {
                    Array.Resize(ref portNames, portNames.Length + 1);
                    portNames[portNames.Length - 1] = s;
                    comboBox1.Items.Add(s);
                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            portNames = System.IO.Ports.SerialPort.GetPortNames();
            string dirScanner = @"g:\music\";
            allFiles = System.IO.Directory.GetFiles(dirScanner, "*.wav");
            /*while (portNames.Length == 0)
            {
                portNames = System.IO.Ports.SerialPort.GetPortNames();

            } */
            foreach (string s in portNames)
            {
                comboBox1.Items.Add(s);
            }
            if (portNames.Length == 0) comboBox1.Items.Add("Test");
            comboBox1.SelectedIndex = 0;
            serialPort1.PortName = comboBox1.Text;
            serialPort1.Open();
            //R = 0;
            //label1.Text = R.ToString();
            //System.Threading.Thread.Sleep(100);
            serialPort1.Write("!B");
            serialPort1.Write(new byte[] { B, 0x00 }, 0, 2);
            //System.Threading.Thread.Sleep(100);
            serialPort1.Write("!G");
            serialPort1.Write(new byte[] { G, 0x00 }, 0, 2);
            //System.Threading.Thread.Sleep(100);
            serialPort1.Write("!R");
            serialPort1.Write(new byte[] { R, 0x00 }, 0, 2);
            timer1.Enabled = false;
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            System.Threading.Thread.Sleep(100);
            label8.Text = serialPort1.ReadExisting();
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void trackBar2_ValueChanged(object sender, EventArgs e)
        {
            R = (byte)trackBar2.Value;
            label2.Text = "Red: " + R.ToString();
            
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            //serialPort1.Write("!M1");
            //serialPort1.Write(new byte[] { 0x00 }, 0, 1);
            if (axWindowsMediaPlayer1.URL.Equals(""))
            {
                dir = allFiles[rand.Next(0, allFiles.Length)];
                while (dir.Substring(9).Equals(label8.Text)) dir = allFiles[rand.Next(0, allFiles.Length)];
                axWindowsMediaPlayer1.URL = dir;
                label8.Text = dir.Substring(9);
                play = true;
            } else if (play)
            {
                axWindowsMediaPlayer1.Ctlcontrols.pause();
                play = false;
            } else
            {
                axWindowsMediaPlayer1.Ctlcontrols.play();
                play = true;
            }

        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {
            axWindowsMediaPlayer1.Ctlcontrols.stop();
            dir = allFiles[rand.Next(0, allFiles.Length)];
            while (dir.Substring(9).Equals(label8.Text)) dir = allFiles[rand.Next(0, allFiles.Length)];
            axWindowsMediaPlayer1.URL = dir;
            label8.Text = dir.Substring(9);
            pos = "";
            play = true;
        }

        private void label8_Click(object sender, EventArgs e)
        {

        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Write("!R");
                serialPort1.Write(new byte[] { R, 0x00 }, 0, 2);
                serialPort1.Write("!G");
                serialPort1.Write(new byte[] { G, 0x00 }, 0, 2);
                serialPort1.Write("!B");
                serialPort1.Write(new byte[] { B, 0x00 }, 0, 2);

            }
            else
            {
                try
                {
                    serialPort1.Open();
                } catch (Exception ee)
                {

                }
            }
        }

        private void axWindowsMediaPlayer1_Enter(object sender, EventArgs e)
        {

        }

        private void axWindowsMediaPlayer1_EndOfStream(object sender, AxWMPLib._WMPOCXEvents_EndOfStreamEvent e)
        {
            axWindowsMediaPlayer1.Ctlcontrols.stop();
            axWindowsMediaPlayer1.URL = allFiles[rand.Next(0, allFiles.Length - 1)];
        }

        private void axWindowsMediaPlayer1_PlayStateChange(object sender, AxWMPLib._WMPOCXEvents_PlayStateChangeEvent e)
        {
            //axWindowsMediaPlayer1.Ctlcontrols.
        }

        private void timer3_Tick(object sender, EventArgs e)
        {
            if (play)
            {
                if (axWindowsMediaPlayer1.Ctlcontrols.currentPositionString == pos)
                {
                    axWindowsMediaPlayer1.Ctlcontrols.stop();
                    dir = allFiles[rand.Next(0, allFiles.Length)];
                    while (dir.Substring(9).Equals(label8.Text)) dir = allFiles[rand.Next(0, allFiles.Length)];
                    axWindowsMediaPlayer1.URL = dir;
                    label8.Text = dir.Substring(9);
                }
                pos = axWindowsMediaPlayer1.Ctlcontrols.currentPositionString;
                //label8.Text = pos;
            }
        }
    }
}

LED lighting effects

Effects:

  1. fade - LEDs fade through color wheel
  2. flash - random colors flash at a specified rate
  3. rainbow - a rainbow is shifted through the length of the LED strip
  4. trail - a pattern trails repeatedly over the strip
  5. random - a set of random LEDs change to a random color every half second

Specified by RGB sliders:

  1. solid - all LEDs are one color
  2. pulse - the brightness increases and decreases gradually
  3. shift - fills and unfills the LED strip with specified color

/media/uploads/kingalicia51/rainbowled.jpg

Using mbed RTOS to put it all together

mbed RTOS is used to simultaneously play the music, process input from the C# GUI, and display the LED effects. There are different threads for reading file names, playing music, the LED effects, choosing which LED effect, and the main thread, which runs everything and does basic setup for the LEDs.

main

Our main.cpp file, ran in the mbed compiler, defines the LED effect functions and runs the RTOS threads

main.cpp

#include "mbed.h"
#include <rtos.h>
#include "uLCD_4DGL.h"
#include <vector>
#include <string>
#include <wave_player.h>
#include <SDFileSystem.h>
#include <Speaker.h>
#include <DotStar.h>
#include <ctime>    // For time()
#include <cstdlib>


Serial pc(USBTX, USBRX);
DigitalOut one(LED1);
DigitalOut two(LED2);
DigitalOut three(LED3);
DigitalOut four(LED4);

Adafruit_DotStar strip(60, p12, p11, p13, 800000, DOTSTAR_BGR);
Thread led;

//const char* c;
string dir;
Mutex spi_lock;
char *a;
char *b;
unsigned int red, orange, yellow, green, blue, violet;

//uLCD_4DGL uLCD(p28, p27, p29);
volatile unsigned char R = 255, G = 255, B = 255;
volatile char ledthread = '0'; 

void led_solid();
void set_strip(unsigned char r, unsigned char g, unsigned char b);
void set_strip(uint32_t rgb);



void led_pulse() { // pulses brightness from 0-50 slowly. Color determined by global vars
unsigned char r = 0, g = 0, b = 0;

    while(ledthread == '8') {
        for (int i = 127; i > 0; i--) {
            if (ledthread != '8') {
                strip.setBrightness(127);
                return;
            }
            strip.setBrightness(i);
            if (r != R || g != G || b != B) {
                r = R;
                g = G;
                b = B;
                for (int i = 0; i < 60; i++) {
                    strip.setPixelColor(i, R, G, B);
                }
                strip.show();
            }
            strip.show();
            Thread::wait(30);
        }
        for (int i = 0; i < 128; i++) {
            if (ledthread != '8') {
                strip.setBrightness(127);
                return;
            }
            strip.setBrightness(i);
            if (r != R || g != G || b != B) {
                r = R;
                g = G;
                b = B;
                for (int i = 0; i < 60; i++) {
                    strip.setPixelColor(i, R, G, B);
                }
                strip.show();
            }
            strip.show();
            Thread::wait(30);
        }
    }
    strip.setBrightness(127);
}

void led_shift() { //number of LEDs lit determined by current frequency of music. Color determined by global vars
    while (ledthread == '9') {
        for (int i = 0; i < 60; i++) {
            for (int j = 0; j <= i; j++) {
                strip.setPixelColor(j, R, G, B);
            }
            for (int j = i + 1; j < 60; j++) {
                strip.setPixelColor(j, 0, 0, 0);
            }
            strip.show();
            if (ledthread != '9') {return;}
            Thread::wait(100);
        }
        for (int i = 59; i >= 0; i--) {
            for (int j = 59; j >= i; j--) {
                strip.setPixelColor(j, 0, 0, 0);
            }
            for (int j = i - 1; j >= 0; j--) {
                strip.setPixelColor(j, R, G, B);
            }
            strip.show();
            if (ledthread != '9') {return;}
            Thread::wait(100);
        }
    }
}

void led_rainbow() { //Repeats pattern of Red-Orange-Yellow-Green-Blue-Voilet down the strip, and shifts that down the strip
    uint32_t colors[60];
    uint32_t tmp;
    uint32_t rainbow[10] = {red, orange, yellow, green, blue, violet, blue, green, yellow, orange};
    for (int i = 0; i < 60; i++) {
        colors[i] = rainbow[i % 10];
        strip.setPixelColor(i, colors[i]);
    }
    strip.show();
    Thread::wait(300);
    while (ledthread == '4') {
        tmp = colors[0];
        for (int i = 1; i < 60; i++) {
            colors[i - 1] = colors[i];
            strip.setPixelColor(i, colors[i]);
        }
        colors[59] = tmp;
        strip.setPixelColor(0, colors[0]);
        strip.show();
        Thread::wait(300);
    }
}

void led_trail() { // Slowly transitions entire strip through color wheel
uint32_t colors[60];
    //uint32_t tmp;
    uint32_t rainbow[10] = {red, orange, yellow, green, blue, violet, blue, green, yellow, orange};
    for (int i = 0; i < 60; i++) {
        colors[i] = rainbow[i % 10];
    }
    while (ledthread == '5') {
        strip.clear();
        for (int i = 1; i < 59; i++) {
            if (ledthread != '5') {return;}
            strip.setPixelColor(i-1, colors[i-1]);
            strip.setPixelColor(i, colors[i]);
            strip.setPixelColor(i+1, colors[i+1]);
            strip.show();
            Thread::wait(25);
            strip.clear();
        }
        for (int i = 59; i > 0; i--) {
            if (ledthread != '5') {return;}
            strip.setPixelColor(i-1, colors[i-1]);
            strip.setPixelColor(i, colors[i]);
            strip.setPixelColor(i+1, colors[i+1]);
            strip.show();
            Thread::wait(25);
            strip.clear();
        }
    }
}

void led_flash() {
    uint32_t rainbow[10] = {red, orange, yellow, green, blue, violet, blue, green, yellow, orange};
    while (ledthread == '3') {
        set_strip(rainbow[rand() % 10]);
        Thread::wait(300);
        if (ledthread != '3') return;
        strip.clear();
        strip.show();
        Thread::wait(300);
    }
}

void led_fade() {
    set_strip(255, 0, 0);
    uint8_t r = 255, g = 0, b = 0;
    while (ledthread == '2') {
        while (g < 255) {
            if (ledthread != '2') return;
            g++;
            set_strip(r, g, b);
            Thread::wait(5);
        } while (r > 0) {
            if (ledthread != '2') return;
            r--;
            set_strip(r, g, b);
            Thread::wait(5);
        } while (b < 255) {
            if (ledthread != '2') return;
            b++;
            set_strip(r, g, b);
            Thread::wait(5);
        } while (g > 0) {
            if (ledthread != '2') return;
            g--;
            set_strip(r, g, b);
            Thread::wait(5);
        } while (r < 255) {
            if (ledthread != '2') return;
            r++;
            set_strip(r, g, b);
            Thread::wait(5);
        } while (b > 0) {
            if (ledthread != '2') return;
            b--;
            set_strip(r, g, b);
            Thread::wait(5);
        }
    }
}

void led_random() {
    uint32_t rainbow[10] = {red, orange, yellow, green, blue, violet, blue, green, yellow, orange};
    while (ledthread == '6') {
        for (int i = 0; i < 10; i++) {
            strip.setPixelColor(rand() % 60, rainbow[rand() % 10]);
        }
        strip.show();
        Thread::wait(500);
    }
}

void set_strip(unsigned char r, unsigned char g, unsigned char b) {
    uint32_t tmp = strip.Color(r, g, b);
    for (int i = 0; i < 60; i++) {
        strip.setPixelColor(i, tmp);
    }
    strip.show();
}
void set_strip(uint32_t tmp) {
    //uint32_t tmp = strip.Color(r, g, b);
    for (int i = 0; i < 60; i++) {
        strip.setPixelColor(i, tmp);
    }
    strip.show();
}

void led_main() {
    while(1) {
        //pc.puts("test");
        switch(ledthread) {
            case '2': led_fade();
                break;
            case '3': led_flash();
                break;
            case '4': led_rainbow();
                break;
            case '5': led_trail();
                break;
            case '6': led_random();
                break;
            case '7': led_solid();
                break;
            case '8': led_pulse();
                break;
            case '9': led_shift();
                break;
            default: break;
        }
    }
}

/*
Main Thread. Handles communication with the C# app.
Recieves commands in the format "!<type><argument>\0"
Types:
R: Takes an argument of 0-255 as a byte. Changes global unsigned char R for red LED color.
G: Takes an argument of 0-255 as a byte. Changes global unsigned char G for green LED color.
B: Takes an argument of 0-255 as a byte. Changes global unsigned char B for blue LED color.
L: Takes an argument of '1' - '9' as a char. Changes LED thread, or terminates LED thread if argument is '1'

*/
int main() {
    pc.baud(9600);
    strip.begin();
    strip.setBrightness(127);
    strip.clear();
    strip.show();
     red = strip.Color(255, 0, 0);
     orange = strip.Color(255, 40, 0);
     yellow = strip.Color(255, 255, 0);
     green = strip.Color(0, 255, 0);
     blue = strip.Color(0, 0, 255);
     violet = strip.Color(238, 130, 238);
    char c;
    while(1) {
        while(!pc.readable()) {Thread::wait(1);}
        if (pc.getc() == '!') {
            c = pc.getc();
            if (c == 'R') {
                R = (unsigned char)pc.getc();
            }
            if (c == 'G') {
                G = (unsigned char)pc.getc();
            }
            if (c == 'B') {
                B = (unsigned char)pc.getc();
            }
            if (c == 'L') {
                c = pc.getc();
                if (ledthread != c) {
                    //led.terminate();
                    ledthread = c;
                    switch(c) {
                        case '1': led.terminate();
                        strip.setBrightness(127);
                        strip.clear();
                        strip.show();
                        break;
                        default: if (led.get_state() == Thread::Deleted || led.get_state() == Thread::Inactive) {
                            led.start(led_main);
                        }
                        break;
                    }
                }
            }
            
        }
    //pc.putc(ledthread);
    Thread::wait(10);
    }
}

void led_solid() {// Solid color
    //pc.puts("test");
    while (ledthread == '7') {
        //spi_lock.lock();
        //uint32_t rgb = strip.Color(R, G, B);
        for (int i = 0; i < 60; i++) {
            strip.setPixelColor(i, R, G, B);
        }
        spi_lock.lock();
        strip.show();
        spi_lock.unlock();
        Thread::wait(10);
    }
}

/media/uploads/kingalicia51/circuitboard1.jpg

Videos


Please log in to post comments.