ADXL345 Accelerometer


50 posts   Page 1 of 2   1, 2
by mjk » Thu Jul 26, 2012 2:45 pm
Has anyone managed to get one of these accelerometers working on their Pi?

According to the manufacturers website (http://wiki.analog.com/resources/tools-software/linux-drivers/input-misc/adxl345), the driver has been in the mainline Linux kernel for a while, and I can load the driver module fine. But the accelerometer just isn't being recognised as being there when the module is loaded.

It must be possible, as this person seems to have got it working - http://www.raspberrypi.org/phpBB3/viewtopic.php?p=92023#p92023.

I'm trying this on the new Raspbian distro, but I've had a go on the earlier ones as well with no success.
Posts: 2
Joined: Fri Jul 20, 2012 1:45 pm
by engineerbynight » Fri Jul 27, 2012 11:04 pm
I'm toying with the Analog Linux devices drivers as well, but you're one step ahead of me... I can't figure out how to install and use the drivers.

I have successfully interfaced with an ADXL362, without using a Analog Devices Linux driver:
http://www.instructables.com/id/Preliminary-SPI-on-the-Pi-Communicating-with-a-/

If you're able to guide me on how to install and use drivers, I could see if I can get it to work, and let you know if I have success.
User avatar
Posts: 3
Joined: Fri Jul 27, 2012 2:32 am
by rgetz » Fri Jul 27, 2012 11:37 pm
Analog Devices (the manufacture of the ADXL345) provides free Linux (any platform/CPU) support for their drivers/parts on their forums.[*] - Did you try asking there?

http://ez.analog.com/community/linux-device-drivers/linux-software-drivers

We have the driver working on lots of Linux platforms (including ARM11) - I'm sure we can work through any Raspberry Pi specific issues that you might have.

-Robin

[*] Disclaimer - I work for ADI, and work on the team which does the Linux drivers.
Posts: 2
Joined: Fri Jul 27, 2012 11:32 pm
by pygmy_giant » Sat Jul 28, 2012 9:37 pm
I'm thinking of using this via SPI and these drivers: http://www.open.com.au/mikem/bcm2835/index.html
Posts: 1569
Joined: Sun Mar 04, 2012 12:49 am
by mjk » Sun Jul 29, 2012 7:07 pm
Robin - I haven't tried posting anything there yet, it seems like there might just be something obvious I'm missing. If I understand the wiki page about the drivers for this accelerometer, getting it to work should just be a case of hooking up the device to the right GPIO pins on the Pi and then loading the adxl34x driver, correct?
Actually, I upon re-reading, I suspect I'm going to have to compile the kernel myself and configure it to enable these particular drivers. Perhaps this is the obvious bit I'm missing?
Posts: 2
Joined: Fri Jul 20, 2012 1:45 pm
by messinwu » Thu Aug 16, 2012 11:10 pm
I guess this thread is about a month old, but I wanted to chime in and say that I'm attempting to get this chip working as well. I've not been successful yet though. I don't really know what I'm doing I guess. I tried with I2C, but i2c-detect -y 0 found nothing. Every time I tried to initiate the device, dmesg says "No IRQ?" and nothing shows up in the inputs.

I also tried the SPI interface, but am not sure how to physically hook it up to the Pi, and not sure what to do software-wise.

I don't even care if I don't use a nice API and just get raw data, I'd be happy to get something. I tried a "cat /dev/spidev0.0" but it says the message is too long. I tried to do "minicom -D /dev/spidev0.0", but just junk comes up on the screen, so perhaps I have the wrong parameters.

Has anyone got this device to work? It'd be nice to detect free-fall for my balloon project.
Posts: 17
Joined: Wed Aug 08, 2012 1:33 pm
by joan » Fri Aug 17, 2012 8:32 am
I'm using http://www.ebay.co.uk/itm/3-5v-ADXL345-Digital-3-Axis-Acceleration-of-Gravity-Tilt-Module-GY-291-/221074086394.

Works fine with I2C on the raspberry.

You need to enable the i2c module
sudo modprobe i2c-dev
sudo chmod o+rw /dev/i2c*

The module I use needs CS tied to VCC and SDO tied to ground.

I use the following code to read a SRF02 and the ADXL345 on the same I2C bus.
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/i2c-dev.h>

#define SRF02_I2C_ADDR 0x70
#define ADXL345_I2C_ADDR 0x53

void selectDevice(int fd, int addr, char * name)
{
   if (ioctl(fd, I2C_SLAVE, addr) < 0)
   {
      fprintf(stderr, "%s not present\n", name);
      //exit(1);
   }
}

void writeToDevice(int fd, int reg, int val)
{
   char buf[2];
   buf[0]=reg; buf[1]=val;
   if (write(fd, buf, 2) != 2)
   {
      fprintf(stderr, "Can't write to ADXL345\n");
      //exit(1);
   }
}

int main(int argc, char **argv)
{
   unsigned int range;
   int count, b;
   short x, y, z;
   float xa, ya, za;
   int fd;
   unsigned char buf[16];
   
   if ((fd = open("/dev/i2c-0", O_RDWR)) < 0)
   {
      // Open port for reading and writing
      fprintf(stderr, "Failed to open i2c bus\n");
      exit(1);
   }
   
   /* initialise ADXL345 */

   selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

   writeToDevice(fd, 0x2d, 0);
   writeToDevice(fd, 0x2d, 16);
   writeToDevice(fd, 0x2d, 8);
   writeToDevice(fd, 0x31, 0);
   writeToDevice(fd, 0x31, 11);

   while (1)
   {   
      /* select SRF02 */

      selectDevice(fd, SRF02_I2C_ADDR, "SRF02");

      buf[0]=0; buf[1]=81;
      if ((write(fd, buf, 2)) != 2)
      {
         fprintf(stderr, "Can't write to SRF02\n");
         //exit(1);
      }
   
      usleep(100000);  // wait long enough to ensure ping
   
      buf[0] = 0;
      if ((write(fd, buf, 1)) != 1)
      {
         fprintf(stderr, "Can't write to SRF02\n");
         //exit(1);
      }
   
      if (read(fd, buf, 4) != 4)
      {
         fprintf(stderr, "Can't read from SRF02\n");
         //exit(1);
      }
      else
      {
         range = buf[2]<<8 | buf[3];
         printf("%3u ", range);
      }

      /* select ADXL345 */

      selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

      buf[0] = 0x32;
   
      if ((write(fd, buf, 1)) != 1)
      {
         // Send the register to read from
         fprintf(stderr, "Error writing to i2c slave\n");
         //exit(1);
      }
   
      if (read(fd, buf, 6) != 6)
      {
         //  X, Y, Z accelerations

         fprintf(stderr, "Unable to read from ADXL345\n");
         //exit(1);
      }
      else
      {
         x = buf[1]<<8| buf[0];
         y = buf[3]<<8| buf[2];
         z = buf[5]<<8| buf[4];
         xa = (90.0 / 256.0) * (float) x;
         ya = (90.0 / 256.0) * (float) y;
         za = (90.0 / 256.0) * (float) z;
         //printf("x=%d, y=%d, z=%d\n", x, y, z);
         printf("%4.0f %4.0f %4.0f\n", xa, ya, za);
         //for (b=0; b<6; b++) printf("%02x ",buf[b]); printf("\n");
      }
      usleep(900000);
   }
   
   return 0;
}
User avatar
Posts: 5978
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by messinwu » Fri Aug 17, 2012 11:19 am
Thanks Joan!

Actually, I finally got somewhere late last night, after figuring out that you need to connect the CS pin to 3.3v as well as connecting the VIN (? i think that's what it's labeled, the obvious one) to 3.3v to put the module in I2C mode.

Then, I was able to send the 0-16-8 values to turn it on with i2cset, then get a value from registers 0x32-0x38 (I think, going from memory this morning, not near the Pi). But your code in C looks much better, I'll give it a try when I get a chance later today.

Thanks a bunch!!
Posts: 17
Joined: Wed Aug 08, 2012 1:33 pm
by messinwu » Sat Aug 18, 2012 12:58 pm
Joan - your code works great! I had to remove the bit about the other device since currently I only have one device on I2C, but thank you!! Would you be able to offer any hints about determining free fall, activity or inactivity? I see the register values in the datasheet, but I'm new to C programming and kind of lost as to how to implement what's needed in the script. I push in the right direction would be much appreciated, if you're able.
Posts: 17
Joined: Wed Aug 08, 2012 1:33 pm
by joan » Sat Aug 18, 2012 1:07 pm
I know a little C but apart from that I probably know less than you regarding the ADXL-345.

You mention a script which needs implementing. Is it something you can post? If so I may be able to comment on how easy it would be to implement.
User avatar
Posts: 5978
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by messinwu » Sat Aug 18, 2012 1:48 pm
Oops, by 'script' I meant your C code you posted, I'm trying to tweak it to utilize the other features of the ADXL345. Apparently, there is a register to turn on the activity/inactivity detection, then I'm supposing it generates a value on another register when such is detected. There's also threshold values to set as well, which is where I get a little lost.

I've always been the kind of coder who can look at existing code to understand what's going on, then take it from there. (Novice)

It's a cool gadget for sure, now that I have data being outputted from your code (which appear to be angles of each axis), I'm not sure how to actually USE the data in a visual sense. What fun though! :)

