Monthly Archives: August 2013

Project – Saitek Trim Wheel Internals Replacement

Downloads

Eagle Schematic

Source Code (91KB)

The above is stable code for this Project, but new features may be added in my SVN Repo.

Introduction

trimwheel_complete

Over a year ago, I purchased a Saitek Cessna Trim Wheel to complement my Flight Simulator setup. At first it was a decent enough product, but over time took a number of USB resets to be recognised by Windows. Then not long after the warranty expired, it completely stopped being enumerated and would no longer work no matter what i tried. In stead of binning the device, and inspired my some of the mods that Tom at FSX Times gets up to; i decided to pop it open and see what i could do to repair it.

Inside, it turned out to be a fairly straight forward setup. I small MCU, connected to an optical rotary encoder, using a plastic disc with notches cut around the outside to provide the mechanism (which in turn was connected to the actual trim wheel). After tracing out PCB tacks to produce a rough circuit diagram, it was time to see if the issue was with the MCU, or the optical RX/TX components.

trimwheel_encoder_schematic

Rough sketch up the Saitek circuit

The TX part of the encoder looked like a standard IR emitter, given only two of the four pins where connected, and it was running at 1.17V (Down from 5V via the 390 ohm resistor). The Opto Encoder however required a little more research, as i had not heard of these devices. I ended up coming across the HLC2701 IR detector. Reading the specs on this made me smile, as it outputs in quadrature; something i had been working with very recently making life a little easier. Given that the entire device wasn’t registering within Window, i figured it meant that the MCU would need to be replaced with my own. This also meant working with a USB interface (Something i hadn’t really done up until this point).

trimwheel_board_test_cables

Two test wires soldered to the IR Detector

Skipping ahead a little bit, i decided to check the RX/TX part of the optical encoders. Being able to use those meant not having to create my own mounting hardware if by using the current board with mine piggy backed onto it. First up, I soldered a couple of wires to the output (A & B) of the RX IR detector. This allowed me to easily hook it up to my Bitscope, and within a couple turns on the Trim Wheel, was registering a quadrature output from the two signals. With these confirmations, it was time to think about how I could piggy back my own device onto the the optical encoder, and how to fit it in the casing.

Being the impatient sort, i decided to whip up a test circuit circuit based on my Rotary Encoder Example. My biggest concern at the this point was trying to get the ATTiny85 to talk to Windows as a USB HID Joystick. The quicker i had a playground to start testing with, the better.

trimwheel_schematic

 

Testing the rotary encoder of the function was the quickest success I have had with any electrical project! The setup was receiving the quadrature output of the encoder on my first attempt, and re-invigorated me to pursue this hack.

trimwheel_breadboard

Breadboard circuit hooked up to the Trim Wheel test wires.

Next up was getting the circuit to talk to Windows! The original Saitek device talks to Windows via a Saitek propriety USB joystick driver. At this point, i didn’t know much about Windows USB drivers, so opted to use a Windows USB HID Joystick arrangement. This is essentially a descriptor file that lives on the USB device, that tells Windows what kind of data to expect, and what it means in terms of user input. This bypasses the need to a custom driver for every device (Mouses, Keyboards and generic joysticks all use this functionality).

Replacement prototype

Replacement prototype

While researching USB HID and how this would work with an ATTin85 device, i came across the V-USB project. This is essentially a USB 1.1 all firmware library for AVR’s, that would seem to fit the bill perfectly. I also came across this project from Code and Life using V-USB that provides the entire base template for my project (Both schematic and code!). Without both of these sources, i doubt this project would have ever seen the light of day!

Fast forward through a lot of hacking and breaking things to get the HID descriptor working in Windows (And never plug a V-USB device into a USB3.0 hub, it just won’t work!), and I had a reasonably working replacement for the Saitek MCU.  The next few photo’s will show how to interface my replacement MCU with the Optical Encoder.

trimwheel_board_cut_tracks

The tracks between the RX pins and the MCU must be cut

trimwheel_board_solder_wires

A & B output connections (White & Grey), Ground (Blue) and +5V (Green) connections.

trimwheel_proto_test_quadgen

Testing the board prior to installation

After some thorough speed testing using my Quadrature Generator module and some testing in FSX, it was time to mount the new board in the Trim Wheel case, and put the thing to work. Although I had soldered the wires directly to the Saitek MCU board, i decided to use pin heads on my proto board in case i wanted to swap it out for a different version later. This also made it much easier to mount my proto board in side the case, as i didn’t have to connect the cables until it was all glued in place. The below image shows my final placement for the board, and the oodles of hot glue I used to hold it in place.

trimwheel_mounting02

Todo: Insert picture of HID Joystick in Windows

Conclusion

