http://www.analog.com/static/imported-files/data_sheets/ADXL346.pdf
#include <Wire.h>
#include <Servo.h>
/*
Experiment med Arduino UNO R3 och accelerometer med gyro, servo och en summer.
Har gjort denna sketch för att lättare komma igång,
när du har köpt en Accelerometer på Tradera av användare pc_h.
Se skiss för koppling
En ADXL345 Accelerometer
Koppla 5V till 5v på Accelerometer
Koppla GND till GND på Accelerometer
Koppla A5 till SLC på Accelerometer
Koppla A4 till SDA på Accelerometer
Koppla GND till SDO på Accelerometer
Koppla 2 till INT1 på Accelerometer
Koppla 3V3 på Accelerometer till CS på Accelerometer (En bygling alltså)
En Micro servo 9g SG90.
Koppla GND till Svart på servo
Koppla 5V till Röd på servo
Koppla 9 till Vit på servo
En Aktiv ton summer på 85 dB 5V.
Montera summer melllan lång pinne (plus) på pinne 11
och kort pinne på GND
Alla kablar får inte plats på GND och 5V, så ett kopplingsdäck kan användas som förgrening.
Denna sketch är skriven av Per-Anders Hult
*/
#define ADDRESS_I2C 0x53 //Modulens adress (0x53 om SDO kopplad till GND annars 0x1D?
//Namn givning av Modulens ADXL345 register.
#define ADDRESS_DEVID 0x00
#define THRESH_TAP 0x1D //Tap Threshold
#define ADDRESS_DATA_FORMAT 0x31
#define DURATION 0x21 //Tap Duration
#define LATENT 0x22 //Tap latency
#define WINDOW 0x23 //Tap window
#define POWER_CTL 0x2D
#define VALUE_POWER_CTL 0x08 //Measure
#define TAP_AXES 0x2A //Axis control for tap/double tap
#define INT_ENABLE 0x2E //Interrupt Enable Control
#define INT_MAP 0x2F //Interrupt Mapping Control
#define INT_SOURCE 0x30 //Source of interrupts
#define DATAX0 0x32 //X-Axis Data 0
#define ADRESS_DATAX0 0x32
#define ACCEL 0x53 // Accel I2c Address
byte buffert[6]; // Skapar en lista som kan ha 6 värden
int gyro_x;
int gyro_y;
int gyro_z;
int accel_x;
int accel_y;
int accel_z;
int i;
int knack=0;
int pinneSummer = 11;
int situation = 0;
Servo Servo9g;
void setup(){
pinMode(pinneSummer, OUTPUT);
byte val = 0;
Serial.begin(9600);
Wire.begin();
// Inställningar till servot
Servo9g.attach(9,610,2500);
Servo9g.writeMicroseconds(1500);
//Denna del är för att kolla att allt är rätt kopplat
//Skriver id = E5 i Serial Monitor(Om inte är det dax att felsöka)
byte id = 0;
id = ReadRegisterSingle(ADDRESS_DEVID);
Serial.print("id = ");
Serial.println(id, HEX);
//Gör att arduino använder avbrott
attachInterrupt(0, taping, RISING);
//Modulen ADXL345 inställningar.
writeRegister(ADDRESS_DATA_FORMAT, 0x01);
writeRegister(INT_MAP, 0x9F);
writeRegister(TAP_AXES, 0x01);
writeRegister(THRESH_TAP, 0x38);
writeRegister(DURATION, 0x10);
writeRegister(LATENT, 0x50);
writeRegister(WINDOW, 0xFF);
writeRegister(INT_ENABLE, 0xE0);
//Modulen ADXL345 är klar för mätning.
writeRegister(POWER_CTL, 0x08); //Mätläge
ReadRegisterSingle(INT_SOURCE); //Läser register för att nollställa avbrott.
Serial.println("Inställninga klara");
}
void loop(){
int x,y,z;
double xg, yg, zg;
int tapType;
int servo = 17;
//Denna del kollar om en knackning har gjorts.
//Denna del är förenklad programmering.
if(knack == 1){
knack = 0;
tapType = ReadRegisterSingle(INT_SOURCE);
if(tapType == 195){
pip(1);
situation = 0;
}else{
pip(2);
situation = 1;
}
}
readRegister(DATAX0, 6);
// Dessa tre rader är riktigt krångliga.
// << Är att skifta in binära ettor och nollor åt vänster och värdet dubblas då,
// detta görs 8 gånger. I detta fall gör det att värdet blir negativt eller positivt.
// Läs mer på http://arduino.cc/en/Reference/Bitshift
// Det lodrätta sträcket "|" betyder att man slår i hop värdena med en logisk ELLER-fuktion(OR).
// Läs mer på http://arduino.cc/en/Reference/BitwiseAnd
x = ((int)buffert[1]<<8)|(int)buffert[0];
y = ((int)buffert[3]<<8)|(int)buffert[2];
z = ((int)buffert[5]<<8)|(int)buffert[4];
//Räkna om värdet till g-kraft, X måste vara horisontalt för mätning av g-kraft i X-led(Se video)
//Mätning sker med 10 bitars upplösning alltså värde från 0 till 1023.
//Värde från 0 till 511 är positiva värden. 512 till 1023 negativa värden (Ja vet KRÅNGLIGT).
// -4g till +4g Total 8g
// 8/1023=0.0078
xg = x * 0.0078;
yg = y * 0.0078;
zg = z * 0.0078;
if(situation == 0){
//om situationen är i läge ENKEL(noll) skrivs vinkel-värden till datorns USB-port
//Värden skrivs till servot bara om situationen är i läge ENKEL
Serial.println("ENKEL");
Serial.print(x);
Serial.print(',');
Serial.print(y);
Serial.print(',');
Serial.println(z);
//Skriv värden till servot.
//130 och 17 är gränsvärden
//2,4 är skala
servo = (int) (x + 130) / 2,4;
Serial.print("Servo = ");
Serial.println(servo);
Servo9g.write(servo + 17);
}else{
//om situationen är i läge DUBBEL(inte noll) skrivs g-värden till datorns USB-port
//Värden skrivs INTE till servot om situationen är i läge DUBBEL
Serial.println("DUBBEL");
Serial.print((float)xg,2);
Serial.print("g,");
Serial.print((float)yg,2);
Serial.print("g,");
Serial.print((float)zg,2);
Serial.println("g");
}
//Ta bort snedsträcken från nästa rad om du inte hinner läsa alla värden på monitorn
//delay(1000);
}
// Läser ett värde från ADXL345 modulens register.
// Denna funktion returnerar värdet till anroparen
byte ReadRegisterSingle(byte registerAddress) {
byte v = 0;
Wire.beginTransmission(ADDRESS_I2C);
Wire.write(registerAddress);
Wire.endTransmission();
Wire.requestFrom(ADDRESS_I2C,1,true);
v = Wire.read();
return v;
}
// Läser flera värde från ADXL345 modulens register.
// Sparar svaren buffert listan. Max 6 byte
void readRegister(char registerAddress, int numBytes){
byte v = 0;
Wire.beginTransmission(ADDRESS_I2C);
Wire.write(registerAddress);
Wire.endTransmission();
// Önska antal byte som du vill läsa.
Wire.requestFrom(ADDRESS_I2C, numBytes, true);
// Läs in alla byte med while-slingan
int i = 0;
while(Wire.available())
{
buffert[i] = Wire.read();
i++;
}
}
// Skriv ett värde till ADXL345 modulens register
void writeRegister(byte address, byte val) {
Wire.beginTransmission(ADDRESS_I2C);
Wire.write(address);
Wire.write(val);
Wire.endTransmission();
}
//Piper antal gånger som c.
void pip(int c){
for (int i=0; i < c; i++){
digitalWrite(pinneSummer, HIGH);
delay(100);
digitalWrite(pinneSummer, LOW);
delay(100);
}
}
//Denna startas vid avbrotts önskan från ADXL345 modulen till ingång 2 på Arduino-kortet
void taping(void){
knack=1;
}