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.
You could make a scalextrics like game which would handle the averaging well!
ReplyDelete