Code Repo: https://github.com/ravenOSS/maxPhoton5Mqqt
Given the popularity and widespread use of Maxbotix sensors, it would seem that this topic would be well covered but it has been difficult to find examples. Until recently, the Maxbotix website only dealt with analog and pulse width reading.
Many examples illustrate reading the sensor range data and logging to the serial console. However, most Industrial IoT applications require either the local evaluation of data to initiate an action or transmission of a range (distance) data packet.
In a development effort for tank fluid level measurement, we are working with a Maxbotix XL-MaxSonar 7092 sensor suitable for large target sensing. It has analog, pulse width, and RS232 serial output. Other sensor models have I2C or TTL options.
Most micro-controllers do not support true RS232 (incompatible voltage and signal polarity). Therefore, the RS232 output has to be converted to signals that the controller can digest. For prototyping, we are using the MAX3232 breakout board from Sparkfun. This has two sets of inputs & outputs for TTL and RS232 conversion.
The Particle Photon is used for testing and this has both USB serial (“Serial” in example code) and hardware serial (Serial1).
Some Arduino micros only have one serial port available. A great option is the SoftWareSerial library for an additional port and signal conversion. Configuration sets the TX and RX pins, and true/false for signal conversion. Read the docs for some cautions about using this library.
The sensor provides a range reading in the format of ‘R’ + range (3 digit cm) + carriage return (ASCII 13). An important consideration for network bandwidth was to be able to set the timing of range readings instead of just continuously data streaming.
In the initial pass through some code, Serial1.peek() was tried to check for the beginning of the range reading. If ‘R’ was detected, a read of the data was set using atoi() which ignores any proceeding alpha character and only converts ASCII numeric values. Therefore, the ending ‘\n’ is ignored. This approach only returned one value and failed to provide periodic readings.
The next version read the Serial1 stream and tested for ‘R’. parseInt() is used on the stream class to extract ASCII numeric data and convert to an integer range.
This appears to work except that the sensor appears to buffer range readings because after the wait delay, a lot of debug messages are seen followed by a range reading. A Serial1.flush() failed to clear the sensor buffer.
char inChar; // type for data read
char buf[5]; // array to store range data - not used
int range = 0; // type declaration
char inByte; // not used
void setup()
{
Serial.begin(57600);
while (!Serial)
{
; // wait for serial port to connect.
}
Serial.println("Serial open");
Serial1.begin(9600, SERIAL_8N1); // Default but set explicitly anyway
while (!Serial1)
{
; // wait for Serial1 port to connect.
}
Serial.println("Sensor connected");
}
void loop()
{
range = maxRead();
Serial.print("Range: ");
Serial.println(range);
delay(5000);
}
int maxRead()
{
Serial1.flush()
while (Serial1.available() > 0)
{
inChar = Serial1.read();
if (inChar == 'R')
{
Serial.println("Got R");
range = Serial1.parseInt();
Serial.println(range);
}
}
return range;
}
#include "application.h"
/*
* Project maxPhoton5
* Description: Interface Maxbotix serial sensor to Particle Photon or Arduino compatible
* Author: David Richards / ravenIoT LLC
* Date: May 22, 2019
*/
// Using hardware UART on Photon, Electron, Fio
// Maxbotix 7092 sensor with RS232 conversion to TTL with MAX3232
void setup();
void loop();
uint16_t maxRead();
void setup()
{
Serial.begin(57600);
while (!Serial)
{
; // wait for serial port to connect.
}
Serial.println("Serial open");
// set the data rate from the sensor
Serial1.begin(9600, SERIAL_8N1); // Default but set explicitly anyway
while (!Serial1)
{
; // wait for Serial1 port to connect.
}
Serial.println("Sensor connected");
}
void loop()
{
delay(100);
uint16_t range = maxRead();
Serial.print("Range: ");
Serial.println(range);
delay(1000);
}
uint16_t maxRead() // should not have to declare data type again
{
char inChar; // type for data read
const uint8_t length = 3; // number of ascii numeric characters in sensor data
char charArray[length]; // array to store range data
uint8_t i = 0; // initialize counter
while (Serial1.available()) {
inChar = Serial1.read(); // continuously read sensor input in while loop
if (inChar == 'R') { // test if char == R for beginning data
Serial.println("Got an R"); // could use decimal 82 for R
while (i < length) {
charArray[i] = Serial1.read(); // assign input char to charArray index
Serial.print("char: ");
Serial.println(charArray[i]);
i++;
}
}
}
for (i = 0; i < 3; i++){ // Just to print the range data to console
Serial.print("charArray: ");
Serial.println(charArray[i]);
}
return atoi(charArray); // extract integer range from char charArray
}