Turning PC On with a Knock Using ATtiny45 and a Piezoelectric Sensor

PS/2 with ATtiny45

Today’s post is something I’ve prepared for a long time. Hardware-wise it’s a simple thing – ATtiny45 emulating a PS/2 device, sending a keypress when three knocks are detected in the attached piezoelectric sensor (or piezo buzzer as they are also called). But if your computer can boot on PS/2 keyboard input and you have your computer stowed somewhere hard to reach (or just want to impress your friends), it’s a pretty neat little gadget! Here’s a video of it in action:

My PC takes a few seconds to put anything on display, but if you look at the bottom right corner, you can see the blue power LEDs light up immediately after the knocks.

What You’ll Need

Components
Hardware-wise this hack is super simple. You’ll need less than $10 in parts and many probably already have these lying around:

  • ATtiny45. Actually, any ATtiny or ATmega with 4kB or more flash, A/D converter and two timers will work with small adjustments, and with -Os -DMINIMAL compiler flags also 2kB MCUs (ATtiny2313 doesn’t have a A/D but you can either work around it or use a button)
  • Piezo buzzer and 1 Mohm resistor to act as knock sensor
  • PS/2 connector, or alternatively a passive USB-PS/2 adapter (I have half a dozen from old keyboards and mice) and USB cable (like the one I used in my V-USB tutorial)
  • Breadboard and wire. Alternatively you can solder it on a simple PCB like I eventually did.
  • Optionally, a 4k7 ohm pullup resistor for RESET line, and a LED and 330 ohm resistor to indicate state

The Schematic and Breadboard Setup

Schematic

The PS/2 part as discussed in my minimal PS/2 keyboard post doesn’t require any other hardware than the ATtiny. The piezo element uses a 1 Mohm resistor like in the Arduino Knock Sensor tutorial, providing a path for voltage level to get back to zero over time. The LED is connected to PB4.

The PS/2 connector also provides power to the device. Instead of soldering a custom PS/2 connector for the project, I took a passive USB-PS/2 adapter I had lying around and used a multimeter to find out which USB pins correspond to the PS/2 ones. Not surprisingly, PS/2 GND and VCC are connected to USB GND and VCC. In my adapters, PS/2 clock was connected to D+ and data to D-. You can see the mnemonic printout I made on that one below, as well as one possible breadboard configuration.
Continue reading Turning PC On with a Knock Using ATtiny45 and a Piezoelectric Sensor

Tutorial: State Machines with C Callbacks

State machine

Many electronics projects involve the device transitioning from one state to another. On a high level, it could be that your project is initially in a state where it awaits input, and once it receives it, it goes to another state where it performs a series of actions, eventually returning back to the initial state. On a lower level, many communications protocols are often simple or increasingly complex state machines. In many cases, an elegantly implemented state machine can simplify your code and make it easier to manage.

There are several methods to implement state machines programmatically starting from simple if-conditions to state variables and switch structures. In this tutorial I’ll cover a slightly more advanced method of using callbacks or “function pointers” as they are implemented in C. This has some performance benefits, makes up for some clean code, and you’ll learn a bit on the way!

State Machines with Conditionals

First, to introduce the idea of a state machine, lets take a simple example: Blinking LEDs. Imagine you want the LED to turn on for a second, and then turn off. We could do it with a simple 2-state machine:

enum states { 
  LED_ON,
  LED_OFF
};

enum states state = LED_OFF;

while(1) {
  if(state == LED_OFF) {
    led_on();
    state = LED_ON;
  } else {
    led_off();
    state = LED_OFF;
  }
  sleep(1); // sleep for a second
}

If you can understand the code above, you have pretty much grasped the fundamentals of state machines. We have some processing specific to given state, and when we want to go to another state, we use a variable (in this example it’s called state) to do that. And by the way, if you haven’t encountered enum before, you should check out Enumerated type in Wikipedia. It’s a very handful tool to add to your C coding arsenal.
Continue reading Tutorial: State Machines with C Callbacks

Super Simple 50+ kHz Logic Analysis with ATtiny2313 and FTDI Friend

AVR & FTDI logic analyzer

While banging my head against the wall with debugging my PS/2 keyboard thingy, I really wished I had a dedicated logic analyzer (preferably with PS/2 decoder, but even raw binary data would’ve been fine). So I decided to try out a long hatched idea – combine an ATtiny2313 and FTDI for some unlimited-length logic capturing with a PC. You’ll only need:

  1. ATtiny2313
  2. 20 MHz crystal and caps (slower will also work, frequency just defines what baud rates you’ll achieve)
  3. FTDI USB/serial converter, like the FTDI friend from Adafruit
  4. Optionally, some power-stabilizing capacitors, reset pullup and ISP programming header for flashing the firmware

ATtiny2313 is ideal for this, as it has all eight port B pins on one side in numerical order – attaching up to 8 logic lines is really straightforward. With 20 MHz crystal, baud rates close to 1 Mbps can be achieved in fast serial mode. I used Adafruit’s FTDI Friend for really simple (and way faster than most cheap serial adapter dongles) serial to USB conversion – just connect ATtiny RXD pin to TX, and TXD to RX, and you can even get power from the Friend so you’re all set! For crystal and that other stuff, see my ATtiny2313 breadboard header post for schematic, the picture above should fill you in with the rest.

Firmware code

This device has some of the smallest firmware codebases ever (firmware is 128 bytes). All we need to do is to set up UART with desired speed, and have the AVR chip to fire up an interrupt whenever data has been sent, and then use that to send current state of port B (using PINB):

#include <avr/io.h>
#include <avr/interrupt.h>

void USARTInit(unsigned int ubrr_value, uint8_t x2, uint8_t stopbits) { 
  // Set baud rate
  UBRRL = ubrr_value & 255; 
  UBRRH = ubrr_value >> 8;

  // Frame Format: asynchronous, 8 data bits, no parity, 1/2 stop bits
  UCSRC = _BV(UCSZ1) | _BV(UCSZ0);
  if(stopbits == 2) UCSRC |= _BV(USBS);

  if(x2) UCSRA = _BV(U2X); // 2x

  // USART Data Register Empty Interrupt Enable
  UCSRB = _BV(UDRIE);

  // Enable The receiver and transmitter
  UCSRB |= _BV(RXEN) | _BV(TXEN);
}

int main() {
  // 230.4 kbps, 8 data bits, no parity, 2 stop bits
  USARTInit(10, 1, 2); // replace 10 with 4 to get 0.5 Mbps

  sei(); // enable interrupts

  while(1) {}
	
  return 1;
}

ISR(USART_UDRE_vect) {
  UDR = PINB;
}

Continue reading Super Simple 50+ kHz Logic Analysis with ATtiny2313 and FTDI Friend

Retronics USB Joystick Adapter and Other Coolness with V-USB

Retronics joystick adapter

There are a ton of cool gadgets available in eBay, and even though I sometimes do impulse buys, I rarely mention those in my blog. However, this extremely cool piece of retro tech is something I just cannot pass by without a comment: Retronic Design USB joystick adapter. It is essentially a joystick adapter for the popular 9-pin D-SUB connector used in many of the 80s consoles, most notably Atari, Commodore 64 and Amiga. On the outside, it’s not much to be excited about – USB connector on the one end, and grey dongle that accepts a joystick on the other. However, things quickly change when you open up the enclosure (click on the image for a large view):

Retronics USB adapter opened up

Inside the D-SUB end there is a very neat little piece of engineering, and many of my readers probably know how to program it — it isn’t anything other than a ATmega8A, a 8-bit AVR microcontroller that employs the same V-USB library I’ve covered in my tutorials to appear as a USB HID device on PC side.

All the components are on one side, and you have to admire the tiny ISP header the Retronic Design guys have fitted on the PCB. And wait, it doesn’t stop there. On the Retronic Design web site, they have full specifications for the device, and the download page includes both schematic, as well as full source code to the firmware.
Continue reading Retronics USB Joystick Adapter and Other Coolness with V-USB

DIY ATtiny45/85 ISP Header

ATtiny ISP header in practice

A quick weekend tip for a change, I thought to share a nice small soldering project will make programming ATtiny45 and ATtiny85-based projects a flash:

Basically I took a piece of veroboard, soldered some extra long pin headers on the bottom so it will form a tent of sorts above a ATtiny45/85 attached to a breadboard project. Then I soldered a 6-pin header to attach the ISP programming cable to, and used short pieces of jumper wire to route the header pins to correct ATtiny85 pins.

Now whenever I need to flash a ATtiny45/85 project sitting on a breadboard, I can just put this on top of that and never need to look up the pin layout again!

