-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Plane: add As5600 angle-of-attack sensor #16795
Changes from all commits
c2fbc83
a5f0f81
da95f43
20ed5a4
f223c83
f24e111
c26e328
82225f8
892bb6e
43c25dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -67,6 +67,9 @@ void Plane::init_ardupilot() | |||||
|
||||||
rpm_sensor.init(); | ||||||
|
||||||
//initialise AS5600_AOA sensor | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
aoa_sensor.init(); | ||||||
|
||||||
// setup telem slots with serial ports | ||||||
gcs().setup_uarts(); | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -29,6 +29,7 @@ def build(bld): | |||||
'AP_Devo_Telem', | ||||||
'AP_OSD', | ||||||
'AC_AutoTune', | ||||||
'AP_AS5600_AOA', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Before merge we'll need to rename this library so we can support more sensors into the future. Related changes not mentioned in this review. |
||||||
'AP_KDECAN', | ||||||
], | ||||||
) | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,209 @@ | ||||||||
/**************************************************** | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file will become (it's possible people will actually prefer |
||||||||
* AS5600 Angle of Attack Class for Ardupilot platform | ||||||||
* Author: Cole Mero | ||||||||
* Date: 15 Feb 2021 | ||||||||
* File: AS5600_AOA.cpp | ||||||||
* Based on: www.ams.com | ||||||||
* | ||||||||
* Description: This class has been designed to | ||||||||
* access the AS5600 magnetic encoder sensor to | ||||||||
* read the angle of attack and record it for experimental purposes | ||||||||
* | ||||||||
* It was adapted from the Arduino library available for the AS5600 sensor. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice to give a link to the original implementation here. |
||||||||
* | ||||||||
***************************************************/ | ||||||||
|
||||||||
#include <unistd.h> | ||||||||
#include "AS5600_AOA.h" | ||||||||
#include <AP_Common/AP_Common.h> | ||||||||
#include <GCS_MAVLink/GCS.h> | ||||||||
|
||||||||
|
||||||||
extern const AP_HAL::HAL &hal; | ||||||||
|
||||||||
/************************************************** | ||||||||
* Method: AS5600_AOA | ||||||||
* In: none | ||||||||
* Out: none | ||||||||
* Description: constructor for AS5600_AOA | ||||||||
***************************************************/ | ||||||||
AS5600_AOA::AS5600_AOA() | ||||||||
{ | ||||||||
bus = 2; //Sets the bus number for the device, unclear what this number should be, trial and error to make it work | ||||||||
address = 0x36; //This is the I2C address for the device, it is set by the manufacturer | ||||||||
} | ||||||||
|
||||||||
bool AS5600_AOA::init() | ||||||||
{ | ||||||||
dev = hal.i2c_mgr->get_device(bus, address); | ||||||||
colejmero marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
|
||||||||
if (!dev){ | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
WITH_SEMAPHORE(dev->get_semaphore()); | ||||||||
dev->set_speed(AP_HAL::Device::SPEED_LOW); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should be looking for a |
||||||||
dev->set_retries(2); | ||||||||
|
||||||||
colejmero marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
dev->register_periodic_callback( | ||||||||
50000, | ||||||||
FUNCTOR_BIND_MEMBER(&AS5600_AOA::_timer, void)); | ||||||||
|
||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
/* mode = 0, output PWM, mode = 1 output analog (full range from 0% to 100% between GND and VDD*/ | ||||||||
//void AS5600_AOA::setOutPut(uint8_t mode){ | ||||||||
// uint8_t config_status; | ||||||||
// if (!dev->read_registers(REG_CONF_LO, &config_status, 1)){ | ||||||||
// return; | ||||||||
// } | ||||||||
// if (mode == 1){ | ||||||||
// config_status = config_status & 0xcf; | ||||||||
// }else{ | ||||||||
// config_status = config_status & 0xef; | ||||||||
// } | ||||||||
// | ||||||||
// if (!dev->write_register(REG_CONF_LO, config_status)){ | ||||||||
// return; | ||||||||
// } | ||||||||
//} | ||||||||
|
||||||||
|
||||||||
/******************************************************* | ||||||||
* Method: update | ||||||||
* In: none | ||||||||
* Out: value of raw angle register | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not accurate. |
||||||||
* Description: gets raw value of magnet position. | ||||||||
* start, end, and max angle settings do not apply | ||||||||
*******************************************************/ | ||||||||
void AS5600_AOA::update(void) | ||||||||
{ | ||||||||
WITH_SEMAPHORE(sem); | ||||||||
|
||||||||
//Gets the two relevant register values and multiplies by conversion factor to get degrees | ||||||||
uint16_t angleRaw = ((highByte << 8) | lowByte)*0.087; | ||||||||
|
||||||||
AP::logger().Write("AOAR", "TimeUS, Angle", "QH", AP_HAL::micros64(), angleRaw); | ||||||||
|
||||||||
gcs().send_text(MAV_SEVERITY_INFO, "Angle: %d", angleRaw); | ||||||||
} | ||||||||
|
||||||||
|
||||||||
void AS5600_AOA::_timer(void) | ||||||||
{ | ||||||||
gcs().send_text(MAV_SEVERITY_INFO, "update called - regHiRead: %d regLoRead: %d", regHiRead, regLoRead); | ||||||||
|
||||||||
uint8_t low, high; | ||||||||
|
||||||||
{ | ||||||||
WITH_SEMAPHORE(dev->get_semaphore()); | ||||||||
|
||||||||
if (!dev->read_registers(REG_RAW_ANG_HI, &high, 1)){ | ||||||||
return; | ||||||||
} | ||||||||
|
||||||||
regHiRead = true; | ||||||||
gcs().send_text(MAV_SEVERITY_INFO, "REG_RAW_ANG_HI: %d", high); | ||||||||
|
||||||||
if (!dev->read_registers(REG_RAW_ANG_LO, &low, 1)){ | ||||||||
return; | ||||||||
} | ||||||||
|
||||||||
gcs().send_text(MAV_SEVERITY_INFO, "REG_RAW_ANG_LO: %d", low); | ||||||||
regLoRead = true; | ||||||||
} | ||||||||
|
||||||||
WITH_SEMAPHORE(sem); | ||||||||
lowByte = low; | ||||||||
highByte = high; | ||||||||
} | ||||||||
|
||||||||
|
||||||||
/******************************************************* | ||||||||
* Method: setMaxAngle | ||||||||
* In: new maximum angle to set OR none | ||||||||
* Out: value of max angle register | ||||||||
* Description: sets a value in maximum angle register. | ||||||||
* If no value is provided, method will read position of | ||||||||
* magnet. Setting this register zeros out max position | ||||||||
* register. | ||||||||
*******************************************************/ | ||||||||
/*uint16_t AS5600_AOA::setMaxAngle(uint16_t newMaxAngle) | ||||||||
{ | ||||||||
if(newMaxAngle == -1){ | ||||||||
maxAngle = getRawAngle(); | ||||||||
} else { | ||||||||
maxAngle = newMaxAngle; | ||||||||
} | ||||||||
|
||||||||
WITH_SEMAPHORE(dev->get_semaphore()); | ||||||||
|
||||||||
if (!dev->write_register(REG_MANG_HI, HIGHBYTE(rawStartAngle))){ | ||||||||
return -1; | ||||||||
} | ||||||||
if (!dev->write_register(REG_MANG_LO, LOWBYTE(rawStartAngle))){ | ||||||||
return -1; | ||||||||
} | ||||||||
if (!dev->read_registers(REG_MANG_HI, &highByte, 1) || !dev->read_registers(REG_MANG_LO, &lowByte, 1)){ | ||||||||
return -1; | ||||||||
} | ||||||||
|
||||||||
maxAngle = ((highByte << 8) | lowByte); | ||||||||
return maxAngle; | ||||||||
}*/ | ||||||||
|
||||||||
|
||||||||
/******************************************************* | ||||||||
* Method: getMaxAngle | ||||||||
* In: none | ||||||||
* Out: value of max angle register | ||||||||
* Description: gets value of maximum angle register. | ||||||||
*******************************************************/ | ||||||||
uint16_t AS5600_AOA::getMaxAngle() | ||||||||
{ | ||||||||
WITH_SEMAPHORE(dev->get_semaphore()); | ||||||||
|
||||||||
if (!dev->read_registers(REG_MANG_HI, &highByte, 1) || !dev->read_registers(REG_MANG_LO, &lowByte, 1)){ | ||||||||
return -1; | ||||||||
} | ||||||||
|
||||||||
maxAngle = ((highByte << 8) | lowByte); | ||||||||
|
||||||||
return maxAngle; | ||||||||
} | ||||||||
|
||||||||
|
||||||||
/******************************************************* | ||||||||
* Method: setStartPosition | ||||||||
* In: new start angle position | ||||||||
* Out: value of start position register | ||||||||
* Description: sets a value in start position register. | ||||||||
* If no value is provided, method will read position of | ||||||||
* magnet. | ||||||||
*******************************************************/ | ||||||||
/*uint16_t AS5600_AOA::setStartPosition(uint16_t startAngle = -1) | ||||||||
{ | ||||||||
if(startAngle == -1) | ||||||||
{ | ||||||||
rawStartAngle = getRawAngle(); | ||||||||
} else { | ||||||||
rawStartAngle = startAngle; | ||||||||
} | ||||||||
|
||||||||
WITH_SEMAPHORE(dev->get_semaphore()); | ||||||||
|
||||||||
if (!dev->write_register(REG_ZPOS_HI, HIGHBYTE(rawStartAngle))){ | ||||||||
return -1; | ||||||||
} | ||||||||
if (!dev->write_register(REG_ZPOS_LO, LOWBYTE(rawStartAngle))){ | ||||||||
return -1; | ||||||||
} | ||||||||
if (!dev->read_registers(REG_ZPOS_HI, &highByte, 1) || !dev->read_registers(REG_ZPOS_LO, &lowByte, 1)){ | ||||||||
return -1; | ||||||||
} | ||||||||
|
||||||||
uint16_t zPosition = ((highByte << 8) | lowByte); | ||||||||
|
||||||||
return(zPosition); | ||||||||
}*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#include <cstdint> | ||
#include <AP_HAL/AP_HAL.h> | ||
#include <AP_HAL/utility/OwnPtr.h> | ||
#include <AP_HAL/I2CDevice.h> | ||
#include <unistd.h> | ||
|
||
#include <AP_Common/AP_Common.h> | ||
#include <AP_Logger/AP_Logger.h> | ||
|
||
|
||
class AS5600_AOA { | ||
|
||
public: | ||
|
||
AS5600_AOA(void); | ||
|
||
bool init(); | ||
|
||
void update(void); | ||
|
||
uint16_t setMaxAngle(uint16_t newMaxAngle = -1); | ||
uint16_t getMaxAngle(); | ||
uint16_t setStartPosition(uint16_t startAngle = -1); | ||
uint16_t getStartPosition(); | ||
uint16_t setEndPosition(uint16_t endAngle = -1); | ||
uint16_t getEndPosition(); | ||
uint16_t getScaledAngle(); | ||
|
||
int detectMagnet(); | ||
int getMagnetStrength(); | ||
int getAgc(); | ||
uint16_t getMagnitude(); | ||
|
||
int getBurnCount(); | ||
int burnAngle(); | ||
int burnMaxAngleAndConfig(); | ||
void setOutPut(uint8_t mode); | ||
|
||
bool regHiRead = false; | ||
bool regLoRead = false; | ||
|
||
private: | ||
|
||
HAL_Semaphore sem; | ||
|
||
AP_HAL::OwnPtr<AP_HAL::I2CDevice> dev; | ||
|
||
uint8_t bus; | ||
uint8_t address; | ||
|
||
uint16_t rawStartAngle; | ||
uint16_t zPosition; | ||
uint16_t rawEndAngle; | ||
uint16_t mPosition; | ||
uint16_t maxAngle; | ||
|
||
/* Registers */ | ||
|
||
static const uint8_t REG_ZMCO = 0x00; | ||
static const uint8_t REG_ZPOS_HI = 0x01; | ||
static const uint8_t REG_ZPOS_LO = 0x02; | ||
static const uint8_t REG_MPOS_HI = 0x03; | ||
static const uint8_t REG_MPOS_LO = 0x04; | ||
static const uint8_t REG_MANG_HI = 0x05; | ||
static const uint8_t REG_MANG_LO = 0x06; | ||
static const uint8_t REG_CONF_HI = 0x07; | ||
static const uint8_t REG_CONF_LO = 0x08; | ||
static const uint8_t REG_RAW_ANG_HI = 0x0c; | ||
static const uint8_t REG_RAW_ANG_LO = 0x0d; | ||
static const uint8_t REG_ANG_HI = 0x0e; | ||
static const uint8_t REG_ANG_LO = 0x0f; | ||
static const uint8_t REG_STAT = 0x0b; | ||
static const uint8_t REG_AGC = 0x1a; | ||
static const uint8_t REG_MAG_HI = 0x1b; | ||
static const uint8_t REG_MAG_LO = 0x1c; | ||
static const uint8_t REG_BURN = 0xff; | ||
|
||
int readOneByte(uint8_t in_adr); | ||
int readTwoBytes(uint8_t in_adr_hi, uint8_t in_adr_lo); | ||
int writeOneByte(uint8_t adr_in, uint8_t dat_in); | ||
|
||
uint8_t lowByte; | ||
uint8_t highByte; | ||
|
||
|
||
void _timer(void); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#include "SIM_AS5600.h" | ||
|
||
#include <stdio.h> | ||
|
||
void SITL::AS5600::update(const class Aircraft &aircraft) | ||
{ | ||
|
||
// gcs().send_text(MAV_SEVERITY_INFO, "SIM_AS5600: PWM0=%u PWM1=%u PWM2=%u ENABLE=%u", last_print_pwm0, last_print_pwm1, last_print_pwm2, last_print_enable); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove