IMU Sensors Integration and Visualization in 3D- Arduinp Project

  • calendar_today  Dec, 16 2024
  • visibility  54

The goal of this project is to integrate an accelerometer (ADXL345) and a magnetometer (HMC5883L) using I2C communication with an Arduino. The data from these sensors will be transmitted to a Processing-based visualization tool. The accelerometer measures linear acceleration along three axes (X, Y, Z), and the magnetometer measures the Earth's magnetic field along these axes. The data is used to visualize the sensor readings in 3D space and create a compass-like display.


Hardware Components:

  1. ADXL345 Accelerometer:
    • I2C address: 0x53
    • Measures acceleration on the X, Y, and Z axes.
    • Range: ±4g (configured in the code).
  2. HMC5883L Magnetometer:
    • I2C address: 0x1E
    • Measures the magnetic field on the X, Y, and Z axes.
    • Used to simulate a compass for orientation.
  3. Arduino (Controller):
    • Communicates with both the accelerometer and magnetometer via I2C.
    • Sends sensor data to a PC over serial communication.
  4. Processing (Visualization):
    • Displays sensor data visually on a 3D canvas.
    • Provides real-time 3D visualizations for the accelerometer and magnetometer data.





Software Components:

  1. Arduino Code:
    • Configures and reads data from the ADXL345 accelerometer and HMC5883L magnetometer using I2C.
    • Calibrates the accelerometer by averaging multiple readings.
    • Sends the accelerometer and magnetometer data to the serial port in CSV format.
  1. #include <Wire.h>

  2. #define SENSOR 0x53         // ADXL345 I2C address
  3. #define MAGNETOMETER 0x1E   // HMC5883L I2C address

  4. #define POWER_CTL 0x2D
  5. #define DATA_FORMAT 0x31
  6. #define DATA_REG 0x32

  7. int16_t xOffset = 0, yOffset = 0, zOffset = 0;

  8. void setup() {
  9.   Wire.begin();
  10.   Serial.begin(9600);

  11.   // Initialize ADXL345
  12.   Wire.beginTransmission(SENSOR);
  13.   Wire.write(POWER_CTL);
  14.   Wire.write(0x08);  // Set to measurement mode
  15.   Wire.endTransmission();

  16.   Wire.beginTransmission(SENSOR);
  17.   Wire.write(DATA_FORMAT);
  18.   Wire.write(0x01);  // Full resolution, +/-4g
  19.   Wire.endTransmission();

  20.   // Initialize Magnetometer
  21.   setupMagnetometer();

  22.   Serial.println("Sensor initialized!");
  23.   calibrate();
  24. }

  25. void loop() {
  26.   // Read accelerometer values
  27.   int16_t ax = readAxis(0) - xOffset;
  28.   int16_t ay = readAxis(2) - yOffset;
  29.   int16_t az = readAxis(4) - zOffset;

  30.   // Read magnetometer values
  31.   int16_t mx, my, mz;
  32.   readMagnetometer(mx, my, mz);

  33.   // Send accelerometer and magnetometer data
  34.   Serial.print(ax)Serial.print(",");
  35.   Serial.print(ay)Serial.print(",");
  36.   Serial.print(az)Serial.print(",");
  37.   Serial.print(mx)Serial.print(",");
  38.   Serial.print(my)Serial.print(",");
  39.   Serial.println(mz);

  40.   delay(100);
  41. }

  42. int16_t readAxis(uint8_t offset) {
  43.   Wire.beginTransmission(SENSOR);
  44.   Wire.write(DATA_REG + offset);
  45.   Wire.endTransmission();
  46.   Wire.requestFrom(SENSOR, 2);
  47.   if (Wire.available() == 2) {
  48.     return (Wire.read() | (Wire.read() << 8));
  49.   }
  50.   return 0;
  51. }

  52. void setupMagnetometer() {
  53.   Wire.beginTransmission(MAGNETOMETER);
  54.   Wire.write(0x00);  // Configuration Register A
  55.   Wire.write(0x70);  // 8 samples averaged, 15 Hz data output rate
  56.   Wire.endTransmission();

  57.   Wire.beginTransmission(MAGNETOMETER);
  58.   Wire.write(0x01);  // Configuration Register B
  59.   Wire.write(0xA0);  // Gain configuration
  60.   Wire.endTransmission();

  61.   Wire.beginTransmission(MAGNETOMETER);
  62.   Wire.write(0x02);  // Mode Register
  63.   Wire.write(0x00);  // Continuous measurement mode
  64.   Wire.endTransmission();
  65. }

  66. void readMagnetometer(int16_t &mxint16_t &myint16_t &mz) {
  67.   mx = readMagnetometerAxis(0x03);
  68.   my = readMagnetometerAxis(0x05);
  69.   mz = readMagnetometerAxis(0x07);
  70. }

  71. int16_t readMagnetometerAxis(uint8_t reg) {
  72.   Wire.beginTransmission(MAGNETOMETER);
  73.   Wire.write(reg);
  74.   Wire.endTransmission();
  75.   Wire.requestFrom(MAGNETOMETER, 2);
  76.   if (Wire.available() == 2) {
  77.     return (Wire.read() << 8) | Wire.read();
  78.   }
  79.   return 0;
  80. }

  81. void calibrate() {
  82.   Serial.println("Calibrating... Keep the device flat and still.");
  83.   int32_t xSum = 0, ySum = 0, zSum = 0;
  84.   int samples = 100;

  85.   for (int i = 0; i < samples; i++) {
  86.     xSum += readAxis(0);
  87.     ySum += readAxis(2);
  88.     zSum += readAxis(4);
  89.     delay(10);
  90.   }

  91.   xOffset = xSum / samples;
  92.   yOffset = ySum / samples;
  93.   zOffset = (zSum / samples) - 256;

  94.   Serial.println("Calibration complete!");
  95. }

Processing Code:


  • Reads the sensor data from the serial port.
  • Maps accelerometer values to rotate a 3D box based on X and Y acceleration.
  • Uses magnetometer data to simulate a compass, rotating an arrow in the direction of the magnetic field.

  import processing.serial.*;

  Serial myPort;

  float ax = 0, ay = 0, az = 0;  // Accelerometer values

  float mx = 0, my = 0, mz = 0;  // Magnetometer values

  void setup() {

    size(600, 600, P3D);

    println(Serial.list());

    String portName = Serial.list()[0];  // Adjust port if necessary

    myPort = new Serial(this, portName, 9600);

    myPort.bufferUntil('\n');

  }

  void draw() {

    background(200);

    lights();

    // Read serial data

    if (myPort.available() > 0) {

      String data = myPort.readStringUntil('\n');

      if (data != null) {

        println(data);

        String[] values = split(trim(data), ',');

        if (values.length == 6) {  // Ensure correct data length

          ax = float(values[0]);

          ay = float(values[1]);

          az = float(values[2]);

          mx = float(values[3]);

          my = float(values[4]);

          mz = float(values[5]);

        }

      }

    }

    // Map accelerometer to rotations

    float rotX = map(ax, 256, -256, -PI, PI);

    float rotY = map(ay, 256, -256, -PI, PI);

    // Draw accelerometer visualization

    pushMatrix();

    translate(width / 2, height / 2, 0);

    rotateX(rotX);

Orders

  • Addresses
  • Personal Info