Sunday, August 12, 2012

Lovebirds 112

Two friends of mine are getting married. So, I decided a few months ago, I'd make them a personal wedding present which would light up their living room.

I knew I wanted to make an artwork with LEDs, but I had no idea what I would depict. The inspiration came when I received the wedding invitation. It contained two nice lovebirds.


So, that was it. Those two lovebirds were going to be LEDified. The first step was to make the design. There were some limitations to the design, I had already ordered 60 red LEDs and 50 white ones. I was going to use a 12V power supply and I decided to hook up the LEDs in goups of 4 in series. The number of LEDs used for each "component" would have to be a multiple of 4. The design shown below was not the final design, it used too many white LEDs, but it was the first concept I was really happy about.


After the design, I breadboarded the control circuit of the fading LEDs. I've done this using an AVRTiny2313 chip. This may be a bit overkill, but I had one lying around. In the picture you can see the AVRISP mkII to program the AVRTiny.


To drill the holes in the mdf board, I've edited the initial design and printed it for easy drilling.


112 holes and 1 spraypaint later...



After yet another spraypaint and a lot of work mounting and wiring the LEDs, this is what it looked like:
 To finish it all, I made the PCB and mounted it all in an ikea frame.




112 LEDs, 112 LED mounts, 32 resistors, 10 bolts and screws, 3 transistors, 2 capacitors, 1 voltage regulator, 1 transformer, 1 diode, 1 mdf board, 1 ikea frame, 1 AVRTiny2313 and lots of wire gives you this:



The source code:
#ifndef F_CPU
   #define F_CPU 8000000UL     
#endif 
#include <avr/io.h>
#include <util/delay.h>

//Functions
uint16_t readPWMValue(uint8_t reg);
void writePWMValue(uint8_t reg, uint16_t value);
void pulse(uint8_t port, int8_t speed, int8_t* direction);
void fadeIn(uint8_t port);

int main(void)
{
 // Set Port B pins as all outputs
 DDRB = 0xff;
 // Set Port D pins as all outputs
 DDRD = 0xff;

 // OC1A, OC1B outputs
 DDRB |= (1<<PB4)|(1<<PB3);

 // Timer 0 setup (8 bit timer)
 // /8 prescaler
 TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM01) | (1 << WGM00); 
 TCCR0B = (1<<CS01);

 // Timer 1 setup (16 bit timer)
 // TOP, set to 255 to behave similarly to the 8-bit timer
 ICR1 = 255;
 // Timer 1 fast PWM mode 14
 // Clear on compare, set at TOP
 // /8 prescaler
 TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
 TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS11);

 // Initialize compare registers
 OCR0A = 10;
 OCR0B = 10;
    OCR1A = 10;
    OCR1B = 10;
  
   //Initialize variables
  int8_t direction[4];
 direction[0] = direction[1] = direction[2] = direction[3] = 1;

 //Startup sequence
 writePWMValue(0, 0);
 writePWMValue(1, 0);
 writePWMValue(2, 0);

 _delay_ms(500);

 for(int i = 0; i < 3; i++)
 {
  fadeIn(i);
  _delay_ms(1000);
 }

 _delay_ms(500);

 for(int j = 0; j < 10; j++)
 {
  for(int i = 0; i < 3; i++)
  {
   writePWMValue(0, 0);
   writePWMValue(1, 0);
   writePWMValue(2, 0);
   writePWMValue(i, 255);
   _delay_ms(100);
  }
 }

 //Loop
 while(1)
 {
  pulse(0, 3, &direction[0]);
  pulse(1, 3, &direction[1]);
  pulse(2, 1, &direction[2]);
  pulse(3, 50, &direction[3]);
  _delay_ms(40);


  // Set all Port B pins as HIGH
  /*PORTB = 0xff;

  _delay_ms(2000);  

  PORTB = 0;

  _delay_ms(2000);*/
 }

  return 1;
}
void fadeIn(uint8_t port)
{
 writePWMValue(port, 0);

 for(int i = 0; i < 50; i++)
 {
  writePWMValue(port, i);
  _delay_ms(20);
 }

 for(int i = 50; i < 256; i++)
 {
  writePWMValue(port, i);
  _delay_ms(5);
 }
}
void pulse(uint8_t port, int8_t speed, int8_t* direction)
{
  int16_t registerValue = readPWMValue(port);

  if(registerValue < 60)
  {
   registerValue += (*direction)*speed;
  }
  else
  {
   registerValue += (*direction)*speed*3;
  }

  if(registerValue > 255)
  {
   *direction = -1;
   registerValue = 255;
  }
  else if(registerValue < 0)
  {
   *direction = 1;
   registerValue = 0;
  }

  writePWMValue(port, registerValue);
}

