00001 #include "DualMC33926.h" 00002 00003 // Defines for setting and clearing register bits 00004 #ifndef cbi 00005 #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 00006 #endif 00007 #ifndef sbi 00008 #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 00009 #endif 00010 // Constructors //////////////////////////////////////////////////////////////// 00011 00012 DualMC33926::DualMC33926() 00013 { 00014 //Pin map 00015 _nD2 = 4; 00016 _M1DIR = 7; 00017 _M2DIR = 8; 00018 _nSF = 12; 00019 _M1PWM = 9; 00020 _M2PWM = 10; 00021 _M1FB = A0; 00022 _M2FB = A1; 00023 } 00024 00025 DualMC33926::DualMC33926(unsigned char M1DIR, unsigned char M1PWM, unsigned char M1FB, 00026 unsigned char M2DIR, unsigned char M2PWM, unsigned char M2FB, 00027 unsigned char nD2, unsigned char nSF) 00028 { 00029 //Pin map 00030 //PWM1 and PWM2 cannot be remapped because the library assumes PWM is on timer1 00031 _M1PWM = M1PWM; 00032 _M2PWM = M2PWM; 00033 _nD2 = nD2; 00034 _M1DIR = M1DIR; 00035 _M2DIR = M2DIR; 00036 _nSF = nSF; 00037 _M1FB = M1FB; 00038 _M2FB = M2FB; 00039 } 00040 00041 // Public Methods ////////////////////////////////////////////////////////////// 00042 void DualMC33926::init() 00043 { 00044 // Define pinMode for the pins and set the frequency for timer1. 00045 00046 pinMode(_M1DIR,OUTPUT); 00047 pinMode(_M1PWM,OUTPUT); 00048 // pinMode(_M1FB,INPUT); 00049 pinMode(_M2DIR,OUTPUT); 00050 pinMode(_M2PWM,OUTPUT); 00051 // pinMode(_M2FB,INPUT); 00052 pinMode(_nD2,OUTPUT); 00053 digitalWrite(_nD2,HIGH); // default to on 00054 pinMode(_nSF,INPUT); 00055 00056 #ifdef __SAM3X8E__ //DUE 00057 analogReadResolution(12); //0-4095 00058 // #undef PWM_FREQUENCY 00059 //#define PWM_FREQUENCY 20000 //20khz 00060 00061 #else //mega 00062 // PWM frequency calculation 00063 // 16MHz / 1 (prescaler) / 2 (phase-correct) / 400 (top) = 20kHz 00064 00065 //TCCR1A = 0b10100000; 00066 // TCCR1B = 0b00010001; 00067 // ICR1 = 400; 00068 // TCCR2A settings 00069 //--------------------------------------------------------------------- 00070 // These bits control the Output Compare pin (OC2A) behavior. If one or 00071 // both of the COM2A1:0 bits are set, the OC2A output overrides the 00072 // normal port functionality of the I/O pin it is connected to. 00073 // However, note that the Data Direction Register (DDR) bit 00074 // corresponding to the OC2A pin must be set in order to enable the 00075 // output driver. 00076 // When OC2A is connected to the pin, the function of the COM2A1:0 bits 00077 // depends on the WGM22:0 bit setting. 00078 // 00079 // Fast PWM Mode 00080 // COM2A1 COM2A0 00081 // 0 0 Normal port operation, OC2A disconnected. 00082 // 0 1 WGM22 = 0: Normal Port Operation, OC0A Disconnected. 00083 // WGM22 = 1: Toggle OC2A on Compare Match. 00084 // 1 0 Clear OC2A on Compare Match, set OC2A at BOTTOM 00085 // 1 1 Clear OC2A on Compare Match, clear OC2A at BOTTOM 00086 cbi(TCCR2A,COM2A1); 00087 cbi(TCCR2A,COM2A0); 00088 sbi(TCCR2A,COM2B1); 00089 cbi(TCCR2A,COM2B0); 00090 00091 // Combined with the WGM22 bit found in the TCCR2B Register, these bits 00092 // control the counting sequence of the counter, the source for maximum 00093 // (TOP) counter value, and what type of waveform generation to be used 00094 // Modes of operation supported by the Timer/Counter unit are: 00095 // - Normal mode (counter), 00096 // - Clear Timer on Compare Match (CTC) mode, 00097 // - two types of Pulse Width Modulation (PWM) modes. 00098 // 00099 // Mode WGM22 WGM21 WGM20 Operation TOP 00100 // 0 0 0 0 Normal 0xFF 00101 // 1 0 0 1 PWM 0xFF 00102 // 2 0 1 0 CTC OCRA 00103 // 3 0 1 1 Fast PWM 0xFF 00104 // 4 1 0 0 Reserved - 00105 // 5 1 0 1 PWM OCRA 00106 // 6 1 1 0 Reserved - 00107 // 7 1 1 1 Fast PWM OCRA 00108 cbi(TCCR2B,WGM22); 00109 sbi(TCCR2A,WGM21); 00110 sbi(TCCR2A,WGM20); 00111 00112 //--------------------------------------------------------------------- 00113 // TCCR2B settings 00114 //--------------------------------------------------------------------- 00115 // The FOC2A bit is only active when the WGM bits specify a non-PWM 00116 // mode. 00117 // However, for ensuring compatibility with future devices, this bit 00118 // must be set to zero when TCCR2B is written when operating in PWM 00119 // mode. When writing a logical one to the FOC2A bit, an immediate 00120 // Compare Match is forced on the Waveform Generation unit. The OC2A 00121 // output is changed according to its COM2A1:0 bits setting. Note that 00122 // the FOC2A bit is implemented as a strobe. Therefore it is the value 00123 // present in the COM2A1:0 bits that determines the effect of the 00124 // forced compare. 00125 // A FOC2A strobe will not generate any interrupt, nor will it clear 00126 // the timer in CTC mode using OCR2A as TOP. 00127 // The FOC2A bit is always read as zero. 00128 cbi(TCCR2B,FOC2A); 00129 cbi(TCCR2B,FOC2B); 00130 00131 // The three Clock Select bits select the clock source to be used by 00132 // the Timer/Counter. 00133 // CS22 CS21 CS20 Prescaler 00134 // 0 0 0 No clock source (Timer/Counter stopped). 00135 // 0 0 1 No prescaling 00136 // 0 1 0 8 00137 // 0 1 1 32 00138 // 1 0 0 64 00139 // 1 0 1 128 00140 // 1 1 0 256 00141 // 1 1 1 1024 00142 cbi(TCCR2B,CS22); 00143 cbi(TCCR2B,CS21); 00144 sbi(TCCR2B,CS20); 00145 00146 #endif 00147 00148 00149 00150 } 00151 00152 // Return torque status 00153 unsigned char DualMC33926::getTorque() { 00154 return digitalRead(_nD2); 00155 } 00156 00157 // Set torque status 00158 void DualMC33926::setTorque(bool t) 00159 { 00160 if (t) digitalWrite(_nD2,HIGH); 00161 else digitalWrite(_nD2,LOW); 00162 } 00163 00164 //restart driver 00165 void DualMC33926::restart() 00166 { 00167 digitalWrite(_nD2,LOW); 00168 delay(1); 00169 digitalWrite(_nD2,HIGH); 00170 } 00171 00172 // Set speed for motor 1, speed is a number betwenn -255 and 255 00173 void DualMC33926::setM1Speed(int speed) 00174 { 00175 unsigned char reverse = 0; 00176 00177 if (speed < 0) 00178 { 00179 speed = -speed; // Make speed a positive quantity 00180 reverse = 1; // Preserve the direction 00181 } 00182 if (speed > 255) // Max PWM dutycycle 00183 speed = 255; 00184 00185 analogWrite(_M1PWM,speed); 00186 00187 if (reverse) 00188 digitalWrite(_M1DIR,HIGH); 00189 else 00190 digitalWrite(_M1DIR,LOW); 00191 } 00192 00193 // Set speed for motor 2, speed is a number betwenn -255 and 255 00194 void DualMC33926::setM2Speed(int speed) 00195 { 00196 unsigned char reverse = 0; 00197 00198 if (speed < 0) 00199 { 00200 speed = -speed; // Make speed a positive quantity 00201 reverse = 1; // Preserve the direction 00202 } 00203 if (speed > 255) // Max PWM dutycycle 00204 speed = 255; 00205 00206 analogWrite(_M2PWM,speed); 00207 00208 if (reverse) 00209 digitalWrite(_M2DIR,HIGH); 00210 else 00211 digitalWrite(_M2DIR,LOW); 00212 } 00213 00214 // Set speed for motor 1 and 2 00215 void DualMC33926::setSpeeds(int m1Speed, int m2Speed) 00216 { 00217 setM1Speed(m1Speed); 00218 setM2Speed(m2Speed); 00219 } 00220 00221 // Return motor 1 current value in milliamps. 00222 float DualMC33926::getM1CurrentMilliamps() 00223 { 00224 #ifdef __SAM3X8E__ //DUE 00225 // 3.3V / 4096 ADC counts / 525 mV per A = 1.5346 mA per count 00226 return (float)analogRead(_M1FB) * 1.5346; 00227 #else //Mega 00228 // 5V / 1024 ADC counts / 525 mV per A = 9.3 mA per count 00229 return (float)analogRead(_M1FB) * 9.3; 00230 #endif 00231 00232 00233 } 00234 00235 // Return motor 2 current value in milliamps. 00236 float DualMC33926::getM2CurrentMilliamps() 00237 { 00238 #ifdef __SAM3X8E__ //DUE 00239 // 3.3V / 4096 ADC counts / 525 mV per A = 1.5346 mA per count 00240 return (float)analogRead(_M2FB) * 1.5346; 00241 #else //Mega 00242 // 5V / 1024 ADC counts / 525 mV per A = 9.3 mA per count 00243 return (float)analogRead(_M2FB) * 9.3; 00244 #endif 00245 00246 } 00247 00248 // Return error status 00249 unsigned char DualMC33926::getFault() 00250 { 00251 return !digitalRead(_nSF); 00252 } 00253 00254