pga460.h 15.2 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
/****************************************************************************
 *
 *   Copyright (c) 2012-2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file pga460.h
 * @author Jacob Dahl <jacob.dahl@tealdrones.com>
 *
 * Driver for the TI PGA460 Ultrasonic Signal Processor and Transducer Driver
 */

#ifndef _PGA460_H
#define _PGA460_H

#include <cstring>
#include <termios.h>

#include <drivers/device/device.h>
#include <drivers/drv_hrt.h>

#include <uORB/topics/distance_sensor.h>

#include <px4_platform_common/module.h>
#include <px4_platform_common/module_params.h>
#include <px4_platform_common/tasks.h>


#define PGA460_DEFAULT_PORT "/dev/ttyS6"
#define MAX_DETECTABLE_DISTANCE          3.0f
#define MIN_DETECTABLE_DISTANCE          0.05f
#define MAX_DETECTABLE_TEMPERATURE     100.0f
#define MIN_DETECTABLE_TEMPERATURE     -20.0f
#define MODE_SET_THRESH                  0.6f
#define MODE_SET_HYST                    0.0f
#define MAX_SAMPLE_DEVIATION             0.15f
#define NUM_SAMPLES_CONSISTENT           5
// #define POLL_RATE_US 50000ULL
#define POLL_RATE_US 0ULL

#define MODE_SHORT_RANGE P1BL
#define MODE_LONG_RANGE  P2BL

#define SYNCBYTE        0x55

//      Define UART commands by name

// Single Address
#define P1BL            0x00    // Burst and Listen (Preset 1)
#define P2BL            0x01    // Burst and Listen (Preset 2)
#define P1LO            0x02    // Listen Only (Preset 1)
#define P2LO            0x03    // Listen Only (Preset 2)
#define TNLM            0x04    // Temperature and Noise-level measurement
#define UMR             0x05    // Ultrasonic Measurement Result
#define TNLR            0x06    // Temperature and noise level result
#define TEDD            0x07    // Transducer echo data dump
#define SD              0x08    // System diagnostics
#define SRR             0x09    // Register read
#define SRW             0x0A    // Register write
#define EEBR            0x0B    // EEPROM bulk read
#define EEBW            0x0C    // EEPROM bulk write
#define TVGBR           0x0D    // Time-varying-gain bulk read
#define TVGBW           0x0E    // Time-varying-gain bulk write
#define THRBR           0x0F    // Threshold bulk read
#define THRBW           0x10    // Threshold bulk write

// Broadcast -- device will execute command irrespecive of UART address field
#define BC_P1BL         0x11    // Burst and listen (Preset 1)
#define BC_P2BL         0x12    // Burst and listen (Preset 2)
#define BC_P1LO         0x13    // Listen only (Preset 1)
#define BC_P2LO         0x14    // Listen only (Preset 2)
#define BC_TNLM         0x15    // Temperature and noise-level measurement
#define BC_SRW          0x16    // Register write
#define BC_EEBW         0x17    // EEPROM bulk write
#define BC_TVGBW        0x18    // Time varying-gain bulk write
#define BC_THRBW        0x19    // Threshold bulk write

// Addresses and Settings
#define EE_CNTRL_ADDR   0x40
#define EE_UNLOCK_ST1   0x68
#define EE_UNLOCK_ST2   0x69

