Using LED command line without root

A few of the people who tried to build the LED cube had problems getting it to run. Several people didn’t realise that you needed root. I’ve now had to solve this problem for my self as I’m now trying to use it from my ubuntu plug. I found the solution here and have adapted it for the cube. The solution to this is too use udev, which allows devices to be run from user space.

Create new rule for udev

sudo emacs /etc/udev/rules.d/60-objdev.rules

Edit new rule in emacs and add following:

SUBSYSTEM!=”usb_device”, ACTION!=”add”, GOTO=”objdev_rules_end”

SYSFS{idVendor}==”16c0″, SYSFS{idProduct}==”05df”, GROUP=”users”, MODE=”666″
LABEL=”objdev_rules_end”

For other devices replace the vendor and product id with values you can get from lsusb. For example:

daveh@mbp:~$ lsusb

Bus 001 Device 005: ID 16c0:05df VOTI

Restart udev

sudo /etc/init.d/udev restart

Plug in the cube, and try the command.

Advertisements

Mail notifier clone

I’ve been a bit slack with blog posts of late. I’ll probably start with more electronics when the weather turns, but for now I’m enjoying the sun.

In the mean time several of the forum members on eeeuser.com have been attempting to build a mail notifier inspired the LED cube that I’ve built. They’ve put their progress in this thread. Forum member posted some pictures to that thread. They’ve gone a bit further than I have by etching their own PCBs and using SMT components.

Here is the completed circuit controlling a mini lava lamp from forum member AlphaCentauri whom has also adapted with Twitter/ICQ/Mail notifier software, dBird to control the cube.

AVR Fuse settings

I’ve managed to ‘brick’ two of my ATTiny2313 chips by getting the fuse settings wrong. I’m not sure what I have done but I suspect I’ve set them to use an external oscillator without one. It should be able to get them working if I add an oscillator to my circuit.

Here is a tool that will help calculate the correct values for l/h/e fues.

It is possible to turn off the reset pin. When this happens the only option is to use the HV programmer. When the device is dead you might be able to recover them with this HV Rescue Arduino shield. I’m not planning to buy as I’d like to be able to use it with ATTiny45 which it does not support.

ProjectSteve: Cylon attachment

My friend Johnny has brought into work a Roomba clone. Apparently it is not particularly effective at cleaning, so we have decided to hack it. It is named ProjectSteve. He’s already has his vacuum cleaning parts removed and he is pretty good at carrying stuff. When discussing what to build we came up with the idea of building a light strip like KIT or a Cylon. It seems someone else already had the idea of Cylons and has added one to a Roomba.

I have loads of 3mm red LEDs and I’m going to use 25 of them to make this LED strip. I want each LED to be independently addressable so I have decided to configure the LEDs in a matrix. I’ve previously discussed how to use an LED matrix with an Arduino. If you were to wire the LEDs individually you would need 25 pins, one to control each LEDs. Using a matrix can reduce this.

I begin by wiring up the LED matrix. I decided to use 5 groups of 5 Leds

For each group, of LEDs, solder all the cathodes together. I have attached a black wire to this group and this will be used to connect to the MCU.

Close up of the back of the LED strip
Close up of the back of the LED strip

The group’s anodes are then wired together with the corresponding anode from the other groups; the first LED’s anode, from the first group, is wired to the anode of the first LED in each of the other groups. This gives ten wires to control all the LEDs. I’ve soldered each wire to a pin on some PCB header so I should be able to plug it into breadboard, or alternatively a female header when I have made the PCB.

Wiring completed
Wiring completed

The LEDs are mounted in a bent strip of acrylic. I bent this over my kitchen hob but I didn’t get particularly good quality results.

LED strip front
The finished LED strip from the front

As usual I first prototype the design on my Arduino. I’ve connected the ground pins to digital pins 2 to 6 and the positive pins to 7 to 11. I’ve again used Port Manipulation for the Arduino. The Arduino wiki advises against using it because it makes things more complicated, but I feel that it actually makes things simpler in this case. 

Here is the Arduino source. The ‘anim’ array contains the display information. Each byte is used to represent the five LED group. You should be able to see the pattern, 1’s mean LED on 0’s mean LED off.

