0

I'm relatively new to embedded linux so apologies if there's a simple answer to this question or if I'm not providing the necessary information.

And if there's a concept here that I clearly don't understand please point it out as I'm doing all of this as a learning exercise.

I recently need to use GPS receiver neo-6m and 3-axis accelerator adxl345 to collect GPS data and acceleration on Raspberry Pi 3 for the project I currently working on. Individually both work fine. However when my program runs them together only one of them will receive data. Below are my code to setup both of them:

int setup_for_acc_impl(void) {
    // Create I2C bus
    int file;
    char *bus = "/dev/i2c-1";
    if ((file = open(bus, O_RDWR)) < 0) {
        printf("Failed to open the bus. \n");
        exit(1);
    }
    // Get I2C device, ADXL345 I2C address is 0x53(83)
    ioctl(file, I2C_SLAVE, 0x53);

    // Select Bandwidth rate register(0x2C)
    // Normal mode, Output data rate = 100 Hz(0x0A)
    char config[2] = {0};
    config[0] = 0x2C;
    config[1] = 0x0A;
    write(file, config, 2);
    // Select Power control register(0x2D)
    // Auto-sleep disable(0x08)
    config[0] = 0x2D;
    config[1] = 0x08;
    write(file, config, 2);
    // Select Data format register(0x31)
    // Self test disabled, 4-wire interface, Full resolution, range = +/-2g(0x08)
    config[0] = 0x31;
    config[1] = 0x08;
    write(file, config, 2);
    return file;
}

and set up for gps:

void gps_setup(void){
   int uart0_filestream = -1;
   uart0_filestream = open(PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY);

    if (uart0_filestream == -1)
    {
        printf("Failed to open the ttyS0. \n");
        exit(1);
    }
    struct termios options;
    tcgetattr(uart0_filestream, &options);
    options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
    options.c_iflag = IGNPAR;
    options.c_oflag = 0;
    options.c_lflag = 0;
    tcflush(uart0_filestream, TCIFLUSH);
    tcsetattr(uart0_filestream, TCSANOW, &options);
}

and how I read data from both of them:

//read data from adxl345,simply read
read(obu->i2c_fd, data, 6) ;
//read data from gps module
void serial_read_for_gps(char *buffer, int len)
{
    char c;
    char *b = buffer;
    int rx_length = -1;
    while(1) {
        rx_length = read(uart0_filestream, (void*)(&c), 1);

        if (rx_length <= 0) {
            //wait for messages
            printf("didn't receive any data\n");
            sleep(1);
        } else {
            if (c == '\n') {
                *b++ = '\0';
                break;
            }
            *b++ = c;
        }
    }
}

I'm not sure where the problem is coming from, any help would be great.

Thanks

  • 1
    You need to provide a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the problem. BTW since you are trying to read a line of text (terminated by a newline character) from the GPS using a serial terminal, you could simplify the code (and let the OS do the work) by using canonical mode. See https://stackoverflow.com/questions/57152937/canonical-mode-linux-serial-port/57155531#57155531 – sawdust Feb 21 '20 at 09:00
  • Is it Linux? Why don't you use the accelerometer in-kernel driver? – 0andriy Feb 21 '20 at 09:48
  • Thank you for your valuable comments,but as i say I'm relatively new to embedded linux,so I don't actually understand what is "use the accelerometer in-kernel driver?" mean, does it meaning there is no need for me to write code to do the i2c communication myself? – steven_cs_1245 Feb 21 '20 at 11:44
  • In-kernel driver provides standard interface with help of IIO framework. These links may be helpful: https://elixir.bootlin.com/linux/latest/source/drivers/iio/accel/adxl345_i2c.c (driver), https://www.kernel.org/doc/html/latest/driver-api/iio/intro.html (subsystem), https://wiki.analog.com/resources/tools-software/linux-software/libiio (libiio in user space) – 0andriy Feb 21 '20 at 22:55
  • Yes, using in-kernel driver allow you not to think about I2C communication at all. You will get values from the sensor. – 0andriy Feb 21 '20 at 22:56
  • By the way, don't forget to add @ nickname to the comments to notify the other party about your new input. – 0andriy Feb 21 '20 at 23:01
  • @0andriy thank you for your reply,I spent a lot of time figure out how to get adxl345 driver working,but somehow i still can't figure a clear way,does it mean I need to recompile the kernel with some config option about adxl345? – steven_cs_1245 Feb 22 '20 at 17:22
  • Yes, you need to enable IIO subsystem and driver itself. Usually you may perform this via running `make nconfig` in the kernel source tree before building. – 0andriy Feb 22 '20 at 18:58

0 Answers0