static bool baroCheck(orb_advert_t *mavlink_log_pub, unsigned instance, bool optional, int &device_id, bool report_fail)
{
	bool success = true;

	char s[30];
	sprintf(s, "%s%u", BARO_BASE_DEVICE_PATH, instance);
	DevHandle h;
	DevMgr::getHandle(s, h);

	if (!h.isValid()) {
		if (!optional) {
			if (report_fail) {
				mavlink_and_console_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: NO BARO SENSOR #%u", instance);
			}
		}

		return false;
	}

	device_id = -1000;

	// TODO: There is no baro calibration yet, since no external baros exist
	// int ret = check_calibration(fd, "CAL_BARO%u_ID");

	// if (ret) {
	// 	mavlink_and_console_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: BARO #%u UNCALIBRATED", instance);
	// 	success = false;
	// 	goto out;
	// }

//out:

	DevMgr::releaseHandle(h);
	return success;
}
int start()
{
	PX4_ERR("start");
	g_dev = new DfISL29501Wrapper();

	if (g_dev == nullptr) {
		PX4_ERR("failed instantiating DfISL29501Wrapper object");
		return -1;
	}

	int ret = g_dev->start();

	if (ret != 0) {
		PX4_ERR("DfISL29501Wrapper start failed");
		return ret;
	}

	// Open the range sensor
	DevHandle h;
	DevMgr::getHandle(ISL_DEVICE_PATH, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    ISL_DEVICE_PATH, h.getError());
		return -1;
	}

	DevMgr::releaseHandle(h);

	return 0;
}
int start(enum Rotation rotation)
{
	g_dev = new DfHmc9250Wrapper(rotation);

	if (g_dev == nullptr) {
		PX4_ERR("failed instantiating DfHmc9250Wrapper object");
		return -1;
	}

	int ret = g_dev->start();

	if (ret != 0) {
		PX4_ERR("DfHmc9250Wrapper start failed");
		return ret;
	}

	// Open the MAG sensor
	DevHandle h;
	DevMgr::getHandle(MAG_DEVICE_PATH, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    MAG_DEVICE_PATH, h.getError());
		return -1;
	}

	DevMgr::releaseHandle(h);

	return 0;
}
Exemple #4
0
/**
 * Start the driver.
 */
void
start(const char *uart_path, bool fake_gps, bool enable_sat_info)
{
	DevHandle h;

	/* create the driver */
	g_dev = new GPSSIM(uart_path, fake_gps, enable_sat_info);

	if (g_dev == nullptr) {
		goto fail;
	}

	if (OK != g_dev->init()) {
		goto fail;
	}

	/* set the poll rate to default, starts automatic data collection */
	DevMgr::getHandle(GPSSIM_DEVICE_PATH, h);

	if (!h.isValid()) {
		PX4_ERR("getHandle failed: %s", GPSSIM_DEVICE_PATH);
		goto fail;
	}

	return;

fail:

	if (g_dev != nullptr) {
		delete g_dev;
		g_dev = nullptr;
	}

	PX4_ERR("start failed");
}
Exemple #5
0
int ImuTester::run()
{
	// Default is fail unless pass critera met
	m_pass = TEST_FAIL;

	// Register the driver
	int ret = m_sensor.init();

	// Open the IMU sensor
	DevHandle h;
	DevMgr::getHandle(IMU_DEVICE_PATH, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    IMU_DEVICE_PATH, h.getError());
		m_done = true;

	} else {
		m_done = false;
	}

	while (!m_done) {
		++m_read_attempts;

		struct imu_sensor_data data;

		ret = ImuSensor::getSensorData(h, data, true);

		if (ret == 0) {
			uint32_t count = data.read_counter;
			DF_LOG_INFO("count: %d", count);

			if (m_read_counter != count) {
				m_read_counter = count;
				ImuSensor::printImuValues(h, data);
			}

		} else {
			DF_LOG_INFO("error: unable to read the IMU sensor device.");
		}

		if (m_read_counter >= num_read_attempts) {
			// Done test - PASSED
			m_pass = TEST_PASS;
			m_done = true;

		} else if (m_read_attempts > num_read_attempts) {
			DF_LOG_INFO("error: unable to read the IMU sensor device.");
			m_done = true;
		}
	}

	DevMgr::releaseHandle(h);

	DF_LOG_INFO("Closing IMU sensor");
	m_sensor.stop();
	return m_pass;
}
Exemple #6
0
int PressureTester::run()
{
	DF_LOG_INFO("Entering: run");
	// Default is fail unless pass critera met
	m_pass = TEST_FAIL;

	// Register the driver
	int ret = m_sensor.init();

	// Open the pressure sensor
	DevHandle h;
	DevMgr::getHandle(BARO_DEVICE_PATH, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    BARO_DEVICE_PATH, h.getError());
		m_done = true;

	} else {
		m_done = false;
		m_sensor_data.read_counter = 0;
	}

	while (!m_done) {
		++m_read_attempts;
		ret = BaroSensor::getSensorData(h, m_sensor_data, true);
		DF_LOG_INFO("Got data");

		if (ret == 0) {
			uint32_t count = m_sensor_data.read_counter;

			if (m_read_counter != count) {
				DF_LOG_INFO("count: %d", count);
				m_read_counter = count;
				BaroSensor::printPressureValues(m_sensor_data);
			}

		} else {
			DF_LOG_INFO("error: unable to read the pressure sensor device.");
		}

		if ((m_read_counter >= 1000) && (m_read_attempts == m_read_counter)) {
			// Done test - PASSED
			m_pass = TEST_PASS;
			m_done = true;

		} else if (m_read_attempts > 1000) {
			DF_LOG_INFO("error: unable to read the pressure sensor device.");
			m_done = true;
		}
	}

	DF_LOG_INFO("Closing pressure sensor\n");
	m_sensor.stop();
	return m_pass;
}
int
Sensors::adc_init()
{
	DevMgr::getHandle(ADC0_DEVICE_PATH, _h_adc);

	if (!_h_adc.isValid()) {
		PX4_ERR("no ADC found: %s (%d)", ADC0_DEVICE_PATH, _h_adc.getError());
		return PX4_ERROR;
	}

	return OK;
}
Exemple #8
0
/**
 * Reset the driver.
 */
