I decided to sit down and build something last night, and I’m surprised by how functional it is! Nothing about it is extraordinarily complex, and it’s extremely flexible, accommodating almost any crystal you want to drop in. Although I doubt I’ll use this exact design for a permanent transmitter, it was fun to build and I’ll post photos hoping to inspire others to tinker with RF circuitry as well! The final device worked on 7.000MHz and had 3 components: power supply, oscillator/amplifier (making 20mW), and amplifier (making 1.5W). IMG_4916

First, I needed an oscillator. I had an easy source of one because I had a pile of ATTiny25 microcontrollers. Often I run a microcontroller at my transmit frequency with a crystal (applied to XTAL1 and XTAL2 pins) and collect the convenient 5V square wave on the CKOUT pin (after the appropriate fuse setting is applied). However, although the ATTiny25 has both XTAL and CKOUT pins, they overlap! This means that CKOUT cannot be obtained when using a crystal. This complicates things slightly… IMG_4906

I ended-up getting a nice sine wave from the XTAL1 pin, although it was less than 1PPV. I tried having this signal directly switch an N-channel MOSFET as an amplifier, but it didn’t work that well (a transformer might help increase PPV, but that complicates things). I instead used a 74HC240 (8 inverting buffers on one chip) to help boost the signal. However, 1PPV wasn’t enough to get the buffer oscillating. I therefore added a 2 resisters and a capacitor to the first inverting output, such that a persistent low would slowly raise the voltage of a wire, and I attached that wire to the input of the buffer chip. This way, although 1ppv wasn’t enough to start oscillations, a few milliseconds of time allowed the inverting output (high when the input is low) to raise voltage of the input until it was enough to fire the buffers. Once it starts, it starts! I’m trilled, because a voltage divider or a potentiometer would have been a pain, and required specific parts. IMG_4908

The result is about 20mW of power with no tuned circuit! This means it will work on pretty much any crystal you can pop in the micro-controller. This may be suitable for a QRSS transmitter, and since we’re not pushing any of the components very little heat is produced, should it should be thermostable and easy to regulate. Modulation is achieved by a reverse-biased LED varactor diode varying crystal capacitance to ground, discussed elsewhere on my site so I won’t go there again. IMG_4910

Power supply is one I built a while back and had available. 5V for the microcontroller, and 12V for the amplifier. Simple!

Amplifying the signal was pretty easy as well. The 5V signal output of the buffer goes from 0V to 5V, which was enough to trigger an IRF510 N-channel MOSFET with a convenient packaging that I screwed into a huge heatsink. I push the MOSFET a lot, and a lot of heat is produced, but as long as I keep it separate from the oscillator the heat shouldn’t affect frequency too much. Although on my workbench I use exposed wires connecting components, this is prone to getting RFI so obviously use shielded cable of some sort, or use extremely short leads. The MOSFET is arranged as a class C amplifier, with a RFC inductor at the drain.IMG_4911

In retrospect I’m doubting that 5V is enough to fully activate the IRF510. I should probably use some method to bring voltage just below firing threshold, so the 5V can more fully open the gate. I’ll try that later! The output is filtered with a PI lowpass filter. I use two 1nF capacitors and a coil which I wind until the output on the scope looks acceptable. I know there are more exacting ways. Anyhow, I had fun, so I thought I’d post. I’m just tinkering at this point!

IMG_4917

It’s putting out about a watt and a half into 50 ohms. How cool? Adding a code key is trivial, as the 74hc240 has “gate enable” pins for easy on/off control – even from a microcontroller! Food for thought… 73!

UPDATE – I decided to slap a 10.140MHz (QRSS window) crystal in there and see what happened. I saw my signal locally (AJ4VD/W4DFU grabber), but not elsewhere, so I left it up for about a day. Vince Adams, N9VN spotted it in IL (about 1,000 miles away) and made a post on a mailing list asking who it was. Awesome! Note that for QRSS I used a lower-current power supply, so I don’t actually know what power output was, but I’d estimate it to be about 500mW.
n9vn
(It’s the “V-shape” at the bottom)





Additional Resources

I did this purely for the fun of it, and am aware there are many ways to accomplish the same thing. I was playing Counter Strike Source (you should buy it and play with me, name “swharden”) and my fingers are really cold from the winter weather, and wondered if I could have a button help with the rapid firing of pistols. I mentioned it on the microphone, and one of the players (“{Ẋpli¢it} shadow”) said I should go for it. Because it was a fun little project, I documented it so I could share it. Check out the cool photos and video!

