Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

So I’m working on building a crystal oven to keep my QRSS MEPT (radio transmitter) at an extremely stable frequency. Even inside a thick Styrofoam box, slight changes in my apartment temperature caused by the AC turning on and off is enough to change the crystal temperature of the transmitter, slightly modifying its oscillation frequency. For a device that vibrates exactly 10,140,070 times a second, even 3 to many or too few vibrations per second is too much. Keeping in the spirit of hacking things together with a minimum of parts, this is what I came up with!

It uses a thermistor, potentiometer, and comparator of a microcontroller (ATTiny44a) to tightly sense and regulate temperature. The heater element is a junk MOSFET I found in an old battery backup system. I simply have pass a ton of current (turned on/off by the gate) to generate heat, transferred into a piece of steel for smooth regulation. One of the unexpected advantages is that the light flickers rapidly near equilibrium, which is great because it has the ability to turn the heater on a little or a lot based upon the averaging effect of the flicker. Here is the code I wrote on the microcontroller to handle the comparator. It couldn’t be simpler!

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

int main(void) {
	DDRA=0; // all inputs
	DDRB=255; // all outputs

	while (1){
		if (ACSR & _BV(ACO)) {
			/* AIN0 is more positive than AIN1 right now */
			PORTB|=(1<<PB0);
			PORTB&=~(1<<PB1);

		} else {
	  		/* AIN0 is more negative than AIN1 */
			PORTB|=(1<<PB1);
			PORTB&=~(1<<PB0);
		}

	}
}




Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

My expression is completely flat right now. I simply cannot believe I’m about to say what I’m preparing to say. I spent nearly a year cracking large prime numbers. In short, I took-on a project I called The Flowering N’th Prime Project, where I used my SheevaPlug to generate a list of every [every millionth] prime number. The current “golden standard” is this page where one can look-up the N’th prime up to 1 trillion. My goal was to reach over 1 trillion, which I did just this morning! I was planning on being the only source on the web to allow lookups of prime numbers greater than 1 trillion.

flowering_primes

However, when I went to look at the logs, I realized that the software had a small, fatal bug in it. Apparently every time the program restarted (which happened a few times over the months), although it resumed at its most recent prime number, it erased the previous entries. As a result, I have no logs below N=95 billion. In other words, although I reached my target this morning, it’s completely irrelevant since I don’t have all the previous data to prove it. I’m completely beside myself, and have no idea what I’m going to do. I can start from the beginning again, but that would take another YEAR. [sigh]

So here’s the screw-up. Apparently I coded everything correctly on paper, but due to my lack of experience I overlooked the potential for multiple appends to occur simultaneously. I can only assume that’s what screwed it up, but I cannot be confident. Honestly, I still don’t know specifically what the problem is. All in all, it looks good to me. Here is the relevant Python code.

def add2log(c,v):
 f=open(logfile,'a')
 f.write("%d,%dn"%(c,v))
 f.close()

def resumeFromLog():
 f=open('log.txt')
 raw=f.readlines()[-1]
 f.close()
 return eval("["+raw+"]")

For what it’s worth, this is what remains of the log file:

953238,28546251136703
953239,28546282140203
953240,28546313129849
...
1000772,30020181524029
1000773,30020212566353
1000774,30020243594723




Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

One of my microcontroller projects requires me to measure values and transmit then in Morse code. There may be code out there to do this already, but I couldn’t find it. I’m sure there are more elegant and efficient ways to handle the conversion, but this works for me. Hopefully someone will find it useful!

binary_to_Morse
#include <stdio.h>

//Morse code numbers from 0 to 9
char * array [10] = {"-----",".----","..---","...--","....-",
	 ".....","-....","--...","---..","----."};

void beep(char v){
	// beep (or print) Morse code as necessary
	printf("%s ",array[v]);
}

void send(int l){
	// convert a number into Morse code
	char d=0;int t=0;int val=0;
	for (t=100000;t>0;t=t/10){ //number of digits here
		if (l>t){d=l/t;beep(d);l-=d*t;}else{beep(0);}
	}
	printf("n");
}

