3 Axis Accelerometer - Data Acquisition

Howdy Everyone,

I am trying to take real-time data using a H3LIS331DL accelerometer I got from controleverything.com.

I’m currently using this code;

// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// H3LIS331DL
// This code is designed to work with the H3LIS331DL_I2CS I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Accelorometer?sku=H3LIS331DL_I2CS#tabs-0-product_tabset-2

#include <application.h>
#include <spark_wiring_i2c.h>

// H3LIS331DL I2C address is 0x18(24)
#define Addr 0x18

int xAccl = 0, yAccl =  0, zAccl = 0;
void setup()
{
// Set variable
Particle.variable("i2cdevice", "H3LIS331DL");
Particle.variable("xAccl", xAccl);
Particle.variable("yAccl", yAccl);
Particle.variable("zAccl", zAccl);

// Initialise I2C communication as MASTER
Wire.begin();
// Initialize serial communication, set baud rate = 9600
Serial.begin(9600);

// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select control register 1
Wire.write(0x20);
// Enable X, Y, Z axis, power on mode, data output rate 50Hz
Wire.write(0x27);
// Stop I2C Transmission
Wire.endTransmission();

// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select control register 4
Wire.write(0x23);
// Set full scale, +/- 100g, continuous update
Wire.write(0x00);
// Stop I2C Transmission
Wire.endTransmission();
delay(300);
}

void loop()
{
unsigned int data[6];
for(int i = 0; i < 6; i++)
{
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select data register
    Wire.write((40 + i));
    // Stop I2C Transmission
    Wire.endTransmission();
    
    // Request 1 byte of data
    Wire.requestFrom(Addr, 1);
    
    // Read 6 bytes of data
    // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
    if(Wire.available() == 1)
    {
        data[i] = Wire.read();
    }
    delay(300);
}

// Convert the data
int xAccl = ((data[1] * 256) + data[0]);
if(xAccl > 32767)
{
    xAccl -= 65536;
}
int yAccl = ((data[3] * 256) + data[2]);
if(yAccl > 32767)
{
    yAccl -= 65536;
}
int zAccl = ((data[5] * 256) + data[4]);
if(zAccl > 32767)
{
    zAccl -= 65536;
}

// Output data to dashboard
Particle.publish("Acceleration in X-Axis is :", String(xAccl));
Particle.publish("Acceleration in Y-Axis is :", String(yAccl));
Particle.publish("Acceleration in Z-Axis is :", String(zAccl));
delay(300);
}

The data is currently being output to the Dashboard but that is much too slow for taking accurate measurements in real time.

I’m looking to output the data to a file (instead of to the dashboard), and increase the data output rate (currently set to 50hz and don’t know how to change).

Any help is very very appreciated. Thank you!

-Alex

@goondry, Particle.publish() has a 1 publish/second rate limit and trying to publish! If you want to send data out at 50Hz, you will need to send the data using TCP or UDP directly.

2 Likes

@peekay123 Thank you for the reply! I am currently working on establishing the TCP connection and sending data, but I’m running into a Usage Error (5 red blinks after sos). Here is what I have done

#include "Particle.h"
#include <application.h>
#include <spark_wiring_i2c.h>
// H3LIS331DL I2C address is 0x18(24)
#define Addr 0x18

SYSTEM_MODE(MANUAL);
int serverPort = 5001;
byte server[] = {xxxxxxxxx};//server's ip address
char clientmsg0[60] ="    Data Stream Successful to o  ";
char clientmsg1[60] ="    Data Stream Successful to 1  ";
char clientmsg2[60] ="    Data Stream Successful to 2   ";
TCPClient client;

//Begin Sensor Code
int xAccl = 0, yAccl =  0, zAccl = 0;

void out(const char *s) {
  client.write( (const uint8_t*)s, strlen(s) );
}

void setup1(){
// Set variable
Particle.variable("i2cdevice", "H3LIS331DL");
Particle.variable("xAccl", xAccl);
Particle.variable("yAccl", yAccl);
Particle.variable("zAccl", zAccl);

// Initialise I2C communication as MASTER
Wire.begin();
// Initialize serial communication, set baud rate = 9600
Serial.begin(9600);

// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select control register 1
Wire.write(0x20);
// Enable X, Y, Z axis, power on mode, data output rate 50Hz
Wire.write(0x27);
//Enable X, Y, Z axis, power on mode, data output rate 1000Hz
//Wire.write(0x3F)
// Stop I2C Transmission
Wire.endTransmission();

// Start I2C Transmission
Wire.beginTransmission(Addr);
// Select control register 4
Wire.write(0x23);
// Set full scale, +/- 100g, continuous update
Wire.write(0x00);
// Stop I2C Transmission
Wire.endTransmission();
delay(300);
}

void stream() {
while (client.connected()){
    void loop(){
        unsigned int data[6];
        for(int i = 0; i < 6; i++){
            // Start I2C Transmission
            Wire.beginTransmission(Addr);
            // Select data register
            Wire.write((40 + i));
            // Stop I2C Transmission
            Wire.endTransmission();
            
            // Request 1 byte of data
            Wire.requestFrom(Addr, 1);
            
            // Read 6 bytes of data
            // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
            if(Wire.available() == 1){
                data[i] = Wire.read();
            }
            delay(300);
        }
        out(clientmsg1);
        // Convert the data
        int xAccl = ((data[1] * 256) + data[0]);
        if(xAccl > 32767){
            xAccl -= 65536;
        }
        
        int yAccl = ((data[3] * 256) + data[2]);
        if(yAccl > 32767){
            yAccl -= 65536;
        }
        
        int zAccl = ((data[5] * 256) + data[4]);
        if(zAccl > 32767){
            zAccl -= 65536;
        }
        // //Still need to scale output
    
        // // Output data
        client.printf("x Acceleration Data:",xAccl);
        client.println();
        client.printf("y Acceleration Data:",yAccl);
        client.println();
        client.printf("z Acceleration Data:",zAccl);
        client.println();
        out(clientmsg2);
    }
}
}//stream