There’s a summary of the project in video form. Some details of the project are below…rapidfire_mouse_mod (1)

Here you can see the original circuit board in the mouse. The microchip on the bottom right of the image seems to do the data processing, so I investigated it a bit and found the pin that the left-click button goes to.rapidfire_mouse_mod (2)

Here’s the underside. It helped me identify good locations to grab +5V and GND solder points.rapidfire_mouse_mod (3)

This is the microcontroller I decided to use for the project. It’s an ATTiny25, $1.33 USD (10+ quantity from Mouser), and has a built in 8MHz oscillator (which can run at 1MHz thanks to the DIV/8 clock prescaler.rapidfire_mouse_mod (4)

I slap the chip in the homebrew development board (a glorified AVR-ISP mkII) and it’s ready for programming. Code and schematics are at the bottom.rapidfire_mouse_mod (5)

After programming, I glued the microchip upside-down in the mouse case and soldered wires directly to the pins. I used small (about 28AWG) magnet wire because it’s a lot easier than stripping wires. Just heat the tip with a soldering iron, the coating melts away, and you can stick it wherever you need to with a dab of solder. Not too many people use this method, but I recommend you try it at least once! It can be very useful at times, and is about as cheap as you can get. (eBay has good prices)rapidfire_mouse_mod (6)

BIG PROBLEM! It didn’t work *AT ALL*. Why? Didn’t know… I checked the o-scope and saw everything seemed to be working fine. It turns out that 50 clicks per second was too fast to register, and when I reduced the speed to 25 clicks per second it worked fine. Unfortunately I had to add extra wires to allow myself to program the chip while it was in the mouse – a major pain that complicated the project more than I wished!

rapidfire_mouse_mod (7)

Here’s a good view of the transistor. Simply put, when the microcontroller sends power to the “base” pin of the 2n2222 transistor, the “collector” is drained through the “emitter”, and the transistor acts like a switch. It’s shorting the pin, just like would happen if you physically pressed the left click mouse button. When the mouse microchip is positive (+5V), it’s “no click”, but when it goes to ground (shorted by the click button), a click is detected. I biased the “base” pin toward ground by connecting it to GND through a high value resistor. This makes sure it doesn’t accidentally fire when it’s not supposed to.

rapidfire_mouse_mod (8)

Here you can clearly see the programmer pins I added. This lets me quickly access the chip and reprogram it if I decide to add/modify functionality.

rapidfire_mouse_mod (9)

When it’s all said and done, it’s surprisingly slick and functional. I’m using it right now to write my blog, and the button isn’t really in the way. I think it’s one of those el-cheapo buttons you get in a pack of 10 from RadioShack, but I would highly recommend eBay as RadioShack is ridiculously overpriced on components.

rapidfire_mouse_mod (10)

There’s the schematic. Grabbing 5v and GND from a usb mouse is trivial. Heck, most of the circuity/code is trivial! Now that I think about it, this represents are really great starter project for anyone interested in microcontrollers.

ATtiny25-45-85V

Use this diagram of the pin functions for reference.

Remember there’s more than one way to skin a cat! For example, if you don’t want to program a microcontroller, a 555 timer is a simple method and there are tutorials out there demonstrating how to do this. I chose a microcontroller because I can precisely control the rate of firing and the duration. If you decide to do something similar, send me photos and I’d be happy to share them on the site! I love doing tangible projects, however silly they are.

And finally, the code!

#define F_CPU 1000000UL	// frequency (20MHz)
#include <avr/io.h>
#include <util/delay.h>



void on(){
	PORTB |= 1 << PB3; //led
	PORTB |= 1 << PB2; //heater
	}
void off(){
	PORTB &= ~( 1 << PB3 );//led
	PORTB &= ~( 1 << PB2 );//heater
	}


void main() {
	DDRB |= (1<<PB3)|(1<<PB2);
	int ticks;

	for (;;) { //FOREVER
		while ((PINB & _BV(PB4))==0) {} // NOT PRESSED, DO NOTHING
		for(ticks=0;ticks<125;ticks++) // CLICK FOR 5 seconds
			{
			on();_delay_ms(20);off();_delay_ms(20);
			} // CLICK TAKES 1/50'th second
	}
}




Additional Resources

Now that I’ve finished my 6-channel data logger (previous post), it’s time to put it to the test! I’m using a handful of LM335 temperature sensors to measure temperature, and a 20 Ohm resistor to act as a heater. When 1A of current passes through it, it gets quite toasty! First, I’ll make some temperature probes…IMG_4581IMG_4588

UPDATE: Those photos show a partially completed sensor. Obviously the third wire is required between the resistor and the LM335 to allow for measurement! Here’s a more completed sensor before the shrink tube was massaged over the electrical elements:IMG_4591

Then I mounted the sensors on a block of steel with the heater on one side. This way I can use one temperature to measure the heater temperature, and the other to measure the temperature of the metal chassis. I then put the whole thing in a small Styrofoam box. IMG_4606IMG_4615

When I fire the heater, that sucker gets pretty darn hot. In 40 minutes it got almost 250F (!) at which time I pulled the plug on the heater and watched the whole thing cool. Notice how the metal chassis lags behind the temperature of the heater. I guess it’s a bit of a “thermal low-pass filter”. Also, yes, I’m aware I spelled chassis incorrectly in the graphs.howhotquicktest

But how do we use this to build a thermo-stable crystal oven for a MEPT (radio transmitter)? I tried a lot of code, simply “if it’s too cold, turn heater on / if it’s too hot, turn heater off” but because the chassis always swung behind the heater, and even the heater itself had a bit of a delay in heating up, the results were always slowly oscillating temperatures around 10F every 20 min. That’s worse than no heater! My best luck was a program to hold temperature stable at 100F with the following rules:
1.) If heater > 155F, turn heater off (prevent fire)
2.) If chassis < 100F, turn heater on
3.) if (heater-target) > (target-chassis), turn heater offheaterworks