I did tweak it slightly to make it update quicker (changed the sleep value to 100000), and made the number always appear on the same line, instead of on the next line. So, as the sensor moves, the numbers change rapidly with it, based on its movement.

I've also looked at articles and videos where this sensor used in balancing projects and even a ball which takes panoramic photos when thrown up in the air, just before it starts to fall back down.

I will be getting a 3-axis magnetometer, vibration sensor, and barometric pressure sensor in the mail any day now also. What fun indeed! I will post what I can when I get those working, to help future users with those sensors on the Pi.
Posts: 17
Joined: Wed Aug 08, 2012 1:33 pm
by joan » Sat Aug 18, 2012 2:10 pm
OK, I understand. I'm waiting for a small servo to replace one which has stripped its gears (well I suppose I stripped the gears by forcing it to move against its will).

When that arrives I'll bung it into my pan/tilt head and start looking at the ADXL-345 more seriously. I want to see how reliably I can use servos and feedback from the ADXL-345 to maintain a level plane.

This pdf has some code examples which may be more to your taste.
http://www.analog.com/static/imported-files/application_notes/AN-1023.pdf

I haven't bothered to connect the interrupt lines on the module I bought as I expect I2C will be fast enough for my needs.
User avatar
Posts: 5978
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by messinwu » Sat Aug 18, 2012 2:18 pm
That sounds really interesting, I think it should work for what you're talking about, based on my observations of what other people have done with this sensor. Be sure to post when you get it going, please!
Posts: 17
Joined: Wed Aug 08, 2012 1:33 pm
by joan » Sat Aug 18, 2012 3:59 pm
Just to clarify. When I say level plane I'm using the mathematical sense, not the jumbo jet sense.
User avatar
Posts: 5978
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by messinwu » Sat Aug 18, 2012 4:14 pm
Yeah I think I know what you mean, you're trying to keep something level with movement utilizing the ADXL345's measurements as it's moving... no?
Posts: 17
Joined: Wed Aug 08, 2012 1:33 pm
by joan » Sat Aug 18, 2012 4:23 pm
Yes.
User avatar
Posts: 5978
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by garym1957 » Mon Sep 17, 2012 5:55 am
Hey good people. I'm trying to duplicate the results from the following link (scroll WAY down), they're interfacing the breakout board to a Raspberry Pi. Can anyone guess the pinout on the RPi GPIO header? They told you what lines to use, SCL, SDA, INT1, blaj blah, but they didnt mention where to connect those lines on the RPi. Anyone have a proper schematic for this?
http://wiki.analog.com/resources/tools-software/linux-drivers/input-misc/adxl345