char anim[][5] = {
{ B00000, B00000, B11111, B00000, B00000},
{ B00000, B00000, B00111, B11000, B00000},
{ B00000, B00000, B00011, B11100, B00000},
{ B00000, B00000, B00000, B11111, B00000},
{ B00000, B00000, B00000, B01111, B10000},
{ B00000, B00000, B00000, B00111, B11000},
{ B00000, B00000, B00000, B00001, B11110},
{ B00000, B00000, B00000, B00000, B11111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B00111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B01111},
{ B00000, B00000, B00000, B00000, B11111},
{ B00000, B00000, B00000, B00001, B11110},
{ B00000, B00000, B00000, B00111, B11000},
{ B00000, B00000, B00000, B01111, B10000},
{ B00000, B00000, B00000, B11111, B00000},
{ B00000, B00000, B00011, B11100, B00000},
{ B00000, B00000, B00111, B11000, B00000},
{ B00000, B00000, B11111, B00000, B00000},
{ B00000, B00011, B11100, B00000, B00000},
{ B00000, B00111, B11000, B00000, B00000},
{ B00000, B11111, B00000, B00000, B00000},
{ B00001, B11110, B00000, B00000, B00000},
{ B00011, B11100, B00000, B00000, B00000},
{ B01111, B10000, B00000, B00000, B00000},
{ B11111, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11100, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11110, B00000, B00000, B00000, B00000},
{ B11111, B00000, B00000, B00000, B00000},
{ B01111, B10000, B00000, B00000, B00000},
{ B00011, B11100, B00000, B00000, B00000},
{ B00001, B11110, B00000, B00000, B00000},
{ B00000, B11111, B00000, B00000, B00000},
{ B00000, B00111, B11000, B00000, B00000},
{ B00000, B00011, B11100, B00000, B00000},
};
void setGnd(int i)
{
  PORTD &= B10000011;
  PORTD |= (~(1 << (i+2))) & B01111100;
}
void clearGnd()
{
  PORTD |= B01111100;
}
void setLeds(unsigned int frame, unsigned int block)
{
  PORTD &= B01111111;
  PORTD |= B10000000 & (anim[frame][4 – block] << 7);
  
  PORTB &= B11110000;
  PORTB |= B00001111 & (anim[frame][4 – block] >> 1);
}
void setup()
{
  DDRD |= B11111100;
  DDRB = B00001111;
}
void loop()
{
  int frames = sizeof(anim) / (5 * sizeof(char));
  unsigned int t = millis();
  unsigned int f = (t / 40) % frames;
  for (int i = 0; i < 5; ++i)
  {
    setGnd(i);
    setLeds(f, i);
    delay(1);
    clearGnd();
  }
}
char anim[][5] = {
	{ B00000, B00000, B11111, B00000, B00000},
	{ B00000, B00000, B00111, B11000, B00000},
	{ B00000, B00000, B00011, B11100, B00000},
	{ B00000, B00000, B00000, B11111, B00000},
	{ B00000, B00000, B00000, B01111, B10000},
	{ B00000, B00000, B00000, B00111, B11000},
	{ B00000, B00000, B00000, B00001, B11110},
	{ B00000, B00000, B00000, B00000, B11111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B00111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B01111},
	{ B00000, B00000, B00000, B00000, B11111},
	{ B00000, B00000, B00000, B00001, B11110},
	{ B00000, B00000, B00000, B00111, B11000},
	{ B00000, B00000, B00000, B01111, B10000},
	{ B00000, B00000, B00000, B11111, B00000},
	{ B00000, B00000, B00011, B11100, B00000},
	{ B00000, B00000, B00111, B11000, B00000},
	{ B00000, B00000, B11111, B00000, B00000},
	{ B00000, B00011, B11100, B00000, B00000},
	{ B00000, B00111, B11000, B00000, B00000},
	{ B00000, B11111, B00000, B00000, B00000},
	{ B00001, B11110, B00000, B00000, B00000},
	{ B00011, B11100, B00000, B00000, B00000},
	{ B01111, B10000, B00000, B00000, B00000},
	{ B11111, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11100, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11110, B00000, B00000, B00000, B00000},
	{ B11111, B00000, B00000, B00000, B00000},
	{ B01111, B10000, B00000, B00000, B00000},
	{ B00011, B11100, B00000, B00000, B00000},
	{ B00001, B11110, B00000, B00000, B00000},
	{ B00000, B11111, B00000, B00000, B00000},
	{ B00000, B00111, B11000, B00000, B00000},
	{ B00000, B00011, B11100, B00000, B00000},

};

void setGnd(int i)
{
  PORTD &= B10000011;
  PORTD |= (~(1 << (i+2))) & B01111100;
}

void clearGnd()
{
  PORTD |= B01111100;
}

void setLeds(unsigned int frame, unsigned int block)
{
  PORTD &= B01111111;
  PORTD |= B10000000 & (anim[frame][4 - block] <> 1);
}

void setup()
{
  DDRD |= B11111100;
  DDRB = B00001111;
}

void loop()
{
  int frames = sizeof(anim) / (5 * sizeof(char));
  unsigned int t = millis();
  unsigned int f = (t / 40) % frames;
  for (int i = 0; i < 5; ++i)
  {
    setGnd(i);
    setLeds(f, i);
    delay(1);
    clearGnd();
  }
}

As Arduino has much much than I need  I want to simplify the design. Here is a simple circuit using an ATTiny2313 to control the LEDs. The capacitors and the chip on the right are a voltage regulator. The orange LED is a power indicator. This is the first circuit I’ve made using this chip, so I’ve yet to figure it out how to properly program it. I’ve manage to brick two chips so far, so I’m going to investigate fixing them before I continue with the next stage of this project.

