Got ADS1299 working in syncronous mode.

This commit is contained in:
Nicolas Trimborn
2021-08-23 21:03:39 +02:00
parent 65e1957d2a
commit 1230e96c1f
14 changed files with 1171 additions and 150 deletions

View File

@@ -2400,9 +2400,10 @@ pads:
SPI2_SS:
name: PA14
definition: Atmel:SAME51_Drivers:0.0.1::SAME51J19A-MF::pad::PA14
mode: Peripheral IO
mode: Digital output
user_label: SPI2_SS
configuration: null
configuration:
pad_initial_level: High
SPI2_MISO:
name: PA15
definition: Atmel:SAME51_Drivers:0.0.1::SAME51J19A-MF::pad::PA15

View File

@@ -7,6 +7,41 @@
#include "ADS1299.h"
/* Settings
* No daisy:
* 4 EMG channels channels at 1000.0 Hz.
* Gain 24, SRB2 Open, Normal electrode input
* Route all Channels_P to Bias derivation
* Route all Channels_P to Bias derivation
* Lead off functions off
Expected ADS Board Registers
* ADS_ID, 00, 3C, 0, 0, 1, 1, 1, 1, 1, 0
* CONFIG1, 01, 94, 1, 0, 0, 1, 0, 1, 0, 0
* CONFIG2, 02, C0, 1, 1, 0, 0, 0, 0, 0, 0
* CONFIG3, 03, EC, 1, 1, 1, 0, 1, 1, 0, 0
* LOFF, 04, 02, 0, 0, 0, 0, 0, 0, 1, 0
* CH1SET, 05, 68, 0, 1, 1, 0, 1, 0, 0, 0
* CH2SET, 06, 68, 0, 1, 1, 0, 1, 0, 0, 0
* CH3SET, 07, 68, 0, 1, 1, 0, 1, 0, 0, 0
* CH4SET, 08, 68, 0, 1, 1, 0, 1, 0, 0, 0
* CH5SET, 09, 68, 0, 1, 1, 0, 1, 0, 0, 0
* CH6SET, 0A, 68, 0, 1, 1, 0, 1, 0, 0, 0
* CH7SET, 0B, 68, 0, 1, 1, 0, 1, 0, 0, 0
* CH8SET, 0C, 68, 0, 1, 1, 0, 1, 0, 0, 0
* BIAS_SENSP, 0D, FF, 1, 1, 1, 1, 1, 1, 1, 1
* BIAS_SENSN, 0E, FF, 1, 1, 1, 1, 1, 1, 1, 1
* LOFF_SENSP, 0F, 00, 0, 0, 0, 0, 0, 0, 0, 0
* LOFF_SENSN, 10, 00, 0, 0, 0, 0, 0, 0, 0, 0
* LOFF_FLIP, 11, 00, 0, 0, 0, 0, 0, 0, 0, 0
* LOFF_STATP, 12, 00, 0, 0, 0, 0, 0, 0, 0, 0
* LOFF_STATN, 13, 00, 0, 0, 0, 0, 0, 0, 0, 0
* GPIO, 14, 0F, 0, 0, 0, 0, 1, 1, 1, 1
* MISC1, 15, 00, 0, 0, 0, 0, 0, 0, 0, 0
* MISC2, 16, 00, 0, 0, 0, 0, 0, 0, 0, 0
* CONFIG4, 17, 00, 0, 0, 0, 0, 0, 0, 0, 0
*/
void initialize_ads()
{
spi_m_sync_disable(ADS1299.SPI_descr);
@@ -16,17 +51,41 @@ void initialize_ads()
/* Init SPI*/
spi_m_sync_enable(ADS1299.SPI_descr);
gpio_set_pin_level(ADS1299.SS_pin, true);
delay_us(20);
/* Reset ADS1299 - Reset Active Low*/
gpio_set_pin_level(ADS1299.reset_pin, false);
delay_us(5);
delay_us(20);
gpio_set_pin_level(ADS1299.reset_pin, true);
delay_us(20);
ADS1299_RESET(); // all registers set to default
ADS1299_SDATAC(); // stop Read Data Continuous mode to communicate with ADS
ADS1299_RREGS(0x00, 0x17); // read ADS registers starting at 0x00 and ending at 0x17
/* Write Config Registers */
ADS1299_WREG(CONFIG1,0x94); // Set Config 1 Register
ADS1299_WREG(CONFIG2,0xC0); // Set Config 2 Register
ADS1299_WREG(CONFIG3,0xEC); // Set Config 3 Register
ADS1299_WREG(LOFF,0x02); // Set LOFF Register
for(uint8_t i=CH1SET; i<=CH4SET; i++) // set up to modify the 4 channel setting registers
{
ADS1299.regData[i] = 0x68; // the regData array mirrors the ADS1299 register addresses
}
ADS1299_WREGS(CH1SET,3); // write new channel settings
ADS1299_WREG(BIAS_SENSP,0xFF); // Set BIAS_SENSP Register
ADS1299_WREG(BIAS_SENSN,0xFF); // Set BIAS_SENSN Register
ADS1299_WREG(BIAS_SENSP,0xFF); // Set BIAS_SENSP Register
ADS1299_WREG(GPIO_REG,0x0F); // Set BIAS_SENSP Register
/* Remaining Registers left at 0x00 */
ADS1299_RREGS(0x00, 0x17); // read ADS registers to verify settings
ADS1299_RDATAC(); // enter Read Data Continuous mode
volatile int x = 0;
}
uint8_t getDeviceID()
{
uint8_t data = RREG(0x00);
uint8_t data = ADS1299_RREG(0x00);
return data;
}
@@ -34,120 +93,179 @@ uint8_t getDeviceID()
// AS5048 Registers & Commands
// ----------------------------------------------------------------------
void WAKEUP() {
void ADS1299_WAKEUP() {
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, _WAKEUP);
_transfer_byte(ADS1299.SPI_descr, _WAKEUP);
gpio_set_pin_level(ADS1299.SS_pin, true);
delay_us(3); //must wait 4 tCLK cycles before sending another command (Datasheet, pg. 35)
}
void STANDBY() { // only allowed to send WAKEUP after sending STANDBY
void ADS1299_STANDBY() { // only allowed to send WAKEUP after sending STANDBY
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, _STANDBY);
_transfer_byte(ADS1299.SPI_descr, _STANDBY);
gpio_set_pin_level(ADS1299.SS_pin, true);
}
void RESET() { // reset all the registers to default settings
void ADS1299_RESET() { // reset all the registers to default settings
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, _RESET);
_transfer_byte(ADS1299.SPI_descr, _RESET);
delay_us(12); //must wait 18 tCLK cycles to execute this command (Datasheet, pg. 35)
gpio_set_pin_level(ADS1299.SS_pin, true);
}
void START() { //start data conversion
void ADS1299_START() { //start data conversion
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, _START);
_transfer_byte(ADS1299.SPI_descr, _START);
gpio_set_pin_level(ADS1299.SS_pin, true);
}
void STOP() { //stop data conversion
void ADS1299_STOP() { //stop data conversion
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, _STOP);
_transfer_byte(ADS1299.SPI_descr, _STOP);
gpio_set_pin_level(ADS1299.SS_pin, true);
}
void RDATAC() {
void ADS1299_RDATAC() {
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, _RDATAC);
_transfer_byte(ADS1299.SPI_descr, _RDATAC);
gpio_set_pin_level(ADS1299.SS_pin, true);
delay_us(3);
}
void SDATAC() {
void ADS1299_SDATAC() {
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, _SDATAC);
_transfer_byte(ADS1299.SPI_descr, _SDATAC);
gpio_set_pin_level(ADS1299.SS_pin, true);
delay_us(3); //must wait 4 tCLK cycles after executing this command (Datasheet, pg. 37)
}
// ----------------------------------------------------------------------
// SPI register Related Commands
// ----------------------------------------------------------------------
// reads ONE register at _address
uint8_t RREG(uint8_t _address)
uint8_t ADS1299_RREG(uint8_t _address)
{
uint8_t opcode1 = _address + 0x20; // RREG expects 001rrrrr where rrrrr = _address
uint8_t opcode1 = _address + 0x20; // RREG expects 001rrrrr where rrrrr = _address
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, opcode1);
transfer_byte(ADS1299.SPI_descr, 0x00);
ADS1299.regData[_address] = transfer_byte(ADS1299.SPI_descr, 0x00);
_transfer_byte(ADS1299.SPI_descr, opcode1);
_transfer_byte(ADS1299.SPI_descr, 0x00);
ADS1299.regData[_address] = _transfer_byte(ADS1299.SPI_descr, 0x00);
gpio_set_pin_level(ADS1299.SS_pin, true);
return ADS1299.regData[_address];
}
// Read more than one register starting at _address
void RREGS(uint8_t _address, uint8_t _numRegistersMinusOne)
void ADS1299_RREGS(uint8_t _address, uint8_t _numRegistersMinusOne)
{
uint8_t opcode1 = _address + 0x20; // RREG expects 001rrrrr where rrrrr = _address
uint8_t opcode1 = _address + 0x20; // RREG expects 001rrrrr where rrrrr = _address
gpio_set_pin_level(ADS1299.SS_pin, false);
transfer_byte(ADS1299.SPI_descr, opcode1);
transfer_byte(ADS1299.SPI_descr, _numRegistersMinusOne);
for(int i = 0; i <= _numRegistersMinusOne; i++){
ADS1299.regData[_address + i] = transfer_byte(ADS1299.SPI_descr, 0x00); // add register uint8_t to mirror array
_transfer_byte(ADS1299.SPI_descr, opcode1);
_transfer_byte(ADS1299.SPI_descr, _numRegistersMinusOne);
for(int i = 0; i <= _numRegistersMinusOne; i++){ // add register uint8_t to mirror array
ADS1299.regData[_address + i] = _transfer_byte(ADS1299.SPI_descr, 0x00);
}
ADS1299.regData[_address] = transfer_byte(ADS1299.SPI_descr, 0x00);
//ADS1299.regData[_address] = _transfer_byte(ADS1299.SPI_descr, 0x00);
gpio_set_pin_level(ADS1299.SS_pin, true);
}
void WREG(uint8_t _address, uint8_t _value) { // Write ONE register at _address
void ADS1299_WREG(uint8_t _address, uint8_t _value) { // Write ONE register at _address
uint8_t opcode1 = _address + 0x40; // WREG expects 010rrrrr where rrrrr = _address
gpio_set_pin_level(ADS1299.SS_pin, false); // open SPI
transfer_byte(ADS1299.SPI_descr, opcode1); // Send WREG command & address
transfer_byte(ADS1299.SPI_descr, 0x00); // Send number of registers to read -1
transfer_byte(ADS1299.SPI_descr, _value); // Write the value to the register
_transfer_byte(ADS1299.SPI_descr, opcode1); // Send WREG command & address
_transfer_byte(ADS1299.SPI_descr, 0x00); // Send number of registers to read -1
_transfer_byte(ADS1299.SPI_descr, _value); // Write the value to the register
gpio_set_pin_level(ADS1299.SS_pin, true); // close SPI
ADS1299.regData[_address] = _value; // update the mirror array
}
void WREGS(uint8_t _address, uint8_t _numRegistersMinusOne) {
void ADS1299_WREGS(uint8_t _address, uint8_t _numRegistersMinusOne) {
uint8_t opcode1 = _address + 0x40; // WREG expects 010rrrrr where rrrrr = _address
gpio_set_pin_level(ADS1299.SS_pin, false); // open SPI
transfer_byte(ADS1299.SPI_descr, opcode1); // Send WREG command & address
transfer_byte(ADS1299.SPI_descr, _numRegistersMinusOne); // Send number of registers to read -1
_transfer_byte(ADS1299.SPI_descr, opcode1); // Send WREG command & address
_transfer_byte(ADS1299.SPI_descr, _numRegistersMinusOne); // Send number of registers to read -1
for (int i=_address; i <=(_address + _numRegistersMinusOne); i++){
transfer_byte(ADS1299.SPI_descr, ADS1299.regData[i]); // Write to the registers
_transfer_byte(ADS1299.SPI_descr, ADS1299.regData[i]); // Write to the registers
}
gpio_set_pin_level(ADS1299.SS_pin, true); // close SPI
}
void updateChannelData()
//read data
void ADS1299_RDATA() { // use in Stop Read Continuous mode when DRDY goes low
uint8_t inByte;
ADS1299.stat_1 = 0; // clear the status registers
int nchan = 4; //assume 4 channel.
gpio_set_pin_level(ADS1299.SS_pin, false); // open SPI
_transfer_byte(ADS1299.SPI_descr, _RDATA);
for(int i=0; i<3; i++){ // read 3 byte status register (1100+LOFF_STATP+LOFF_STATN+GPIO[7:4])
inByte = _transfer_byte(ADS1299.SPI_descr, 0x00);
ADS1299.stat_1 = (ADS1299.stat_1<<8) | inByte;
}
for(int i = 0; i<nchan; i++){
for(int j=0; j<3; j++){ // read 24 bits of channel data from 1st ADS in 8 3 byte chunks
inByte = _transfer_byte(ADS1299.SPI_descr, 0x00);
ADS1299.channel_data[i] = (ADS1299.channel_data[i]<<8) | inByte;
}
}
for(int i=0; i<nchan; i++){ // convert 3 byte 2's compliment to 4 byte 2's compliment
if(bitRead(ADS1299.channel_data[i],23) == 1){
ADS1299.channel_data[i] |= 0xFF000000;
}else{
ADS1299.channel_data[i] &= 0x00FFFFFF;
}
}
}
//int32_t* ADS1299_UPDATECHANNELDATA()
//{
//uint8_t inByte;
//int nchan=4; //assume 8 channel. If needed, it automatically changes to 16 automatically in a later block.
//gpio_set_pin_level(ADS1299.SS_pin, false); // open SPI
//
//// READ CHANNEL DATA FROM FIRST ADS IN DAISY LINE
//for(int i=0; i<3; i++){ // read 3 byte status register from ADS 1 (1100+LOFF_STATP+LOFF_STATN+GPIO[7:4])
//inByte = _transfer_byte(ADS1299.SPI_descr,0x00);
//ADS1299.stat_1 = (ADS1299.stat_1<<8) | inByte;
//}
//
//for(int i = 0; i<8; i++){
//for(int j=0; j<3; j++){ // read 24 bits of channel data from 1st ADS in 8 3 byte chunks
//inByte = _transfer_byte(ADS1299.SPI_descr, 0x00);
//ADS1299.channel_data[i] = (ADS1299.channel_data[i]<<8) | inByte;
//}
//}
//
//gpio_set_pin_level(ADS1299.SS_pin, true); // close SPI
//
////reformat the numbers
//for(int i=0; i<nchan; i++){ // convert 3 byte 2's compliment to 4 byte 2's compliment
//if(bitRead(ADS1299.channel_data[i],23) == 1){
//ADS1299.channel_data[i] |= 0xFF000000;
//}else{
//ADS1299.channel_data[i] &= 0x00FFFFFF;
//}
//}
//return &ADS1299.channel_data;
//}
int32_t* ADS1299_UPDATECHANNELDATA()
{
uint8_t inByte;
int nchan=4; //assume 8 channel. If needed, it automatically changes to 16 automatically in a later block.
gpio_set_pin_level(ADS1299.SS_pin, false); // open SPI
// READ CHANNEL DATA FROM FIRST ADS IN DAISY LINE
for(int i=0; i<3; i++){ // read 3 byte status register from ADS 1 (1100+LOFF_STATP+LOFF_STATN+GPIO[7:4])
inByte = transfer_byte(ADS1299.SPI_descr,0x00);
for(int i=0; i<3; i++){ // read 3 byte status register from ADS 1 (1100+LOFF_STATP+LOFF_STATN+GPIO[7:4])
inByte = _transfer_byte(ADS1299.SPI_descr,0x00);
ADS1299.stat_1 = (ADS1299.stat_1<<8) | inByte;
}
for(int i = 0; i<8; i++){
for(int j=0; j<3; j++){ // read 24 bits of channel data from 1st ADS in 8 3 byte chunks
inByte = transfer_byte(ADS1299.SPI_descr, 0x00);
ADS1299.channel_data[i] = (ADS1299.channel_data[i]<<8) | inByte;
inByte = _transfer_byte(ADS1299.SPI_descr, 0x00);
_channel_data[i] = (_channel_data[i]<<8) | inByte;
}
}
@@ -155,16 +273,16 @@ void updateChannelData()
//reformat the numbers
for(int i=0; i<nchan; i++){ // convert 3 byte 2's compliment to 4 byte 2's compliment
if(bitRead(ADS1299.channel_data[i],23) == 1){
ADS1299.channel_data[i] |= 0xFF000000;
if(bitRead(_channel_data[i],23) == 1){
_channel_data[i] |= 0xFF000000;
}else{
ADS1299.channel_data[i] &= 0x00FFFFFF;
_channel_data[i] &= 0x00FFFFFF;
}
}
return &_channel_data;
}
uint8_t transfer_byte(struct spi_m_sync_descriptor *spi, uint8_t command)
uint8_t _transfer_byte(struct spi_m_sync_descriptor *spi, uint8_t command)
{
uint8_t in_buf[1], out_buf[1];
uint8_t wordRead;
@@ -175,11 +293,11 @@ uint8_t transfer_byte(struct spi_m_sync_descriptor *spi, uint8_t command)
xfer.txbuf = out_buf;
xfer.size = 1;
spi_m_sync_transfer(ADS1299.SPI_descr, &xfer);
wordRead = in_buf;
wordRead = in_buf[0];
return (wordRead);
}
uint16_t transfer_word(struct spi_m_sync_descriptor *spi, uint16_t command)
uint16_t _transfer_word(struct spi_m_sync_descriptor *spi, uint16_t command)
{
uint8_t in_buf[2], out_buf[2];
uint16_t wordRead;

View File

@@ -52,53 +52,56 @@
#define MISC2 0x16
#define CONFIG4 0x17
volatile int32_t _channel_data[8];
/* Struct Definitions */
struct SPI_ADS1299 {
struct spi_m_sync_descriptor *SPI_descr;
uint8_t flags;
uint32_t SS_pin;
uint32_t reset_pin;
uint8_t regData [24];
int16_t channel_data[16]; // Must Equal n_dev
int16_t stat_1;
volatile struct SPI_ADS1299 {
volatile struct spi_m_sync_descriptor *SPI_descr;
volatile bool data_ReadyFlag;
volatile uint32_t SS_pin;
volatile uint32_t reset_pin;
volatile uint8_t regData [24];
volatile int32_t* channel_data; // Must Equal n_dev
volatile int16_t stat_1;
};
static struct SPI_ADS1299 ADS1299 = {
static volatile struct SPI_ADS1299 ADS1299 = {
.SPI_descr = &SPI_2,
.flags = 0,
.data_ReadyFlag = false,
.SS_pin = SPI2_SS,
.reset_pin = ADS_RESET,
.regData = {0},
.channel_data = {0},
.channel_data = &_channel_data[0],
};
void initialize_ads();
//ADS1299 SPI Command Definitions (Datasheet, p35)
//System Commands
void WAKEUP();
void STANDBY();
void RESET();
void START();
void STOP();
void ADS1299_WAKEUP();
void ADS1299_STANDBY();
void ADS1299_RESET();
void ADS1299_START();
void ADS1299_STOP();
//Data Read Commands
void RDATAC();
void SDATAC();
void RDATA();
void ADS1299_RDATAC();
void ADS1299_SDATAC();
void ADS1299_RDATA();
//Register Read/Write Commands
uint8_t getDeviceID();
uint8_t RREG(uint8_t _address);
void RREGS(uint8_t _address, uint8_t _numRegistersMinusOne);
uint8_t ADS1299_RREG(uint8_t _address);
void ADS1299_RREGS(uint8_t _address, uint8_t _numRegistersMinusOne);
void printRegisterName(uint8_t _address);
void WREG(uint8_t _address, uint8_t _value);
void WREGS(uint8_t _address, uint8_t _numRegistersMinusOne);
void ADS1299_WREG(uint8_t _address, uint8_t _value);
void ADS1299_WREGS(uint8_t _address, uint8_t _numRegistersMinusOne);
void printHex(uint8_t _data);
void updateChannelData();
int32_t* ADS1299_UPDATECHANNELDATA();
uint8_t transfer_byte(struct spi_m_sync_descriptor *spi, uint8_t command);
uint16_t transfer_word(struct spi_m_sync_descriptor *spi, uint16_t command);
uint8_t _transfer_byte(struct spi_m_sync_descriptor *spi, uint8_t command);
uint16_t _transfer_word(struct spi_m_sync_descriptor *spi, uint16_t command);
//SPI Transfer function

View File

@@ -11,6 +11,8 @@
#include "Ethercat_QSPI.h"
extern volatile int32_t _channel_data[8];
//Write To Ecat Total Bytes (XX bytes)
/* Motor 1*/
static volatile uint8_t *M1_Status = (uint8_t *)&QSPI_tx_buffer[0];
@@ -37,14 +39,10 @@ static volatile int16_t *M2_Motor_currentPhC = (((int16_t *)&QSPI_tx_buffer[8]
static volatile int16_t *M2_Motor__hallState = ((int16_t *)&QSPI_tx_buffer[9]);
static volatile int16_t *M2_Motor_dutyCycle = (((int16_t *)&QSPI_tx_buffer[9])+1);
/* EMG */
static volatile int16_t *EMG_CH1 = (((int16_t *)&QSPI_tx_buffer[10]));
static volatile int16_t *EMG_CH2 = (((int16_t *)&QSPI_tx_buffer[10])+1);
static volatile int16_t *EMG_CH3 = (((int16_t *)&QSPI_tx_buffer[11]));
static volatile int16_t *EMG_CH4 = (((int16_t *)&QSPI_tx_buffer[11])+1);
static volatile int16_t *EMG_CH5 = (((int16_t *)&QSPI_tx_buffer[12]));
static volatile int16_t *EMG_CH6 = (((int16_t *)&QSPI_tx_buffer[12])+1);
static volatile int16_t *EMG_CH7 = (((int16_t *)&QSPI_tx_buffer[13]));
static volatile int16_t *EMG_CH8 = (((int16_t *)&QSPI_tx_buffer[13])+1);
static volatile int32_t *EMG_CH1 = (((int32_t *)&QSPI_tx_buffer[10]));
static volatile int32_t *EMG_CH2 = (((int32_t *)&QSPI_tx_buffer[11]));
static volatile int32_t *EMG_CH3 = (((int32_t *)&QSPI_tx_buffer[12]));
static volatile int32_t *EMG_CH4 = (((int32_t *)&QSPI_tx_buffer[13]));
/* Reserved space */
static volatile int16_t *Spare1_tx = (((int16_t *)&QSPI_tx_buffer[14]));
@@ -167,7 +165,7 @@ static void update_telemetry(void)
/* Motor 1 */
*M1_Status = Motor1.motor_state.currentstate;
*M1_Joint_rel_position = Motor1.motor_status.Num_Steps;
//*M1_Joint_abs_position = ((int16_t *)&QSPI_tx_buffer[1]);
*M1_Joint_abs_position = Motor1.motor_status.abs_position;
//*M1_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1])+1);
*M1_Motor_current_bus = convert_to_mA(Motor1.Iphase_pu.Bus);
*M1_Motor_currentPhA = convert_to_mA(Motor1.Iphase_pu.A);
@@ -180,7 +178,7 @@ static void update_telemetry(void)
/* Motor 2 */
*M2_Status = Motor2.motor_state.currentstate;
*M2_Joint_rel_position = Motor2.motor_status.Num_Steps;
//*M1_Joint_abs_position = ((int16_t *)&QSPI_tx_buffer[1]);
*M2_Joint_abs_position = Motor2.motor_status.abs_position;
//*M1_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1])+1);
*M2_Motor_current_bus = convert_to_mA( Motor2.Iphase_pu.Bus);
*M2_Motor_currentPhA = convert_to_mA( Motor2.Iphase_pu.A);
@@ -190,6 +188,15 @@ static void update_telemetry(void)
*M2_Motor_dutyCycle = Motor2.motor_status.duty_cycle;
*M2_Motor_speed = (int16_t)Motor2.motor_status.calc_rpm;
//*M2_Joint_abs_position = Motor2.motor_status.actualDirection;
*EMG_CH1 = _channel_data[0];
*EMG_CH2 = _channel_data[1];
*EMG_CH3 = _channel_data[2];
*EMG_CH4 = _channel_data[3];
//*EMG_CH1 = 1;
//*EMG_CH2 = 2;
//*EMG_CH3 = 3;
//*EMG_CH4 = 4;
}
static void update_setpoints(void)
@@ -291,10 +298,7 @@ static inline void comms_check(void)
*EMG_CH2 = 24;
*EMG_CH3 = -25;
*EMG_CH4 = 26;
*EMG_CH5 = -27;
*EMG_CH6 = 28;
*EMG_CH7 = -29;
*EMG_CH8 = 30;
/* Motor 3*/
*M3_Status = 1;

View File

@@ -11,6 +11,8 @@
#include "Ethercat_QSPI.h"
extern volatile int32_t _channel_data[8];
//Write To Ecat Total Bytes (XX bytes)
/* Motor 1*/
static volatile uint8_t *M1_Status = (uint8_t *)&QSPI_tx_buffer[0];
@@ -37,14 +39,10 @@ static volatile int16_t *M2_Motor_currentPhC = (((int16_t *)&QSPI_tx_buffer[8]
static volatile int16_t *M2_Motor__hallState = ((int16_t *)&QSPI_tx_buffer[9]);
static volatile int16_t *M2_Motor_dutyCycle = (((int16_t *)&QSPI_tx_buffer[9])+1);
/* EMG */
static volatile int16_t *EMG_CH1 = (((int16_t *)&QSPI_tx_buffer[10]));
static volatile int16_t *EMG_CH2 = (((int16_t *)&QSPI_tx_buffer[10])+1);
static volatile int16_t *EMG_CH3 = (((int16_t *)&QSPI_tx_buffer[11]));
static volatile int16_t *EMG_CH4 = (((int16_t *)&QSPI_tx_buffer[11])+1);
static volatile int16_t *EMG_CH5 = (((int16_t *)&QSPI_tx_buffer[12]));
static volatile int16_t *EMG_CH6 = (((int16_t *)&QSPI_tx_buffer[12])+1);
static volatile int16_t *EMG_CH7 = (((int16_t *)&QSPI_tx_buffer[13]));
static volatile int16_t *EMG_CH8 = (((int16_t *)&QSPI_tx_buffer[13])+1);
static volatile int32_t *EMG_CH1 = (((int32_t *)&QSPI_tx_buffer[10]));
static volatile int32_t *EMG_CH2 = (((int32_t *)&QSPI_tx_buffer[11]));
static volatile int32_t *EMG_CH3 = (((int32_t *)&QSPI_tx_buffer[12]));
static volatile int32_t *EMG_CH4 = (((int32_t *)&QSPI_tx_buffer[13]));
/* Reserved space */
static volatile int16_t *Spare1_tx = (((int16_t *)&QSPI_tx_buffer[14]));
@@ -167,7 +165,7 @@ static void update_telemetry(void)
/* Motor 1 */
*M1_Status = Motor1.motor_state.currentstate;
*M1_Joint_rel_position = Motor1.motor_status.Num_Steps;
//*M1_Joint_abs_position = ((int16_t *)&QSPI_tx_buffer[1]);
*M1_Joint_abs_position = Motor1.motor_status.abs_position;
//*M1_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1])+1);
*M1_Motor_current_bus = convert_to_mA(Motor1.Iphase_pu.Bus);
*M1_Motor_currentPhA = convert_to_mA(Motor1.Iphase_pu.A);
@@ -180,7 +178,7 @@ static void update_telemetry(void)
/* Motor 2 */
*M2_Status = Motor2.motor_state.currentstate;
*M2_Joint_rel_position = Motor2.motor_status.Num_Steps;
//*M1_Joint_abs_position = ((int16_t *)&QSPI_tx_buffer[1]);
*M2_Joint_abs_position = Motor2.motor_status.abs_position;
//*M1_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1])+1);
*M2_Motor_current_bus = convert_to_mA( Motor2.Iphase_pu.Bus);
*M2_Motor_currentPhA = convert_to_mA( Motor2.Iphase_pu.A);
@@ -190,6 +188,15 @@ static void update_telemetry(void)
*M2_Motor_dutyCycle = Motor2.motor_status.duty_cycle;
*M2_Motor_speed = (int16_t)Motor2.motor_status.calc_rpm;
//*M2_Joint_abs_position = Motor2.motor_status.actualDirection;
*EMG_CH1 = _channel_data[0];
*EMG_CH2 = _channel_data[1];
*EMG_CH3 = _channel_data[2];
*EMG_CH4 = _channel_data[3];
//*EMG_CH1 = 1;
//*EMG_CH2 = 2;
//*EMG_CH3 = 3;
//*EMG_CH4 = 4;
}
static void update_setpoints(void)
@@ -291,10 +298,7 @@ static inline void comms_check(void)
*EMG_CH2 = 24;
*EMG_CH3 = -25;
*EMG_CH4 = 26;
*EMG_CH5 = -27;
*EMG_CH6 = 28;
*EMG_CH7 = -29;
*EMG_CH8 = 30;
/* Motor 3*/
*M3_Status = 1;

View File

@@ -150,7 +150,7 @@
<AcmeProjectActionInfo Action="File" Source="hri/hri_usb_e51.h" IsConfig="false" Hash="x6M7vYgNCS2oECqykr5+yw" />
<AcmeProjectActionInfo Action="File" Source="hri/hri_wdt_e51.h" IsConfig="false" Hash="o9Rg/hyuMzwOCphVc7uG1w" />
<AcmeProjectActionInfo Action="File" Source="main.c" IsConfig="false" Hash="k0AH7j+BrmdFhBPzCCMptA" />
<AcmeProjectActionInfo Action="File" Source="driver_init.c" IsConfig="false" Hash="x19qC0FjPq5Eh54u7ftL1g" />
<AcmeProjectActionInfo Action="File" Source="driver_init.c" IsConfig="false" Hash="Q3o1x3vWYELO1L6mRVKUIA" />
<AcmeProjectActionInfo Action="File" Source="driver_init.h" IsConfig="false" Hash="hkPygmC76Qup+RNNN/cLrA" />
<AcmeProjectActionInfo Action="File" Source="atmel_start_pins.h" IsConfig="false" Hash="q332kmNEqTBha3F9F86pCg" />
<AcmeProjectActionInfo Action="File" Source="examples/driver_examples.h" IsConfig="false" Hash="HwCfGc+NYMxlXMiyssgrQQ" />
@@ -417,7 +417,7 @@
<armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
<armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
<armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
<armgcc.compiler.miscellaneous.OtherFlags>-std=gnu99 -mfloat-abi=hard -mfpu=fpv4-sp-d16</armgcc.compiler.miscellaneous.OtherFlags>
<armgcc.compiler.miscellaneous.OtherFlags>-std=gnu11 -mfloat-abi=hard -mfpu=fpv4-sp-d16</armgcc.compiler.miscellaneous.OtherFlags>
<armgcc.linker.general.UseNewlibNano>True</armgcc.linker.general.UseNewlibNano>
<armgcc.linker.libraries.Libraries>
<ListValues>

View File

@@ -104,6 +104,7 @@ void BldcInitStruct(BLDCMotor_t* const motor, BLDCMotor_param_t * const motor_pa
motor->motor_status.actualDirection = 0;
motor->motor_status.duty_cycle = 0;
motor->motor_status.calc_rpm = 0;
motor->motor_status.abs_position = 0;
motor->motor_status.Num_Steps = 0;
motor->motor_status.cur_comm_step = 0;
motor->motor_status.currentHallPattern = 1;

View File

@@ -62,6 +62,7 @@ volatile typedef struct
volatile uint8_t actualDirection; //! The actual direction of rotation.
volatile uint16_t duty_cycle;
volatile int16_t calc_rpm;
volatile int16_t abs_position;
volatile int16_t Num_Steps;
/* Hall States */
//volatile uint8_t prevHallPattern;

View File

@@ -663,6 +663,16 @@ void system_init(void)
// GPIO on PA14
gpio_set_pin_level(SPI2_SS,
// <y> Initial level
// <id> pad_initial_level
// <false"> Low
// <true"> High
true);
// Set pin direction to output
gpio_set_pin_direction(SPI2_SS, GPIO_DIRECTION_OUT);
gpio_set_pin_function(SPI2_SS, GPIO_PIN_FUNCTION_OFF);
// GPIO on PA25

View File

@@ -60,7 +60,7 @@ void adc_sram_dma_callback(struct _dma_resource *adc_dma_res)
}
// ----------------------------------------------------------------------
// EtherCAT Cycle Timer - 1kHz
// Speed Counter TC2 Overflow handler
// ----------------------------------------------------------------------
void TC2_Handler(void)
{
@@ -71,7 +71,7 @@ void TC2_Handler(void)
}
// ----------------------------------------------------------------------
//
// Speed Counter TC2 Overflow handler
// ----------------------------------------------------------------------
void TC4_Handler(void)
{
@@ -81,7 +81,9 @@ void TC4_Handler(void)
}
}
// ----------------------------------------------------------------------
// BLDC Driver External Interrupt Handlers
// ----------------------------------------------------------------------
static void M1_RESET_BAR(void)
{
volatile int x = 0;
@@ -92,7 +94,15 @@ static void M2_RESET_BAR(void)
volatile int x = 0;
}
// ----------------------------------------------------------------------
// ADS Data Ready Interrupt
// ----------------------------------------------------------------------
void ADS1299_dataReadyISR(void)
{
ADS1299.data_ReadyFlag = true;
//int32_t* temp = ADS1299_UPDATECHANNELDATA();
volatile int x = 1;
}

View File

@@ -6,6 +6,7 @@
#include "bldc.h"
#include "bldc_types.h"
#include "EtherCAT_QSPI.h"
#include "ADS1299.h"
#include "EtherCAT_SlaveDef.h"
//#include "MSIF_master.h"
#include "configuration.h"
@@ -13,7 +14,7 @@
#include "statemachine.h"
#include "angle_sensors.h"
#include "ADS1299.h"
void process_currents()
@@ -79,10 +80,12 @@ void enable_NVIC_IRQ(void)
//NVIC_EnableIRQ(TC4_IRQn); // TC4: M2_Speed_Timer
NVIC_EnableIRQ(DMAC_0_IRQn);
NVIC_EnableIRQ(DMAC_1_IRQn);
NVIC_SetPriority(DMAC_0_IRQn, 2);
NVIC_SetPriority(DMAC_0_IRQn, 1);
NVIC_SetPriority(ADC1_0_IRQn, 3);
NVIC_EnableIRQ(TCC0_0_IRQn);
NVIC_EnableIRQ(TCC1_0_IRQn);
NVIC_EnableIRQ(EIC_2_IRQn);
NVIC_SetPriority(EIC_2_IRQn, 3);
//NVIC_SetPriority(TCC0_0_IRQn, 3);
//NVIC_EnableIRQ(EIC_5_IRQn);
}
@@ -146,40 +149,38 @@ int main(void)
{
/* Initializes MCU, drivers and middleware */
atmel_start_init();
//initMotorParameters();
//configure_tcc_pwm();
//BldcInitStruct(&Motor1, &FH_22mm24BXTR);
//BldcInitStruct(&Motor2, &FH_32mm24BXTR);
//Motor1.readHall = &readHallSensorM1;
//Motor2.readHall = &readHallSensorM2;
//read_zero_current_offset_value(&Motor1, &Motor2);
//adc_sync_enable_channel(&ADC_1, 6);
//adc_init_dma();
//config_qspi();
//custom_logic_enable();
//enable_NVIC_IRQ();
//ECAT_STATE_MACHINE();
//One_ms_timer_init();
__disable_irq();
/* BLDC INIT */
BldcInitStruct(&Motor1, &FH_22mm24BXTR);
BldcInitStruct(&Motor2, &FH_32mm24BXTR);
Motor1.readHall = &readHallSensorM1;
Motor2.readHall = &readHallSensorM2;
/* Current Offeset Calibration */
read_zero_current_offset_value(&Motor1, &Motor2);
/* Configure Hardware */
config_qspi();
configure_tcc_pwm();
adc_sync_enable_channel(&ADC_1, 6);
/* SPI & DMA Configs */
boardToBoardTransferInit();
init_spi_master_dma_descriptors();
adc_init_dma();
ECAT_STATE_MACHINE();
One_ms_timer_init();
custom_logic_enable();
//speed_timer_init();
angle_sensor_init();
initialize_ads();
/* External IRQ Config */
ext_irq_register(GPIO_PIN(ADS_DATA_RDY), ADS1299_dataReadyISR);
enable_NVIC_IRQ();
__enable_irq();
//ADS1299_START();
/* Replace with your application code */
while (1) {
@@ -189,20 +190,15 @@ int main(void)
update_telemetry();
update_setpoints();
PORT->Group[1].OUTCLR.reg = (1<<GPIO_PIN(SPI1_CS));
_dma_enable_transaction(DMAC_CHANNEL_CONF_SERCOM_1_RECEIVE, false);
_dma_enable_transaction(DMAC_CHANNEL_CONF_SERCOM_1_TRANSMIT, false);
volatile int x = 1;
DMAC->Channel[0].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
DMAC->Channel[1].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
//_dma_enable_transaction(DMAC_CHANNEL_CONF_SERCOM_1_RECEIVE, false);
//_dma_enable_transaction(DMAC_CHANNEL_CONF_SERCOM_1_TRANSMIT, false);
//
int16_t* angles;
//int16_t* field;
//int16_t* temp;
angles = read_angle();
*M1_Joint_abs_position = degrees(angles[0]);
*M2_Joint_abs_position = degrees(angles[1]);
START();
*EMG_CH1 = getDeviceID();
//int16_t* angles;
//angles = read_angle();
//Motor1.motor_status.abs_position = degrees(angles[0]);
//Motor2.motor_status.abs_position = degrees(angles[1]);
////field = ang_sense_read(AS_CMD_MAGNITUDE);
//*Spare1_tx = (field[0] & AS_MASK);
@@ -210,10 +206,7 @@ int main(void)
//temp = ang_sense_read(AS_CMD_TEMP);
//*Spare3_tx = (int16_t)(((float)(temp[0] & AS_MASK) / 8.0) - 273.15);
//*Spare4_tx = (int16_t)(((float)(temp[1] & AS_MASK) / 8.0) - 273.15);
volatile int y = 0;
//spi_m_dma_transfer(&SPI_1_MSIF, (uint8_t*)Slave_1.tx_buffer, (uint8_t*)Slave_1.rx_buffer, MASTER_BUFFER_SIZE);
}
if (Motor1.timerflags.current_loop_tic) {
@@ -221,6 +214,12 @@ int main(void)
exec_commutation(&Motor1);
exec_commutation(&Motor2);
}
if (ADS1299.data_ReadyFlag){
ADS1299.data_ReadyFlag = false;
//ADS1299_UPDATECHANNELDATA();
}
if (run_ECAT) {ECAT_STATE_MACHINE();}
}