DIY ISP header closeup

You can click the images for larger versions. I’ve also been quite busy with my PS/2 projects, so I have some nice material to share regarding that when I have some free time again in my hands!

Arduino PS/2 Keyboard Tester

Arduino PS/2 tester

Once I got my minimal AVR PS/2 keyboard device built, it quickly became apparent that such a device should be able to respond to rudimentary PS/2 commands if I would like to avoid irritating errors in BIOS and O/S side.

After spending a couple of educating evenings with my PicoScope (the only device I had at hand that could capture several seconds of PS/2 traffic at 100 kHz or more to make sure I detect each individual level change) and trying to understand bit-level PS/2 signals (I’ll maybe do a short post on that effort later), I decided it would be too complicated for debugging my own wanna-be PS/2 compliant device. So I decided to implement a simple PS/2 tester sketch with Arduino.

Basic Arduino Setup

There is already a great Arduino/Teensy library called PS2keyboard that had done most of the thinking work for me – the core of the library is an interrupt routine that is called automatically when the Arduino detects falling edge (logic level going from HIGH to LOW) on the clock pin. In Arduino Uno, pin 3 is attached to INT1, and setting up the interrupt is very simple:

#define CLOCK_PIN_INT 1 // Pin 3 attached to INT1 in Uno
// ...
attachInterrupt(CLOCK_PIN_INT, ps2int_read, FALLING);

Continue reading Arduino PS/2 Keyboard Tester

Minimal PS/2 Keyboard on ATtiny2313

AVR PS/2 keyboard

I recently got myself a mechanical keyboard (to be precise, a Happy Hacking Keyboard Professional 2). One side effect of this switch was, that the new keyboard no longer works with simple passive PS/2 adapter. And the only type of input my current motherboard can be configured to power up on is spacebar from a PS/2 keyboard.

Well, I had read from somewhere that PS/2 protocol is not too complex, so I decided to find out if I could make a simple gadget that would send spacebar keypress over PS/2 when a switch was toggled. That turned out to be quite easy (with some limitations, read the end of this post to find out more).

PS/2 basics

The Wikipedia page for PS/2 connector already looked promising – there are GND and VCC pins straight available, and only two additional (open collector type) lines are needed for data and clock lines. Communication is bi-directional with the keyboard providing clock signal and sending end toggles data line while the receiving end listens.
Continue reading Minimal PS/2 Keyboard on ATtiny2313

Using WinAVR and Command Line for AVR Development

cmd

Since my V-USB tutorials became popular, a recurring theme in the comments section have been people who are obviously motivated to try out the tutorial, but due to limited exposure to C language and command-line are either having trouble following my short instructions to compile the example .hex files, or being scared of the command-line, have tried to use AVR Studio instead, and fail.

I have to admit that first I was a bit annoyed by these people – why are they trying to follow a challenging project, when they seemingly have no understanding of how command line, makefiles, C compiler and linking process works? Then, comment by comment, I finally realized that not everyone started coding in the nineties where you launched Windows 3.11 mostly to play Solitaire, and biggest thing in coding productivity was 80×50 text mode which allowed you to have 16-color hacking bliss in your Borland Turbo C++ 3.0 IDE (or RHIDE, after DJGPP came around).

So, instead of either ignoring these people, or spending any more hours answering the same questions, I decided to start a new series of tutorials to cover really basics of getting into AVR development the way I like to do it: Old skool.

Navigating the command line

The bar for command-line wizardry in AVR development is low. There are four levels in it:

  1. Firing up command prompt
  2. Navigating to a directory and viewings its contents
  3. Running commands

The first one is really easy. In Windows 7 you can just click the start button, type “cmd”, and you’re there. Or type “command”, as the Command Prompt is usually the first search hit displayed. More hardcore persons use Win+R (that key with flag symbol finally does something useful!) and type “cmd” into the Run dialog as shown in title image of this post.

Windows Explorer

Once you’ve bitten the blue pill, commanding #2 is also quite easy. First, you need to understand that command prompt is very much like Windows explorer (shown in the above screenshot) – you are always in some directory, and the commands you enter usually work within that directory. In the example above, we are in directory E:\Koodi\AVR\usb_tutorial – let’s try if we can replicate that in command line:
Continue reading Using WinAVR and Command Line for AVR Development

PiSerial Arduino Communication Library

RGB LED demo

As a continuation to my Raspberry Pi and Arduino communication post, I thought I’d do the same but opposite way. This time, I thought it would be nice to make a proper Arduino library to make the process more streamlined.

To make communication more robust, I decided to implement a more formal communication over serial to enable applications that have some idea if a command sent to Arduino was successfully carried out or not, and also introduce basic error recovery if invalid commands or wrong number of parameters are received.

If you haven’t worked with Arduino libraries before, I suggest you to familiarize yourself with this basic tutorial or the other one at Arduino Playground. If you’re not familiar with AnalogWrite(), a quick peek to Arduino PWM Tutorial may also be in order.

Serial communication protocol

I wanted to make a simple formal protocol to send commands and hex, byte or word-sized parameters related to that command over serial line to the Arduino. For the protocol, I had these requirements:

  1. Text-based, so communication can be emulated with Arduino IDE’s “Serial Monitor” tool
  2. Size-efficient to speed up communications with slow baud rates
  3. Support for at least a few dozen commands and free number of parameters
  4. Success and error messages from Arduino
  5. Capability to return to known state after invalid commands, invalid number of arguments, communication errors or breakdowns

After some consideration, I chose to select non-overlapping sets of symbols from the ASCII character set for commands, parameters, control characters and success/error messages:

  • Small letters (a-z) for commands (26 should be enough for everyone, right?)
  • Numbers 0-9 and capital letters A-F to send parameters as hex-encoded values
  • Newline to mark end of command and parameters (either ‘\r’ + ‘\n’ or just ‘\n’)
  • Capital letters O, K, and R for success (OK) and error (RR) indications

With non-overlapping characters used for different things, detecting errors in sent commands becomes easier, as any “non-expected” character marks an error situation and as status messages OK and RR do not appear in commands, implementing two-way communication (commands to both directions) is easy later on.
Continue reading PiSerial Arduino Communication Library

Raspberry Pi as Arduino HDMI Shield

Arduino to Pi serial link

Merry Christmas to everyone! Today’s hack is something that I’ve been planning to try out for a while: Using the Raspberry Pi as a (relatively inexpensive) “HDMI shield” for the Arduino microcontroller. While the Pi can easily do most things that the Arduino can and usually much more, one might have an otherwise complete project (for example, something related to home theater automation) that would benefit from HDMI output.

Arduino display shields are not the least expensive, so why not use a RaspPi instead? There have been hacks for using RaspPi as network shield, too, and this project is very much like it (actually, you could change the Pi-side code just a bit and have some network-related commands available for your Arduino in no time).

The basic hardware premise for this hack is very straightforward – wire the Pi and Arduino together using the serial interface available on both. Because Pi is 3.3V and Arduino 5V, a level converter is needed – I used one from Adafruit this time, as it’s dead simple to use and doesn’t pose the dangers of overloading Pi like my simple resistor option does (you might, however, check that link out as it contains the pinouts for RaspPi serial pins in the GPIO header).

On software side, the Pi acts as a “server”, taking simple display commands via serial link. You could even start the Pi server script and connect to the serial port with Putty, and the session could look a bit like the following:


# initialize viewport - not actually implemented yet
init 500 500
# draw a 10x10 rectangle at (5,15)
draw 5 15 10 10
# exit the server
exit

The python server uses pyserial for serial communications, currently at 9600 bps, but the Pi and Arduino should be able to do 115 200 as well. For graphics, pygame framework is used. Current version of code initializes a 500×500 pixel graphics viewport, but one could use the parameters given by “init” command from Arduino side to define that, too. The code should be rather straightforward to understand: there are only two supported commands, “draw” with four parameters, and “quit” to exit the otherwise infinite loop waiting for draw commands (I named the file ar2pi.py):

#!/usr/bin/env python

import serial
import string
import pygame

ser = serial.Serial("/dev/ttyAMA0",9600)
ser.open()

pygame.init()
window = pygame.display.set_mode((500, 500))
colour = pygame.Color("blue")
pygame.mouse.set_visible(False)

quit = False

while not quit:
	line = ser.readline()
	words = line.split()

	if words[0] == "rect":
		pygame.draw.rect(window, colour, (int(words[1]), 
                                 int(words[2]), int(words[3]), int(words[4])))
	elif words[0] == "exit":
		quit = True
		
	pygame.display.flip()

ser.close()

Continue reading Raspberry Pi as Arduino HDMI Shield