void main(){
	// program starts here
	int l=0b1111111111; //sample number (maximum 10-bit)
	printf("%d ",l);send(l);
	l=0b11010001100101100011; //larger sample number
	printf("%d ",l);send(l);
}




Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

SUMMARY: A small group of high school students taking an AP class for college credit launched a high-altitude weather balloon with a small payload. In addition to a video transmitter and GPS transmitter, they decided to include a simple transmitter built from scratch. This is the story of the project, with emphasis on the simple transmitter’s design, construction, implementation, and reception (which surprised me, being detected ~200 miles away and lasting the entire duration of the flight!) [sample.ogg]

6/16/2010 – TRACKING

I’m impressed how well the transmitter/receiver worked! For only a few milliwatts, I was able to track that thing all the way from takeoff to landing in Gainesville, FL a few hundred miles away.

ANALYSIS: the text on the image describes most if it, but one of the most interesting features is the “multipathing” during the final moments of the descent, where the single carrier signal splits into two. I believe this is due to two Doppler shifts: (1) as the distance between the falling transmitter and the receiver is decreasing, producing a slight in increase in frequency, and (2) a signal reflected off of a layer of the atmosphere above the craft (the ionosphere?) before it gets to the receiver, the distance of which is increasing as the craft falls, producing a decrease in frequency. I’ll bet I can mathematically work backwards and determine how high the craft was, how fast it was falling, and/or how high the layer of the reflecting material is – but that’s more work than this dental student is prepared to do before his morning coffee!

HERE IS SOME AUDIO of some of the strongest signals I received. Pretty good for a few milliwatts a hundred miles away! [beeps.ogg]

6/16/2010 – THE FLIGHT


The design team
Walking the balloon to its launch destination at NASA with an awesome rocket (Saturn 1B – identified by Lee, KU4OS) in the background.
The team again, getting ready for launch. I’ve been informed that the reason their hands are up is to prevent the balloon from tilting over too much. I’d imagine that a brush with a grass blade could be bad news for the project!


Last minute checks – you can see the transmitter and battery holders for it taped to the Styrofoam.
The transmitter in its final position

Note the coil of yellow wire. That serves as a rudimentary “ground” for the antenna’s signal to push off of. I wasn’t very clear on my instructions on how to make it. I meant that it should be a huge coil wrapped around the entire payload (as large as it can be), which would have probably produced a better signal, but since I was able to capture the signal during the whole flight it turned out to be a non-issue.

The antenna can be seen dropping down as a yellow wire beneath the payload. (arrow)
Launch! Look how fast that balloon is rising!
It’s out of our hands now. When I got the text message that it launched, I held my breath. I was skeptical that the transmitter would even work!
One of the students listening to my transmitter with QRSS VD software (score!)
Video capture from an on-board camera was also attempted (900MHz), but from what I hear it didn’t function well for very long.

6/15/2010 – IMPROVED BUILD

Here you can see me (center arrow) showing the students how to receive the Morse code signal sent from the small transmitter (left arrow) using a laptop running QRSS VD (my software) analyzing audio from and an Icom706 mkII radio receiver attached to a dipole (right arrow).

I amped-up the output of the oscillator using an octal buffer chip (74HC240) with some decent results. I’m pleased! It’s not perfect (it’s noisy as heck) but it should be functional for a 2 hour flight.

Closeup of the transmitter showing the oscillator at 29.4912 MHz, the Atmel ATTiny44a AVR microcontroller (left chip), octal buffer 74HC240 (right chip), and some status lights which blink as the code is executed.

This is my desk where I work from home. Note the styrofoam box in the background – that’s where my low-power transmitter lives (the one that’s spotted around the world). All I needed to build this device was a soldering iron.

Although I had a radio, it is not capable of receiving 29MHz so I was unable to test the transmitter from home. I had to take it to the university to assess its transmitting capabilities.

I connected the leads to the output of the transmitter, shorted by a 39ohm resistor. By measuring the peak-to-peak voltage of the signal going into a resistor, we can measure its power.

Here’s the test setup. The transmitter is on the blue pad on the right, and the waveform can be seen on the oscilloscope on the upper left.

With the amplifier off, the output power is just that of the oscillator. Although the wave should look like a sine wave, it’s noisy, and simply does not. While this is unacceptable if our goal is a clean radio signal with maximum efficiency, this is good enough to be heard at our target frequency. The PPV (peak-to-peak voltage) as seen on the screen is about 100mV. Since I’m using a x10 probe, this value should be multiplied by 10 = 1V. 1V PPV into 39 ohms is about 3 milliwatts! ((1/(2*2^.5))^2/39*1000=3.2). For the math, see this post

With the amplifier, the output is much more powerful. At 600mV peak-to-peak with a 10x probe (actually 6V peak-to-peak, expected because that’s the voltage of the 4xAAA battery supply we’re using) into 39 ohms we get 115 millivolts! (6/(2*2^.5))^2/39*1000=115.38.

Notes about power: First of all, the actual power output isn’t 115mW. The reason is that the math equations I used work only for pure sine waves. Since our transmitter has multiple waves in it, less than that power is going to produce our primary signal. It’s possible that only 50mW are going to our 29MHz signal, so the power output assessment is somewhat qualitative. Something significant however is the difference between the measured power with and without the amplifier. The 6x increase in peak-to-peak voltage results in a 36x (6^2) increase in power, which is very beneficial. I’m glad I added this amplifier! A 36 times increase in power will certainly help.

6/14/2010 – THE BUILD

Last week I spoke with a student in the UF aerospace engineering department who told me he was working with a group of high school students to add a payload to a high-altitude balloon being launched at (and tracked by) NASA. We tossed around a few ideas about what to put on it, and we decided it was worth a try to add a transmitter. I’ll slowly add to this post as the project unfolds, but with only 2 days to prepare (wow!) I picked a simplistic design which should be extremely easy to understand by everyone. Here’s the schematic:

The code is as simple as it gets. It sends some Morse code (“go gators”), then a long tone (about 15 seconds) which I hope can be measured QRSS style. I commented virtually every line so it should be easy to understand how the program works.

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

char call[]={2,2,1,0,2,2,2,0,0,2,2,1,0,1,2,0,2,0,2,2,2,0,1,2,1,0,1,1,1,0,0};
// 0 for space, 1 for dit, 2 for dah


void sleep(){
  _delay_ms(100); // sleep for a while
  PORTA^=(1<<PA1); // "flip" the state of the TICK light
}

void ON(){
 PORTB=255; // turn on transmitter
 PORTA|=(1<<PA3); // turn on the ON light
 PORTA&=~(1<<PA2); // turn off the ON light
}

void OFF(){
 PORTB=0; // turn off transmitter
 PORTA|=(1<<PA2); // turn on the OFF light
 PORTA&=~(1<<PA3); // turn off the OFF light
}

void ID(){
        for (char i=0;i<sizeof(call);i++){
                if (call[i]==0){OFF();} // space
                if (call[i]==1){ON();} // dot
                if (call[i]==2){ON();sleep();sleep();} // dash
    sleep();OFF();sleep();sleep(); // between letters
        }
}

void tone(){
 ON(); // turn on the transmitter
 for (char i=0;i<200;i++){ // do this a lot of times
  sleep();
 }
 OFF();sleep();sleep();sleep(); // a little pause
}

int main(void) // PROGRAM STARTS HERE
{
    DDRB = 255; // set all of port B to output
 DDRA = 255; // set all of port A to output
 PORTA = 1; // turn on POWER light

 while (1){ // loop forever
  ID(); // send morse code ID
  tone(); // send a long beep
 }
}

