Skip to content

Ultrasonic Ranger

For a table exhibit at the Vintage Computer Festival in September I’ve built an ultrasonic ranger to show the 1802 hooking up to off-the-shelf modern components meant for an Arduino. In this case, a Seeed Studio ultrasonic transceiver, a Nokia 3310 cellphone screen from Sparkfun all connected through a Maker Shield prototype board.

Here’s a video of the ranger in operation

Here’s a teardown video

Below is a static shot of the assembly
14-08-24 oblique

And here’s just the shield that converts 5V to 3.3V for the LCD
14-08-24 maker shield

The code works although I’m not crazy about it. I’ll include it here now for completeness and I’ll update it if it gets better.

The main procedure initializes the LCD then enters a loop that displays one frame of animation and prints the distance reported by the pinger on the bottom line. The calculation (pinger()+3)/5 is converting the round-trip distancce in centimetres to inches with rounding. LcdString prints an ascii string and itoa converts the distance to an ascii string.

void main()
{
	char buff[8]; //buffer for ascii conversion
 	PIN4=0;			//initialize output port
	LcdInitialise();//and LCD
	LcdClear();

	while(1){//forever
		animone();//move the starship image one frame
		gotoXY(0,5);//point to the bottom line of the display to print the ping reading
		LcdString("Dist. ");LcdString(itoa((pinger()+3)/5,buff));LcdString(" in  ");
	}
}

The animone() routine does one frame of animation. The LCD’s 48 pixel height is divided into six lines of eight bits. The ship is on 3 of those lines so we don’t have to touch the others.

void animone(){
	static unsigned int offset=01;
	{
		gotoXY(0,1); //position to 1st line with ship in it
		digitalWrite(lcdcmd,LCD_D); //get out of command mode
		LcdWriteN(spibytes+84+offset,84-offset);
		LcdWriteN(spibytes+84,offset);

		gotoXY(0,2); //position to 2nd line with ship in it
		digitalWrite(lcdcmd,LCD_D); //get out of command mode
		LcdWriteN(spibytes+168+offset,84-offset);
		LcdWriteN(spibytes+168,offset);

		gotoXY(0,3); //position to 3rd line with ship in it
		digitalWrite(lcdcmd,LCD_D); //get out of command mode
		LcdWriteN(spibytes+252+offset,84-offset);
		LcdWriteN(spibytes+252,offset);
	}
	offset++; if (offset>83) offset=1;
}

The pinger routine is written in plain 1802 assembler and is simple enough although, of course, C makes everything ugly.

void pingerholder(){ //dummy function
//pinger() read an ultrasonic ping distance sensor
//pulsing the Q line high then low starts the ultrasonic sensor
//it responds in around a ms with a pulse on EF1 with a length equal to the echo time
//the distance in cm is approximately (flight time in microseconds) /29 (inverse speed of sound in us/cm)/2 (round trip)
//with the mc running at 1.6mhz, each instruction is about 10 us
// so a 3 inst. loop yields a rough result in cm for the round trip
	asm("	align 16\n" //make sure branches stay on page
		"_pinger:\n" //label looks like pinger() to C
		"	seq\n"	//begin a short pulse
		"	seq\n"	//extend the pulse to 20 us
		"	req\n" //end the short pulse
		"	ldaD R15,0\n"
		"yn1: b1 yn1\n"	//wait for the return pulse to start
		"nn1: inc R15\n"	//count pulse length
		"	skp\n	idl\n"	//soak up one instruction time
		"	bn1 nn1\n"	//keep counting while return pulse is high
		"	Cretn\n"		//return to caller with count in r15
	);
}

The preamble copies in the definitions for the basic olduino routines and standard library, the hardware spi routines the basic LCD routines and those needed for character display, and the bit pattern used to display the starship. The corresponding .c files are included at the bottom of the program. All of the code can be found on the LCC1802 downloads page and in the LCC1802 include and examples directory. Except for the assembly code it is often cribbed from arduino examples.

#include <olduino.h>
#include <nstdlib.h>
#define putc(x) out(7,x)
#include <hspi2.h>
#include <hspi2Lcd.h>
#include <lcdchar.h>
#include <spiship.h>
Leave a Comment

Leave a comment