Saturday, March 1, 2014

Using a scalextrics controller with teensy through ADC

I wanted to try using a scalextrics controller as an input device to my computer via the teensy, the controller itself is just a variable resistor - I tried to measure its resistance (against the jack) using my multimeter but I got no reading which was frustrating.. I opened it up and it definitely is a variable resistor.

So I opened up the part of the scalextrics track which you plug these devices into and it contained this nice PCB:

(I took a green and white wire and soldered them onto the bottom two pins for my own use).

The way this works is that you have a transformer from the mains which goes from 240V to 15V, and goes into PLG1 - then if you trace out the schematic you can see that this is exactly a four diode full wave rectifier:

So this converts the sine-wave from AC mains into a purely positive "bump" wave that drives the cars forwards - since they have a bit of inertia you don't need any capacitors to smooth it out into a DC signal. Of course the speed is limited by the controllers.

I tried measuring the resistance again but this time through the wires on my modified microtrack PCB and I got readings from between 20 and 200 ohms as I squeezed it!

I needed to design a circuit to connect this to the teensy, so I first tried to limit the current (so as not to damage my nice micro) using a 470ohm resistor then into the variable resistor and to the ADC pin but I thought I should also have a plug into the ground for some reason?

I thought about the voltages at the various nodes (like in Kirchoffs laws) and realized actually this would not work at all - I think it wouldn't get any different readings. So I changed my design to this:

Now you can see the voltage will change nicely as the variable resistor changes. in fact this is a very basic voltage divider circuit!

I modified my earlier usb_serial code using the nice example code for ADC from pjrc to get a program that streamed the scalextric reading to my computer through serial:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#include "usb_serial.h"
#include "analog.h"

#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))

// Send a string to the USB serial port.  The string must be in
// flash memory, using PSTR
//
void send_str(const char *s)
{
    char c;
    while (1) {
        c = pgm_read_byte(s++);
        if (!c) break;
        usb_serial_putchar(c);
    }
}

int main(void) {
  int16_t a;
  int i;
 
  CPU_PRESCALE(0);
 
  // USB initialization routine taken from example.c
  usb_init();
  while (!usb_configured());
  _delay_ms(1000);
  // wait for the user to run their terminal emulator program
  // which sets DTR to indicate it is ready to receive.
  while (!(usb_serial_get_control() & USB_SERIAL_DTR)) /* wait */ ;
  // discard anything that was received prior.  Sometimes the
        // operating system or other software will send a modem
        // "AT command", which can still be buffered.
 
  usb_serial_putchar('s');
  usb_serial_putchar('c');
  usb_serial_putchar('a');
  usb_serial_putchar('l');
  usb_serial_putchar('e');
  usb_serial_putchar('x');
  usb_serial_putchar('t');
  usb_serial_putchar('r');
  usb_serial_putchar('i');
  usb_serial_putchar('c');
  usb_serial_putchar('\r');
  usb_serial_putchar('\n');
  while(1) {
    a = adc_read(0);
    usb_serial_putchar(hex[((a>>12)&0xF)]);
    usb_serial_putchar(hex[((a>>8)&0xF)]);
    usb_serial_putchar(hex[((a>>4)&0xF)]);
    usb_serial_putchar(hex[((a>>0)&0xF)]);
   
    usb_serial_putchar('\n');
   
    _delay_ms(70);
  }
}

Once I had calibrated the values I made it print lines of #'s so that I could draw waves by squeezing it:

It's nice to have it all working but the readings go a bit weird when you squeeze it fully, I don't think it's precise enough to use as an input device for games on the computer (for example), at least not without some clever post processing and averaging.

1 comment:

  1. You could make a scalextrics like game which would handle the averaging well!

    ReplyDelete