I’m now wondering if I should further amplify this signal’s output power. Perhaps a 74HC240 can handle 9V? … or maybe it would be better to use 4 AAA batteries in series to give me about 6V. [ponders] this is the schematic I’m thinking of building.

UPDATE

This story was featured on Hack-A-Day! Way to go everyone!





Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

This page documents the progress of my MEPT (manned experimental propagation transmitter) endeavors. If you have questions, feel free to E-mail me! My contact information can be found by clicking the link on the right navigation menu.

The Soup-Can Transmitter

The Signal

The Spots

Florida – 288.3 miles away (W4HBK) May 22, 2010

Massachusetts – 1,075.5 miles away (W1BW) May 27, 2010

Belgium – 4,496.3 miles away (ON5EX) May 27, 2010

Germany- 4,869.2 miles away (DL4MGM) May 28, 2010

Essex – 4,356.4 miles away (G6AVK) May 28, 2010

New Zealand – 8,077.6 miles away (ZL2IK) May 29, 2010





Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

I re-wrote the code from the previous entry to do several things. Once of which was to make a gator rather than a fish. It’s more appropriate since I’m planning on housing the transmitter at the University of Florida. To do it, I drew a gator in paint and wrote a python script to convert the image into a series of points. I’ll post it later. One thing to note was that size was a SERIOUS issue. I only have two thousand bytes of code, and every point of that gator was a byte, so it was a memory hog. I helped it dramatically by using repeating segments wherever possible, and some creative math to help out the best I could (i.e., the spines on the back) Here’s what it looks like, and the code below it…

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

// front top LED - PA0
// inside top LED - PA1
// inside bot LED - PA2
// front bot LED - PA3

unsigned long int t_unit; // units of time
const int tDit = 100; //units for a dit
const int tDah = 255; //units for a dah
char fsk; // degree of frequency shift to use for CW
char fsk2; // degree of frequency shift to use for HELL

char light = 0; // which lights are on/off


void delay(){
        _delay_loop_2(t_unit);
        }

void blink(){
	return;
	if (light==0){
    	PORTA|=(1<<PA0); //on
    	PORTA|=(1<<PA1); //on
		PORTA&=~(1<<PA2); //off
		PORTA&=~(1<<PA3); //off
		light=1;
	} else {
    	PORTA|=(1<<PA2); //on
    	PORTA|=(1<<PA3); //on
		PORTA&=~(1<<PA0); //off
		PORTA&=~(1<<PA1); //off
		light=0;

	}
}

void tick(unsigned long ticks){
        while (ticks>0){
                delay();
                delay();
                ticks--;
        }
}

void pwm_init() {
    //Output on PA6, OC1A pin (ATTiny44a)
    OCR1A = 0x00; //enter the pulse width. We will use 0x00 for now, which is 0 power.
    TCCR1A = 0x81; //8-bit, non inverted PWM
    TCCR1B = 1; //start PWM
}

void set(int freq, int dly){
        OCR1A = freq;
        tick(dly);
}

void fish(){
	char mult = 3;

	char f2[]={2, 3, 4, 5, 6, 7, 4, 3, 7, 4, 7, 7, 6, 5, 4, 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 3, 4, 5, 6, 7, 8, 4, 9, 5, 9, 6, 9, 6, 9, 6, 9, 8, 8, 7, 7, 6, 5, 4, 3, 3, 3, 4, 5, 5};

	for (int i=0;i<sizeof(f2);i++) {
		OCR1A = f2[i]*mult;
		blink();
		tick(20);
		OCR1A = 1*mult;
		blink();
		tick(20);
		}

	char f3[]={1,2,3,4,3,2};

	char offset=0;
	while (offset<9){
		for (char j=0;j<3;j++){
			for (char i=0;i<sizeof(f3);i++){
				char val = (f3[i]+5-offset)*mult;
				if (val<mult || val > 10*mult){val=mult;}
				OCR1A = val;
				blink();
				tick(20);
				OCR1A = 1*mult;
				blink();
				tick(20);
				}
			}
		offset++;
	}


}