// EEPROM -- non-volatile
#define USER_DATA1      0xAA    //reg addr      0x0
#define USER_DATA2      0x0     //reg addr      0x1
#define USER_DATA3      0x0     //reg addr      0x2
#define USER_DATA4      0x0     //reg addr      0x3
#define USER_DATA5      0x0     //reg addr      0x4
#define USER_DATA6      0x0     //reg addr      0x5
#define USER_DATA7      0x0     //reg addr      0x6
#define USER_DATA8      0x0     //reg addr      0x7
#define USER_DATA9      0x0     //reg addr      0x8
#define USER_DATA10     0x0     //reg addr      0x9
#define USER_DATA11     0x0     //reg addr      0x0A
#define USER_DATA12     0x0     //reg addr      0x0B
#define USER_DATA13     0x0     //reg addr      0x0C
#define USER_DATA14     0x0     //reg addr      0x0D
#define USER_DATA15     0x0     //reg addr      0x0E
#define USER_DATA16     0x0     //reg addr      0x0F
#define USER_DATA17     0x0     //reg addr      0x10
#define USER_DATA18     0x0     //reg addr      0x11
#define USER_DATA19     0x0     //reg addr      0x12
#define USER_DATA20     0x0     //reg addr      0x13
#define TVGAIN0         0x9D    //reg addr      0x14
#define TVGAIN1         0xBD    //reg addr      0x15
#define TVGAIN2         0xEF    //reg addr      0x16
#define TVGAIN3         0x31    //reg addr      0x17
#define TVGAIN4         0x48    //reg addr      0x18
#define TVGAIN5         0x67    //reg addr      0x19
#define TVGAIN6         0xAC    //reg addr      0x1A
#define INIT_GAIN       0x40    //reg addr      0x1B
#define FREQUENCY   (uint8_t)(5*(_resonant_frequency - 30.0f))       //reg addr      0x1C
#define DEADTIME        0xF0    //reg addr      0x1D
#define PULSE_P1        0x0C    //reg addr      0x1E
#define PULSE_P2        0x1F    //reg addr      0x1F
#define CURR_LIM_P1     0x7F    //reg addr      0x20
#define CURR_LIM_P2     0x7F    //reg addr      0x21
#define REC_LENGTH      0x44    //reg addr      0x22
#define FREQ_DIAG       0x1B    //reg addr      0x23
#define SAT_FDIAG_TH    0x2C    //reg addr      0x24
#define FVOLT_DEC       0x7C    //reg addr      0x25
#define DECPL_TEMP      0xDF    //reg addr      0x26
#define DSP_SCALE       0x0     //reg addr      0x27
#define TEMP_TRIM       0x0     //reg addr      0x28
#define P1_GAIN_CTRL    0x0     //reg addr      0x29
#define P2_GAIN_CTRL    0x8     //reg addr      0x2A
#define EE_CRC          0x29    //reg addr      0x2B

// Register-based -- volatile
#define EE_CNTRL        0x0     //reg addr      0x40

#define BPF_A2_MSB      0x85    //reg addr      0x41
#define BPF_A2_LSB      0xEA    //reg addr      0x42
#define BPF_A3_MSB      0xF9    //reg addr      0x43
#define BPF_A3_LSB      0xA5    //reg addr      0x44
#define BPF_B1_MSB      0x3     //reg addr      0x45
#define BPF_B1_LSB      0x2D    //reg addr      0x46
#define LPF_A2_MSB      0x7E    //reg addr      0x47
#define LPF_A2_LSB      0x67    //reg addr      0x48
#define LPF_B1_MSB      0x0     //reg addr      0x49
#define LPF_B1_LSB      0xCD    //reg addr      0x4A

#define TEST_MUX        0x0     //reg addr      0x4B
#define DEV_STAT0       0x80    //reg addr      0x4C
#define DEV_STAT1       0x0     //reg addr      0x4D

