Interfacing the Hi-AT 50m laser range finder

The Hi-AT range finder is a useful distance measuring sensor with a range to 50M and claimed accuracy to +/- 1mm. Cost is about 30$US from the usual sources at the time I'm posting this (2/2021). It appears to be the guts of a wide variety of inexpensive range finders, with the difference being that it's internal firmware has been reprogrammed to communicate over a serial line to a micro-controller or terminal. The instructions that come with it are sparse, so I'm sharing what I've discovered about interfacing the device. It's

The basic wiring as described in the reference that comes with the sensor is correct. You connect the Vcc to 3.3V (not 5V!), so you'll need level shifters for the Tx, Rx, and a step-down on the voltage if you're using a 5V device (eg, Arduino Nano).

The challenge is the programming. The manual says that the device reads a single char command, then responds with a string that is specific to the command. The command string to the device is just that single byte, no CR/LF or any other kind of terminator. What the manual does not tell you is that the device echoes the command char back to you, so you will need to read and dispose of that character before looking for the response string.

The other gotcha is that the device can take a fair amount of time to reply. If you naively call read() and keep reading until the buffer is empty (read() = 0xFF), you will not see the reply because you will be attempting to read before any response is available. The response strings are terminated with CR/LF (0xD, 0xA). You are better off looking for this.

Here's some sample code to read the reply from ranger:

SoftwareSerial laser_ranger(Rx, Tx);
char buf[16];
int pos;
bool done;
bool CR_seen;
void readLaserRanger()
{
	// read the echo char
	while ((echo = laser_ranger.read()) == 0xFF)
	{}

	pos = 0;
	done = false;
	CR_seen = false;
	
	while (!done)
	{
		buf[pos] = (char) laser_ranger.read();
		if (buf[pos] != 0xFF)
		{
			if (buf[pos] == 0xD) //CR
				CR_seen = true;
			else if (CR_seen && buf[pos] == 0xA)
				done = true;
			++pos;
		}
	}
	buf[pos] = 0;
}

This is just the minimal code to read the reply. There is no error checking here.
Also, in the while loop where the echo char is read it would seem there is no reason to assign the return value of read() to anything because it's not used. I tried this and it didn't work - the initial return char is not read and discarded. I don't know if that's because of an incorrect optimization or a nuance of C++ that I don't recognize.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.