uint16_t readPWMValue(uint8_t reg)
{
 switch(reg)
 {
  case 0:
   return OCR1A;
  case 1:
   return OCR1B;
  case 2:
   return OCR0A;
  case 3:
   return OCR0B;
 }
 return 0;
}

void writePWMValue(uint8_t reg, uint16_t value)
{
 switch(reg)
 {
  case 0:
   OCR1A = value;
   break;
  case 1:
   OCR1B = value;
   break;
  case 2:
   OCR0A = value;
   break;
  case 3:
   OCR0B = value;
   break;
 }
}

Saturday, January 22, 2011

Pedalboard

The amount of cables and power supplies tends to explode as bassists or guitarists get more and more effect pedals. So I thought I needed a pedalboard, one board to contain all my (frequently used) effect pedals, power supplies and wiring.

I found a thread which contained a build report for such a pedalboard. This was all my father-in-law needed and started doing all the woodwork for me (as I don't have the necessary tools). I finished it off with the Velcro strips, the power supply and an A/B switch pedal which also functions as the power supply for all the 9V pedals.

As you can see, there is still some space left for extra pedals :)


Thursday, November 4, 2010

Moodlight "Oodles"

I've made a moodlight using an AVR chip (ATTiny2313) and lots of blue LEDs. You might even say, oodles of blue LEDs. "Oodles" seemed like a good name to describe these. So here it is: Moodlight "Oodles".
The light animations in this video are much faster than they would normally be, I didn't want to post minutes-long footage.





Tuesday, August 17, 2010

Quiz Buzzer System

I finished a new project! It is a Quiz Buzzer System. I gave it a name, a horrible name, the BnB-0x7DA.

A friend of mine asked me to build this a while ago. My god, it's been nearly a year he first spoke of this! The system he had in mind needed to do only a few things: "When a button is pressed a light goes on (matching the button) and a sound is played. Oh, and could you display the person who triggered it on the screen too?"

The prototype
The first step: make a prototype. It looked something like this:
An Arduino to implement the logic of the lights and the communication with an application on a PC via USB and a few shift registers. The shift registers were required because I needed to control 16 LEDs (not enough pins on the Arduino to do that).

I also did something most people find unusual: I prototyped the software as well (most software prototypes end up being the final product). The application communicating with the arduino was written in Processing. It had only the basic functionality, but it clearly showed the idea was feasible and was a good way to show to my friend how I interpreted his "specs". The eventual application would be written in Qt / C++, more on that below.

The shield
I decided it was time that I made a decent Arduino-type shield, instead of my usual big mess of wires. I'm pretty pleased with the result. It just fits right on top of an Arduino, brilliant! I can also recommend using a 2-hole-per-strip stripboard, it works really well for connecting ICs with one another.

The drilling
As soon as the electronic core was finished, it was time for the drilling. Oh boy, did I drill: 17 holes in the top cover, 6 in the bottom cover, 2 of those had to be rectangular shaped, which is a special kind of hard (drills don't come in rectangular shapes).


The wiring
To prevent messy internal wiring, I used flat cable (re-used some old IDE cable). Again, very pleased with the result.

The buttons
Next up: the buttons. My friend and I decided to come up with something other than the usual square-box-with-a-button-on-top design. So we decided to use wooden handles. These wooden handles would be fitted with illuminated buttons. (Did this just start to sound really expensive?) Not an easy thing to do, fit buttons into wooden handles. Here are some pictures of the process.

To control both a button and an LED via only 2 wires I needed a few electrical components on the buttons themselves. Luckily, these components were small enough. So they could be fitted right between the leads of the button. (The diameter of a button is 8mm.)


The BnB-0x7DA
So there you go, those were the hardware steps required to finish the project. The result can be admired in the image below: 8 player buttons, one reset button on top of the case, one button is connected to the side of the case to also function as a reset button, one spare button on the left and one toggle switch on the right to enable or disable the buzzer. Between a handle and a connector there is about 10m of cable. Totalling more than 100m of cable in this picture! Notice the nice blue and green lights :)


The software
For the software side of things, I made an application with Qt. It has a very good IDE and a clean API. It's especially easy to create decent GUIs in Qt. GUI code tends to become really messy, really fast, but Qt manages to encapsulate the messy part of GUI code in a generated source file.

The application did not need to do much. Every button is attached to a name and a sound. If enabled, this sound is played when the player presses his button first and his name shows up on the screen. The application also supports teams of players, saving and loading, auto detection of the serial port and a basic score system.

I tried some experimental GUI design. Not sure if it is æsthetic, but it definitely is user friendly.

The conclusion
Although, technically, this wasn't one of the hardest projects I have done, it surely wasn't easy. The main goal was to finish a professionally looking product which is easy to use and somewhat durable (this remains to be seen). Thomas Edison said "Success is 10 percent inspiration and 90 percent perspiration". This is definitely the case with this project. Like I said, technically, not the most difficult, but I put more time in this than any other project so far. And it was totally worth it.

Wednesday, October 21, 2009

Processing

I'd like to introduce Processing to those who have not heard of it yet. It is a programming environment and language which shields you from the "annoying little details" of programming.

You can just jump in with little or no programming experience and have a GUI, 3D or a network application up and running in no time.

The Arduino development environment is based on the Processing environment. Which is why I thought it would be a good idea to check out Processing.. and I love it :)

It's probably the best way to learn programming... then again, you will probably end up hating all other development environments if you are used to the ease of Processing ;)

Friday, September 11, 2009

BBox Drum Generator

The BBox Drum Generator is an Arduino-based Midi sequencer mounted inside a Banana Box. The BBox contains a few preset drumbeats. These drumbeats form the basis for a drum variation algorithm (explained here). The amount of introduced variations is controlled by the blue rotary knob.

I've created four pushbuttons by mounting LEDs on top of PCB mounted mini pushbuttons. This idea is based on this article.

The two top buttons navigate through the functions of the BBox. The two lower buttons change the value of the function. Currently only the BPM and the Drum Preset can be changed.

The BBox only generates midi messages, the sound is generated by a Roland Juno-D.

The Video



The Picture




The Guts
Big mess o' wires O_o

Next time, I'll create a proper Arduino shield.

Friday, September 4, 2009

Drum Variation Algorithm

The context
I've been experimenting a bit with the Arduino as a basic midi sequencer. A drum sequencer is a good place to start. It's easier than an actual melodic music sequencer. You can leave out the length of a note, as a drum is a one-shot sounds device.

Because allowing the user to program drum sequences himself requires an extensive interface, or a piece of software, I thought I would write a drum generator.

Wouldn't it be cool if you can just push a button and a computer/chip does the whole creative process for you?

Yes, it would. But it scares me a little bit as well.

I've started with a mechanism that chopped up existing drum sequences in pieces and reassembles them to generate new drum sequences. This could work for breakbeat style drum patterns, but most of the time it seemed to create a build up of expectations, only to leave the listener behind with an empty feeling.


The drum sequence format
Because the format in which the drum sequence is saved on the Arduino is essential to the Drum Variation Algorithm, I will explain this first.

The size of the RAM memory of the Arduino (based on an Atmega168) is small. Really small. Only 1kB. 1024 bytes. 8192 ones and zeros.

I'll just pause here for a while to let this sink in, I suggest you do the same.

Alright, if I want to use lots of data structures, I will have to make them small. The best way to make data small, is to assume as much as you can about the data in question and limit the possibilities as much as possible. So I introduced three limitations.