// Register-based -- volatile
#define P1_THR_0        0x54    //reg addr      0x5F
#define P1_THR_1        0x5C    //reg addr      0x60
#define P1_THR_2        0xBD    //reg addr      0x61
#define P1_THR_3        0xE0    //reg addr      0x62
#define P1_THR_4        0x6     //reg addr      0x63
#define P1_THR_5        0xCF    //reg addr      0x64
#define P1_THR_6        0xEE    //reg addr      0x65
#define P1_THR_7        0x8E    //reg addr      0x66
#define P1_THR_8        0x84    //reg addr      0x67
#define P1_THR_9        0xB6    //reg addr      0x68
#define P1_THR_10       0x5A    //reg addr      0x69
#define P1_THR_11       0xFF    //reg addr      0x6A
#define P1_THR_12       0xFF    //reg addr      0x6B
#define P1_THR_13       0xFF    //reg addr      0x6C
#define P1_THR_14       0xFF    //reg addr      0x6D
#define P1_THR_15       0x0     //reg addr      0x6E
#define P2_THR_0        0xBA    //reg addr      0x6F
#define P2_THR_1        0xCF    //reg addr      0x70
#define P2_THR_2        0xFF    //reg addr      0x71
#define P2_THR_3        0xF5    //reg addr      0x72
#define P2_THR_4        0x1A    //reg addr      0x73
#define P2_THR_5        0x5F    //reg addr      0x74
#define P2_THR_6        0xFA    //reg addr      0x75
#define P2_THR_7        0xD6    //reg addr      0x76
#define P2_THR_8        0xB6    //reg addr      0x77
#define P2_THR_9        0x35    //reg addr      0x78
#define P2_THR_10       0xDF    //reg addr      0x79
#define P2_THR_11       0xFF    //reg addr      0x7A
#define P2_THR_12       0xFF    //reg addr      0x7B
#define P2_THR_13       0xFF    //reg addr      0x7C
#define P2_THR_14       0xFF    //reg addr      0x7D
#define P2_THR_15       0x0     //reg addr      0x7E
#define THR_CRC         0x1D    //reg addr      0x7F

class PGA460 : public ModuleBase<PGA460>
{
public:

	PGA460(const char *port = PGA460_DEFAULT_PORT);

	virtual ~PGA460();

	/**
	 * @see ModuleBase::custom_command().
	 * @brief main Main entry point to the module that should be
	 *        called directly from the module's main method.
	 * @param argc The input argument count.
	 * @param argv Pointer to the input argument array.
	 * @return Returns 0 iff successful, -1 otherwise.
	 */
	static int custom_command(int argc, char *argv[]);

	/**
	 * @see ModuleBase::instantiate().
	 * @brief Instantiates the pga460 object.
	 * @param argc The input argument count.
	 * @param argv Pointer to the input argument array.
	 */
	static PGA460 *instantiate(int argc, char *argv[]);

	/**
	 * @see ModuleBase::print_usage().
	 * @brief Prints the module usage to the nuttshell console.
	 * @param reason The requested reason for printing to console.
	 */
	static int print_usage(const char *reason = nullptr);

	/**
	 * @see ModuleBase::task_spawn().
	 */
	static int task_spawn(int argc, char *argv[]);

	/**
	 * @brief Closes the serial port.
	 * @return Returns 0 if success or ERRNO.
	 */
	int close_serial();

	/**
	 * @brief Opens the serial port.
	 * @return Returns true if the open was successful or ERRNO.
	 */
	int open_serial();

	/**
	 * @brief Reports the diagnostic data from device status registers 1 and 2 if there is anything to report.
	 */
	void print_device_status();
	/**
	 * @brief Reports the diagnostic data the diagnostic byte (first byte from slave).
	 * @param diagnostic_byte The diagnostic byte that contains the bitflags.
	 */
	void print_diagnostics(const uint8_t diagnostic_byte);

	/**
	 * @brief Reads the threshold registers.
	 * @return Returns true if the threshold registers are set to default
	 */
	int read_threshold_registers();

	/**
	 * @see ModuleBase::run().
	 */
	void run() override;

	/**
	 * @brief Reads the EEPROM and checks to see if it matches the default parameters.
	 * @note This method is only called once at boot.
	 * @return Returns PX4_OK if the EEPROM has default values, PX4_ERROR otherwise.
	 */
	int read_eeprom();