void
reset()
{
	DevHandle h;
	DevMgr::getHandle(GPSSIM_DEVICE_PATH, h);

	if (!h.isValid()) {
		PX4_ERR("failed ");
	}

	if (h.ioctl(SENSORIOCRESET, 0) < 0) {
		PX4_ERR("reset failed");
	}
}
bool
VotedSensorsUpdate::apply_mag_calibration(DevHandle &h, const struct mag_calibration_s *mcal, const int device_id)
{
#if !defined(__PX4_QURT) && !defined(__PX4_POSIX)

	if (!h.isValid()) {
		return false;
	}

	/* On most systems, we can just use the IOCTL call to set the calibration params. */
	return !h.ioctl(MAGIOCSSCALE, (long unsigned int)mcal);

#else
	/* On QURT & POSIX, the params are read directly in the respective wrappers. */
	return true;
#endif
}
static bool gyroCheck(orb_advert_t *mavlink_log_pub, unsigned instance, bool optional, int &device_id, bool report_fail)
{
	bool success = true;

	char s[30];
	sprintf(s, "%s%u", GYRO_BASE_DEVICE_PATH, instance);
	DevHandle h;
	DevMgr::getHandle(s, h);

	if (!h.isValid()) {
		if (!optional) {
			if (report_fail) {
				mavlink_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: NO GYRO SENSOR #%u", instance);
			}
		}

		return false;
	}

	int ret = check_calibration(h, "CAL_GYRO%u_ID", device_id);

	if (ret) {
		if (report_fail) {
			mavlink_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: GYRO #%u UNCALIBRATED", instance);
		}

		success = false;
		goto out;
	}

	ret = h.ioctl(GYROIOCSELFTEST, 0);

	if (ret != OK) {
		if (report_fail) {
			mavlink_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: GYRO #%u SELFTEST FAILED", instance);
		}

		success = false;
		goto out;
	}

out:
	DevMgr::releaseHandle(h);
	return success;
}
Exemple #11
0
int led_init()
{
	blink_msg_end = 0;

	led_control.led_mask = 0xff;
	led_control.mode = led_control_s::MODE_OFF;
	led_control.priority = 0;
	led_control.timestamp = hrt_absolute_time();
	led_control_pub = orb_advertise_queue(ORB_ID(led_control), &led_control, LED_UORB_QUEUE_LENGTH);

#if !defined(CONFIG_ARCH_BOARD_RPI) && !defined(CONFIG_ARCH_BOARD_BBBLUE)
	/* first open normal LEDs */
	DevMgr::getHandle(LED0_DEVICE_PATH, h_leds);

	if (!h_leds.isValid()) {
		PX4_WARN("LED: getHandle fail\n");
		return PX4_ERROR;
	}

	/* the green LED is only available on FMUv5 */
	(void)h_leds.ioctl(LED_ON, LED_GREEN);

	/* the blue LED is only available on AeroCore but not FMUv2 */
	(void)h_leds.ioctl(LED_ON, LED_BLUE);

	/* switch blue off */
	led_off(LED_BLUE);

	/* we consider the amber led mandatory */
	if (h_leds.ioctl(LED_ON, LED_AMBER)) {
		PX4_WARN("Amber LED: ioctl fail\n");
		return PX4_ERROR;
	}

	/* switch amber off */
	led_off(LED_AMBER);
#endif

	return 0;
}
int start(bool mag_enabled, enum Rotation rotation)
{
	g_dev = new DfLsm9ds1Wrapper(mag_enabled, rotation);

	if (g_dev == nullptr) {
		PX4_ERR("failed instantiating DfLsm9ds1Wrapper object");
		return -1;
	}

	int ret = g_dev->start();

	if (ret != 0) {
		PX4_ERR("DfLsm9ds1Wrapper start failed");
		return ret;
	}

	// Open the IMU sensor
	DevHandle h;
	DevMgr::getHandle(IMU_DEVICE_ACC_GYRO, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    IMU_DEVICE_ACC_GYRO, h.getError());
		return -1;
	}

	DevMgr::releaseHandle(h);

	DevMgr::getHandle(IMU_DEVICE_MAG, h);

	if (!h.isValid()) {
		DF_LOG_INFO("Error: unable to obtain a valid handle for the receiver at: %s (%d)",
			    IMU_DEVICE_MAG, h.getError());
		return -1;
	}

	DevMgr::releaseHandle(h);
	return 0;
}
Exemple #13
0
int led_init()
{
	blink_msg_end = 0;

#ifndef CONFIG_ARCH_BOARD_RPI
	/* first open normal LEDs */
	DevMgr::getHandle(LED0_DEVICE_PATH, h_leds);

	if (!h_leds.isValid()) {
		PX4_WARN("LED: getHandle fail\n");
		return PX4_ERROR;
	}

	/* the blue LED is only available on FMUv1 & AeroCore but not FMUv2 */
	(void)h_leds.ioctl(LED_ON, LED_BLUE);

	/* switch blue off */
	led_off(LED_BLUE);

	/* we consider the amber led mandatory */
	if (h_leds.ioctl(LED_ON, LED_AMBER)) {
		PX4_WARN("Amber LED: ioctl fail\n");
		return PX4_ERROR;
	}

	/* switch amber off */
	led_off(LED_AMBER);
#endif

	/* then try RGB LEDs, this can fail on FMUv1*/
	DevHandle h;
	DevMgr::getHandle(RGBLED0_DEVICE_PATH, h_rgbleds);

	if (!h_rgbleds.isValid()) {
		PX4_WARN("No RGB LED found at " RGBLED0_DEVICE_PATH);
	}

	return 0;
}
bool
VotedSensorsUpdate::apply_accel_calibration(DevHandle &h, const struct accel_calibration_s *acal, const int device_id)
{
#if !defined(__PX4_QURT) && !defined(__PX4_POSIX_RPI) && !defined(__PX4_POSIX_BEBOP)

	/* On most systems, we can just use the IOCTL call to set the calibration params. */
	return !h.ioctl(ACCELIOCSSCALE, (long unsigned int)acal);

#else
	/* On QURT, the params are read directly in the respective wrappers. */
	return true;
#endif
}
int SPIDevObj::bulkRead(DevHandle &h, uint8_t address, uint8_t *out_buffer, int length)
{
#if defined(__RPI2)
	/* implement sensor interface via rpi2 spi */
	SPIDevObj *obj = DevMgr::getDevObjByHandle<SPIDevObj>(h);

	if (obj) {
		return obj->_bulkRead(address, out_buffer, length);
	}

	return -1;

#elif defined(__QURT)
	int result = 0;
	int transfer_bytes = 1 + length; // first byte is address
	struct dspal_spi_ioctl_read_write ioctl_write_read;
	uint8_t write_buffer[transfer_bytes];
	uint8_t read_buffer[transfer_bytes];

	write_buffer[0] = address | DIR_READ;

	ioctl_write_read.read_buffer = out_buffer;
	ioctl_write_read.read_buffer_length = transfer_bytes;
	ioctl_write_read.write_buffer = write_buffer;
	ioctl_write_read.write_buffer_length = transfer_bytes;
	result = h.ioctl(SPI_IOCTL_RDWR, (unsigned long)&ioctl_write_read);

	if (result != transfer_bytes) {
		DF_LOG_ERR("bulkRead error %d (%d)", result, h.getError());
		return result;
	}

	memcpy(out_buffer, &read_buffer[1], transfer_bytes - 1);

	return 0;
#else
	return -1;
#endif
}
static int check_calibration(DevHandle &h, const char* param_template, int &devid)
{
	bool calibration_found;

	/* new style: ask device for calibration state */
	int ret = h.ioctl(SENSORIOCCALTEST, 0);

	calibration_found = (ret == OK);

	devid = h.ioctl(DEVIOCGDEVICEID, 0);

	char s[20];
	int instance = 0;

	/* old style transition: check param values */
	while (!calibration_found) {
		sprintf(s, param_template, instance);
		param_t parm = param_find(s);

		/* if the calibration param is not present, abort */
		if (parm == PARAM_INVALID) {
			break;
		}

		/* if param get succeeds */
		int calibration_devid;
		if (!param_get(parm, &(calibration_devid))) {

			/* if the devid matches, exit early */
			if (devid == calibration_devid) {
				calibration_found = true;
				break;
			}
		}
		instance++;
	}

	return !calibration_found;
}
int SPIDevObj::setLoopbackMode(DevHandle &h, bool enable)
{
#if defined(__RPI2)
	/* implement sensor interface via rpi2 spi */
	DF_LOG_ERR("ERROR: attempt to set loopback mode in software fails.");
	return -1;

#elif defined(__QURT)
	struct dspal_spi_ioctl_loopback loopback;

	loopback.state = enable ? SPI_LOOPBACK_STATE_ENABLED : SPI_LOOPBACK_STATE_DISABLED;
	return h.ioctl(SPI_IOCTL_LOOPBACK_TEST, (unsigned long)&loopback);
#else
	return -1;
#endif
}
Exemple #18
0
int buzzer_init()
{
	tune_end = 0;
	tune_current = 0;
	memset(tune_durations, 0, sizeof(tune_durations));
	tune_durations[TONE_NOTIFY_POSITIVE_TUNE] = 800000;
	tune_durations[TONE_NOTIFY_NEGATIVE_TUNE] = 900000;
	tune_durations[TONE_NOTIFY_NEUTRAL_TUNE] = 500000;
	tune_durations[TONE_ARMING_WARNING_TUNE] = 3000000;

	DevMgr::getHandle(TONEALARM0_DEVICE_PATH, h_buzzer);

	if (!h_buzzer.isValid()) {
		PX4_WARN("Buzzer: px4_open fail\n");
		return PX4_ERROR;
	}

	return PX4_OK;
}
int SPIDevObj::setBusFrequency(DevHandle &h, SPI_FREQUENCY freq_hz)
{
#if defined(__RPI2)
	/* implement sensor interface via rpi2 spi */
	SPIDevObj *obj = DevMgr::getDevObjByHandle<SPIDevObj>(h);

	if (obj) {
		return obj->_setBusFrequency(freq_hz);
	}

	return -1;

#elif defined(__QURT)
	struct dspal_spi_ioctl_set_bus_frequency bus_freq;
	bus_freq.bus_frequency_in_hz = freq_hz;
	return h.ioctl(SPI_IOCTL_SET_BUS_FREQUENCY_IN_HZ, (unsigned long)&bus_freq);
#else
	return -1;
#endif
}
Exemple #20
0
void set_tune(int tune)
{
	unsigned int new_tune_duration = tune_durations[tune];

	/* don't interrupt currently playing non-repeating tune by repeating */
	if (tune_end == 0 || new_tune_duration != 0 || hrt_absolute_time() > tune_end) {
		/* allow interrupting current non-repeating tune by the same tune */
		if (tune != tune_current || new_tune_duration != 0) {
			h_buzzer.ioctl(TONE_SET_ALARM, tune);
		}

		tune_current = tune;

		if (new_tune_duration != 0) {
			tune_end = hrt_absolute_time() + new_tune_duration;

		} else {
			tune_end = 0;
		}
	}
}
void VotedSensorsUpdate::parameters_update()
{
	get_rot_matrix((enum Rotation)_parameters.board_rotation, &_board_rotation);
	/* fine tune board offset */
	math::Matrix<3, 3> board_rotation_offset;
	board_rotation_offset.from_euler(M_DEG_TO_RAD_F * _parameters.board_offset[0],
					 M_DEG_TO_RAD_F * _parameters.board_offset[1],
					 M_DEG_TO_RAD_F * _parameters.board_offset[2]);

	_board_rotation = board_rotation_offset * _board_rotation;

	/* set offset parameters to new values */
	bool failed;
	char str[30];
	unsigned mag_count = 0;
	unsigned gyro_count = 0;
	unsigned accel_count = 0;

	/* run through all gyro sensors */
	for (unsigned s = 0; s < SENSOR_COUNT_MAX; s++) {

		(void)sprintf(str, "%s%u", GYRO_BASE_DEVICE_PATH, s);

		DevHandle h;
		DevMgr::getHandle(str, h);

		if (!h.isValid()) {
			continue;
		}

		bool config_ok = false;

		/* run through all stored calibrations */
		for (unsigned i = 0; i < SENSOR_COUNT_MAX; i++) {
			/* initially status is ok per config */
			failed = false;

			(void)sprintf(str, "CAL_GYRO%u_ID", i);
			int device_id;
			failed = failed || (OK != param_get(param_find(str), &device_id));

			if (failed) {
				DevMgr::releaseHandle(h);
				continue;
			}

			/* if the calibration is for this device, apply it */
			if (device_id == h.ioctl(DEVIOCGDEVICEID, 0)) {
				struct gyro_calibration_s gscale = {};
				(void)sprintf(str, "CAL_GYRO%u_XOFF", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.x_offset));
				(void)sprintf(str, "CAL_GYRO%u_YOFF", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.y_offset));
				(void)sprintf(str, "CAL_GYRO%u_ZOFF", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.z_offset));
				(void)sprintf(str, "CAL_GYRO%u_XSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.x_scale));
				(void)sprintf(str, "CAL_GYRO%u_YSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.y_scale));
				(void)sprintf(str, "CAL_GYRO%u_ZSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.z_scale));

				if (failed) {
					PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "gyro", i);

				} else {
					/* apply new scaling and offsets */
					config_ok = apply_gyro_calibration(h, &gscale, device_id);

					if (!config_ok) {
						PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "gyro ", i);
					}
				}

				break;
			}
		}

		if (config_ok) {
			gyro_count++;
		}
	}

	/* run through all accel sensors */
	for (unsigned s = 0; s < SENSOR_COUNT_MAX; s++) {

		(void)sprintf(str, "%s%u", ACCEL_BASE_DEVICE_PATH, s);

		DevHandle h;
		DevMgr::getHandle(str, h);

		if (!h.isValid()) {
			continue;
		}

		bool config_ok = false;

		/* run through all stored calibrations */
		for (unsigned i = 0; i < SENSOR_COUNT_MAX; i++) {
			/* initially status is ok per config */
			failed = false;

			(void)sprintf(str, "CAL_ACC%u_ID", i);
			int device_id;
			failed = failed || (OK != param_get(param_find(str), &device_id));

			if (failed) {
				DevMgr::releaseHandle(h);
				continue;
			}

			/* if the calibration is for this device, apply it */
			if (device_id == h.ioctl(DEVIOCGDEVICEID, 0)) {
				struct accel_calibration_s ascale = {};
				(void)sprintf(str, "CAL_ACC%u_XOFF", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.x_offset));
				(void)sprintf(str, "CAL_ACC%u_YOFF", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.y_offset));
				(void)sprintf(str, "CAL_ACC%u_ZOFF", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.z_offset));
				(void)sprintf(str, "CAL_ACC%u_XSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.x_scale));
				(void)sprintf(str, "CAL_ACC%u_YSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.y_scale));
				(void)sprintf(str, "CAL_ACC%u_ZSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.z_scale));

				if (failed) {
					PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "accel", i);

				} else {
					/* apply new scaling and offsets */
					config_ok = apply_accel_calibration(h, &ascale, device_id);

					if (!config_ok) {
						PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "accel ", i);
					}
				}

				break;
			}
		}

		if (config_ok) {
			accel_count++;
		}
	}

	/* run through all mag sensors */
	for (unsigned s = 0; s < SENSOR_COUNT_MAX; s++) {

		/* set a valid default rotation (same as board).
		 * if the mag is configured, this might be replaced
		 * in the section below.
		 */
		_mag_rotation[s] = _board_rotation;

		(void)sprintf(str, "%s%u", MAG_BASE_DEVICE_PATH, s);

		DevHandle h;
		DevMgr::getHandle(str, h);

		if (!h.isValid()) {
			/* the driver is not running, abort */
			continue;
		}

		bool config_ok = false;

		/* run through all stored calibrations */
		for (unsigned i = 0; i < SENSOR_COUNT_MAX; i++) {
			/* initially status is ok per config */
			failed = false;

			(void)sprintf(str, "CAL_MAG%u_ID", i);
			int device_id;
			failed = failed || (OK != param_get(param_find(str), &device_id));
			(void)sprintf(str, "CAL_MAG%u_ROT", i);
			(void)param_find(str);

			if (failed) {
				DevMgr::releaseHandle(h);
				continue;
			}

			// int id = h.ioctl(DEVIOCGDEVICEID, 0);
			// PX4_WARN("sensors: device ID: %s: %d, %u", str, id, (unsigned)id);

			/* if the calibration is for this device, apply it */
			if (device_id == h.ioctl(DEVIOCGDEVICEID, 0)) {
				struct mag_calibration_s mscale = {};
				(void)sprintf(str, "CAL_MAG%u_XOFF", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.x_offset));
				(void)sprintf(str, "CAL_MAG%u_YOFF", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.y_offset));
				(void)sprintf(str, "CAL_MAG%u_ZOFF", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.z_offset));
				(void)sprintf(str, "CAL_MAG%u_XSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.x_scale));
				(void)sprintf(str, "CAL_MAG%u_YSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.y_scale));
				(void)sprintf(str, "CAL_MAG%u_ZSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.z_scale));

				(void)sprintf(str, "CAL_MAG%u_ROT", i);

				if (h.ioctl(MAGIOCGEXTERNAL, 0) <= 0) {
					/* mag is internal */
					_mag_rotation[s] = _board_rotation;
					/* reset param to -1 to indicate internal mag */
					int32_t minus_one;
					param_get(param_find(str), &minus_one);

					if (minus_one != MAG_ROT_VAL_INTERNAL) {
						minus_one = MAG_ROT_VAL_INTERNAL;
						param_set_no_notification(param_find(str), &minus_one);
					}

				} else {

					int32_t mag_rot;
					param_get(param_find(str), &mag_rot);

					/* check if this mag is still set as internal */
					if (mag_rot < 0) {
						/* it was marked as internal, change to external with no rotation */
						mag_rot = 0;
						param_set_no_notification(param_find(str), &mag_rot);
					}

					/* handling of old setups, will be removed later (noted Feb 2015) */
					int32_t deprecated_mag_rot = 0;
					param_get(param_find("SENS_EXT_MAG_ROT"), &deprecated_mag_rot);

					/*
					 * If the deprecated parameter is non-default (is != 0),
					 * and the new parameter is default (is == 0), then this board
					 * was configured already and we need to copy the old value
					 * to the new parameter.
					 * The < 0 case is special: It means that this param slot was
					 * used previously by an internal sensor, but the the call above
					 * proved that it is currently occupied by an external sensor.
					 * In that case we consider the orientation to be default as well.
					 */
					if ((deprecated_mag_rot != 0) && (mag_rot <= 0)) {
						mag_rot = deprecated_mag_rot;
						param_set_no_notification(param_find(str), &mag_rot);
						/* clear the old param, not supported in GUI anyway */
						deprecated_mag_rot = 0;
						param_set_no_notification(param_find("SENS_EXT_MAG_ROT"), &deprecated_mag_rot);
					}

					/* handling of transition from internal to external */
					if (mag_rot < 0) {
						mag_rot = 0;
					}

					get_rot_matrix((enum Rotation)mag_rot, &_mag_rotation[s]);
				}

				if (failed) {
					PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "mag", i);

				} else {

					/* apply new scaling and offsets */
					config_ok = apply_mag_calibration(h, &mscale, device_id);

					if (!config_ok) {
						PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "mag ", i);
					}
				}

				break;
			}
		}

		if (config_ok) {
			mag_count++;
		}
	}
}
Exemple #22
0
void rgbled_set_pattern(rgbled_pattern_t *pattern)
{

	h_rgbleds.ioctl(RGBLED_SET_PATTERN, (unsigned long)pattern);
}
/**
 * Transition from one hil state to another
 */
