Library for MAX14871 Shield, MAXREFDES89#
Dependents: MAXREFDES89_MAX14871_Shield_Demo MAXREFDES89_Test_Program Line_Following_Bot Line_Following_Bot_Pololu
max14871_shield.cpp
- Committer:
- j3
- Date:
- 2015-07-23
- Revision:
- 0:b5189f4ce1cb
- Child:
- 1:7e9b864ddacf
File content as of revision 0:b5189f4ce1cb:
/******************************************************************//** * @file max14871_shield.h * * @author Justin Jordan * * @version 0.0 * * Started: 18JUL15 * * Updated: * * @brief Source file for Max14871_Shield class *********************************************************************** * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Maxim Integrated * Products, Inc. shall not be used except as stated in the Maxim Integrated * Products, Inc. Branding Policy. * * The mere transfer of this software does not imply any licenses * of trade secrets, proprietary technology, copyrights, patents, * trademarks, maskwork rights, or any other form of intellectual * property whatsoever. Maxim Integrated Products, Inc. retains all * ownership rights. **********************************************************************/ #include "max14871_shield.h" #define MIN_PERIOD (20) //50KHz //Motor Driver control inputs #define MD_EN (0x01) #define MD_DIR (0x02) #define MD_MODE0 (0x04) #define MD_MODE1 (0x08) #define MAX_VREF (100) //GPIO Expander Default Configurations #define MAX7300_ALL_OUTPUTS (0x55) #define MAX7300_ALL_INPUTS (0xFF) #define MAX7300_OUTPUT_DEFAULT (0xBB) //********************************************************************* Max14871_Shield::Max14871_Shield(I2C *i2c_bus, bool default_config): _p_i2c(i2c_bus) { _i2c_owner = false; if(default_config) { _p_io_expander = new Max7300(_p_i2c, Max7300::MAX7300_I2C_ADRS0); _p_digi_pot1 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS0); _p_digi_pot2 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS1); _p_pwm1 = new PwmOut(D4); _p_pwm2 = new PwmOut(D5); _p_pwm3 = new PwmOut(D9); _p_pwm4 = new PwmOut(D10); } else { _p_io_expander = new Max7300(_p_i2c, Max7300::MAX7300_I2C_ADRS1); _p_digi_pot1 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS2); _p_digi_pot2 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS3); _p_pwm1 = new PwmOut(D3); _p_pwm2 = new PwmOut(D6); _p_pwm3 = new PwmOut(D8); _p_pwm4 = new PwmOut(D11); } init_board(); } //********************************************************************* Max14871_Shield::Max14871_Shield(PinName sda, PinName scl, bool default_config) { _p_i2c = new I2C(sda, scl); _i2c_owner = true; if(default_config) { _p_io_expander = new Max7300(_p_i2c, Max7300::MAX7300_I2C_ADRS0); _p_digi_pot1 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS0); _p_digi_pot2 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS1); _p_pwm1 = new PwmOut(D4); _p_pwm2 = new PwmOut(D5); _p_pwm3 = new PwmOut(D9); _p_pwm4 = new PwmOut(D10); } else { _p_io_expander = new Max7300(_p_i2c, Max7300::MAX7300_I2C_ADRS1); _p_digi_pot1 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS2); _p_digi_pot2 = new Max5387(_p_i2c, Max5387::MAX5387_I2C_ADRS3); _p_pwm1 = new PwmOut(D3); _p_pwm2 = new PwmOut(D6); _p_pwm3 = new PwmOut(D8); _p_pwm4 = new PwmOut(D11); } init_board(); } //********************************************************************* Max14871_Shield::~Max14871_Shield() { if(_i2c_owner) { delete _p_i2c; } delete _p_io_expander; delete _p_digi_pot1; delete _p_digi_pot2; delete _p_pwm1; delete _p_pwm2; delete _p_pwm3; delete _p_pwm4; } //********************************************************************* int16_t Max14871_Shield::set_operating_mode(max14871_motor_driver_t md, max14871_operating_mode_t mode) { int16_t result = 0; int16_t port_data; Max7300::max7300_port_number_t low_port; //determine the low port of an 8 bit register to read/write if(md < MD3) { low_port = Max7300::MAX7300_PORT_04; } else { low_port = Max7300::MAX7300_PORT_12; } //get current state of outputs port_data = _p_io_expander->read_8_ports(low_port); switch(mode) { //if(md % 2) for following cases, modify control bits //of odd motor driver case COAST: if(md % 2) { port_data |= MD_EN; } else { port_data |= (MD_EN << 4); } break; case BRAKE: if(md % 2) { port_data &= ~MD_EN; } else { port_data &= ~(MD_EN << 4); } set_pwm_duty_cycle(md, 0); break; case REVERSE: if(md % 2) { port_data &= ~(MD_EN + MD_DIR); } else { port_data &= ~((MD_EN + MD_DIR) << 4); } break; case FORWARD: if(md % 2) { port_data &= ~MD_EN; port_data |= MD_DIR; } else { port_data &= ~(MD_EN << 4); port_data |= (MD_DIR << 4); } break; default: result = -1; break; } if(!result) { //write data back to port result = _p_io_expander->write_8_ports(low_port, (uint8_t) port_data); } return result; } //********************************************************************* int16_t Max14871_Shield::set_current_regulation_mode(max14871_motor_driver_t md, max14871_current_regulation_mode_t mode, uint8_t vref) { int16_t result = 0; int16_t port_data; Max7300::max7300_port_number_t low_port; Max5387 *p_digi_pot; //determine the low port of an 8 bit register to read/write if(md < MD3) { low_port = Max7300::MAX7300_PORT_04; p_digi_pot = _p_digi_pot1; } else { low_port = Max7300::MAX7300_PORT_12; p_digi_pot = _p_digi_pot2; } //get current state of outputs port_data = _p_io_expander->read_8_ports(low_port); switch(mode) { case RIPPLE_25_INTERNAL_REF: if(md % 2) { port_data &= ~MD_MODE0; port_data |= MD_MODE1; p_digi_pot->write_ch_A(0); } else { port_data &= ~(MD_MODE0 << 4); port_data |= (MD_MODE1 << 4); p_digi_pot->write_ch_B(0); } break; case RIPPLE_25_EXTERNAL_REF: if(md % 2) { port_data &= ~MD_MODE0; port_data |= MD_MODE1; if(vref > MAX_VREF) { vref = MAX_VREF; } p_digi_pot->write_ch_A(vref); } else { port_data &= ~(MD_MODE0 << 4); port_data |= (MD_MODE1 << 4); if(vref > MAX_VREF) { vref = MAX_VREF; } p_digi_pot->write_ch_B(vref); } break; case TCOFF_FAST_INTERNAL_REF: if(md % 2) { port_data |= (MD_MODE1 + MD_MODE0); p_digi_pot->write_ch_A(0); } else { port_data |= ((MD_MODE1 + MD_MODE0) << 4); p_digi_pot->write_ch_B(0); } break; case TCOFF_SLOW_INTERNAL_REF: if(md % 2) { port_data |= MD_MODE0; port_data &= ~MD_MODE1; p_digi_pot->write_ch_A(0); } else { port_data |= (MD_MODE0 << 4); port_data &= ~(MD_MODE1 << 4); p_digi_pot->write_ch_B(0); } break; case TCOFF_FAST_EXTERNAL_REF: if(md % 2) { port_data |= (MD_MODE1 + MD_MODE0); if(vref > MAX_VREF) { vref = MAX_VREF; } p_digi_pot->write_ch_A(vref); } else { port_data |= ((MD_MODE1 + MD_MODE0) << 4); if(vref > MAX_VREF) { vref = MAX_VREF; } p_digi_pot->write_ch_B(vref); } break; case TCOFF_SLOW_EXTERNAL_REF: if(md % 2) { port_data |= MD_MODE0; port_data &= ~MD_MODE1; if(vref > MAX_VREF) { vref = MAX_VREF; } p_digi_pot->write_ch_A(vref); } else { port_data |= (MD_MODE0 << 4); port_data &= ~(MD_MODE1 << 4); if(vref > MAX_VREF) { vref = MAX_VREF; } p_digi_pot->write_ch_B(vref); } break; default: result = -1; break; } if(!result) { //write data back to port result = _p_io_expander->write_8_ports(low_port, (uint8_t) port_data); } return result; } //********************************************************************* int16_t Max14871_Shield::set_pwm_period(max14871_motor_driver_t md, uint16_t period) { int16_t result = 0; if(period < MIN_PERIOD) { result = -1; } else { switch(md) { case MD1: _p_pwm1->period_us(period); break; case MD2: _p_pwm2->period_us(period); break; case MD3: _p_pwm3->period_us(period); break; case MD4: _p_pwm4->period_us(period); break; default: result = -1; break; } } return result; } //********************************************************************* int16_t Max14871_Shield::set_pwm_duty_cycle(max14871_motor_driver_t md, uint16_t duty_cycle) { int16_t result = 0; switch(md) { case MD1: _p_pwm1->pulsewidth_us(duty_cycle); break; case MD2: _p_pwm2->pulsewidth_us(duty_cycle); break; case MD3: _p_pwm3->pulsewidth_us(duty_cycle); break; case MD4: _p_pwm4->pulsewidth_us(duty_cycle); break; default: result = -1; break; } return result; } //********************************************************************* void Max14871_Shield::init_board(void) { //configure these ports as outputs _p_io_expander->config_4_ports(Max7300::MAX7300_PORT_04, MAX7300_ALL_OUTPUTS); _p_io_expander->config_4_ports(Max7300::MAX7300_PORT_08, MAX7300_ALL_OUTPUTS); _p_io_expander->config_4_ports(Max7300::MAX7300_PORT_12, MAX7300_ALL_OUTPUTS); _p_io_expander->config_4_ports(Max7300::MAX7300_PORT_16, MAX7300_ALL_OUTPUTS); //Set /EN and DIR pin of all motor drivers and set mode pin //of all motor drivers to 0.75V _p_io_expander->write_8_ports(Max7300::MAX7300_PORT_04, MAX7300_OUTPUT_DEFAULT); _p_io_expander->write_8_ports(Max7300::MAX7300_PORT_12, MAX7300_OUTPUT_DEFAULT); //configure these ports as inputs w/pull-up, _p_io_expander->config_4_ports(Max7300::MAX7300_PORT_20, MAX7300_ALL_INPUTS); _p_io_expander->config_4_ports(Max7300::MAX7300_PORT_24, MAX7300_ALL_INPUTS); _p_io_expander->config_4_ports(Max7300::MAX7300_PORT_28, MAX7300_ALL_INPUTS); //config port 31 as output for interrupt _p_io_expander->config_port(Max7300::MAX7300_PORT_31, Max7300::MAX7300_PORT_OUTPUT); _p_io_expander->enable_transition_detection(); _p_io_expander->enable_ports(); //set Vref pin of all motor drivers to 1.3V _p_digi_pot1->write_ch_AB(MAX_VREF); _p_digi_pot2->write_ch_AB(MAX_VREF); //set switching frequency of all motor drivers to 50KHz _p_pwm1->period_us(MIN_PERIOD); _p_pwm2->period_us(MIN_PERIOD); _p_pwm3->period_us(MIN_PERIOD); _p_pwm4->period_us(MIN_PERIOD); }