void id(){
        char f[]={0,0,1,2,0,1,2,2,2,0,1,1,1,1,2,0,1,1,1,2,0,2,1,1,0,0};
        char i=0;
        while (i<sizeof(f)) {
                blink();
                if (f[i]==0){OCR1A = 0;tick(tDah);}
                if (f[i]==1){OCR1A = fsk;tick(tDit);}
                if (f[i]==2){OCR1A = fsk;tick(tDah);}
                blink();
                OCR1A=0;
				tick(tDit);
                i++;
                }
}

void slope(){
        char i=0;
        while (i<25){
                OCR1A = 255-i;
                i++;
        }
        while (i>0){
                i--;
                OCR1A = 255-i;
        }
}


int main(void)
{
        DDRA = 255;
		blink();
        pwm_init();
        t_unit=1000;fsk=10;id(); // set to fast and ID once
        //fsk=50;//t_unit = 65536; // set to slow for QRSS
		t_unit=60000;

        while(1){;
                fish();
                id();
        }

        return 1;
}




Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

Finally! After a few years tumbling around in my head, a few months of reading-up on the subject, a few weeks of coding, a few days of bread-boarding, a few hours of building, a few minutes of soldering, and a few seconds of testing I’ve finally done it – I’ve created my first QRSS transmitter! I’ll describe it in more detail once I finalize the design, but for now an awesome working model. It’s all digital, consisting of 2 ICs (an ATTiny44a for the PWM-controlled frequency modulation, and an octal buffer for the pre-amplifier) followed by a simple pi low-pass filter.

My desk is a little messy. I’m hard at work! Actually, I’m thinking of building another desk. I love the glass because I don’t have to worry (as much) about fires. That sounds scary, I know.

This is the transmitter. The box is mostly empty space, but it consists of the circuit, an antenna connection, a variable capacitor for center frequency tuning, and a potentiometer for setting the degree of frequency shift modulation.

Yeah, that’s a fishy. Specifically a goldfish (the cracker). It’s made with a single tone, shifting rapidly (0.5 sec) between tones. So cool. Anyway, I’m outta here for now – getting back to the code! I think I’ll try to make a gator next…

Here’s the code that makes the fish. It sends my ID quickly, some fish, then my ID in QRSS speed using PWM.

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

const int tDit = 270/3;
const int tDah = 270;

char fsk;
unsigned long int t_unit;

void delay(){
	_delay_loop_2(t_unit);
	}

void blink(){
  	PORTA^=(1<<0);
  	PORTA^=(1<<1);
  	PORTA^=(1<<2);
  	PORTA^=(1<<3);
}

void tick(unsigned long ticks){
	while (ticks>0){
		delay();
		delay();
		ticks--;
	}
}


void pwm_init() {
    //Output on PA6, OC1A pin (ATTiny44a)
    OCR1A = 0x00; //enter the pulse width. We will use 0x00 for now, which is 0 power.
    TCCR1A = 0x81; //8-bit, non inverted PWM
    TCCR1B = 1; //start PWM
}

void set(int freq, int dly){
	OCR1A = freq;
	tick(dly);
}

void fish(){
	char f[]={0,0,0,4,5,3,6,2,7,1,5,6,8,1,8,1,8,1,8,1,8,2,7,3,6,2,7,1,8,1,8,4,5,2,3,6,7,0,0,0};
	char i=0;
	while (i<sizeof(f)) {
		i++;
		OCR1A = 255-f[i]*15;
		blink();
		tick(20);
		}
}

void id(){
	char f[]={0,0,1,2,0,1,2,2,2,0,1,1,1,1,2,0,1,1,1,2,0,2,1,1,0,0};
	char i=0;
	while (i<sizeof(f)) {
		blink();
		if (f[i]==0){OCR1A = 255;tick(tDah);}
		if (f[i]==1){OCR1A = 255-fsk;tick(tDit);}
		if (f[i]==2){OCR1A = 255-fsk;tick(tDah);}
		blink();
		OCR1A = 255;tick(tDit);
		i++;
		}
}