transition_result_t hil_state_transition(hil_state_t new_state, orb_advert_t status_pub, struct vehicle_status_s *current_status, orb_advert_t *mavlink_log_pub)
{
	transition_result_t ret = TRANSITION_DENIED;

	if (current_status->hil_state == new_state) {
		ret = TRANSITION_NOT_CHANGED;

	} else {
		switch (new_state) {
		case vehicle_status_s::HIL_STATE_OFF:
			/* we're in HIL and unexpected things can happen if we disable HIL now */
			mavlink_and_console_log_critical(mavlink_log_pub, "Not switching off HIL (safety)");
			ret = TRANSITION_DENIED;
			break;

		case vehicle_status_s::HIL_STATE_ON:
			if (current_status->arming_state == vehicle_status_s::ARMING_STATE_INIT
			    || current_status->arming_state == vehicle_status_s::ARMING_STATE_STANDBY
			    || current_status->arming_state == vehicle_status_s::ARMING_STATE_STANDBY_ERROR) {

#ifdef __PX4_NUTTX
				/* Disable publication of all attached sensors */
				/* list directory */
				DIR		*d;
				d = opendir("/dev");

				if (d) {
					struct dirent	*direntry;
					char devname[24];

					while ((direntry = readdir(d)) != NULL) {

						/* skip serial ports */
						if (!strncmp("tty", direntry->d_name, 3)) {
							continue;
						}

						/* skip mtd devices */
						if (!strncmp("mtd", direntry->d_name, 3)) {
							continue;
						}

						/* skip ram devices */
						if (!strncmp("ram", direntry->d_name, 3)) {
							continue;
						}

						/* skip MMC devices */
						if (!strncmp("mmc", direntry->d_name, 3)) {
							continue;
						}

						/* skip mavlink */
						if (!strcmp("mavlink", direntry->d_name)) {
							continue;
						}

						/* skip console */
						if (!strcmp("console", direntry->d_name)) {
							continue;
						}

						/* skip null */
						if (!strcmp("null", direntry->d_name)) {
							continue;
						}

						snprintf(devname, sizeof(devname), "/dev/%s", direntry->d_name);

						int sensfd = ::open(devname, 0);

						if (sensfd < 0) {
							warn("failed opening device %s", devname);
							continue;
						}

						int block_ret = ::ioctl(sensfd, DEVIOCSPUBBLOCK, 1);
						close(sensfd);

						printf("Disabling %s: %s\n", devname, (block_ret == OK) ? "OK" : "ERROR");
					}
					closedir(d);

					ret = TRANSITION_CHANGED;
					mavlink_and_console_log_critical(mavlink_log_pub, "Switched to ON hil state");

				} else {
					/* failed opening dir */
					mavlink_log_info(mavlink_log_pub, "FAILED LISTING DEVICE ROOT DIRECTORY");
					ret = TRANSITION_DENIED;
				}

#else

				// Handle VDev devices
				const char *devname;
				unsigned int handle = 0;
				for(;;) {
					devname = px4_get_device_names(&handle);
					if (devname == NULL)
						break;

						/* skip mavlink */
					if (!strcmp("/dev/mavlink", devname)) {
							continue;
					}


					int sensfd = px4_open(devname, 0);

					if (sensfd < 0) {
						warn("failed opening device %s", devname);
							continue;
					}

					int block_ret = px4_ioctl(sensfd, DEVIOCSPUBBLOCK, 1);
					px4_close(sensfd);

					printf("Disabling %s: %s\n", devname, (block_ret == OK) ? "OK" : "ERROR");
				}


				// Handle DF devices
				const char *df_dev_path;
				unsigned int index = 0;
				for(;;) {
					if (DevMgr::getNextDeviceName(index, &df_dev_path) < 0) {
						break;
					}

					DevHandle h;
					DevMgr::getHandle(df_dev_path, h);

					if (!h.isValid()) {
						warn("failed opening device %s", df_dev_path);
						continue;
					}

					int block_ret = h.ioctl(DEVIOCSPUBBLOCK, 1);
					DevMgr::releaseHandle(h);

					printf("Disabling %s: %s\n", df_dev_path, (block_ret == OK) ? "OK" : "ERROR");
				}

				ret = TRANSITION_CHANGED;
				mavlink_and_console_log_critical(mavlink_log_pub, "Switched to ON hil state");
#endif

			} else {
				mavlink_and_console_log_critical(mavlink_log_pub, "Not switching to HIL when armed");
				ret = TRANSITION_DENIED;
			}
			break;

		default:
			warnx("Unknown HIL state");
			break;
		}
	}

	if (ret == TRANSITION_CHANGED) {
		current_status->hil_state = new_state;
		current_status->timestamp = hrt_absolute_time();
		// XXX also set lockdown here
		orb_publish(ORB_ID(vehicle_status), status_pub, current_status);
	}
	return ret;
}
void VotedSensorsUpdate::parameters_update()
{
	get_rot_matrix((enum Rotation)_parameters.board_rotation, &_board_rotation);
	/* fine tune board offset */
	math::Matrix<3, 3> board_rotation_offset;
	board_rotation_offset.from_euler(M_DEG_TO_RAD_F * _parameters.board_offset[0],
					 M_DEG_TO_RAD_F * _parameters.board_offset[1],
					 M_DEG_TO_RAD_F * _parameters.board_offset[2]);

	_board_rotation = board_rotation_offset * _board_rotation;

	// initialze all mag rotations with the board rotation in case there is no calibration data available
	for (int topic_instance = 0; topic_instance < MAG_COUNT_MAX; ++topic_instance) {
		_mag_rotation[topic_instance] = _board_rotation;
	}

	/* Load & apply the sensor calibrations.
	 * IMPORTANT: we assume all sensor drivers are running and published sensor data at this point
	 */

	/* temperature compensation */
	_temperature_compensation.parameters_update();

	/* gyro */
	for (unsigned topic_instance = 0; topic_instance < GYRO_COUNT_MAX; ++topic_instance) {

		if (topic_instance < _gyro.subscription_count) {
			// valid subscription, so get the driver id by getting the published sensor data
			struct gyro_report report;

			if (orb_copy(ORB_ID(sensor_gyro), _gyro.subscription[topic_instance], &report) == 0) {
				int temp = _temperature_compensation.set_sensor_id_gyro(report.device_id, topic_instance);

				if (temp < 0) {
					PX4_ERR("gyro temp compensation init: failed to find device ID %u for instance %i",
						report.device_id, topic_instance);
					_corrections.gyro_mapping[topic_instance] = 0;

				} else {
					_corrections.gyro_mapping[topic_instance] = temp;

				}
			}
		}
	}


	/* accel */
	for (unsigned topic_instance = 0; topic_instance < ACCEL_COUNT_MAX; ++topic_instance) {

		if (topic_instance < _accel.subscription_count) {
			// valid subscription, so get the driver id by getting the published sensor data
			struct accel_report report;

			if (orb_copy(ORB_ID(sensor_accel), _accel.subscription[topic_instance], &report) == 0) {
				int temp = _temperature_compensation.set_sensor_id_accel(report.device_id, topic_instance);

				if (temp < 0) {
					PX4_ERR("accel temp compensation init: failed to find device ID %u for instance %i",
						report.device_id, topic_instance);
					_corrections.accel_mapping[topic_instance] = 0;

				} else {
					_corrections.accel_mapping[topic_instance] = temp;

				}
			}
		}
	}

	/* baro */
	for (unsigned topic_instance = 0; topic_instance < BARO_COUNT_MAX; ++topic_instance) {

		if (topic_instance < _baro.subscription_count) {
			// valid subscription, so get the driver id by getting the published sensor data
			struct baro_report report;

			if (orb_copy(ORB_ID(sensor_baro), _baro.subscription[topic_instance], &report) == 0) {
				int temp = _temperature_compensation.set_sensor_id_baro(report.device_id, topic_instance);

				if (temp < 0) {
					PX4_ERR("baro temp compensation init: failed to find device ID %u for instance %i",
						report.device_id, topic_instance);
					_corrections.baro_mapping[topic_instance] = 0;

				} else {
					_corrections.baro_mapping[topic_instance] = temp;

				}
			}
		}
	}


	/* set offset parameters to new values */
	bool failed;
	char str[30];
	unsigned gyro_count = 0;
	unsigned accel_count = 0;
	unsigned gyro_cal_found_count = 0;
	unsigned accel_cal_found_count = 0;

	/* run through all gyro sensors */
	for (unsigned driver_index = 0; driver_index < GYRO_COUNT_MAX; driver_index++) {

		(void)sprintf(str, "%s%u", GYRO_BASE_DEVICE_PATH, driver_index);

		DevHandle h;
		DevMgr::getHandle(str, h);

		if (!h.isValid()) {
			continue;
		}

		uint32_t driver_device_id = h.ioctl(DEVIOCGDEVICEID, 0);
		bool config_ok = false;

		/* run through all stored calibrations that are applied at the driver level*/
		for (unsigned i = 0; i < GYRO_COUNT_MAX; i++) {
			/* initially status is ok per config */
			failed = false;

			(void)sprintf(str, "CAL_GYRO%u_ID", i);
			int32_t device_id;
			failed = failed || (OK != param_get(param_find(str), &device_id));

			(void)sprintf(str, "CAL_GYRO%u_EN", i);
			int32_t device_enabled = 1;
			failed = failed || (OK != param_get(param_find(str), &device_enabled));

			_gyro.enabled[i] = (device_enabled == 1);

			if (failed) {
				continue;
			}

			if (driver_index == 0 && device_id > 0) {
				gyro_cal_found_count++;
			}

			/* if the calibration is for this device, apply it */
			if (device_id == driver_device_id) {
				struct gyro_calibration_s gscale = {};
				(void)sprintf(str, "CAL_GYRO%u_XOFF", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.x_offset));
				(void)sprintf(str, "CAL_GYRO%u_YOFF", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.y_offset));
				(void)sprintf(str, "CAL_GYRO%u_ZOFF", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.z_offset));
				(void)sprintf(str, "CAL_GYRO%u_XSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.x_scale));
				(void)sprintf(str, "CAL_GYRO%u_YSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.y_scale));
				(void)sprintf(str, "CAL_GYRO%u_ZSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &gscale.z_scale));

				if (failed) {
					PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "gyro", i);

				} else {
					/* apply new scaling and offsets */
					config_ok = apply_gyro_calibration(h, &gscale, device_id);

					if (!config_ok) {
						PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "gyro ", i);
					}
				}

				break;
			}
		}

		if (config_ok) {
			gyro_count++;
		}
	}

	// There are less gyros than calibrations
	// reset the board calibration and fail the initial load
	if (gyro_count < gyro_cal_found_count) {

		// run through all stored calibrations and reset them
		for (unsigned i = 0; i < GYRO_COUNT_MAX; i++) {

			int32_t device_id = 0;
			(void)sprintf(str, "CAL_GYRO%u_ID", i);
			(void)param_set(param_find(str), &device_id);
		}
	}

	/* run through all accel sensors */
	for (unsigned driver_index = 0; driver_index < ACCEL_COUNT_MAX; driver_index++) {

		(void)sprintf(str, "%s%u", ACCEL_BASE_DEVICE_PATH, driver_index);

		DevHandle h;
		DevMgr::getHandle(str, h);

		if (!h.isValid()) {
			continue;
		}

		uint32_t driver_device_id = h.ioctl(DEVIOCGDEVICEID, 0);
		bool config_ok = false;

		/* run through all stored calibrations */
		for (unsigned i = 0; i < ACCEL_COUNT_MAX; i++) {
			/* initially status is ok per config */
			failed = false;

			(void)sprintf(str, "CAL_ACC%u_ID", i);
			int32_t device_id;
			failed = failed || (OK != param_get(param_find(str), &device_id));

			(void)sprintf(str, "CAL_ACC%u_EN", i);
			int32_t device_enabled = 1;
			failed = failed || (OK != param_get(param_find(str), &device_enabled));

			_accel.enabled[i] = (device_enabled == 1);

			if (failed) {
				continue;
			}

			if (driver_index == 0 && device_id > 0) {
				accel_cal_found_count++;
			}

			/* if the calibration is for this device, apply it */
			if (device_id == driver_device_id) {
				struct accel_calibration_s ascale = {};
				(void)sprintf(str, "CAL_ACC%u_XOFF", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.x_offset));
				(void)sprintf(str, "CAL_ACC%u_YOFF", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.y_offset));
				(void)sprintf(str, "CAL_ACC%u_ZOFF", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.z_offset));
				(void)sprintf(str, "CAL_ACC%u_XSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.x_scale));
				(void)sprintf(str, "CAL_ACC%u_YSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.y_scale));
				(void)sprintf(str, "CAL_ACC%u_ZSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &ascale.z_scale));

				if (failed) {
					PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "accel", i);

				} else {
					/* apply new scaling and offsets */
					config_ok = apply_accel_calibration(h, &ascale, device_id);

					if (!config_ok) {
						PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "accel ", i);
					}
				}

				break;
			}
		}

		if (config_ok) {
			accel_count++;
		}
	}

	// There are less accels than calibrations
	// reset the board calibration and fail the initial load
	if (accel_count < accel_cal_found_count) {

		// run through all stored calibrations and reset them
		for (unsigned i = 0; i < ACCEL_COUNT_MAX; i++) {

			int32_t device_id = 0;
			(void)sprintf(str, "CAL_ACC%u_ID", i);
			(void)param_set(param_find(str), &device_id);
		}
	}

	/* run through all mag sensors
	 * Because we store the device id in _mag_device_id, we need to get the id via uorb topic since
	 * the DevHandle method does not work on POSIX.
	 */
	for (unsigned topic_instance = 0; topic_instance < MAG_COUNT_MAX && topic_instance < _mag.subscription_count;
	     ++topic_instance) {

		struct mag_report report;

		if (orb_copy(ORB_ID(sensor_mag), _mag.subscription[topic_instance], &report) != 0) {
			continue;
		}

		int topic_device_id = report.device_id;
		bool is_external = report.is_external;
		_mag_device_id[topic_instance] = topic_device_id;

		// find the driver handle that matches the topic_device_id
		DevHandle h;

		for (unsigned driver_index = 0; driver_index < MAG_COUNT_MAX; ++driver_index) {

			(void)sprintf(str, "%s%u", MAG_BASE_DEVICE_PATH, driver_index);

			DevMgr::getHandle(str, h);

			if (!h.isValid()) {
				/* the driver is not running, continue with the next */
				continue;
			}

			int driver_device_id = h.ioctl(DEVIOCGDEVICEID, 0);

			if (driver_device_id == topic_device_id) {
				break; // we found the matching driver

			} else {
				DevMgr::releaseHandle(h);
			}
		}

		bool config_ok = false;

		/* run through all stored calibrations */
		for (unsigned i = 0; i < MAG_COUNT_MAX; i++) {
			/* initially status is ok per config */
			failed = false;

			(void)sprintf(str, "CAL_MAG%u_ID", i);
			int32_t device_id;
			failed = failed || (OK != param_get(param_find(str), &device_id));

			(void)sprintf(str, "CAL_MAG%u_EN", i);
			int32_t device_enabled = 1;
			failed = failed || (OK != param_get(param_find(str), &device_enabled));

			_mag.enabled[i] = (device_enabled == 1);

			if (failed) {
				continue;
			}

			/* if the calibration is for this device, apply it */
			if (device_id == _mag_device_id[topic_instance]) {
				struct mag_calibration_s mscale = {};
				(void)sprintf(str, "CAL_MAG%u_XOFF", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.x_offset));
				(void)sprintf(str, "CAL_MAG%u_YOFF", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.y_offset));
				(void)sprintf(str, "CAL_MAG%u_ZOFF", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.z_offset));
				(void)sprintf(str, "CAL_MAG%u_XSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.x_scale));
				(void)sprintf(str, "CAL_MAG%u_YSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.y_scale));
				(void)sprintf(str, "CAL_MAG%u_ZSCALE", i);
				failed = failed || (OK != param_get(param_find(str), &mscale.z_scale));

				(void)sprintf(str, "CAL_MAG%u_ROT", i);

				int32_t mag_rot;
				param_get(param_find(str), &mag_rot);

				if (is_external) {

					/* check if this mag is still set as internal, otherwise leave untouched */
					if (mag_rot < 0) {
						/* it was marked as internal, change to external with no rotation */
						mag_rot = 0;
						param_set_no_notification(param_find(str), &mag_rot);
					}

				} else {
					/* mag is internal - reset param to -1 to indicate internal mag */
					if (mag_rot != MAG_ROT_VAL_INTERNAL) {
						mag_rot = MAG_ROT_VAL_INTERNAL;
						param_set_no_notification(param_find(str), &mag_rot);
					}
				}

				/* now get the mag rotation */
				if (mag_rot >= 0) {
					// Set external magnetometers to use the parameter value
					get_rot_matrix((enum Rotation)mag_rot, &_mag_rotation[topic_instance]);

				} else {
					// Set internal magnetometers to use the board rotation
					_mag_rotation[topic_instance] = _board_rotation;
				}

				if (failed) {
					PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "mag", i);

				} else {

					/* apply new scaling and offsets */
					config_ok = apply_mag_calibration(h, &mscale, device_id);

					if (!config_ok) {
						PX4_ERR(CAL_ERROR_APPLY_CAL_MSG, "mag ", i);
					}
				}

				break;
			}
		}
	}

}
Exemple #25
0
int led_toggle(int led)
{
	return h_leds.ioctl(LED_TOGGLE, led);
}
Exemple #26
0
/**
 * Start the driver.
 *
 * This function call only returns once the driver is
 * up and running or failed to detect the sensor.
 */