void setup(){
  while (!WiFi.ready()) {
Particle.process();
WiFi.connect();
while(WiFi.connecting()){
    Particle.process();
}
  }// while (!WiFi.ready())
  client.connect(server, serverPort);
  stream();
}//setup()

I just have no idea what the problem is now, especially since the code compiles.

Thank you for any help,

-Alex

First, drop these includes, they are not required

#include <application.h>
#include <spark_wiring_i2c.h>

Then I’d change this

void setup() {
// replace
//  while (!WiFi.ready()) {
//    Particle.process();
//    WiFi.connect();
//    while(WiFi.connecting()){
//      Particle.process();
//    }
//  }// while (!WiFi.ready())
// with
  WiFi.connect();
  waitUntil(WiFi.ready);
  Particle.process();

  client.connect(server, serverPort);
  stream();
}//setup()

Why are you not putting the functionality of stream() (minus the wrapping while()) into loop()?
And why on earth have you got void loop() inside that while() in void stream()???

BTW, if you use int16_t instead of int you can drop that if (x > 32767) stuff.
like

 int16_t xAccl = (data[1] << 8) | data[0];

You are also hiding the global variables xAccl / yAccl / zAccl with local ones of the same name.

And I’d also only send one TCP packet like this

        client.printf("x Acceleration Data: %d\r\n"
                      "y Acceleration Data: %d\r\n"
                      "z Acceleration Data: %d\r\n"
                      ,xAccl,yAccl,zAccl);

And I’m not entirely sure that’s the way you’d read that sensor either.
I’m pretty sure you’d only set the address once and then read all 6 registes in one go.

And where is your Wire.begin() in your code? (apart from the never executed setup1())

2 Likes

@ScruffR Thank you for your comments I went through and made the changes you suggested! Most of the stuff in that code was a 4am last ditch effort to make it work, but now I think the code is much closer to working correctly.

The issue I’m running into now is the device is disconnecting from the internet every time I try to flash the code (LED blinks slowly green). Here is what I have.

#include "Particle.h"
// H3LIS331DL I2C address is 0x18(24)
#define Addr 0x18

//Just Added
SYSTEM_MODE(MANUAL);
int serverPort = 5002;
byte server[] = {192, 168, 0, 104.};//server's ip address
TCPClient client;

void send(const char *s) {
  client.write( (const uint8_t*)s, strlen(s) );
}


void setup()
{
    // Set variable
    //Particle.variable("i2cdevice", "H3LIS331DL");
    //Particle.variable("xAccl", xAccl);
    //Particle.variable("yAccl", yAccl);
    //Particle.variable("zAccl", zAccl);

    // Initialise I2C communication as MASTER
    Wire.begin();
    // Initialize serial communication, set baud rate = 9600
    Serial.begin(9600);
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select control register 1
    Wire.write(0x20);
    // Enable X, Y, Z axis, power on mode, data output rate 50Hz
    Wire.write(0x27);
    //Enable X, Y, Z axis, power on mode, data output rate 1000Hz
    //Wire.write(0x3F)
    // Stop I2C Transmission
    Wire.endTransmission();
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select control register 4
    Wire.write(0x23);
    // Set full scale, +/- 100g, continuous update
    Wire.write(0x00);
    // Stop I2C Transmission
    Wire.endTransmission();
    delay(300);
    
    //Just Added
    //From Forum
    WiFi.connect();
    waitUntil(WiFi.ready);
    Particle.process();
    
    client.connect(server, serverPort);
}

void loop()
{
    unsigned int data[6];
    for(int i = 0; i < 6; i++)
    {
        // Start I2C Transmission
        Wire.beginTransmission(Addr);
        // Select data register
        Wire.write((40 + i));
        // Stop I2C Transmission
        Wire.endTransmission();
        
        // Request 1 byte of data
        Wire.requestFrom(Addr, 1);
        
        // Read 6 bytes of data
        // xAccl lsb, xAccl msb, yAccl lsb, yAccl msb, zAccl lsb, zAccl msb
        if(Wire.available() == 1)
        {
            data[i] = Wire.read();
        }
        delay(300);
    }
    
    // Convert the data
    int16_t xAccl = ((data[1] << 8) | data[0]);
    int16_t yAccl = ((data[3] << 8) | data[1]);
    int16_t zAccl = ((data[5] * 256) + data[4]);
    
    //Still need to scale output

    // Output data to dashboard
    //Particle.publish("Acceleration in X-Axis is :", String(xAccl));
    //Particle.publish("Acceleration in Y-Axis is :", String(yAccl));
    //Particle.publish("Acceleration in Z-Axis is :", String(zAccl));
    
    char clientmsg[60];
    sprintf(clientmsg, "X Acceleration Data is %d", xAccl);
    send (clientmsg);
    
    delay(300);
}

Any ideas on why it is doing this? Thank you!

-Alex

Yes, I do know why.
You are using SYSTEM_MODE(MANUAL) but don’t connect to the Particle cloud (Particle.connect()) but even if you did, you don’t maintain the connection by regularly calling Particle.process().

OTA flashing is a Particle cloud action.

1 Like