Thanks very much!
Posts: 11
Joined: Fri Aug 24, 2012 6:04 am
by kaos » Mon Sep 17, 2012 12:59 pm
Can anyone guess the pinout on the RPi GPIO header?


No need to guess: http://elinux.org/Rpi_Low-level_peripherals ;)

--
Best regards,
Kári.
Posts: 102
Joined: Mon Mar 26, 2012 8:14 pm
by messinwu » Mon Sep 17, 2012 1:03 pm
Personally, I couldn't get the driver to function at all. Maybe it's the distro I'm using, not sure. I ended up just using a C program (earlier in this thread) to get data from the sensor.
Posts: 17
Joined: Wed Aug 08, 2012 1:33 pm
by garym1957 » Mon Sep 17, 2012 2:34 pm
Thank you Kari. So ...

Which wire is the THIRD wire? On the Accelerometer BOB its labeled "INT1", and constitutes the third of the three data connections. SCL and SDO are labeled.

Did you look at the picture I posted? the author chose to use all black wires for all connections except for VCC.

If anyone has actually gotten this to work, could you please post how to wire it?
Posts: 11
Joined: Fri Aug 24, 2012 6:04 am
by kaos » Mon Sep 17, 2012 7:43 pm
From the picture, it seems to be connected to P1-11, which is GPIO17. It seems to be an interrupt signal of some kind, and I expect the driver polls this pin when waiting for interrupt. Note that I haven't tried this module or driver.

--
Best regards,
Kári.
Posts: 102
Joined: Mon Mar 26, 2012 8:14 pm
by pablo_paul » Sun Sep 30, 2012 2:41 pm
Hi all,

How do i remove the SR02 from the above code? I've just started learning to program in c (very hard) and all the mods i make result in a compile error. Everything else is setup and i can see the device on the bus and have read data from another device using some adafruit python code so i know it's all working. Help.

Code repeated

Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/i2c-dev.h>

#define SRF02_I2C_ADDR 0x70
#define ADXL345_I2C_ADDR 0x53

void selectDevice(int fd, int addr, char * name)
{
   if (ioctl(fd, I2C_SLAVE, addr) < 0)
   {
      fprintf(stderr, "%s not present\n", name);
      //exit(1);
   }
}

void writeToDevice(int fd, int reg, int val)
{
   char buf[2];
   buf[0]=reg; buf[1]=val;
   if (write(fd, buf, 2) != 2)
   {
      fprintf(stderr, "Can't write to ADXL345\n");
      //exit(1);
   }
}

int main(int argc, char **argv)
{
   unsigned int range;
   int count, b;
   short x, y, z;
   float xa, ya, za;
   int fd;
   unsigned char buf[16];
   
   if ((fd = open("/dev/i2c-0", O_RDWR)) < 0)
   {
      // Open port for reading and writing
      fprintf(stderr, "Failed to open i2c bus\n");
      exit(1);
   }
   
   /* initialise ADXL345 */

   selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

   writeToDevice(fd, 0x2d, 0);
   writeToDevice(fd, 0x2d, 16);
   writeToDevice(fd, 0x2d, 8);
   writeToDevice(fd, 0x31, 0);
   writeToDevice(fd, 0x31, 11);

   while (1)
   {   
      /* select SRF02 */

      selectDevice(fd, SRF02_I2C_ADDR, "SRF02");

      buf[0]=0; buf[1]=81;
      if ((write(fd, buf, 2)) != 2)
      {
         fprintf(stderr, "Can't write to SRF02\n");
         //exit(1);
      }
   
      usleep(100000);  // wait long enough to ensure ping
   
      buf[0] = 0;
      if ((write(fd, buf, 1)) != 1)
      {
         fprintf(stderr, "Can't write to SRF02\n");
         //exit(1);
      }
   
      if (read(fd, buf, 4) != 4)
      {
         fprintf(stderr, "Can't read from SRF02\n");
         //exit(1);
      }
      else
      {
         range = buf[2]<<8 | buf[3];
         printf("%3u ", range);
      }

      /* select ADXL345 */

      selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

      buf[0] = 0x32;
   
      if ((write(fd, buf, 1)) != 1)
      {
         // Send the register to read from
         fprintf(stderr, "Error writing to i2c slave\n");
         //exit(1);
      }
   
      if (read(fd, buf, 6) != 6)
      {
         //  X, Y, Z accelerations

         fprintf(stderr, "Unable to read from ADXL345\n");
         //exit(1);
      }
      else
      {
         x = buf[1]<<8| buf[0];
         y = buf[3]<<8| buf[2];
         z = buf[5]<<8| buf[4];
         xa = (90.0 / 256.0) * (float) x;
         ya = (90.0 / 256.0) * (float) y;
         za = (90.0 / 256.0) * (float) z;
         //printf("x=%d, y=%d, z=%d\n", x, y, z);
         printf("%4.0f %4.0f %4.0f\n", xa, ya, za);
         //for (b=0; b<6; b++) printf("%02x ",buf[b]); printf("\n");
      }
      usleep(900000);
   }
   
   return 0;
}
Posts: 8
Joined: Mon Sep 10, 2012 7:22 pm
by joan » Sun Sep 30, 2012 2:56 pm
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/i2c-dev.h>

