Arduino LED DeskPet

by Emanuelsonia in Circuits > Arduino

320 Views, 0 Favorites, 0 Comments

Arduino LED DeskPet

DSC_0783.JPG

In this project I'll be making a DeskPet using Arduino UNO and a LED matrix.

A DeskPet is an interactive display that will accompany you while you're working on big documents or code. The images are customizable through code, so you can display anything you want.

This project was inspired by the Ellora65 mechanical keyboard, which features a tiny dog on a display.

Supplies

  • Arduino UNO
  • WS2812B LED Matrix
  • MDF wood (3mm , black)
  • 3 jumper cables (Female - Female)
  • A diffuser of some kind

Code (Python)

The code part of this project is divided in two parts; Arduino and Python. To read the keyboard input on a laptop, you need to run a Python script on the background, and communicate the registered information to Arduino.

I used the following code:

from pynput import keyboard
import serial
import time

ser = serial.Serial('COM4', 9600, timeout=1)
time.sleep(2)

print(ser.readline())

def on_press(key):
    try:
        print('{0}'.format(key.char))
        ser.write(key.char.encode())
    except AttributeError:
        print('special key {0} pressed'.format(
            key))


listener = keyboard.Listener(on_press=on_press)
listener.start()  # start to listen on a separate thread
listener.join()

Important while implementing these line of code is registering the Arduino in your Python script. Make sure you use the correct COM's port and baud rate.


Code (Arduino)

Up next is making sure the Arduino UNO can recieve the messages send by Python, using this code:

void setup() {
Serial.begin(9600);
Serial.println("Hello Python!");
}

void loop() {

  if (Serial.available() > 0){
    if (Serial.read() > 0){
      YourFunction();
      }
    }
  }

Once you connect your Arduino to the correct COM port on your computer and run the Python script, you'll be greeted with the message "Hello Python!" implying the connection was succesful.

After that, the Arduino will run the function of your choice once a key is pressed.

To make sure an animation is played, I created the function Walk(). In this function the Arduino displays two sprites after eachother with a small delay in between.

In order to save space on the Arduino, you need to save the sprites in Flash Memory. I did this using this tutorial and sprites. After following the tutorial I added the following code in my Arduino script, which also connects the LED Matrix:

#include <avr/pgmspace.h>  // Needed to store stuff in Flash using PROGMEM
#include "FastLED.h"       // Fastled library to control the LEDs

// How many leds are connected?
#define NUM_LEDS 256

// Define the Data Pin
#define DATA_PIN 3  // Connected to the data pin of the first LED strip

// Define the array of leds
CRGB leds[NUM_LEDS];

bool walk;

// Create the array of retro arcade characters and store it in Flash memory
const long Qbert01[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xffffcc, 0xffffcc, 0xff0033, 0xffffcc, 0xffffcc, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0xff0033, 0xff0033,
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033,  
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff0033,
0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff0033, 0x000000, 0xff0033, 0xff0033, 0x000033, 0x000033, 0xff6600, 0x000000,
0x000000, 0xff0033, 0x000033, 0x000033, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0x000000
};

const long Qbert02[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xffffff, 0xffffff, 0xff0033, 0xffffff, 0xffffff, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0xff0033, 0x000000,
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033,
0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000,
0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff6600, 0xff0033, 0xff0033,
0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff6600, 0xff0033, 0xff0033, 0x000000, 0xff0033, 0xff0033, 0x000000, 0x000000, 0xff6600, 0x000000,
0x000000, 0xff0033, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0xff0033, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000, 0xff0033, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0x000000, 0x000000, 0xff0033, 0xff6600, 0xff6600, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0xff6600, 0xff6600, 0xff6600, 0xff0033, 0x000000, 0x000000, 0x000000
};

void setup() {
FastLED.addLeds<NEOPIXEL,DATA_PIN>(leds, NUM_LEDS);  // Init of the Fastled library
FastLED.setBrightness(15);
}

void Walk(){
  bool walk;

 if(!walk){
  for(int i = 0; i < NUM_LEDS; i++) {
      leds[i] = pgm_read_dword(&(Qbert01[i]));  // Read array from Flash
  }

  FastLED.show();
  delay(100);
  walk = true;
}

 if (walk){
  for(int i = 0; i < NUM_LEDS; i++) {
      leds[i] = pgm_read_dword(&(Qbert02[i]));
  }
  FastLED.show();
  delay(100);
  walk = false;
}
}


The Casing

Behuizing-01.jpg

While designing the casing for the arduino an LED matrix, I wanted to make sure the LED's were isolated so the light doesn't start to bleed. I aimed for a look, similar to the casing made by Brainy-Bits. I also made a hole on the right side of the casing so there's room for the USB-cable that connects the Arduino to the laptop.

The end result and blueprint is shown above.

Assembly

DSC_0784.JPG
DSC_0785.JPG
DSC_0788.JPG
DSC_0789.JPG
DSC_0790.JPG

Now it's time to asseble every part of the project.

In order to build the casing, first connect the outsides of the box. After that insert your diffuser of choice and the cut out grid to isolate en diffuse the LEDs. Then its time to insert the LED matrix, make sure it's right side up.

To connect your arduino to the LED Matrix, as seen on the image above:

  • Connect the 5V out on the Arduino, to the 5V in on the matrix
  • Connect the Digital Out pin (PIN 3), to the Digital In on the marix
  • Connect the Ground of the matrix to the ground of the Arduino

Finally you can connect the USB cable to your Arduino and close up the back panel.

If the LED matrix sits a bit loose in the casing, you can add foam padding to the back panel so all the loose parts are pushed together.

Lastly, connect the Display to your laptop, run the Python script and watch the magic happen!

End Result

DSC_0783.JPG
DSC_0790.JPG