What a great job! That thing is practically stable in 20 minutes. The advantage of this over an analog method is that I can set the temperature in software (or provide an interface to change temperature) and my readings are analytical, such that they can be conveyed in a radio message. Again, my best results came when I implemented rule 3 in the code above. More experiments to come!





Additional Resources

While working to perfect my temperature-controlled manned experimental propagation transmitter (MEPT), I developed the need to accurately measure temperature inside my Styrofoam enclosure (to assess drift) and compare it to external temperature (to assess insulation effects). I accomplished this utilizing the 8 ADC channels of the ATMega48 and used its in-chip USART capabilities to send this data to a PC for logging. I chose the ATMega48 over the ATTiny2313 (which has USART but no ADCs) and the ATTiny44a (which has ADCs but no USART). From when I see, no ATTiny series ATMEL AVR has both! Lucky for me, the ATMega48 is cheap at $2.84 USD. Here’s my basic circuit idea: IMG_4559

EDIT: the SCHEMATIC1 : PAGE1voltage reference diagram is wrong at the bottom involving the zener diode. Reference the picture to the right for the CORRECT way to use such a diode as a voltage reference. (stupid me!)

MULTIPLE SENSORS – Although in this demonstration post I only show a single sensor, it’s possible to easily have 8 sensors in use simultaneously since the ATMega48 has 8 ADC pins, and even more (infinitely) if you want to design a clever way to switch between them.

LM335 Temperature Sensor – selected because it’s pretty cheap (< $1) and quantitative. In other words, every 10mV drop in voltage corresponds to a change of 1ºC. If I wanted to be even cheaper, I would use thermistors (<$0.10) which are more qualitative, but can be calibrated I guess. Notes on power stability - The output of the sensor is measured with the ADC (analog to digital converter) of the microcontroller. The ADC has a 10-bit resolution, so readings are from 0 to 2^10 (1024). AREF and AVCC can be selected as a voltage reference to set what the maximum value (1024) should be. If the ADC value is 1V (for example) and AREF is 1V, the reading will be 1024. If AREF becomes 5V, the reading will be 1024/5. Make sense? If AREF is fluctuating like crazy, the same ADC voltage will be read as differing vales which is not what we want, therefore care should be taken to ensure AREF is ripple-free and constant. Although I did it by adding a few capacitors to the lines of the power supply (not very precise), a better way would be to use a zener diode (perhaps 4.1V?) as a voltage reference.IMG_4575

Here is my circuit. I’m clocking the chip at 9.21MHz which works well for 19200 baud for serial communication. Refer to my other MAX232 posts for a more detailed explanation of how I chose this value. The temperature sensor (blurry) is toward the camera, and the max232 is near the back. Is that an eyelash on the right? Gross!logger

The data is read by a Python script which watches the serial port for data and averages 10 ADC values together to produce a value with one more significant digit. This was my way of overcoming continuously-fluctuating values.
IMG_4564

Here you can see me testing the device by placing an ice cube on the temperature sensor. I had to be careful to try to avoid getting water in the electrical connections. I noticed that when I pressed the ice against the sensor firmly, it cooled at a rate different than if I simply left the ice near it.