ATTiny2312 LED controller
Breadboard ATTiny2312 LED controller

Cube follow up

I’ve been asked a few more questions about the Cube, so here is a follow up post with some answers.

Here are the previous posts with the information so far:

Questions

What toolchain did you use? 

I use Crosspack tool chain (formerly AVR MacPack) 
I also use V-USB (formerly AVR-USB) by the same author as Crosspack. This is a software USB implementation that works great in this scenario when only a small amount of information needs to be transferred.

How do you flash the chip?

I’ve created a small board powered by USB which I can insert the ATTiny into and attach an Atmel ISP mkII. Flashing the program is as simple as typing ‘make program’ from the firmware directory in the code.

 

Atmel AVR ISP mkII
Atmel AVR ISP mkII

How much did the components cost?

  • ATTiny45 £1.26
  • USB Connector £0.29 
  • LEDs approx £0.60
  • Resistors, Diodes, strip board approx £0.60

The cube itself was a freebie and I could have salvaged the LEDs. I’ve deliberately aimed to keep things simple with as few components as possible. It has cost less than £3 (~$5).

Is it fast enough to do colour fading?

Yes. It uses software PWM to create 24-bit colours. That means the LEDs are turning on and off really quickly to give the impression that they’re either bright or dim and mix in different proportions to create all the shades.

At the moment I just run the executable (in the commandline directory in the code) many times to create the fade. It wouldn’t be too complicated to extend the firmware to add smooth fading or alternatively to the command line tool.

How fast can you change the colours?

Pretty much instantly. However, it depends what you mean by ‘change’. As I mentioned before the LEDs are turning on and off constantly. You are limited by the transfer rate of the USB, but you could add colour fading in the firmware reducing he number of instructions required to change. 

Can I see more pictures?

I probably won’t revisit this project, but I promise to add more to future posts.

My cube is a bit dim how can I make it brighter?

It depends, I have build one board where I have removed the resistors protecting the LEDs as they are rated at approximately 3v. It is also possible to run LEDs at a higher voltage than their max rating if you reduce the duty cycle as described in this article.

USB caps lock fob

When building the USB mail notifier, I found this blog post describing how to build a tiny USB device that randomly turns the caps key on. One of my colleagues, Simon, particularly hates accidental caps presses, so much so that, he physically removed the key from his keyboard. This made him the ideal target for this joke.

The hardware required is very similar to the email notified I built. It is actually possible with a reprogram of the chip to use the same device. However I want to make this small enough to be hidden.

As with all my projects I’m trying to avoid making PCBs or using surface mount devices. I’m sticking with stripboard and normal sized devices. I used the same vertical mount of inline components.

I have removed the USB connector from an old memory stick and, although this is surface mount, the pins are spaced far enough apart to sit on a track each.

When all the parts a soldered and the chip is flashed I tested the device. It doesn’t seem to work on OS X, but fortunately it does on Windows.

Caps locker fob
Caps locker fob

As for Simon, he was perplexed for about 40 minutes, but saw the funny side when he figured it out 🙂

Building the cube

I’ve finally set about building the USB mail alert.
In my previous post, I showed the bread board prototype of my cube hack. Here is the adapted circuit diagram.

schematic
schematic

Note: There is an error in the diagram 2 is actually D+ and 3 is D-

When laying out circuits, it is a good idea to, start with the largest component first, in this case, the ATTiny45. I want to program the chip first so I am using a DIL socket. This also has the advantage of protecting the chip from excessive heat when soldering. I’d also like to use as small a board as possible so I am limiting the width to six tracks. Place all the components on the board before soldering so you can get an idea of how large the board needs to be. I followed the layout of the breadboard, however I want to make the circuit small so I have mounted the resistors and diodes vertically, with one leg bent back.

I also tried to avoid cutting tracks with the spot cutter and instead used a knife to allow components to be closer to each other. This requires a sharp knife and care must be taken to cut only one track. Soldering is also more challenging, solder sparingly, to avoid bridging across your cuts.

I cut the tracks under the chip; note that the reset pin is left disconnected. If you needed extra IO you can flash the chip to use it as such but after that you can no longer reprogram it so I avoid that as I may use the chips from previous devices in future things.

I soldered the LEDs at the end of their leads, towards the end of the PCB. This means they will be in the center of the difuser. They also have a series resistor to reduce the AVR output voltage from 3.6V to the approriate level. This resistor may not be required with some ultrabright LEDs.

To fit in the cube, I have removed the circuit, the coin cells and cover. The cube is going to be used as a cover for the new circuit so I have just cut a space using a sharp knife allowing space for the LEDs to fit into the diffuser. The circuit is slotted into the empty cube to complete the device. Plug it in and test it using the libusb command line tool, mentioned in a previous post.

The finished cube
The finished cube