aerofc: add some fixes to adc driver

- Other channels are irrelevant since they aren't physically
    connected. Avoid the I2C transaction to get invalid data
  - Port the driver to use only one address, as it should be
  - Minor changes here and there
  - Add test() method to read the latest value - helpful during
    debugging.
This commit is contained in:
Lucas De Marchi
2016-12-26 16:11:33 +01:00
committed by Lorenz Meier
parent 53f2c1eb19
commit 0341af4858
2 changed files with 72 additions and 52 deletions
+71 -51
View File
@@ -47,12 +47,8 @@
#include <systemlib/err.h>
#define SLAVE_ADDR 0x50
#define ENABLE_ADC_REG 0x00
#define ADC_CHANNEL_1_REG 0x01
#define ADC_CHANNEL_2_REG 0x02
#define ADC_CHANNEL_3_REG 0x03
#define ADC_CHANNEL_4_REG 0x04
#define ADC_CHANNEL_5_REG 0x05
#define ADC_ENABLE_REG 0x00
#define ADC_CHANNEL_REG 0x05
#define MAX_CHANNEL 5
// 10Hz
@@ -77,12 +73,38 @@ private:
static void cycle_trampoline(void *arg);
struct work_s _work;
adc_msg_s _samples[MAX_CHANNEL];
pthread_mutex_t _samples_mutex;
adc_msg_s _sample;
pthread_mutex_t _sample_mutex;
};
static AEROFC_ADC *instance = nullptr;
static void test()
{
int fd = open(ADC0_DEVICE_PATH, O_RDONLY);
if (fd < 0) {
err(1, "can't open ADC device");
}
adc_msg_s data[MAX_CHANNEL];
ssize_t count = read(fd, data, sizeof(data));
if (count < 0) {
errx(1, "read error");
}
unsigned channels = count / sizeof(data[0]);
for (unsigned j = 0; j < channels; j++) {
printf("%d: %u ", data[j].am_channel, data[j].am_data);
}
printf("\n");
exit(0);
}
int aerofc_adc_main(int argc, char *argv[])
{
if (argc < 2) {
@@ -107,6 +129,9 @@ int aerofc_adc_main(int argc, char *argv[])
instance = nullptr;
}
} else if (!strcmp(argv[1], "test")) {
test();
} else {
warn("Action not supported");
}
@@ -115,13 +140,11 @@ int aerofc_adc_main(int argc, char *argv[])
}
AEROFC_ADC::AEROFC_ADC(uint8_t bus) :
I2C("AEROFC_ADC", ADC0_DEVICE_PATH, bus, 0, 400000)
I2C("AEROFC_ADC", ADC0_DEVICE_PATH, bus, SLAVE_ADDR, 400000),
_sample{}
{
for (unsigned i = 0; i < MAX_CHANNEL; i++) {
_samples[i].am_channel = i + 1;
}
pthread_mutex_init(&_samples_mutex, NULL);
_sample.am_channel = 1;
pthread_mutex_init(&_sample_mutex, NULL);
}
AEROFC_ADC::~AEROFC_ADC()
@@ -145,23 +168,27 @@ int AEROFC_ADC::init()
int AEROFC_ADC::probe()
{
uint8_t buffer[1];
uint8_t buffer[2];
int ret;
_retries = 3;
set_address(SLAVE_ADDR | ENABLE_ADC_REG);
buffer[0] = 1;
ret = transfer(buffer, sizeof(buffer), NULL, 0);
/* Enable ADC */
buffer[0] = ADC_ENABLE_REG;
buffer[1] = 0x01;
ret = transfer(buffer, 2, NULL, 0);
if (ret != PX4_OK) {
goto error;
}
buffer[0] = 0;
ret = transfer(0, 0, buffer, sizeof(buffer));
usleep(10000);
if (ret != PX4_OK || buffer[0] != 1) {
/* Read ADC value */
buffer[0] = ADC_CHANNEL_REG;
ret = transfer(buffer, 1, buffer, 2);
if (ret != PX4_OK) {
goto error;
}
@@ -172,59 +199,52 @@ error:
return -EIO;
}
int
AEROFC_ADC::ioctl(file *filp, int cmd, unsigned long arg)
int AEROFC_ADC::ioctl(file *filp, int cmd, unsigned long arg)
{
return -ENOTTY;
}
ssize_t
AEROFC_ADC::read(file *filp, char *buffer, size_t len)
ssize_t AEROFC_ADC::read(file *filp, char *buffer, size_t len)
{
if (len > sizeof(_samples)) {
len = sizeof(_samples);
if (len < sizeof(_sample)) {
return -ENOSPC;
}
pthread_mutex_lock(&_samples_mutex);
memcpy(buffer, _samples, len);
pthread_mutex_unlock(&_samples_mutex);
if (len > sizeof(_sample)) {
len = sizeof(_sample);
}
pthread_mutex_lock(&_sample_mutex);
memcpy(buffer, &_sample, len);
pthread_mutex_unlock(&_sample_mutex);
return len;
}
void
AEROFC_ADC::cycle_trampoline(void *arg)
void AEROFC_ADC::cycle_trampoline(void *arg)
{
AEROFC_ADC *dev = reinterpret_cast<AEROFC_ADC * >(arg);
dev->cycle();
}
void
AEROFC_ADC::cycle()
void AEROFC_ADC::cycle()
{
int32_t value[MAX_CHANNEL];
uint8_t buffer[2];
int ret;
for (uint8_t i = 0; i < MAX_CHANNEL; i++) {
int ret;
uint8_t buffer[2];
buffer[0] = ADC_CHANNEL_REG;
ret = transfer(buffer, 1, buffer, sizeof(buffer));
set_address(SLAVE_ADDR | (ADC_CHANNEL_1_REG + i));
ret = transfer(0, 0, buffer, sizeof(buffer));
if (ret != PX4_OK) {
warn("Error reading channel %u", i + 1);
}
value[i] = (int32_t)(buffer[0] | (buffer[1] << 8));
if (ret != PX4_OK) {
warn("Error reading sample");
return;
}
pthread_mutex_lock(&_samples_mutex);
pthread_mutex_lock(&_sample_mutex);
for (uint8_t i = 0; i < MAX_CHANNEL; i++) {
_samples[i].am_data = value[i];
}
_sample.am_data = (buffer[0] | (buffer[1] << 8));
pthread_mutex_unlock(&_samples_mutex);
pthread_mutex_unlock(&_sample_mutex);
work_queue(HPWORK, &_work, (worker_t)&AEROFC_ADC::cycle_trampoline, this,
CYCLE_TICKS_DELAY);
+1 -1
View File
@@ -99,7 +99,7 @@
* ADC defines just to not break sensors.cpp build, battery voltage and current
* will be read in another way in future.
*/
#define ADC_BATTERY_VOLTAGE_CHANNEL 5
#define ADC_BATTERY_VOLTAGE_CHANNEL 1
#define ADC_BATTERY_CURRENT_CHANNEL ((uint8_t)(-1))
#define DIRECT_PWM_OUTPUT_CHANNELS 1