Собрал недавно
arduino на atmega8, поморгал диодом, захотелось большего.
Начал изучать различные шилды, цены в РФ на них мягко говоря высокие, а собирать самому дороже выйдет, микросхемы тоже ведь покупать надо.
И тут в голову пришло, ведь на работе куча системных плат от различных телефонов. Почти в каждом современном телефоне есть акселерометр, цифровой термометр и т. д., почему их не использовать?
Оказалось в большинстве телефонов используется одна и та же микросхема акселерометра
LIS302DL от ST.
Содержание статьи / Table Of Contents
Скачал даташит, нашел схему включения. Выводы int1, int2, SDO в данном случае не задействованы.
Вытравил платку ЛУТ-ом.
🎁
Плата в Sprint - arduino_giro.lay.7z
1.01 Kb ⇣ 62
Наш файловый сервис предназначен для полноправных участников сообщества "Datagor Electronics".
Для получения файла зарегистрируйтесь и войдите на сайт с паролем.
По питанию поставил кренку на 3,3 вольта. На всякий пожарный добавил два керамических конденсатора на 10 Мкф и 100 нФ в цепь питания, как на даташите. Vdd io запитал от этой же кренки через дроссель, выпаянный из этого же телефона.
Для активации шины I2C кинул перемычку с CS на + питания.
Саму микросхемку приклеил к платке на супер клей и подпаялся к ней навесным монтажом.
Сверху это дело лучше залить клеем, получится этакий компаунд.
Вставил шилд в Ардуину, загрузил скетч:
#include <LiquidCrystal.h>
#include <Wire.h>
// based on Sketch by bGatti from http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213072318
// for use with http://www.nkcelectronics.com/triple-axis-accelerometer-breakout--lis30302.html
// tested with a seeeduino board, i2c connection established using the breakout pads with angled
// pin headers soldered in.
// Copyright Shu Ning Bian 2008, released under GPLv2
int _slave_id = 0x1D;
int backlight_pin = 3;
LiquidCrystal lcd(5,6,7,8,9,10,11);
uint8_t read_register(uint8_t sub)
{
i2c_send(_slave_id, &sub, 1);
return i2c_read(_slave_id);
}
void write_register(uint8_t sub, uint8_t data)
{
uint8_t bytes[] = {sub, data};
i2c_send(_slave_id, bytes, 2);
}
uint8_t i2c_read(uint8_t id)
{
Wire.requestFrom(_slave_id, 1);
while(!Wire.available())
{
delay(10);
}
return Wire.receive();
}
void i2c_send(uint8_t id, uint8_t * data, uint8_t len)
{
Wire.beginTransmission(id);
for(int i = 0; i < len; ++i)
{
Wire.send(data[i]);
}
Wire.endTransmission();
}
void dot_print(int val)
{
/* prints a number in the form of i.f where i is from val/10 and f
from val%10
*/
int i = val/10;
int f = val%10;
if ( val < 0 )
{
f*=-1;
}
if ( i>=0 )
{
// print a + to counter the - which is added by print when val is negative
lcd.print("+");
}
lcd.print(i, DEC);
lcd.print(".");
lcd.print(f,DEC);
if (i<10)
{
lcd.print(" ");
}
}
void pretty_print(char x, char y, char z)
{
/* The divisor of x,y, and z are chosen to give the "correct" value at 1g. They are worked out
by trial and error, but a rough starting point can be calculated as follows:
1. divided by 128 to normalise the range
2. multiply by 2 since the range is +/- 2,
* combined so this gives divided by 64, giving acceleration in gs
3. multiply by 9.8 to give acceleration in ms/s/s,
* combined this gives multiply by 9.8/64
4. to make things into nicer integer maths, invert 9.8/64 to give 6.5
5. now we can truncate and use divisor of 6, an integer, or sacrifice some cycles and use
a floating value around 6 which gives the "correct" value of 9.8m/s/s for an axis when that
axis is "pointing" towards the centre of the earth.
Note I have multiplied everything by 10 implicitly to keep us in int domain
*/
int xx = x * 100 / 55;
int yy = y * 100 / 55;
int zz = z * 100 / 63;
lcd.clear();
lcd.print("X:");dot_print(xx);lcd.print(" ");
lcd.print("Y:");dot_print(yy);lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("Z:");dot_print(zz);lcd.print(" (m/s/s)");
}
#define CTRL_REG2 0x21
#define CTRL_REG1 0x20
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
lcd.print("Setting up...");
write_register(CTRL_REG2, B01000000);
/* 0 - SPI mode selection
1 - reboot memory contents
0 - none
0 - filtered data selection, 0 = bypassed
0 - high pass filter enable for freefall/wakeup #2, 0 = bypassed
0 - high pass filter enable for freefall/wakeup #1, 0 = bypassed
0 - high pass coefficient 2
0 - high pass coefficient 1
the last 2 bits configure the high pass filter cutoff frequency
*/
write_register(CTRL_REG1, B01000111);
/* 0 - data rate selection, 1=100Hz
1 - power down control, 1 = active mode
0 - full scale selection, 0 = +/- 2g, 1 = +/- 8g
0 - self test P enable, 0 = normal mode
0 - self test M enabled, 0 = normal mode
1 - z axis enable, 1 = enabled
1 - y axis enable, 1 = enabled
1 - x axis enable, 1 = enabled
*/
pinMode(backlight_pin, OUTPUT);
analogWrite(backlight_pin, 128);
}
void loop()
{
#define OUT_X 0x29
#define OUT_Y 0x2B
#define OUT_Z 0x2D
#define STATUS_REG 0x27
//----------Status Register-----------------------
byte status = read_register(STATUS_REG);
#define ZYXDA 0x08
if ( status & ZYXDA == 0)
{
// ZYXDA is 1 when new set of data is available, so since its 0, lets skip
return;
}
//----------X Values-----------------------
char x_val = read_register(OUT_X);
//----------Y Values-----------------------
char y_val = read_register(OUT_Y);
//----------Z Values-----------------------
char z_val = read_register(OUT_Z);
//Serial.print("status "); Serial.println(status, BIN);
pretty_print(x_val, y_val, z_val);
delay(200);
}
Если нет дисплея, можно увидеть результат в Serial monitor:
//==========================================================
#include <Wire.h>
#define i2cID 0x1D
//TWI (I2C) sketch to communicate with the LIS302DL accelerometer - Modified and tested Ben Gatti - 6/9/2008
//http://www.st.com/stonline/products/literature/ds/12726.pdf
//Note 5.6K pullup resister on data lines.
//Device is 3 volt was tested at 5 volts no level shifting.
//Reference claims 6 volts is pin max.
//Modified from // TWI (I2C) sketch to communicate with the LIS3LV02DQ accelerometer
//http://www.nearfuturelaboratory.com/2007/01/11/arduino-and-twi/
//Modified code from http://research.techkwondo.com/blog/julian/279
//Thanks Julian.
// Using the Wire library (created by Nicholas Zambetti)
// http://wiring.org.co/reference/librarie ... index.html
// On the Arduino board, Analog In 4 is SDA, Analog In 5 is SCL
// These correspond to pin 27 (PC4/ADC4/SDA) and pin 28 (PC5/ADC5/SCL) on the Atmega8
// The Wire class handles the TWI transactions, abstracting the nitty-gritty to make
// prototyping easy.
void setup()
{
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(57600);
Serial.println("Wire.begin");
Wire.beginTransmission(i2cID);
Wire.send(0x21); // CTRL_REG2 (21h)
Wire.send(B01000000);
//SPI 4/3 wire
//1=ReBoot - reset chip defaults
//n/a
//filter off/on
//filter for freefall 2
//filter for freefall 1
//filter freq MSB
//filter freq LSB - Hipass filter (at 400hz) 00=8hz, 01=4hz, 10=2hz, 11=1hz (lower by 4x if sample rate is 100hz)
Wire.endTransmission();
Wire.beginTransmission(i2cID);
Wire.send(0x20); // CTRL_REG1 (20h)
Wire.send(B01000111);
//sample rate 100/400hz
//power off/on
//2g/8g
//self test
//self test
//z enable
//y enable
//x enable
Wire.endTransmission();
}
void loop()
{
#define outXhigh 0x29
#define outYhigh 0x2B
#define outZhigh 0x2D
#define statusReg 0x27
boolean goodRead;
goodRead = false;
//----------Status Register-----------------------
byte status;
status = B00000000;
//
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.send(statusReg);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
status = Wire.receive();
}
//----------X Values-----------------------
byte x_val;
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.send(outXhigh);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
x_val = Wire.receive();
}
//----------Y Values-----------------------
byte y_val;
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.send(outYhigh);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
y_val = Wire.receive();
}
//----------Z Values-----------------------
byte z_val;
//-------------------------------
Wire.beginTransmission(i2cID);
Wire.send(outZhigh);
Wire.endTransmission();
Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
z_val = Wire.receive();
goodRead=true;
}
//-------------------------------
if (goodRead==true)
{
//Serial.print("x_val_l= "); Serial.println(x_val_l, DEC);
//Serial.print("x_val_h= "); Serial.println(x_val_h, DEC);
//Serial.print("x_val= "); Serial.println(x_val, DEC);
//Serial.print("y_val_l= "); Serial.println(y_val_l, DEC);
//Serial.print("y_val_h= "); Serial.println(y_val_h, DEC);
//Serial.print("y_val= "); Serial.println(y_val, DEC);
//Serial.print("z_val_l= "); Serial.println(z_val_l, DEC);
//Serial.print("z_val_h= "); Serial.println(z_val_h, DEC);
//Serial.print("status "); Serial.println(status, BIN);
Serial.print(" val= "); Serial.print(x_val, DEC);
Serial.print(":"); Serial.print(y_val, DEC);
Serial.print(":"); Serial.println(z_val, DEC);
}
else
Serial.print("no data");
delay(100);
}
//==========================================================
Спасибо за внимание!
Георгий
Камрад, рассмотри датагорские рекомендации
🌼 Полезные и проверенные железяки, можно брать
Опробовано в лаборатории редакции или читателями.