void slope(){
	char i=0;
	while (i<25){
		OCR1A = 255-i;
		i++;
	}
	while (i>0){
		i--;
		OCR1A = 255-i;
	}
}

int main(void)
{
	DDRA = 255;
  	PORTA^=(1<<0);
  	PORTA^=(1<<1);
	pwm_init();

	t_unit=2300;fsk=50;id(); // set to fast and ID once

	fsk=50;t_unit = 65536; // set to slow for QRSS

	while(1){
		id();
		for (char i=0;i<3;i++){
			fish();
			}
	}

	return 1;
}




Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

My microcontroller-powered prime number calculator is complete! Although I’m planning on improving the software (better menus, the addition of sound, and implementation of a more efficient algorithm) and hardware (a better enclosure would be nice, battery/DC wall power, and a few LEDs on the bottom row are incorrectly wired), this device is currently functional therefore I met my goal!

This device generates large prime numbers (v) while keeping track of how many prime numbers have been identified (N). For example, the 5th prime number is 11. Therefore, at one time this device displayed N=5 and V=11. N and V are displayed on the LCD. In the photo the numbers mean the 16,521,486th prime is 305,257,039 (see for yourself!). The LCD had some history. In December, 2003 (6 years ago) I worked with this SAME display, and I even located the blog entry on November 25’th, 2003 where I mentioned I was thinking of buying the LCD (it was $19 at the time). Funny stuff. Okay, fast forward to today. Primes (Ns and Vs) are displayed on the LCD.

In addition to the LCD, numbers are displayed in binary: Each row of LEDs represents a number. Each row of 30 LEDs allows me to represent numbers up to 2^31-1 (2,147,483,647, about 2.15 billion) in the binary numeral system. Since there’s no algorithm to simply generate prime numbers (especially the Nth prime), the only way to generate large Nth primes is to start small (2) and work up (to 2 billion) testing every number along the way for primeness. The number being tested is displayed on the middle row (Ntest). The last two digits of Ntest are shown on the top left. To test a number (Ntest) for primeness, it is divided by every number from 2 to the square root of Ntest. If any divisor divides evenly (with a remainder of zero) it’s assumed not to be prime, and Ntest is incremented. If it can’t be evenly divided by any number, it’s assumed to be prime and loaded into the top row. In the photo (with the last prime found over 305 million) the device is generating new primes every ~10 seconds.

I’d like to emphasize that this device is not so much technologically innovative as it is creative in its oddness and uniqueness. I made it because no one’s ever made one before. It’s not realistic, practical, or particularly useful. It’s just unique. The brain behind it is an ATMEL ATMega8 AVR microcontroller (What is a microcontroller?), the big 28-pin microchip near the center of the board. (Note: I usually work with ATTiny2313 chips, but for this project I went with the ATMega8 in case I wanted to do analog-to-digital conversions. The fact that the ATMega8 is the heart of the Arduino is coincidental, as I’m not a fan of Arduino for purposes I won’t go into here).

I’d like to thank my grandmother’s brother and his wife (my great uncle and aunt I guess) for getting me interested in microcontrollers almost 10 years ago when they gave me BASIC Stamp kit (similar to this one) for Christmas. I didn’t fully understand it or grasp its significance at the time, but every few years I broke it out and started working with it, until a few months ago when my working knowledge of circuitry let me plunge way into it. I quickly outgrew it and ventured into directly programming cheaper microcontrollers which were nearly disposable (at $2 a pop, compared to $70 for a BASIC stamp), but that stamp kit was instrumental in my transition from computer programming to microchip programming.