This project enabled me to revive my Trim Wheel which other wise would have been thrown in the bin, saving me $60, with about $7 worth of parts. This also gave me the knowledge i needed to develop USB devices, and led me to work with FSX SimConnect to enable much richer devices, which i’ll post about in the future (Or see the sneak peak picture below).

My next version of the Trim Wheel will be tightly bound to FSX, instead of being a USB Joystick. This will allow me to pass back to the device the current location of the simulators trim wheel, removing the ‘absolute value’ issues that joysticks have. (Basically where the Trimwheel snaps back to its previous location prior to disabling Auto Pilot).

If there is anything I’ve left out here that you feel is needed to complete your own project, please let me know and i’ll update with greater detail.

commselector_sneak_peak

Sneak peak of my up coming FSX project: The Audio Comms Selector

Gallery of All Pictures For This Project

66_project_trimwheel

[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_complete.jpg]21631
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_board_wheel_02.jpg]19080
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_board_wheel01.jpg]16830
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_encoder_schematic.jpg]15471
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_board_test_cables.jpg]14061
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_breadboard.jpg]13320
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_breadboard_closeup.jpg]12410
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_drawn_schematic.jpg]11820
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_schematic.png]11720
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_proto_being_built.jpg]10920
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_proto_finished.jpg]10380
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_proto_test_quadgen.jpg]9940
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_board_cut_tracks.jpg]9580
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_board_solder_wires.jpg]9230
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_usb_cable_conenctor.jpg]8950
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_mounting01.jpg]8800
[img src=https://www.newioit.com.au/wp-content/flagallery/66_project_trimwheel/thumbs/thumbs_trimwheel_mounting02.jpg]8551

Examples – Rotary Encoders using PCINT

Introduction

This example is about using Rotary Encoders with AVR chips. In provides a brief look at what they are, and how to use them.

While searching the web for how to use rotary encoders, I came across a number of tried methods. Nearly all of them though used the hardware interrupt pins on the chip though. As i use these primarily for USB, i could not spare them for a rotary coder (let alone if when i wanted to use multiple rotary encoders!). For this reason, i developed my own solution using the Pin Change Interrupts (PCINT). These are similar to hardware interrupts, but trigger when any of the Pins enabled to use PCINT change. It is then up to the developer to discover what pins actually changed, and what the changes are.

Rotary Encoders

As usual, Wikipedia has the best definition of a Rotary Encoder:

rotary encoder, also called a shaft encoder, is an electro-mechanical device that converts the angular position or motion of a shaft or axle to an analog or digital code.

Rotary Encoders come in many shapes, forms and output types. The simpliest rotary coder looks like a potentiometer, but is continually turnable. Other have dual shafts (or two inputs), and can come with switches in built (depresses the rotary encoder closed the circuit). Some are made to be connected to large machinery and turned via engines and what not.

The ‘analog or digital code’ describes how the rotary encoder actually encodes the information we have received via input into the rotary coders (i.e. turning the encoder). The type of output we are interested in for this example are those that output in ‘Quadrature’.

Quadrature is two signal that is 90 degrees out of phase with each other. That means that the direction of the turn can be indicated by which of the signals changed first (and the 2nd confirming the turn). The angular speed of the turn can also be indicated by the duration of the pulse. However, for this project, we are only going to look at which way the encoder is turning.

To learn more about quadrature, i suggest reading my previous post detailing how to make a Quadrature Generator.

Example Code and Schematic

For this example, i’ve used the ATTiny2313 chip. Any AVR will do, but you will need to update the code with the correct ports to make it work with other variants (Even the ATMega’s). The 2313 series is a cheap chip for development, but with only 2K of program memory, it seriously limits what you can do with it (Even the newly released 4313 with 4K of PROGMEM is very limiting).

The example im showing here has the rotary encoder as the input, a 3 leds as outputs. The leds function like this:

  • LED1: Indicates the rotary encoder was turned in a direction.
  • LED2: Indicates the rotary encoder was turned in the opposite direction to LED1.
  • LED3: Indicates that an pin change interrupt has been received by the chip.

Rotary Encoder Schematic

Download: The Eagle schematic here

Below is the code for the example. This code can also be viewed on my SVN Repo. The avr-gcc Makefile is also available in the SVN repo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <stdint.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
 
#define F_CPU 12000000
#include <util/delay.h>
 
#define DEPRESS_TIME    1
 
#define sbi(sfr, bit)   ((sfr) |= _BV(bit))             // Set bit 
#define cbi(sfr, bit)   ((sfr) &= ~(_BV(bit)))          // Clear bit
#define xbi(sfr, bit)   ((sfr) ^= _BV(bit))             // Flip bit
#define rbi(sfr, bit)   (((sfr) >> (bit)) & 0x01)
 
volatile uint8_t pcIntCurr = 0;
volatile uint8_t pcIntLast = 0;
volatile uint8_t pcIntMask = 0;
 
volatile uint8_t timer0_ovf = 0;
volatile uint8_t time_rot = 0;
 
void doInt();
 
int main() {
        cbi(DDRB, PCINT2);
        cbi(DDRB, PCINT3);
 
        TIMSK = (1<<TOIE0);                   // Eable timer overflow for Timer0
        TCNT0 = 0x00;                         // Set Timer0 to 0
        TCCR0B = (1<< CS02) | (1<<CS00);      // /1024 prescaler
 
        PORTB |= (( 1 << PCINT2 ) | ( 1 << PCINT3 )); //turn on pullups
        PCMSK |= (( 1 << PCINT2 ) | ( 1 << PCINT3 )); //enable encoder pins interrupt sources
        sei();
        GIMSK |= ( 1 << PCIE ); //enable pin change interupts
 
        DDRD |= ( 1 << PD4 );
        DDRD |= ( 1 << PD5 );
        DDRD |= ( 1 << PD6 );
 
        sbi(PORTD, PD6);
        _delay_ms(1000);
        cbi(PORTD, PD6);
 
        for (;;) {
 
                if (!time_rot) {
                        cbi(PORTD, PD4);
                        cbi(PORTD, PD5);
                }
 
                if (pcIntMask)
                        doInt();
        }
}
 
void doInt() {
  xbi(PORTD, PD6);
 
  if (rbi(pcIntCurr, PCINT2) == 0 && rbi(pcIntCurr, PCINT3) == 0 && rbi(pcIntMask, PCINT2) ) {
        cbi(PORTD, PD5);
        sbi(PORTD, PD4);
        time_rot = 5;
  } else if (rbi(pcIntCurr, PCINT3) == 0 && rbi(pcIntCurr, PCINT2) == 0 && rbi(pcIntMask, PCINT3) ) {
        cbi(PORTD, PD4);
        sbi(PORTD, PD5);
        time_rot = 5;
  }
 
  pcIntMask = 0;
}
 
ISR(TIMER0_OVF_vect) {
        timer0_ovf++;
 
        if (time_rot) {
                time_rot--;
        }
}
 
 
ISR(PCINT_vect)
{
  pcIntCurr = PINB;
  pcIntMask = pcIntCurr ^ pcIntLast;
  pcIntLast = pcIntCurr;
}

Conclusion

Here are the Bitscope Logic outputs dumps for the rotary being turned in either direction. This is actually using the Quadrature Generator to provide input. This is a great way to test the rotary code, and is also great for testing how fast the MCU can detect changes. The definition of each of the traces are:

  1. WHITE – Rotary Encoder A Input.
  2. BROWN – Rotary Encoder B Input.
  3. RED – Clock signal from the Quadrature Generator.
  4. ORANGE – A DIR2 turn event occurred.
  5. YELLOW – A DIR1 turn event occurred.
  6. PURPLE – A Pin Change Interrupt (PCINT) occurred.

Rotary Encoder direction 1

Rotary Encoder direction 2

 

Gallery of all images in this post:

Tutorials – 4MHz Colpitts Crystal Oscillator

Introduction

Colpitts Oscillator, with AY38910 PSG in background

Clock sources are used in pretty much all digital electronics these days. There are many ways to create clock sources, from a simple 555 timers, to using a micro-controller (PIC, AVR) to output a clock source. I had a specific need for a 2MHz clock source to drive an AY38910 programmable sound generator chip I had ordered off ebay.

After looking through my surplus crystal, the lowest speed I could find was a 4Mhz crystal. Using that as a starting point, I went searching for how to quickly put it to use to get a stable and accurate signal. For this, i came across the Colpitts Oscillator.

Wikipedia describes the Colpitt Oscillator as:

A Colpitts oscillator, invented in 1918 by American engineer Edwin H. Colpitts, is one of a number of designs for LC oscillators, electronic oscillators that use a combination of inductors (L) and capacitors (C) to produce an oscillation at a certain frequency. The distinguishing feature of the Colpitts oscillator is that the feedback for the active device is taken from a voltage divider made of two capacitors in series across the inductor.

The Colpitts Oscillator Circuit

So after reviewing some circuit diagrams, and resistor/capacitor values, i came up with this circuit for generating a stable 4Mhz square wave.

4MHz Colpitts Oscillator

Download: The CADSoft Eagle schematic here

This all seemed to work pretty well. I pestered around with bumping up to 8Mhz, which worked with a bit of degradation on the amplitude of this signal. 12MHz had the output so low it wouldn’t drive TTL inputs. Given i was after a fairly low frequency, i didn’t investigate why i couldn’t get to higher speeds. The Colpitts Oscillator should be able to get up to about 20Mhz.

Its time to measure up the frequency of the output. I was a little annoyed at the latest update of the Bitscope DSO software. usually, the cursor frequency shows in the bar down the bottom, but now its in the left hand side bar… which isn’t included in the ‘save as image’ function.

So here is the signal output on the oscilloscope. You’ll have to take my word for it that the cursor (Vertical lines) indicates a 4MHz something resembling a sine wave.

Colpitts Oscillator outputting a 4MHz signal

Creating a 2MHz Signal, with a CMOS 4017 Decade Counter

At the start of this post, you may remember saying that the AY38910 PSG required 2MHz (Or more correctly, between 1 and 2 MHz). You might also remember be saying that the lowest frequency crystal I had was 4MHz. All true. So the question now is how do I get the 4MHz output from the Colpitts Oscillator down to the 2MHz required by the PSG.

I searched around the net for a solution, and most seemed to revolve around using a J-K type Flip-Flop. Havnt not any of these in stock, I remembered an old trick used a while back: Using a CMOS 4017 decade counter with 2nd clock counter pin connected to the reset pin. Thus when the reset pin is triggered, that becomes your ‘divided by two’ output.

This can be used to divide to get all sorts of lower frequencies, i.e.

  • 4 / 2 = 2.00 MHz
  • 4 / 3 = 1.33 MHz
  • 4 / 4 = 1.00 MHz
  • 4 / 5 = 0.80 MHz
  • and so on…

So with the above in mind, I modified the 4 MHz Colpitts Oscillator to look like this:

Download The CADSoft Eagle schematic here

Using the CMOS chip had the added benefit of restoring the rather weak signal from the T1 transistor to the full 5V level (Im guessing this is due to the BC549 transistor’s base not being loaded to near saturation, if anyone can improve this, let me know!). The below oscilloscope screenie shows the yellow trace as the Colpitts output, and the green trace the output from the 4017. Once again you’ll have to take my word that the yellow is 4 MHz, and the green is 2 MHz.

And here is one more showing 1.33 MHz. I ended up using 1.33 MHz to clock the PSG, as the sound produced was a bit more crisp. It’s also the frequency that GIC use for their example circuits in the PSG Data Manual (The best source of info for the AY38910!)

Conclusion

The Colpitts driver is a nice way to generate a stable and accurate clock signal. Truth be told though, its probably much easier just to use a can resonator. It was a nice break from digital electronics though, i dont often get to use the oscilloscope part of my BitScope.

I’ll leave here with a sneak peak video of the Colpitts Oscillator clocking the AY38910 to play… the Overworld Mario Bros. theme song!!. This project will be published here in the next couple of weeks. Its using an arduino to program the PSG, which i’ll be replacing with a straight AtMega168 (I dont use arduino for finished projects).

And another picture of the Colpitts Oscillator driving the AY38910 PSG

Tutorials – Quadrature Generator

Introduction

I’ve been doing quite a lot of work with rotary encoders lately. Testing the code of written for the AVR chips becomes quite a hassle when you need to turn a rotary encoder and just the right speed and duration to produce a good signal to debug against. I found this schematic somewhere on the web that automatically produces a quadrature signal. I’ve bumped it against a 555 timer with trimpot to make an adjustable timing for it.

For those that don’t know what a Quadrature Encoder is, its simply a device that outputs  two signals that are 90 degrees out of phase with each other.   WikiPedia has some decent information about quadrature, along with how they are used with rotary encoders. Briefly however, the below image shows how quadrature works. As a bonus, this is the actual output from the Quadrature Generator.

Output from the Quadrature Generator, captured on Bitscope Logic

The red trace it the clock input from the 555 timer, and the other two traces are is the quadrature. Notice they are 90 degress out of phase of each other, taking four clock cycles for a full rotation.

Schematic

So i must apologise for this schematic. I had it beautifully drawn on my Galaxy Note 10.1, but the Eagle component libraries have different pin locations then what I had used. So the net connections are all over the place. Hope the idea is there though…

Schematic, Flip-Flop is a 74LS74, click for larger version

Download the Cadsoft Eagle schematic here

The 555 timer simply provides a variable clock source (By adjusting TrimPot R2) to the 74LS74 Dual D-type Flip-Flop.  The 4 way jumper provides an connection for the clock, output 1, output 2 and a ground connection (Making it easy to debug). The 2 way jumper is the +/- supply. The 74 series chips limits the Vcc to +5V, but replacing it with a CMOS 4013 flip flop will allow voltages up to around 15V (With a max speed of about 2Mhz).

Bill of Parts

  • 74LS74 Dual type Flip-Flop
  • NE555 Timer
  • 100k trimpot (I’ve used a horizontal mount type)
  • 10k 1/4W resistor
  • 390nF ceramic cap
  • 0.1uF electro cap
  • 0.01uF ceramic cap
  • 2 way jumper header
  • 4 way jumper header

Testing the output with the bitscope