int
start(enum Rotation rotation)
{
	if (g_dev != nullptr) {
		PX4_WARN("already started");
		return 0;
	}

	DevHandle h;
	DevHandle h_mag;

	/* create the driver */
	g_dev = new ACCELSIM(ACCELSIM_DEVICE_PATH_ACCEL, rotation);

	if (g_dev == nullptr) {
		PX4_ERR("failed instantiating ACCELSIM obj");
		goto fail;
	}

	if (OK != g_dev->init()) {
		PX4_ERR("failed init of ACCELSIM obj");
		goto fail;
	}

	/* set the poll rate to default, starts automatic data collection */
	DevMgr::getHandle(ACCELSIM_DEVICE_PATH_ACCEL, h);

	if (!h.isValid()) {
		PX4_WARN("open %s failed", ACCELSIM_DEVICE_PATH_ACCEL);
		goto fail;
	}

	if (h.ioctl(SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
		PX4_ERR("ioctl SENSORIOCSPOLLRATE %s failed", ACCELSIM_DEVICE_PATH_ACCEL);
		DevMgr::releaseHandle(h);
		goto fail;
	}

	DevMgr::getHandle(ACCELSIM_DEVICE_PATH_MAG, h_mag);

	/* don't fail if mag dev cannot be opened */
	if (h_mag.isValid()) {
		if (h_mag.ioctl(SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
			PX4_ERR("ioctl SENSORIOCSPOLLRATE %s failed", ACCELSIM_DEVICE_PATH_MAG);
		}

	} else {
		PX4_ERR("ioctl SENSORIOCSPOLLRATE %s failed", ACCELSIM_DEVICE_PATH_MAG);
	}

	DevMgr::releaseHandle(h);
	DevMgr::releaseHandle(h_mag);

	return 0;
fail:

	if (g_dev != nullptr) {
		delete g_dev;
		g_dev = nullptr;
	}

	PX4_ERR("driver start failed");
	return 1;
}
Exemple #27
0
int led_on(int led)
{
	return h_leds.ioctl(LED_ON, led);
}
Exemple #28
0
int led_off(int led)
{
	return h_leds.ioctl(LED_OFF, led);
}
void
Sensors::adc_poll(struct sensor_combined_s &raw)
{
	/* only read if not in HIL mode */
	if (_hil_enabled) {
		return;
	}

	hrt_abstime t = hrt_absolute_time();

	/* rate limit to 100 Hz */
	if (t - _last_adc >= 10000) {
		/* make space for a maximum of twelve channels (to ensure reading all channels at once) */
		struct adc_msg_s buf_adc[12];
		/* read all channels available */
		int ret = _h_adc.read(&buf_adc, sizeof(buf_adc));

		float bat_voltage_v = 0.0f;
		float bat_current_a = 0.0f;
		bool updated_battery = false;

		if (ret >= (int)sizeof(buf_adc[0])) {

			/* Read add channels we got */
			for (unsigned i = 0; i < ret / sizeof(buf_adc[0]); i++) {

				/* look for specific channels and process the raw voltage to measurement data */
				if (ADC_BATTERY_VOLTAGE_CHANNEL == buf_adc[i].am_channel) {
					/* Voltage in volts */
					bat_voltage_v = (buf_adc[i].am_data * _parameters.battery_voltage_scaling) * _parameters.battery_v_div;

					if (bat_voltage_v > 0.5f) {
						updated_battery = true;
					}

				} else if (ADC_BATTERY_CURRENT_CHANNEL == buf_adc[i].am_channel) {
					bat_current_a = (((float)(buf_adc[i].am_data) * _parameters.battery_current_scaling)
							 - _parameters.battery_current_offset) * _parameters.battery_a_per_v;

#ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL

				} else if (ADC_AIRSPEED_VOLTAGE_CHANNEL == buf_adc[i].am_channel) {

					/* calculate airspeed, raw is the difference from */
					float voltage = (float)(buf_adc[i].am_data) * 3.3f / 4096.0f * 2.0f;  // V_ref/4096 * (voltage divider factor)

					/**
					 * The voltage divider pulls the signal down, only act on
					 * a valid voltage from a connected sensor. Also assume a non-
					 * zero offset from the sensor if its connected.
					 */
					if (voltage > 0.4f && (_parameters.diff_pres_analog_scale > 0.0f)) {

						float diff_pres_pa_raw = voltage * _parameters.diff_pres_analog_scale - _parameters.diff_pres_offset_pa;

						_diff_pres.timestamp = t;
						_diff_pres.differential_pressure_raw_pa = diff_pres_pa_raw;
						_diff_pres.differential_pressure_filtered_pa = (_diff_pres.differential_pressure_filtered_pa * 0.9f) +
								(diff_pres_pa_raw * 0.1f);
						_diff_pres.temperature = -1000.0f;

						int instance;
						orb_publish_auto(ORB_ID(differential_pressure), &_diff_pres_pub, &_diff_pres, &instance,
								 ORB_PRIO_DEFAULT);
					}

#endif
				}
			}

			if (_parameters.battery_source == 0 && updated_battery) {
				actuator_controls_s ctrl;
				orb_copy(ORB_ID(actuator_controls_0), _actuator_ctrl_0_sub, &ctrl);
				_battery.updateBatteryStatus(t, bat_voltage_v, bat_current_a, ctrl.control[actuator_controls_s::INDEX_THROTTLE],
							     _armed, &_battery_status);

				int instance;
				orb_publish_auto(ORB_ID(battery_status), &_battery_pub, &_battery_status, &instance, ORB_PRIO_DEFAULT);
			}

			_last_adc = t;

		}
	}
}
static bool accelerometerCheck(orb_advert_t *mavlink_log_pub, unsigned instance, bool optional, bool dynamic, int &device_id, bool report_fail)
{
	bool success = true;

	char s[30];
	sprintf(s, "%s%u", ACCEL_BASE_DEVICE_PATH, instance);
	DevHandle h;
	DevMgr::getHandle(s, h);

	if (!h.isValid()) {
		if (!optional) {
			if (report_fail) {
				mavlink_and_console_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: NO ACCEL SENSOR #%u", instance);
			}
		}

		return false;
	}

	int ret = check_calibration(h, "CAL_ACC%u_ID", device_id);

	if (ret) {
		if (report_fail) {
			mavlink_and_console_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: ACCEL #%u UNCALIBRATED", instance);
		}
		success = false;
		goto out;
	}

	ret = h.ioctl(ACCELIOCSELFTEST, 0);

	if (ret != OK) {
		if (report_fail) {
			mavlink_and_console_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: ACCEL #%u TEST FAILED: %d", instance, ret);
		}
		success = false;
		goto out;
	}

#ifdef __PX4_NUTTX
	if (dynamic) {
		/* check measurement result range */
		struct accel_report acc;
		ret = h.read(&acc, sizeof(acc));

		if (ret == sizeof(acc)) {
			/* evaluate values */
			float accel_magnitude = sqrtf(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z);

			if (accel_magnitude < 4.0f || accel_magnitude > 15.0f /* m/s^2 */) {
				if (report_fail) {
					mavlink_and_console_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: ACCEL RANGE, hold still on arming");
				}
				/* this is frickin' fatal */
				success = false;
				goto out;
			}
		} else {
			if (report_fail) {
				mavlink_and_console_log_critical(mavlink_log_pub, "PREFLIGHT FAIL: ACCEL READ");
			}
			/* this is frickin' fatal */
			success = false;
			goto out;
		}
	}
#endif

out:
	DevMgr::releaseHandle(h);
	return success;
}