The microcontroller is currently running at 1 MHz, but can be clocked to run faster. The PC I’m writing this entry on is about 2,100 MHz (2.1 GHz) to put it in perspective. This microchip is on par with computers of the 70s that filled up entire rooms. I program it with the C language (a language designed in the 70s with those room-sized computers in mind, perfectly suited for these microchips) and load software onto it through the labeled wires two pictures up. The microcontroller uses my software to bit-bang data through a slew of daisy-chained shift registers (74hc595s, most of the 16-pin microchips), allowing me to control over 100 pin states (on/off) using only 3 pins of the microcontroller. There are also 2 4511-type CMOS chips which convert data from 4 pins (a binary number) into the appropriate signals to illuminate a 7-segment display. Add in a couple switches, buttons, and a speaker, and you’re ready to go!

I’ll post more pictures, videos, and the code behind this device when it’s a little more polished. For now it’s technically complete and functional, and I’m very pleased. I worked on it a little bit every day after work. From its conception on May 27th to completion July 5th (under a month and a half) I learned a heck of a lot, challenged my fine motor skills to complete an impressive and confusing soldering job, and had a lot of fun in the process.

text5130






Bitwise programming techniques (manipulating the 1s and 0s of binary numbers) are simple, but hard to¬† remember if you don’t use them often. Recently I’ve needed to perform a lot of bitwise operations. If I’m storing true/false (1-bit) information in variables, it’s a waste of memory to assign a whole variable to the task (the smallest variable in C is a char, and it contains 8 bits). When cramming multiple values into individual variables, it’s nice to know how to manipulate each bit of a variable.

y = (x >> n) & 1; // stores nth bit of x in y.  y becomes 0 or 1.

x &= ~(1 << n); // forces nth bit of x to be 0.  all other bits left alone.

x &= (1 << (n + 1)) - 1; // leaves lowest n bits of x; all higher bits set to 0.

x |= (1 << n); // forces nth bit of x to be 1.  all other bits left alone.

x ^= (1 << n); // toggles nth bit of x.  all other bits left alone.

x = ~x; // toggles ALL the bits in x.




Warning: This post is several years old and the author has marked it as poor quality (compared to more recent posts). It has been left intact for historical reasons, but but its content (and code) may be inaccurate or poorly written.

img_1984

In my quest to build a hardware-based prime number generator I built a rapid prototype to assess how quickly primes can be found with an 8-bit microcontroller. There is a lot of room for improvement, but the code works. Instead of messing with tons of little LEDs, this design displays numbers on an LCD. Interestingly the library to run the LCD takes up about 90% of the memory of the chip leaving only a handful of bytes to write the prime calculation code in!

#define F_CPU 1E6
#include <stdlib.h>
#include <avr/io.h>
#include <math.h>
#include <util/delay.h>
#include "lcd.h"
#include "lcd.c"

const unsigned long int primeMax=pow(2,25);
unsigned long int primeLast=2;
unsigned long int primeTest=0;
unsigned int primeDivy=0;

void wait(void);
void init(void);
void updateDisplay(void);
char *toString(unsigned long int);

int main(void){
    init();
    short maybePrime;
    unsigned int i;
    for(primeTest=2;primeTest<sqrt(primeMax);primeTest++){
        maybePrime=1;
        for (i=2;i<=(sqrt(primeTest)+1);i++){
            primeDivy=i;
            updateDisplay();
            if (primeTest%primeDivy==0){maybePrime=0;break;}
        }
        if (maybePrime==1){primeLast=primeTest;updateDisplay();}
    }
    return 0;
}

void updateDisplay(void){
    lcd_gotoxy(12,0);lcd_puts(toString(primeLast));
    lcd_gotoxy(5,1);lcd_puts(toString(primeTest));
    lcd_gotoxy(16,1);lcd_puts(toString(primeDivy));
    return;
}

void init(void){
    lcd_init(LCD_DISP_ON);
    lcd_puts("PRIME IDENTIFICATIONn");
    _delay_ms(2000);
    lcd_clrscr();
    lcd_puts("LAST PRIME:n");
    lcd_puts("TRY:");
    lcd_gotoxy(14,1);lcd_puts("/");
    return;
}

char *toString(unsigned long int x){
    char s1[8];
    ltoa(x,s1,10);
    return s1;
}