NOTICE THE PROGRAMMER in the background (slightly blurry). The orange wires connect the AVR programmer to my circuit, and after the final code is completed and loaded onto the microcontroller these orange wires will be cut away.lm335 microcontroller graph annotated

Here is some actual data from the device. The LM335 readout is in Kelvin, such that 3.00V implies 300K = 80ºF = 27ºC (room temperature). The data is smooth until I touch it with the soldering iron (spike), then it gets cool again and I touch it with a cold piece of metal (wimpy dip), then later I put an ice cube on it (bigger dip). Pretty good huh? Remember, 0.01V change = 1ºC change. The bottom of the dip is about 2.8V = 280K = 44ºF = 7ºC. If I left the cube on longer, I imagine it would reach 0ºC (273K, or 2.73V).

For everyone’s reference, here’s the pinout diagram of the ATMega48:atmega48pinout

Finally, the code to record live data:

import socket
import sys
import serial

ser = serial.Serial('COM1', 19200, timeout=1)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

chunk=""
i=0
data = ser.readline()
while True:
    i+=1
    data = ser.readline()
    data=data.replace("n","")
    data=data.replace("r","")
    data="["+data[:-1]+"]"
    data=eval(data)
    val=sum(data)/float(len(data))
    print i,data,val
    chunk=chunk+"%.01f,"%val
    if i==100:
        print "nSAVING"
        i=0
        f=open("data.txt","a")
        f.write(chunk)
        f.close()
        chunk=""

and the code to PLOT the data file:

import matplotlib.pyplot as plt
import numpy

def smoothTriangle(data,degree,dropVals=False):
        """performs moving triangle smoothing with a variable degree."""
        """note that if dropVals is False, output length will be identical
        to input length, but with copies of data at the flanking regions"""
        triangle=numpy.array(range(degree)+[degree]+range(degree)[::-1])+1
        smoothed=[]
        for i in range(degree,len(data)-degree*2):
                point=data[i:i+len(triangle)]*triangle
                smoothed.append(sum(point)/sum(triangle))
        if dropVals: return smoothed
        smoothed=[smoothed[0]]*(degree+degree/2)+smoothed
        while len(smoothed)<len(data):smoothed.append(smoothed[-1])
        return smooth


print "loading..."
f=open("data.txt")
raw="["+f.read()+"]"
f.close()
data=eval(raw)

print "converting..."
data=numpy.array(data)
data=data/1024.0*5 #10-bit resolution, 5V max

print "graphing"
plt.plot(data)

plt.grid(alpha=.5)
plt.title("ATMega48 LM335 Temperature Sensor")
plt.ylabel("Voltage (V)")
plt.xlabel("Time (5/sec)")
plt.show()

Also, the AVR-GCC code loaded on the ATMega48:





#define F_CPU 9210000UL

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

void init_usart(unsigned long);

unsigned int readADC(char times){
	unsigned long avg=0;
	for (char i=0; i<times; i++){
        ADCSRA |= (1<<ADSC); // reset value
        while (ADCSRA & ( 1<<ADSC)) {}; // wait for measurement
		avg=avg+ADC;
	}
	avg=avg/times;
	return avg;
}

int main (void){

    ADMUX = 0b0100101; // AVCC ref on ADC5
    ADCSRA = 0b10000111; //ADC Enable, Manual Trigger, Prescaler 128
	ADCSRB = 0;

	DDRD=255;

	init_usart(19200);
	for(;;){
		for(char j=0;j<10;j++){
			sendNum(readADC(10)>>6); // shift to offset 10bit 16bit
			send(44); // COMMA
			PORTD=255;_delay_ms(10);
			PORTD=0;_delay_ms(10);
			}
		send(10);send(13); // LINE BREAK
		}
	}


void sendNum(unsigned int num){
		char theIntAsString[7];
		int i;
		sprintf( theIntAsString, "%u", num );
		for (i=0; i < strlen(theIntAsString); i++)
		{send(theIntAsString[i]);}
}

void send (unsigned char c){
		while((UCSR0A & (1<<UDRE0)) == 0) {}
		UDR0 = c;
}