#define ADXL345_I2C_ADDR 0x53

    void selectDevice(int fd, int addr, char * name)
    {
       if (ioctl(fd, I2C_SLAVE, addr) < 0)
       {
          fprintf(stderr, "%s not present\n", name);
       }
    }

    void writeToDevice(int fd, int reg, int val)
    {
       char buf[2];
       buf[0]=reg; buf[1]=val;
       if (write(fd, buf, 2) != 2)
       {
          fprintf(stderr, "Can't write to device\n");
       }
    }

    int main(int argc, char **argv)
    {
       unsigned int range;
       int count, b;
       short x, y, z;
       float xa, ya, za;
       int fd;
       unsigned char buf[16];
       
       if ((fd = open("/dev/i2c-0", O_RDWR)) < 0)
       {
          // Open port for reading and writing

          fprintf(stderr, "Failed to open i2c bus\n");

          exit(1);
       }
       
       /* initialise ADXL345 */

       selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

       writeToDevice(fd, 0x2d, 0);
       writeToDevice(fd, 0x2d, 16);
       writeToDevice(fd, 0x2d, 8);
       writeToDevice(fd, 0x31, 0);
       writeToDevice(fd, 0x31, 11);

       while (1)
       {   

          /* select ADXL345 */

          selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

          buf[0] = 0x32;
       
          if ((write(fd, buf, 1)) != 1)
          {
             // Send the register to read from

             fprintf(stderr, "Error writing to i2c slave\n");
          }
       
          if (read(fd, buf, 6) != 6)
          {
             //  X, Y, Z accelerations

             fprintf(stderr, "Unable to read from ADXL345\n");
          }
          else
          {
             x = buf[1]<<8| buf[0];
             y = buf[3]<<8| buf[2];
             z = buf[5]<<8| buf[4];
             xa = (90.0 / 256.0) * (float) x;
             ya = (90.0 / 256.0) * (float) y;
             za = (90.0 / 256.0) * (float) z;
             printf("%4.0f %4.0f %4.0f\n", xa, ya, za);
          }
          usleep(900000);
       }
       
       return 0;
    }
User avatar
Posts: 5978
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK
by gordon@drogon.net » Sun Sep 30, 2012 6:13 pm
pygmy_giant wrote:I'm thinking of using this via SPI and these drivers: http://www.open.com.au/mikem/bcm2835/index.html


SPI is built into the kernel now. It's been stable for some time - months. No need to poke hatdware with that "driver".

-Gordon
--
Gordons projects: https://projects.drogon.net/
User avatar
Posts: 1536
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
by rgetz » Mon Oct 29, 2012 4:59 am
Posts: 2
Joined: Fri Jul 27, 2012 11:32 pm