The drum pattern has a maximal resolution of 16th notes

For one instrument, the maximal number of notes that can be played in one measure is 16


There are only four velocity levels

Midi allows 128 velocity levels, I've made a mapping from 0, 1, 2, 3 to 0, 40, 90, 110 respectively (off, soft, medium, hard)


A measure consists of a maximum of three instruments

A typical measure consists of a hi-hat, a snare and a bassdrum, but which instruments are used is configurable



So if a measure has sixteen notes with four velocity levels, one measure for one instrument can be encoded in 4 bytes.

This is a typical drum notation which is used a lot online.
I've used large and small X's to indicate the velocity level.

HH|X-x-X-x-X-x-X-x-|
SD|----X-------X---|
BD|X---------x-----|


In the datastructure I've described above, this would look something like this. (A B in front of ones and zeros is the binary representation of a number: 11 = B1011 = 0xB)

{
{ 42, B11001000, B11001000, B11001000, B11001000 },
{ 40, 0, B11000000, 0, B11000000 },
{ 36, B11000000, 0, B00000100, 0 }
}

The first number defines the instrument as a midi note number. 42 is a hihat, 40 a snare drum and 36 a bass drum. The total amount of bytes needed to encode a measure of 3 instruments with a maximal resolution of 16th notes requires ... 15 bytes.

A clearer representation would be a number in base 4, but afaik this is not possible in C/C++. B11001000 would be 3020, so a hard hit on the first 16th note, nothing on the second, a medium hit on the third and nothing on the fourth.


The Drum Variation Algorithm

If you've gotten this far, the algorithm itself is actually really simple, I hope it is not too much of a let down. If it is, I will gladly remind you of Occam's Razor.

Everytime a new measure starts, each byte of the datastructure (except the instrument note numbers) is bitwise XOR'ed with a random byte (a number between 0 and 256). The actual random number being calculated is one between 0 and a variable limit [controlled by a potmeter]. If the number is greater than 255, the original byte is left alone. With this you can control the amount of introduced variations.

Why bitwise XOR? It seems good at keeping the feel of the original pattern. It introduces new notes, but an XOR is also affected by the original byte. A bitwise OR can only add notes and a bitwise AND can only take them away.

Here is a video demonstrating the algorithm, the knob controls the amount of introduced variations (it also demonstrates the BBox Drum Generator, a post about this will be here soon).


I love it when simple things give good results :)

Blue LED Mouse

I fixed my mouse!

"Wait, what? And you are writing a post about that?"

Ok ok, not very spectacular. I agree. But I replaced the broken red LED with a blue one!
Still not excited? Ok, you may leave.

For the rest of you, here is a picture.



For those that are interested: the scroll wheel works with an infrared emitter and receiver. The infrared light is blocked and unblocked for every scroll "click". I did not know this, so I thought I'd share it with you. To be honest, I never really gave it any thought..

For people that like salvaging parts, here is a list of parts you can probably salvage from a broken optical mouse:

  • Several pushbuttons

  • A tiny camera with crappy resolution

  • Infrared receiver and emitter

  • An LED.. :)

  • USB cable [with one half missing]

  • Some chips, but I'm not sure if they will be helpful, or if you will be able to find datasheets



Mind you, it's a broken mouse. So some parts may not work :D

Wednesday, August 19, 2009

Arduino Midi Sequencer


I've fiddled with midi and an Arduino before, but now I have integrated an LCD as well. Which makes the whole thing almost usable !

The Arduino makes everything really easy; it has tutorials about communicating with the LCD, there are forumposts where people explain how they hooked it up to midi. It really is just a matter of putting all the elements together.

Currently, the "Arduino Midi Sequencer" only plays a simple drumbeat (with adjustable BPM). I hope to make it a programmable sequencer by adding some buttons and interfacing with some permanent storage. If that doesn't work out, I'll just make it a pre-programmed drum sequencer, which can lay down the groove while I practice guitar and/or bass :)

Friday, July 24, 2009

Little Drummer Robot

Someone made a robot that searches for a "beatable object". When the robot finds this object, it lays down a funky groove ... and I think it's brilliant.