For a project I've used few accelerometers from different suppliers all based on ADXL345
1. GY-291
This module has all pins on one side, it is very sensitive ( more then others) and looks like is not calibrated at all. Price is 2.27 USD with free shipping.
2. ADXL345 module
Pins are distributed on both sides and has two pins for power on if you want to use it with 5V and one for 3.3V so it can be used with arduino or esp8266. It is well calibrated and well build. It costs more then the GY-291 with few cents but for my projects is very good. At this time the price is 2.72 USD with free shipping.
3. SparkFun
Most expensive one 17.95 USD shipping not included is well built, and calibrated. Of course for its price you can buy at least 6 modules like this one.
All the modules have the advantages of the ADXL345 chip like tap, double tap, free fall, two interrupts, range up to 16G
At the end top is 2, 3, 1.
Some code for ESP8266 to play with.
/* ADXL345
* i2c bus SDA = GPIO0; SCL = GPIO2
*
* Just a little test message. Go to http://192.168.4.1 in a web browser
* connected to this access point to see it.
* USER: admin PASSWOR: admin
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
//ADXL345
#include <Wire.h>
/* Set these to your desired credentials. */
const char *ssid = "ESPap";
const char *password = "12345678";
ESP8266WebServer server(80);
#define DEBUG true
#define Serial if(DEBUG)Serial
#define DEVICE (0x53) // Device address as specified in data sheet
float last_value = 0;
float prelast_value = 0;
int show_count = 0;
int trigger_count = 0;
float trigger_value = -5; //DEFAULT VALUE ???
float current_value = 0;
#define ADXL345_MG2G_MULTIPLIER (0.004)
#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH)
#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */
byte _buff[6];
char POWER_CTL = 0x2D; //Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32; //X-Axis Data 0
char DATAX1 = 0x33; //X-Axis Data 1
//char DATAY0 = 0x34; //Y-Axis Data 0
//char DATAY1 = 0x35; //Y-Axis Data 1
//char DATAZ0 = 0x36; //Z-Axis Data 0
//char DATAZ1 = 0x37; //Z-Axis Data 1
float max_x=0;
float min_x=0;
float cal_x=0;
float x = 0;
//Check if header is present and correct
bool is_authentified(){
Serial.println("Enter is_authentified");
if (server.hasHeader("Cookie")){
Serial.print("Found cookie: ");
String cookie = server.header("Cookie");
Serial.println(cookie);
if (cookie.indexOf("ESPSESSIONID=1") != -1) {
Serial.println("Authentification Successful");
return true;
}
}
Serial.println("Authentification Failed");
return false;
}
//root page can be accessed only if authentification is ok
void handleRoot(){
Serial.println("Enter handleRoot");
String header;
if (!is_authentified())
{
String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
server.sendContent(header);
return;
}
if (server.hasArg("RESET"))
{
Serial.println("Reset max and min values");
min_x=0;
max_x=0;
String content = "<html><body><h2>ADXL Demo</h2>";
content += " <a href=\"/login\">reset</a><BR><BR>";
server.send(200, "text/html", content);
}
String content = "<html><body><h2>ADXL demo</h2>";
//<H2>hello, you successfully connected to esp8266!</H2><br>";
if (server.hasHeader("User-Agent"))
{
//content += "the user agent used is : " + server.header("User-Agent") + "<br><br>";
content += "x :" + String((int)current_value ) + " Corr(x):" + String((float)current_value - cal_x ) + " min_x:" + String((float)min_x) + " max_x:" + String((float)max_x) + "<br><br>";
content += "Trigger value:" + String((float)trigger_value) + " trigger count:" + String(trigger_count) + "<br><br>";
}
content += " <a href=\"/login?DISCONNECT=YES\">disconnect</a><BR><BR>";
content += " <a href=\"/?RESET=YES\">Reset min and max values</a><br><br>";
content += " <a href=\"/settings\">Settings</a>";
//last line
content += " </body></html>";
server.send(200, "text/html", content);
}
void handleSettings()
{
//reading
if (server.hasArg("TRIGGER"))
{
trigger_value = server.arg("TRIGGER").toInt();
return;
}
//setting
String msg = " <br><br> <a href=\"/ \">Home</a>";
String content = "<html><body><form action='/settings' method='POST'><br>";
content += "Value:<input type='number' name='TRIGGER' min='-500' max='500' placeholder='trigger value'><br>";
content += "<input type='submit' name='SUBMIT' value='Submit'></form>" + msg + "<br>";
server.send(200, "text/html", content);
}
//login page, also called for disconnect
void handleLogin(){
String msg;
if (server.hasHeader("Cookie")){
Serial.print("Found cookie: ");
String cookie = server.header("Cookie");
Serial.println(cookie);
}
if (server.hasArg("DISCONNECT")){
Serial.println("Disconnection");
String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
server.sendContent(header);
return;
}
if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){
if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin" ){
String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=1\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n";
server.sendContent(header);
Serial.println("Log in Successful");
return;
}
msg = "Wrong username/password! try again.";
Serial.println("Log in Failed");
}
String content = "<html><body><form action='/login' method='POST'>To log in, please use : admin/admin<br>";
content += "User:<input type='text' name='USERNAME' placeholder='user name'><br>";
content += "Password:<input type='password' name='PASSWORD' placeholder='password'><br>";
content += "<input type='submit' name='SUBMIT' value='Submit'></form>" + msg + "<br>";
content += "You also can go <a href='/inline'>here</a></body></html>";
server.send(200, "text/html", content);
}
//no need authentification
void handleNotFound()
{
String message = "File Not Found\n\n";
message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i=0; i<server.args(); i++){
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
}
float readAccel()
{
Serial.print("readAccel");
uint8_t howManyBytesToRead = 6; //6 for all axes
readFrom( DATAX0, howManyBytesToRead, _buff); //read the acceleration data from the ADXL345
short x =0;
x = (((short)_buff[1]) << 8) | _buff[0];
//short y = (((short)_buff[3]) << 8) | _buff[2];
//short z = (((short)_buff[5]) << 8) | _buff[4];
Serial.println(x * ADXL345_MG2G_MULTIPLIER * SENSORS_GRAVITY_STANDARD);
return x * ADXL345_MG2G_MULTIPLIER * SENSORS_GRAVITY_STANDARD;
//x = x + cal_x;
//Serial.print("x: ");
//Serial.print( x*2./512 );
//Serial.print(" y: ");
//Serial.print( y*2./512 );
//Serial.print(" z: ");
//Serial.print( z*2./512 );
//Serial.print("X: "); Serial.print( x);
//Serial.println( sqrtf(x*x+y*y+z*z)*2./512 );
//getX() = read16(ADXL345_REG_DATAX0);
//x = getX() * ADXL345_MG2G_MULTIPLIER * SENSORS_GRAVITY_STANDARD;
}
void writeTo(byte address, byte val)
{
Wire.beginTransmission(DEVICE); // start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); // end transmission
}
// Reads num bytes starting from address register on device in to _buff array
void readFrom(byte address, int num, byte _buff[])
{
Wire.beginTransmission(DEVICE); // start transmission to device
Wire.write(address); // sends address to read from
Wire.endTransmission(); // end transmission
Wire.beginTransmission(DEVICE); // start transmission to device
Wire.requestFrom(DEVICE, num); // request 6 bytes from device
int i = 0;
while(Wire.available()) // device may send less than requested (abnormal)
{
_buff[i] = Wire.read(); // receive a byte
i++;
}
Wire.endTransmission(); // end transmission
}
void setup() {
delay(1000);
Serial.begin(115200);
Serial.println();
Serial.print("Configuring access point...");
/* You can remove the password parameter if you want the AP to be open. */
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.on("/", handleRoot);
server.on("/login", handleLogin);
server.on("/settings", handleSettings);
server.on("/inline", [](){
server.send(200, "text/plain", "this works without need of authentification");
});
server.onNotFound(handleNotFound);
//here the list of headers to be recorded
const char * headerkeys[] = {"User-Agent","Cookie"} ;
size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
//ask server to track these headers
server.collectHeaders(headerkeys, headerkeyssize );
server.begin();
Serial.println("HTTP server started");
//ADXL345
// i2c bus SDA = GPIO0; SCL = GPIO2
Wire.begin(0,2);
// Put the ADXL345 into +/- 2G range by writing the value 0x01 to the DATA_FORMAT register.
// FYI: 0x00 = 2G, 0x01 = 4G, 0x02 = 8G, 0x03 = 16G
writeTo(DATA_FORMAT, 0x00);
// Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
writeTo(POWER_CTL, 0x08);
int i =0;
for(i=0; i<11; i++)
{
//uint8_t howManyBytesToRead = 6;
//readFrom( DATAX0, howManyBytesToRead, _buff);
float calib_x ;//= (((short)_buff[1]) << 8) | _buff[0];
calib_x = readAccel();
//if(i==0)
// cal_x = x;
if(i>0)
cal_x = cal_x + calib_x;
Serial.println(calib_x);
delay(100);
}
cal_x = cal_x/10;
Serial.print("cal_x: ");Serial.println(cal_x);
}
void loop() {
server.handleClient();
current_value = readAccel(); // read ONLY x, for the y and x modify the readAccel function
if((current_value - cal_x) > max_x)
max_x = current_value - cal_x;
if((current_value - cal_x) < min_x)
min_x = current_value - cal_x;
Serial.print("x: ");Serial.print(current_value); Serial.print(" x(corrected): ");Serial.print(current_value - cal_x);
Serial.print(" Min:" );Serial.print(min_x); Serial.print(" Max:" ); Serial.println(max_x);
Serial.print("Trigger value:"); Serial.print(trigger_value); Serial.print(" Count:"); Serial.println(trigger_count);
delay(100); // only read every 100ms
}
For ESP32 info and projects see my ESP32 blog.
how to refresh the value of its content every 100 ms on the webpage?
ReplyDeleteplease help.
great program BTW
You can add the Socket.io in your sketch and send data over websocket directly in your web page without refresh it every time. Also decrease the last line ( delay(100) ) to a small value.
ReplyDeletecan you send me the code for it.
Deleteashutosh0199@gmail.com
thanks
This may be obvious, but I am stuck, sorry if this is a stupid question.
ReplyDeleteThis appears to be working fine (I see the data in the serial monitor, and I can connect to the ESPap wifi.)
But what do I do to see the data through the wifi connection?
I think I need some URL or port in my browser, but cant find the right example.
Thanks for the write-up it has already helped a lot.
Cheers Smitje
Btw what accelerometer did you used and how you did your calibration ?
DeleteYou need to send the values to an MQTT broker or send them over websocket or create a RESTfull api and get data from other app. I've did it over MQTT and over websockets and is working fine. Depend on your project and what do you want to di with your data.
ReplyDeleteI got the wifi connection working now, but very unreliable it keeps losing connection and sometimes it cant find it annymore.
DeleteHow: before I could open the serial monitor the part where the ip is shown was scrolled out of view, I changed the delay to 5000 to see the ip. Then I could connect through my laptop to the wifi.
My sensor is an ADXL module, like the one depicted above with pins on two sides but an different (older?) model.
I haven’t gotten to calibrating yet.
I now have a different problem. the wifi is very unstable, and only works while the usb is connected. It doesnt want to work on 3 AA batteries with a voltage regulator, any tips, or perhaps a link to a tutorial would be much apreciated.
Thanks for your help so far.
Hi i am using module esp-12e ESP8266 Node Mcu with adxl 345.
ReplyDeletecan i use the above program. i want to measure the x, y, z acceleration .
MY question is
what is the connction with adxl 345.
You need to connect the SDA, SCL, VCC and GND. Now depending on what you want to do with ADXL345 you need the interrupt pins. First read the ADXL345 documentation. It is a good point to start with.
ReplyDeleteI am using accelerometer ADXL335 and ESP8266 interfacing with arduino. I need it its code, can you please send it to me on email: naveedkhanuet@gmail.com
ReplyDeleteThanks regards.
And the above written code is best one I have ever seen.
My advice is to move to ADXL345. The 335 is old, limited to +/-3g and I guess it has analog outputs. Use ADXL345 since you can connect it direct to the ESP8266 so you don't need Arduino. Also has sleep mode, free fall detection and I2C and SPI outputs.
DeleteThis is the code I am using for the modules ADXL 335 & ESP8266 interfacing with arduino mega.
ReplyDeleteI use thing speak server for displaying the analytics. But this code only gives me X & Y output values not Z output. Though I am not good at coding,can you please give a time for correcting my code.
Thanks regards.
#include
#include
#include
#include
#include
Timer t;
#include
//SoftwareSerial Serial1(2, 3);
#define heart 13
char *api_key="API KEY"; // Enter your Write API key from ThingSpeak
static char postUrl[150];
void httpGet(String ip, String path, int port=80);
const int groundpin = 18; // analog input pin 4 -- ground
const int powerpin = 19; // analog input pin 5 -- voltage
const int xpin = A3; // x-axis of the accelerometer
const int ypin = A2; // y-axis
const int zpin = A1; // z-axis (only on 3-axis models)
void setup() {
// put your setup code here, to run once:
Serial1.begin(115200);
Serial.begin(9600);
Serial.println("Connecting Wifi....");
connect_wifi("AT",1000);
connect_wifi("AT+CWMODE=1",1000);
connect_wifi("AT+CWQAP",1000);
connect_wifi("AT+RST",5000);
connect_wifi("AT+CWJAP=\"admin\",\"password\"",10000);
delay(5000);
Serial.println("Wifi Connected");
pinMode(heart, OUTPUT);
delay(2000);
t.oscillate(heart, 1000, LOW);
t.every(20000, send2server);
pinMode(groundpin, OUTPUT);
pinMode(powerpin, OUTPUT);
digitalWrite(groundpin, LOW);
digitalWrite(powerpin, HIGH);
}
void loop() {
// put your main code here, to run repeatedly:
// print the sensor values:
Serial.print(analogRead(xpin));
// print a tab between values:
Serial.print("\t");
Serial.print(analogRead(ypin));
// print a tab between values:
Serial.print("\t");
Serial.print(analogRead(zpin));
Serial.println();
// delay before next reading:
delay(10000);
t.update();
}
void send2server()
{
char xpinStr[8];
char ypinStr[8];
char zpinStr[8];
dtostrf(xpin, 5, 3, xpinStr);
dtostrf(ypin, 5, 3, ypinStr);
dtostrf(zpin, 5, 3, zpinStr);
sprintf(postUrl, "update?api_key=%s&field1=%s&field2=%s",api_key,xpinStr, ypinStr, zpinStr);
httpGet("api.thingspeak.com", postUrl, 80);
}
void httpGet(String ip, String path, int port)
{
int resp;
String atHttpGetCmd = "GET /"+path+" HTTP/1.0\r\n\r\n";
//AT+CIPSTART="TCP","192.168.20.200",80
String atTcpPortConnectCmd = "AT+CIPSTART=\"TCP\",\""+ip+"\","+port+"";
connect_wifi(atTcpPortConnectCmd,1000);
int len = atHttpGetCmd.length();
String atSendCmd = "AT+CIPSEND=";
atSendCmd+=len;
connect_wifi(atSendCmd,1000);
connect_wifi(atHttpGetCmd,1000);
}
void connect_wifi(String cmd, int t)
{
int xpin=0,i=0;
while(1)
{
Serial.println(cmd);
Serial1.println(cmd);
while(Serial1.available())
{
if(Serial1.find("OK"))
i=8;
}
delay(t);
if(i>5)
break;
i++;
}
if(i==8)
{
Serial.println("OK");
}
else
{
Serial.println("Error");
}
}
i need u help in iot project
ReplyDeleteLet me know how may I help you with your project.
DeleteHi,
ReplyDeleteWhile below program is uploaded to Arduino Atmel everything works well, have +/-2 measurements from accelerometer. When the same one is uploaded to Lolin wifi esp8266 nodemcu v3 (ESP12-E) the output is very different. Has no negative values and some of the axis jumps sudenly to 255. What is the difference here?
#include // Wire library - used for I2C communication
int ADXL345 = 0x53; // The ADXL345 sensor I2C address
float X_out, Y_out, Z_out; // Outputs
void setup() {
Serial.begin(115200); // Initiate serial communication for printing the results on the Serial monitor
Wire.begin(); // Initiate the Wire library
// Set ADXL345 in measuring mode
Wire.beginTransmission(ADXL345); // Start communicating with the device
Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
// Enable measurement
Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable
Wire.endTransmission();
delay(10);
}
void loop() {
// === Read acceleromter data === //
Wire.beginTransmission(ADXL345);
Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
Y_out = Y_out/256;
Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
Z_out = Z_out/256;
Serial.print("Xa= ");
Serial.print(X_out);
Serial.print(" Ya= ");
Serial.print(Y_out);
Serial.print(" Za= ");
Serial.println(Z_out);
delay(10);
}