Skip to content

In Which I Am Bogged Down By Code and By Physics

November 9, 2014

14-11-09 sensored
I mounted a the forward sensor on the carbot and immediately ran into an issue i’ve been studiously avoiding for some time.  I did a calibration run of the sensor with a simple pinger sketch and found it was stubbornly reporting a 9 inch distance as 22 inches.  After verifying the sensor was ok with the logic analyzer and looking at the code I realized that my pinger routine was counting instructions for timing the return pulse.  With the CPU running at 4MHz, it was getting 2.5X the instructions done in a given time. This problem also affects the olduino delay() routine which counts 100 instructions as one ms.  

Fixing the pinger routine itself was easy enough if messy.  I made an include file which sets a preprocessor variable __CPUSPEED4 for the 4MHz processor then changed the routine to add extra instructions.

#include "cpu1802spd4port7.h"
unsigned int	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
//with the mc running at 4mhz each instruction is about 4 us and you need a 7 instruction loop
	asm("	req\n	req\n"	//make sure Q is low
		"	seq\n"	//begin a short pulse
		"	seq\n	seq\n	seq\n	seq\n"	//extend the pulse to 20 us
		"	req\n" //end the short pulse
		"	ldaD R15,0\n"
		"	lbr yn1\n"	//branch to aligned code area
		"	align 8\n" //align for short branches
		"yn1: b1 yn1\n"	//wait for the return pulse to start
		"nn1: inc R15\n"	//count pulse length
		"	sex sp\n"	//soak up one instruction time
#ifdef __CPUSPEED4 //need to add 4 more instruction times for faster cpu
	asm("	sex sp\n	sex sp\n	sex sp\n	sex sp\n");
	asm("	bn1 nn1\n"	//keep counting while return pulse is high
		"	Cretn\n"		//return to caller with count in r15
//the cretn above returns the count to the caller.
	return 0; //not executed - just prevents an error message

Fixing delay() shouldn’t be much harder but the code is a bit all over the place. The delay() routine itself is in olduino.c but the routine oneMs() that it calls to soak up instructions is in the main runtime include LCC1802EPILODH. I can fix that with the next release but for the moment I included a new oneMsBN() routine in the body of olduino.c. The BN is for Baby Nathan, the working name of the next version of the compiler.

//Feb 7 2013, changed digitalwrite to out4 instead of out5
//Feb 26 added digitalRead on ef3
//Nov 9 2014 added oneMsBN to soak up one ms adjusted for 4mhz clock
void delay(unsigned int howlong){
	unsigned int i;
	for (i=1;i!=howlong;i++){
void olduinoincluder(){
	asm("	align 8\n"
		"_oneMsBN:		;execute enough instructions  for 1 ms\n");
	#ifndef __CPUSPEED4
	asm("	ldi	(100-15-10-2)/2\n"); //for 1.6mhz 1802
	asm("	ldi	(250-15-10-2)/2\n"); //for 4mhz 1802
	asm("$$mslp: smi	1\n"
		"	bnz	$$mslp\n"
		"	Cretn\n");

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: