got angle sensor reading
This commit is contained in:
342
Examples/Arduino/a1335_example/lib/A1335/A1335.cpp
Normal file
342
Examples/Arduino/a1335_example/lib/A1335/A1335.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
/***************************************************
|
||||
Arduino library for the Allegro A1335 Magnetic angle sensor
|
||||
The A1335 sensor detects the absolute angular position of a
|
||||
permanent magnet, typically a diametrically
|
||||
magnetized cylinder on the rotating shaft.
|
||||
|
||||
* by Florian von Bertrab
|
||||
****************************************************/
|
||||
|
||||
#include "A1335.h"
|
||||
|
||||
|
||||
bytes_2::bytes_2(){
|
||||
data.integer = 0;
|
||||
}
|
||||
|
||||
bytes_2::bytes_2(int16_t integ){
|
||||
data.integer = integ;
|
||||
}
|
||||
|
||||
int16_t& bytes_2::in(){
|
||||
return data.integer;
|
||||
}
|
||||
|
||||
byte& bytes_2::lsBy(byte n){
|
||||
if (n > 1) {
|
||||
n = 1;
|
||||
} else if (n < 0) {
|
||||
n = 0;
|
||||
}
|
||||
return data.bytes[n];
|
||||
}
|
||||
|
||||
byte& bytes_2::msBy(byte n){
|
||||
if (n > 1) {
|
||||
n = 1;
|
||||
} else if (n < 0) {
|
||||
n = 0;
|
||||
}
|
||||
return data.bytes[1-n];
|
||||
}
|
||||
|
||||
bytes_4::bytes_4(){
|
||||
data.integer = 0;
|
||||
}
|
||||
|
||||
bytes_4::bytes_4(int32_t integ){
|
||||
data.integer = integ;
|
||||
}
|
||||
|
||||
int32_t& bytes_4::in(){
|
||||
return data.integer;
|
||||
}
|
||||
|
||||
byte& bytes_4::lsBy(byte n){
|
||||
if (n > 3) {
|
||||
n = 3;
|
||||
} else if (n < 0) {
|
||||
n = 0;
|
||||
}
|
||||
return data.bytes[n];
|
||||
}
|
||||
|
||||
byte& bytes_4::msBy(byte n){
|
||||
if (n > 3) {
|
||||
n = 3;
|
||||
} else if (n < 0) {
|
||||
n = 0;
|
||||
}
|
||||
return data.bytes[3-n];
|
||||
}
|
||||
|
||||
//--- Normal Write Registers ---//
|
||||
|
||||
const byte EWA = 0x02; // Extended Write Address
|
||||
const byte EWD = 0x04; // Extended Write Data
|
||||
const byte EWCS = 0x08; // Extended Write Control and Status
|
||||
const byte ERA = 0x0A; // Extended Read Address
|
||||
const byte ERCS = 0x0C; // Extended Read Control and Status
|
||||
const byte ERD = 0x0E; // Extended Read Data
|
||||
const byte CTRL = 0x1E; // Device control
|
||||
const byte ANG = 0x20; // Current angle and related data
|
||||
const byte STA = 0x22; // Device status
|
||||
const byte ERR = 0x24; // Device error status
|
||||
const byte XERR = 0x26; // Extended error status
|
||||
const byte TSEN = 0x28; // Temperature sensor data
|
||||
const byte FIELD = 0x2A; // Magnetic field strength
|
||||
const byte ERM = 0x34; // Device error status masking
|
||||
const byte XERM = 0x36; // Extended error status masking
|
||||
|
||||
//--- Extended Write Registers ---//
|
||||
|
||||
const int16_t ORATE = 0xFFD0; // Output Rate
|
||||
|
||||
|
||||
// Control bytes and their respective keycodes:
|
||||
|
||||
// CTRL(0x1E) KEY(0x1F)
|
||||
// Processor State
|
||||
const byte ipm[] = { B10000000, 0x46 }; // Idle mode
|
||||
const byte rpm[] = { B11000000, 0x46 }; // Run mode
|
||||
// Hard Reset
|
||||
const byte hre[] = { B00100000, 0xB9 }; // Hard reset
|
||||
// Soft Reset
|
||||
const byte sre[] = { B00010000, 0xB9 }; // Soft reset
|
||||
// Clear STA
|
||||
const byte csta[] = { B00000100, 0x46 }; // Clear (STA) registers
|
||||
// Hard Reset
|
||||
const byte cxerr[] = { B00000010, 0x46 }; // Clear (XERR) registers
|
||||
// Hard Reset
|
||||
const byte cerr[] = { B00000001, 0x46 }; // Clear (ERR) registers
|
||||
|
||||
|
||||
// Angle Register read masks
|
||||
|
||||
// ANG(0x20) ANG+1(0x21)
|
||||
// Register Identifier Code
|
||||
const byte ria[] = { B10000000, B00000000}; // Always 0
|
||||
// Error Flag
|
||||
const byte efa[] = { B01000000, B00000000}; // At least one error in register 0x24
|
||||
// New Flag
|
||||
const byte nfa[] = { B00100000, B00000000}; // A new angle is in the angle register
|
||||
// Parity
|
||||
const byte par[] = { B00010000, B00000000}; // Odd parity bit for the whole register
|
||||
// Angle
|
||||
const byte ang[] = { B00001111, B11111111}; // Encoded angle reading (n * 360/4096 = angle in deg.)
|
||||
|
||||
|
||||
// Status Register read masks
|
||||
|
||||
// STA(0x20) STA+1(0x21)
|
||||
// Register Identifier Code
|
||||
const byte ris[] = { B11110000, B00000000}; // Always 1000
|
||||
// Power-On Reset Flag
|
||||
const byte por[] = { B00001000, B00000000}; // There was a power-on reset since last field reset
|
||||
// Soft Reset Flag
|
||||
const byte srf[] = { B00000100, B00000000}; // There was a soft reset since last field reset
|
||||
// New Flag
|
||||
const byte nfs[] = { B00000010, B00000000}; // A new angle is in the angle register
|
||||
// Current Error Flag
|
||||
const byte efs[] = { B00000001, B00000000}; // At least one error in register 0x24
|
||||
// Processor Processing Status
|
||||
const byte mps[] = { B00000000, B11110000}; // 0000 Booting; 0001 Idle or Processing angles; 1110 Self-testmode
|
||||
// Processor Phase Status
|
||||
const byte phase[] = { B00000000, B00001111}; // 0000 Idle; 0001 Processing angles; Only in Self-test mode [0100 Built in self test; 0110 ROM checksum; 0111 CVH self test]
|
||||
|
||||
|
||||
// Temperature Register read masks
|
||||
|
||||
// TSEN(0x28) TSEN+1(0x29)
|
||||
// Register Identifier Code
|
||||
const byte rit[] = { B11110000, B00000000}; // Always 1111
|
||||
// Temperature
|
||||
const byte temp[] = { B00001111, B11111111}; // Encoded temperature reading (n / 8 = temperature in K)
|
||||
|
||||
|
||||
// Field Strenght Register read masks
|
||||
|
||||
// FIELD(0x28) FIELD+1(0x29)
|
||||
// Register Identifier Code
|
||||
const byte rif[] = { B11110000, B00000000}; // Always 1110
|
||||
// Magnetic field strenght
|
||||
const byte field[] = { B00001111, B11111111}; // Magnetic field strenght reading (n = field strenght in Gauss (1/10000 T))
|
||||
|
||||
|
||||
A1335::A1335(){
|
||||
|
||||
}
|
||||
|
||||
int16_t A1335::getAddress(){ // returns I2C address of the sensor
|
||||
return address;
|
||||
}
|
||||
|
||||
byte A1335::getProcessorState(){ // returns current processor state of the sensor
|
||||
return processorState;
|
||||
}
|
||||
|
||||
byte A1335::getOutputRate(){ // returns the current sample rate of the sensor
|
||||
return outputRate;
|
||||
}
|
||||
|
||||
byte A1335::start(int16_t address_){ // Initializes the sensor at the address given and fills the private variables
|
||||
Wire.beginTransmission(address);
|
||||
byte error = Wire.endTransmission();
|
||||
if (error) {
|
||||
processorState = 4;
|
||||
return error;
|
||||
}
|
||||
address = address_;
|
||||
bytes_2 state(normalRead(STA));
|
||||
bytes_4 orate(extendedRead(ORATE));
|
||||
|
||||
byte processing_status = (state.msBy(1) & mps[1]) >> 4;
|
||||
byte processing_phase = (state.msBy(1) & phase[1]) >> 0;
|
||||
switch (processing_status) {
|
||||
case B00000000:
|
||||
processorState = 0;
|
||||
break;
|
||||
case B00000001:
|
||||
if (processing_phase == 0){
|
||||
processorState = 1;
|
||||
} else {
|
||||
processorState = 2;
|
||||
}
|
||||
break;
|
||||
case B00001110:
|
||||
processorState = 3;
|
||||
break;
|
||||
}
|
||||
outputRate = orate.msBy(3);
|
||||
delay(1);
|
||||
return error;
|
||||
}
|
||||
|
||||
double A1335::readAngle(){ // returns Angle in Degrees
|
||||
return double(readAngleRaw()) * 360.0 / 4096.0;
|
||||
}
|
||||
uint16_t A1335::readAngleRaw(){ // returns raw angle data
|
||||
bytes_2 angReg(normalRead(ANG));
|
||||
|
||||
int16_t parityCheck = angReg.in();
|
||||
parityCheck ^= parityCheck >> 8;
|
||||
parityCheck ^= parityCheck >> 4;
|
||||
parityCheck ^= parityCheck >> 2;
|
||||
parityCheck ^= parityCheck >> 1;
|
||||
parityCheck &= 1; // parity Check now contains the parity of all bits in angReg
|
||||
if(!parityCheck) { // odd Parity in this register => a 0 means an error
|
||||
return 0;
|
||||
}
|
||||
|
||||
angReg.msBy(0) &= ang[0]; // mutes bits, that dont contain the angle data
|
||||
return angReg.in();
|
||||
}
|
||||
|
||||
double A1335::readTemp(){ // returns temperature in Kelvin
|
||||
return double(readTempRaw())/8.0;
|
||||
}
|
||||
|
||||
uint16_t A1335::readTempRaw(){ // returns raw temperature data
|
||||
bytes_2 tempReg(normalRead(TSEN));
|
||||
tempReg.msBy(0) &= temp[0]; // mutes bits, that dont contain temperature data
|
||||
return tempReg.in();
|
||||
}
|
||||
|
||||
double A1335::readField(){ // returns field strenght in Tesla
|
||||
return double(readFieldRaw())/10000.0;
|
||||
}
|
||||
|
||||
uint16_t A1335::readFieldRaw(){ // returns raw field strenght data
|
||||
bytes_2 fieldReg(normalRead(FIELD));
|
||||
fieldReg.msBy(0) &= field[0]; // mutes bits, that dont contain temperature data
|
||||
return fieldReg.in();
|
||||
}
|
||||
|
||||
byte A1335::readOutputRate(){ // reads the log2() of the sample rate
|
||||
bytes_4 oRate(extendedRead(ORATE));
|
||||
return oRate.msBy(3); // !!! I don't know yet, which byte holds the output rate !!!
|
||||
}
|
||||
|
||||
byte A1335::setOutputRate(byte rate){ // sets the log2() of the sample rate => (ORate = 2^rate)
|
||||
if (rate < 0) {
|
||||
rate = 0;
|
||||
} else if (rate >=8) {
|
||||
rate = 7;
|
||||
}
|
||||
bytes_2 idle_mode;
|
||||
bytes_2 run_mode;
|
||||
for (int i = 0; i < 2; i++){
|
||||
idle_mode.msBy(i) = ipm[i];
|
||||
run_mode.msBy(i) = rpm[i];
|
||||
}
|
||||
normalWrite(CTRL, idle_mode.in());
|
||||
delayMicroseconds(150);
|
||||
bytes_4 oRate;
|
||||
oRate.msBy(3) = rate;
|
||||
extendedWrite(ORATE, oRate.in()); // !!! I don't know yet, which byte gets the output rate !!!
|
||||
delayMicroseconds(50);
|
||||
normalWrite(CTRL, run_mode.in());
|
||||
delayMicroseconds(150);
|
||||
}
|
||||
|
||||
byte A1335::normalWrite(byte reg, int16_t data){ // writes the 2 bytes in "bytes" to the register with address reg to the sensor with I2C address adress.
|
||||
bytes_2 data_bytes(data);
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(reg); // choose target register
|
||||
for (int i = 0; i<2; i++){
|
||||
Wire.write(data_bytes.msBy(i)); // Writes data MSB first
|
||||
}
|
||||
return Wire.endTransmission();
|
||||
}
|
||||
|
||||
byte A1335::extendedWrite(int16_t reg, int32_t data){ // writes the 4 bytes in "bytes" to the extended register with address reg to the sensor with I2C address adress.
|
||||
bytes_4 data_bytes(data);
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(EWA); // choose write Register
|
||||
Wire.write(byte(reg >> 8)); // Fill with target address
|
||||
Wire.write(byte(reg));
|
||||
for (int i = 0; i<4; i++){
|
||||
Wire.write(data_bytes.msBy(i)); // Writes data MSB first
|
||||
}
|
||||
Wire.write(0x80); // Confirm write
|
||||
Wire.endTransmission();
|
||||
delayMicroseconds(10);
|
||||
Wire.requestFrom(address, 1);
|
||||
return Wire.read(); // Returns 1 if it works
|
||||
}
|
||||
|
||||
int16_t A1335::normalRead(byte reg){
|
||||
bytes_2 data;
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(reg); // choose target Register
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(address, 2);
|
||||
for(int i=0; i< 2; i++){
|
||||
if (Wire.available()){
|
||||
data.msBy(i) = Wire.read(); // read data bytes
|
||||
}
|
||||
}
|
||||
return data.in();
|
||||
}
|
||||
|
||||
int32_t A1335::extendedRead(int16_t reg){
|
||||
bytes_4 data;
|
||||
byte rstate;
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(ERA); // choose write Register
|
||||
Wire.write(byte(reg >> 8)); // Fill with target address
|
||||
Wire.write(byte(reg));
|
||||
Wire.write(0x80); // Confirm read
|
||||
Wire.endTransmission();
|
||||
delayMicroseconds(10);
|
||||
Wire.requestFrom(address,5);
|
||||
rstate = Wire.read(); // Reads status byte
|
||||
for(int i=0; i < 4; i++){
|
||||
if (Wire.available()){
|
||||
data.msBy(i) = Wire.read(); // Reads data bytes
|
||||
}
|
||||
}
|
||||
return data.in();
|
||||
}
|
||||
|
||||
|
||||
99
Examples/Arduino/a1335_example/lib/A1335/A1335.h
Normal file
99
Examples/Arduino/a1335_example/lib/A1335/A1335.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/***************************************************
|
||||
Arduino library for the Allegro A1335 Magnetic angle sensor
|
||||
The A1335 sensor detects the absolute angular position of a
|
||||
permanent magnet, typically a diametrically
|
||||
magnetized cylinder on the rotating shaft.
|
||||
|
||||
* by Florian von Bertrab
|
||||
****************************************************/
|
||||
|
||||
#ifndef A1335_H
|
||||
#define A1335_H
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#include <Wire.h>
|
||||
|
||||
class bytes_2 { // allows easy conversion from two bytes in a given order to a 16 bit int.
|
||||
public:
|
||||
bytes_2();
|
||||
bytes_2(int16_t integ);
|
||||
|
||||
int16_t& in();
|
||||
byte& lsBy(byte n);
|
||||
byte& msBy(byte n);
|
||||
|
||||
private:
|
||||
union {
|
||||
int16_t integer;
|
||||
byte bytes[2];
|
||||
}data;
|
||||
};
|
||||
|
||||
class bytes_4 { // allows easy conversion from four bytes in a given order to a 32 bit int.
|
||||
|
||||
public:
|
||||
bytes_4();
|
||||
bytes_4(int32_t integ);
|
||||
|
||||
int32_t& in();
|
||||
byte& lsBy(byte n);
|
||||
byte& msBy(byte n);
|
||||
|
||||
private:
|
||||
union {
|
||||
int32_t integer;
|
||||
byte bytes[4];
|
||||
}data;
|
||||
};
|
||||
|
||||
class A1335 {
|
||||
public:
|
||||
A1335();
|
||||
|
||||
byte start(int16_t address_); // starts the sensor at the given address
|
||||
|
||||
int16_t getAddress(); // returns I2C address
|
||||
byte getProcessorState(); // returns processor state:
|
||||
// 0 = booting; 1 = idle; 2 = running; 3 = self-test mode; 4 = not found
|
||||
|
||||
byte getOutputRate(); // returns the log2() of the samperate. E.g. 3 would mean 8 samples per data point.
|
||||
|
||||
|
||||
double readAngle(); // returns the angle in degrees
|
||||
|
||||
uint16_t readAngleRaw(); // returns raw angle data (4096 = 360<36>)
|
||||
|
||||
double readTemp(); // returns temperature in Kelvin
|
||||
|
||||
uint16_t readTempRaw(); // returns raw temperature data 8 = 1 K
|
||||
|
||||
double readField(); // returns field strenght in Tesla
|
||||
|
||||
uint16_t readFieldRaw(); // returns raw field strenght data 10 = 1mT
|
||||
|
||||
|
||||
byte readOutputRate(); // reads the log2() of the sample rate. Does not really work yet!
|
||||
|
||||
byte setOutputRate(byte rate);// sets the log2() of the sample rate => (ORate = 2^rate). Does not really work yet!
|
||||
|
||||
byte normalWrite(byte reg, int16_t data); // writes 16 bit to a given register
|
||||
|
||||
int16_t normalRead(byte reg); // reads 16 bit from a given register
|
||||
|
||||
|
||||
byte extendedWrite(int16_t reg, int32_t data); // writes 32 bit to a given extended register
|
||||
|
||||
int32_t extendedRead(int16_t reg); // reads 32 bit from a given extended register
|
||||
|
||||
|
||||
private:
|
||||
int16_t address = 0x0C; // I2C address
|
||||
byte processorState = 4; // 0 = booting; 1 = idle; 2 = running; 3 = self-test mode; 4 = not found
|
||||
byte outputRate = 0; // log2() of the sample rate in the EEPROM
|
||||
};
|
||||
|
||||
#endif //A1335_H
|
||||
8
Examples/Arduino/a1335_example/lib/A1335/README.md
Normal file
8
Examples/Arduino/a1335_example/lib/A1335/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Allegro-A1335-Sensor-library
|
||||
A C++ library for communicating with the A 1335 hall effect encoder
|
||||
|
||||
Arduino library for the Allegro A1335 Magnetic angle sensor.
|
||||
The A1335 sensor detects the absolute angular position of a permanent magnet, typically a diametrically magnetized cylinder on the rotating shaft.
|
||||
|
||||
* by Florian von Bertrab
|
||||
|
||||
Reference in New Issue
Block a user