	/**
	 * @brief Writes the user defined paramaters to device EEPROM.
	 * @return Returns true if the EEPROM was successfully written to.
	 */
	int write_eeprom();

	/**
	 * @brief Reads a register.
	 * @param reg The register to read from.
	 * @return Returns the value of the register at the specified address.
	 */
	uint8_t read_register(const uint8_t reg);

	/**
	 * @brief Writes a value to a register.
	 * @param reg The register address to write to.
	 * @param val The value to write.
	 * @return Returns true for success or false for fail.
	 */
	int write_register(const uint8_t reg, const uint8_t val);

private:

	/**
	* @brief Calculates the checksum of the transmitted commmand + data.
	* @param data Pointer to the data a checksum will be calculated for.
	* @param size The size of the data (bytes) the checksum will be calculated for.
	* @return Returns the single byte checksum.
	*/
	uint8_t calc_checksum(uint8_t *data, const uint8_t size);

	/**
	 * @brief Calculates the distance from the measurement time of flight (time_of_flight) and current temperature.
	 * @param time_of_flight The reported time of flight in ms from the device.
	 * @return Returns the distance measurement in meters.
	 */
	float calculate_object_distance(uint16_t time_of_flight);

	/**
	 * @brief Collects the data in the serial port rx buffer, does math, and publishes the value to uORB
	 * @return Returns the measurment results in format: (u16)time_of_flight, (u8)width, (u8)amplitude
	 */
	uint32_t collect_results();

	/**
	 * @brief Send the program command to the EEPROM to start the flash process.
	 */
	int flash_eeprom();

	/**
	 * @brief Writes program defined threshold defaults to the register map and checks/writes the EEPROM.
	 * @return Returns PX4_OK upon success or PX4_ERROR on fail.
	 */
	int initialize_device_settings();

	/**
	 * @brief Writes the user defined paramaters to device register map.
	 * @return Returns true if the thresholds were successfully written.
	 */
	int initialize_thresholds();

	/**
	 * @brief Measurement is read from UART RX buffer and published to the uORB distance sensor topic.
	 */
	int request_results();

	/**
	 * @brief Checks the measurement from last report and sets the range distance mode (long range , short range).
	 * @return Returns the either P1Bl or P1B2. Preset 1 (P1BL) is short range mode and preset two (P2BL) is long range mode.
	 */
	uint8_t set_range_mode();

	/**
	 * @brief Commands the device to perform an ultrasonic measurement.
	 */
	int take_measurement(const uint8_t mode);

	/*
	 * @brief Gets a temperature measurement in degrees C.
	 * @return Returns the temperature measurement in degrees C.
	 */
	float get_temperature();

	/**
	 * @brief Send the unlock command to the EEPROM to enable reading and writing -- not needed w/ bulk write
	 */
	int unlock_eeprom();

	/**
	 * @brief Commands the device to publish the measurement results to uORB.
	 * @param dist The calculated distance to the object.
	 */
	void uORB_publish_results(const float dist);

	/** @orb_advert_t orb_advert_t uORB advertisement topic. */
	orb_advert_t _distance_sensor_topic{nullptr};

	/** @param _fd Returns the file descriptor from open(). */
	int _fd{-1};

	/** @param _port Stores the port name. */
	char _port[20] {};

	/** @param _previous_report_distance The previous reported sensor distance. */
	float _previous_report_distance{0};

	/** @param _previous_valid_report_distance The previous valid reported sensor distance. */
	float _previous_valid_report_distance{0};

	/** @param _resonant_frequency The sensor resonant (transmit) frequency. */
	float _resonant_frequency{41.0f};

	/** @param _mode_long_range Flag for long range mode. If false, sensor is in short range mode. */
	uint8_t _ranging_mode{MODE_SHORT_RANGE};

	/** @param _start_loop The starting value for the loop time of the main loop. */
	uint64_t _start_loop{0};

	device::Device::DeviceId _device_id;
};

#endif