void init_usart (unsigned long baud)
{
	/////////////////////////
	//		Baud Generation
	unsigned int UBRR_2x_off;
	unsigned int UBRR_2x_on;
	unsigned long closest_match_2x_off;
	unsigned long closest_match_2x_on;
	unsigned char off_2x_error;
	unsigned char on_2x_error;

	UBRR_2x_off = F_CPU/(16*baud) - 1;
	UBRR_2x_on = F_CPU/(8*baud) - 1;

	closest_match_2x_off = F_CPU/(16*(UBRR_2x_off + 1));
	closest_match_2x_on = F_CPU/(8*(UBRR_2x_on + 1));

	off_2x_error = 255*(closest_match_2x_off/baud - 1);
	if (off_2x_error <0) {off_2x_error *= (-1);}
	on_2x_error = 255*(closest_match_2x_on/baud -1);
	if (on_2x_error <0) {on_2x_error *= (-1);}

	if(baud > F_CPU / 16)
	{
		UBRR0L = 0xff & UBRR_2x_on;
		UBRR0H = 0xff & (UBRR_2x_on>>8);
		UCSR0A |= (1<<U2X0);
	} else {

		if (off_2x_error > on_2x_error)
		{
			UBRR0L = 0xff & UBRR_2x_on;
			UBRR0H = 0xff & (UBRR_2x_on>>8);
			UCSR0A |= (1<<U2X0);
		} else {
			UBRR0L = 0xff & UBRR_2x_off;
			UBRR0H = 0xff & (UBRR_2x_off>>8);
			UCSR0A &= ~(1<<U2X0);
		}
	}
	/////////////////////////
	//	Configuration Registers
	UCSR0B = (0<<RXCIE0) |//We don't want this interrupt
	(0<<TXCIE0) |//We don't want this interrupt
	(0<<UDRIE0) |//We don't want this interrupt
	(1<<RXEN0) |//Enable RX, we wont use it here but it can't hurt
	(1<<TXEN0) |//Enable TX, for Talkin'
	(0<<UCSZ02);//We want 8 data bits so set this low

	UCSR0A |= (0<<U2X0) |//already set up, so don't mess with it
	(0<<MPCM0) ;//We wont need this

	UCSR0C = (0<<UMSEL01) | (0<<UMSEL00) |//We want UART mode
	(0<<UPM01) | (0<<UPM00) |//We want no parity bit
	(0<<USBS0) |//We want only one stop bit
	(1<<UCSZ01) | (1<<UCSZ00) |//We want 8 data bits
	(0<<UCPOL0) ;//This doesn't effect UART mode
}

UPDATE: A day later I added multiple sensors to the device. I calibrated one of them by putting it in a plastic bag and letting it set in ice water, then I calibrated the rest to that one. You can see as my room temperature slowly falls for the night, the open air sensor (red) drops faster than the insulated one in a Styrofoam box. Also, I did a touch of math to convert voltage to kelvin to Fahrenheit. You can also see spikes where it quickly approached 90+ degrees from the heat of my fingers as I handled the sensor. Cool!3traces

UPDATE: a day and a half later, here’s what the fluctuations look like. Notice the cooling of night, the heating of day, and now (near the end of the graph) the scattered rain causes more rapid fluctuations. Also, although one sensor is in an insulated styrofoam box, it still fluctuates considerably. This measurement system is prepped and ready to go for crystal oven tests!insulated3





Additional Resources

I’ve been pretty busy lately, but I drip to the hardware store with the XYL produced a PVC enclosure that looked perfect for my ongoing MEPT (manned experimental propagation transmitter) projects. I didn’t want to buy it (it was a little pricey by my standards, at $6 USD, which is about the total cost of the transmitter!) but the wife convinced me and I’m glad she did! I intended it to replace the styrofoam enclosure I had been using, but I wasn’t thinking clearly and drilled holes in the box and mounted screws through them. While electrically this is a wonderful way to add antenna connections, thermally it was a bad idea. The main point of the enclosure was to be temperature stable! Oh well. I put the whole thing in the Styrofoam and as a test, I’m leaving it outside tonight. I can’t wait to see how it goes! Here are some photos of the project.IMG_4526IMG_4534IMG_4547IMG_4548

Update: Even when being housed outdoors when temperature fluctuations vary greatly between day and night, this MEPT is surprisingly stable! When I open the box, it’s very warm inside, so I am thinking that the voltage regulators and the MOSTFETs of the PA are heating the device nicely. Here’s a capture spanning about 2 hours. The vertical height of each “V” is about 10Hz, so I estimate that for this span of time, drift is <1Hz. However, I do believe that long term (day to day) frequency stability is still not optimal, but only time will tell.
qrss_stable

Signal report: briefly, this is my signal in Alaska courtesy of KL7UK. My signal is the V-shaped one near the bottom: KL7UK_alaska