library - L6470
This commit is contained in:
		
							parent
							
								
									363d7c505f
								
							
						
					
					
						commit
						ae9de515b8
					
				
							
								
								
									
										723
									
								
								ArduinoAddons/Arduino_1.6.x/libraries/L6470/L6470.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										723
									
								
								ArduinoAddons/Arduino_1.6.x/libraries/L6470/L6470.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,723 @@ | ||||
| ////////////////////////////////////////////////////////////
 | ||||
| //ORIGINAL CODE 12/12/2011- Mike Hord, SparkFun Electronics
 | ||||
| //LIBRARY Created by Adam Meyer of bildr Aug 18th 2012
 | ||||
| //Released as MIT license
 | ||||
| ////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <Arduino.h> | ||||
| #include "L6470.h" | ||||
| #include <SPI.h> | ||||
| 
 | ||||
| #define ENABLE_RESET_PIN	0 | ||||
| #define K_VALUE			100 | ||||
| 
 | ||||
| L6470::L6470(int SSPin){ | ||||
|   _SSPin = SSPin; | ||||
|   // Serial.begin(9600);
 | ||||
| } | ||||
| 
 | ||||
| void L6470::init(int k_value){ | ||||
|   // This is the generic initialization function to set up the Arduino to
 | ||||
|   // communicate with the dSPIN chip.
 | ||||
|    | ||||
|   // set up the input/output pins for the application.
 | ||||
|   pinMode(SLAVE_SELECT_PIN, OUTPUT); // The SPI peripheral REQUIRES the hardware SS pin-
 | ||||
|   // pin 10- to be an output. This is in here just
 | ||||
|   // in case some future user makes something other
 | ||||
|   // than pin 10 the SS pin.
 | ||||
|    | ||||
|   pinMode(_SSPin, OUTPUT); | ||||
|   digitalWrite(_SSPin, HIGH); | ||||
|   pinMode(MOSI, OUTPUT); | ||||
|   pinMode(MISO, INPUT); | ||||
|   pinMode(SCK, OUTPUT); | ||||
|   pinMode(BUSYN, INPUT); | ||||
| #if (ENABLE_RESET_PIN == 1) | ||||
|   pinMode(RESET, OUTPUT); | ||||
|   // reset the dSPIN chip. This could also be accomplished by
 | ||||
|   // calling the "L6470::ResetDev()" function after SPI is initialized.
 | ||||
|   digitalWrite(RESET, HIGH); | ||||
|   delay(10); | ||||
|   digitalWrite(RESET, LOW); | ||||
|   delay(10); | ||||
|   digitalWrite(RESET, HIGH); | ||||
|   delay(10); | ||||
| #endif | ||||
|    | ||||
|    | ||||
|   // initialize SPI for the dSPIN chip's needs:
 | ||||
|   // most significant bit first,
 | ||||
|   // SPI clock not to exceed 5MHz,
 | ||||
|   // SPI_MODE3 (clock idle high, latch data on rising edge of clock)
 | ||||
|   SPI.begin(); | ||||
|   SPI.setBitOrder(MSBFIRST); | ||||
|   SPI.setClockDivider(SPI_CLOCK_DIV16); // or 2, 8, 16, 32, 64
 | ||||
|   SPI.setDataMode(SPI_MODE3); | ||||
|    | ||||
|   // First things first: let's check communications. The CONFIG register should
 | ||||
|   // power up to 0x2E88, so we can use that to check the communications.
 | ||||
|   if (GetParam(CONFIG) == 0x2E88){ | ||||
|     //Serial.println('good to go');
 | ||||
|   } | ||||
|   else{ | ||||
|     //Serial.println('Comm issue');
 | ||||
|   } | ||||
| 
 | ||||
| #if  (ENABLE_RESET_PIN == 0)  | ||||
|   resetDev(); | ||||
| #endif | ||||
|   // First, let's set the step mode register:
 | ||||
|   // - SYNC_EN controls whether the BUSY/SYNC pin reflects the step
 | ||||
|   // frequency or the BUSY status of the chip. We want it to be the BUSY
 | ||||
|   // status.
 | ||||
|   // - STEP_SEL_x is the microstepping rate- we'll go full step.
 | ||||
|   // - SYNC_SEL_x is the ratio of (micro)steps to toggles on the
 | ||||
|   // BUSY/SYNC pin (when that pin is used for SYNC). Make it 1:1, despite
 | ||||
|   // not using that pin.
 | ||||
|   //SetParam(STEP_MODE, !SYNC_EN | STEP_SEL_1 | SYNC_SEL_1);
 | ||||
|    | ||||
|    | ||||
|   SetParam(KVAL_RUN, k_value); | ||||
|   SetParam(KVAL_ACC, k_value); | ||||
|   SetParam(KVAL_DEC, k_value); | ||||
|   SetParam(KVAL_HOLD, k_value); | ||||
|    | ||||
|   // Set up the CONFIG register as follows:
 | ||||
|   // PWM frequency divisor = 1
 | ||||
|   // PWM frequency multiplier = 2 (62.5kHz PWM frequency)
 | ||||
|   // Slew rate is 290V/us
 | ||||
|   // Do NOT shut down bridges on overcurrent
 | ||||
|   // Disable motor voltage compensation
 | ||||
|   // Hard stop on switch low
 | ||||
|   // 16MHz internal oscillator, nothing on output
 | ||||
|   SetParam(CONFIG, CONFIG_PWM_DIV_1 | CONFIG_PWM_MUL_2 | CONFIG_SR_290V_us| CONFIG_OC_SD_DISABLE | CONFIG_VS_COMP_DISABLE | CONFIG_SW_HARD_STOP | CONFIG_INT_16MHZ); | ||||
|   // Configure the RUN KVAL. This defines the duty cycle of the PWM of the bridges
 | ||||
|   // during running. 0xFF means that they are essentially NOT PWMed during run; this
 | ||||
|   // MAY result in more power being dissipated than you actually need for the task.
 | ||||
|   // Setting this value too low may result in failure to turn.
 | ||||
|   // There are ACC, DEC, and HOLD KVAL registers as well; you may need to play with
 | ||||
|   // those values to get acceptable performance for a given application.
 | ||||
|   //SetParam(KVAL_RUN, 0xFF);
 | ||||
|   // Calling GetStatus() clears the UVLO bit in the status register, which is set by
 | ||||
|   // default on power-up. The driver may not run without that bit cleared by this
 | ||||
|   // read operation.
 | ||||
|   getStatus(); | ||||
|    | ||||
|   hardStop(); //engage motors
 | ||||
| } | ||||
| 
 | ||||
| boolean L6470::isBusy(){ | ||||
|   int status = getStatus(); | ||||
|   return !((status >> 1) & 0b1); | ||||
| } | ||||
| 
 | ||||
| void L6470::setMicroSteps(int microSteps){ | ||||
|   byte stepVal = 0; | ||||
|    | ||||
|   for(stepVal = 0; stepVal < 8; stepVal++){ | ||||
|     if(microSteps == 1) break; | ||||
|     microSteps = microSteps >> 1; | ||||
|   } | ||||
| 
 | ||||
|   SetParam(STEP_MODE, !SYNC_EN | stepVal | SYNC_SEL_1); | ||||
| } | ||||
| 
 | ||||
| void L6470::setThresholdSpeed(float thresholdSpeed){ | ||||
|   // Configure the FS_SPD register- this is the speed at which the driver ceases
 | ||||
|   // microstepping and goes to full stepping. FSCalc() converts a value in steps/s
 | ||||
|   // to a value suitable for this register; to disable full-step switching, you
 | ||||
|   // can pass 0x3FF to this register.
 | ||||
|    | ||||
|   if(thresholdSpeed == 0.0){ | ||||
|     SetParam(FS_SPD, 0x3FF); | ||||
|   } | ||||
|   else{ | ||||
|     SetParam(FS_SPD, FSCalc(thresholdSpeed));	 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setCurrent(int current){} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setMaxSpeed(int speed){ | ||||
|   // Configure the MAX_SPEED register- this is the maximum number of (micro)steps per
 | ||||
|   // second allowed. You'll want to mess around with your desired application to see
 | ||||
|   // how far you can push it before the motor starts to slip. The ACTUAL parameter
 | ||||
|   // passed to this function is in steps/tick; MaxSpdCalc() will convert a number of
 | ||||
|   // steps/s into an appropriate value for this function. Note that for any move or
 | ||||
|   // goto type function where no speed is specified, this value will be used.
 | ||||
|   SetParam(MAX_SPEED, MaxSpdCalc(speed)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setMinSpeed(int speed){ | ||||
|   // Configure the MAX_SPEED register- this is the maximum number of (micro)steps per
 | ||||
|   // second allowed. You'll want to mess around with your desired application to see
 | ||||
|   // how far you can push it before the motor starts to slip. The ACTUAL parameter
 | ||||
|   // passed to this function is in steps/tick; MaxSpdCalc() will convert a number of
 | ||||
|   // steps/s into an appropriate value for this function. Note that for any move or
 | ||||
|   // goto type function where no speed is specified, this value will be used.
 | ||||
|   SetParam(MIN_SPEED, MinSpdCalc(speed)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setAcc(float acceleration){ | ||||
|   // Configure the acceleration rate, in steps/tick/tick. There is also a DEC register;
 | ||||
|   // both of them have a function (AccCalc() and DecCalc() respectively) that convert
 | ||||
|   // from steps/s/s into the appropriate value for the register. Writing ACC to 0xfff
 | ||||
|   // sets the acceleration and deceleration to 'infinite' (or as near as the driver can
 | ||||
|   // manage). If ACC is set to 0xfff, DEC is ignored. To get infinite deceleration
 | ||||
|   // without infinite acceleration, only hard stop will work.
 | ||||
|   unsigned long accelerationBYTES = AccCalc(acceleration); | ||||
|   SetParam(ACC, accelerationBYTES); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setDec(float deceleration){ | ||||
|   unsigned long decelerationBYTES = DecCalc(deceleration); | ||||
|   SetParam(DEC, decelerationBYTES); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| long L6470::getPos(){ | ||||
|   unsigned long position = GetParam(ABS_POS); | ||||
|   return convert(position); | ||||
| } | ||||
| 
 | ||||
| float L6470::getSpeed(){ | ||||
|   /*
 | ||||
|   SPEED | ||||
|   The SPEED register contains the current motor speed, expressed in step/tick (format unsigned fixed point 0.28). | ||||
|   In order to convert the SPEED value in step/s the following formula can be used: | ||||
|   Equation 4 | ||||
|   where SPEED is the integer number stored into the register and tick is 250 ns. | ||||
|   The available range is from 0 to 15625 step/s with a resolution of 0.015 step/s. | ||||
|   Note: The range effectively available to the user is limited by the MAX_SPEED parameter. | ||||
|   */ | ||||
|    | ||||
|   return (float) GetParam(SPEED); | ||||
|   //return (float) speed * pow(8, -22);
 | ||||
|   //return FSCalc(speed); NEEDS FIX
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setOverCurrent(unsigned int ma_current){ | ||||
|   // Configure the overcurrent detection threshold.
 | ||||
|   byte OCValue = floor(ma_current / 375); | ||||
|   if(OCValue > 0x0F)OCValue = 0x0F; | ||||
|   SetParam(OCD_TH, OCValue); | ||||
| } | ||||
| 
 | ||||
| void L6470::setStallCurrent(float ma_current){ | ||||
|   byte STHValue = (byte)floor(ma_current / 31.25); | ||||
|   if(STHValue > 0x80)STHValue = 0x80; | ||||
|   if(STHValue < 0)STHValue = 0; | ||||
|   SetParam(STALL_TH, STHValue); | ||||
| } | ||||
| 
 | ||||
| void L6470::SetLowSpeedOpt(boolean enable){ | ||||
|   // Enable or disable the low-speed optimization option. If enabling,
 | ||||
|   // the other 12 bits of the register will be automatically zero.
 | ||||
|   // When disabling, the value will have to be explicitly written by
 | ||||
|   // the user with a SetParam() call. See the datasheet for further
 | ||||
|   // information about low-speed optimization.
 | ||||
|   Xfer(SET_PARAM | MIN_SPEED); | ||||
|   if (enable) Param(0x1000, 13); | ||||
|   else Param(0, 13); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::run(byte dir, float spd){ | ||||
|   // RUN sets the motor spinning in a direction (defined by the constants
 | ||||
|   // FWD and REV). Maximum speed and minimum speed are defined
 | ||||
|   // by the MAX_SPEED and MIN_SPEED registers; exceeding the FS_SPD value
 | ||||
|   // will switch the device into full-step mode.
 | ||||
|   // The SpdCalc() function is provided to convert steps/s values into
 | ||||
|   // appropriate integer values for this function.
 | ||||
|   unsigned long speedVal = SpdCalc(spd); | ||||
|    | ||||
|   Xfer(RUN | dir); | ||||
|   if (speedVal > 0xFFFFF) speedVal = 0xFFFFF; | ||||
|   Xfer((byte)(speedVal >> 16)); | ||||
|   Xfer((byte)(speedVal >> 8)); | ||||
|   Xfer((byte)(speedVal)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::Step_Clock(byte dir){ | ||||
|   // STEP_CLOCK puts the device in external step clocking mode. When active,
 | ||||
|   // pin 25, STCK, becomes the step clock for the device, and steps it in
 | ||||
|   // the direction (set by the FWD and REV constants) imposed by the call
 | ||||
|   // of this function. Motion commands (RUN, MOVE, etc) will cause the device
 | ||||
|   // to exit step clocking mode.
 | ||||
|   Xfer(STEP_CLOCK | dir); | ||||
| } | ||||
| 
 | ||||
| void L6470::move(long n_step){ | ||||
|   // MOVE will send the motor n_step steps (size based on step mode) in the
 | ||||
|   // direction imposed by dir (FWD or REV constants may be used). The motor
 | ||||
|   // will accelerate according the acceleration and deceleration curves, and
 | ||||
|   // will run at MAX_SPEED. Stepping mode will adhere to FS_SPD value, as well.
 | ||||
|    | ||||
|   byte dir; | ||||
|    | ||||
|   if(n_step >= 0){ | ||||
|     dir = FWD; | ||||
|   } | ||||
|   else{ | ||||
|     dir = REV; | ||||
|   } | ||||
| 
 | ||||
|   long n_stepABS = abs(n_step); | ||||
|    | ||||
|   Xfer(MOVE | dir); //set direction
 | ||||
|   if (n_stepABS > 0x3FFFFF) n_step = 0x3FFFFF; | ||||
|   Xfer((byte)(n_stepABS >> 16)); | ||||
|   Xfer((byte)(n_stepABS >> 8)); | ||||
|   Xfer((byte)(n_stepABS)); | ||||
| } | ||||
| 
 | ||||
| void L6470::goTo(long pos){ | ||||
|   // GOTO operates much like MOVE, except it produces absolute motion instead
 | ||||
|   // of relative motion. The motor will be moved to the indicated position
 | ||||
|   // in the shortest possible fashion.
 | ||||
|    | ||||
|   Xfer(GOTO); | ||||
|   if (pos > 0x3FFFFF) pos = 0x3FFFFF; | ||||
|   Xfer((byte)(pos >> 16)); | ||||
|   Xfer((byte)(pos >> 8)); | ||||
|   Xfer((byte)(pos)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::goTo_DIR(byte dir, long pos){ | ||||
|   // Same as GOTO, but with user constrained rotational direction.
 | ||||
|    | ||||
|   Xfer(GOTO_DIR); | ||||
|   if (pos > 0x3FFFFF) pos = 0x3FFFFF; | ||||
|   Xfer((byte)(pos >> 16)); | ||||
|   Xfer((byte)(pos >> 8)); | ||||
|   Xfer((byte)(pos)); | ||||
| } | ||||
| 
 | ||||
| void L6470::goUntil(byte act, byte dir, unsigned long spd){ | ||||
|   // GoUntil will set the motor running with direction dir (REV or
 | ||||
|   // FWD) until a falling edge is detected on the SW pin. Depending
 | ||||
|   // on bit SW_MODE in CONFIG, either a hard stop or a soft stop is
 | ||||
|   // performed at the falling edge, and depending on the value of
 | ||||
|   // act (either RESET or COPY) the value in the ABS_POS register is
 | ||||
|   // either RESET to 0 or COPY-ed into the MARK register.
 | ||||
|   Xfer(GO_UNTIL | act | dir); | ||||
|   if (spd > 0x3FFFFF) spd = 0x3FFFFF; | ||||
|   Xfer((byte)(spd >> 16)); | ||||
|   Xfer((byte)(spd >> 8)); | ||||
|   Xfer((byte)(spd)); | ||||
| } | ||||
| 
 | ||||
| void L6470::releaseSW(byte act, byte dir){ | ||||
|   // Similar in nature to GoUntil, ReleaseSW produces motion at the
 | ||||
|   // higher of two speeds: the value in MIN_SPEED or 5 steps/s.
 | ||||
|   // The motor continues to run at this speed until a rising edge
 | ||||
|   // is detected on the switch input, then a hard stop is performed
 | ||||
|   // and the ABS_POS register is either COPY-ed into MARK or RESET to
 | ||||
|   // 0, depending on whether RESET or COPY was passed to the function
 | ||||
|   // for act.
 | ||||
|   Xfer(RELEASE_SW | act | dir); | ||||
| } | ||||
| 
 | ||||
| void L6470::goHome(){ | ||||
|   // GoHome is equivalent to GoTo(0), but requires less time to send.
 | ||||
|   // Note that no direction is provided; motion occurs through shortest
 | ||||
|   // path. If a direction is required, use GoTo_DIR().
 | ||||
|   Xfer(GO_HOME); | ||||
| } | ||||
| 
 | ||||
| void L6470::goMark(){ | ||||
|   // GoMark is equivalent to GoTo(MARK), but requires less time to send.
 | ||||
|   // Note that no direction is provided; motion occurs through shortest
 | ||||
|   // path. If a direction is required, use GoTo_DIR().
 | ||||
|   Xfer(GO_MARK); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setMark(long value){ | ||||
| 
 | ||||
|   Xfer(MARK); | ||||
|   if (value > 0x3FFFFF) value = 0x3FFFFF; | ||||
|   if (value < -0x3FFFFF) value = -0x3FFFFF; | ||||
|    | ||||
|    | ||||
|   Xfer((byte)(value >> 16)); | ||||
|   Xfer((byte)(value >> 8)); | ||||
|   Xfer((byte)(value)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void L6470::setMark(){ | ||||
|   long value = getPos(); | ||||
|    | ||||
|   Xfer(MARK); | ||||
|   if (value > 0x3FFFFF) value = 0x3FFFFF; | ||||
|   if (value < -0x3FFFFF) value = -0x3FFFFF; | ||||
|    | ||||
|    | ||||
|   Xfer((byte)(value >> 16)); | ||||
|   Xfer((byte)(value >> 8)); | ||||
|   Xfer((byte)(value)); | ||||
| } | ||||
| 
 | ||||
| void L6470::setAsHome(){ | ||||
|   // Sets the ABS_POS register to 0, effectively declaring the current
 | ||||
|   // position to be "HOME".
 | ||||
|   Xfer(RESET_POS); | ||||
| } | ||||
| 
 | ||||
| void L6470::resetDev(){ | ||||
|   // Reset device to power up conditions. Equivalent to toggling the STBY
 | ||||
|   // pin or cycling power.
 | ||||
|   Xfer(RESET_DEVICE); | ||||
| } | ||||
| 
 | ||||
| void L6470::softStop(){ | ||||
|   // Bring the motor to a halt using the deceleration curve.
 | ||||
|   Xfer(SOFT_STOP); | ||||
| } | ||||
| 
 | ||||
| void L6470::hardStop(){ | ||||
|   // Stop the motor right away. No deceleration.
 | ||||
|   Xfer(HARD_STOP); | ||||
| } | ||||
| 
 | ||||
| void L6470::softFree(){ | ||||
|   // Decelerate the motor and disengage
 | ||||
|   Xfer(SOFT_HIZ); | ||||
| } | ||||
| 
 | ||||
| void L6470::free(){ | ||||
|   // disengage the motor immediately with no deceleration.
 | ||||
|   Xfer(HARD_HIZ); | ||||
| } | ||||
| 
 | ||||
| int L6470::getStatus(){ | ||||
|   // Fetch and return the 16-bit value in the STATUS register. Resets
 | ||||
|   // any warning flags and exits any error states. Using GetParam()
 | ||||
|   // to read STATUS does not clear these values.
 | ||||
|   int temp = 0; | ||||
|   Xfer(GET_STATUS); | ||||
|   temp = Xfer(0)<<8; | ||||
|   temp |= Xfer(0); | ||||
|   return temp; | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::AccCalc(float stepsPerSecPerSec){ | ||||
|   // The value in the ACC register is [(steps/s/s)*(tick^2)]/(2^-40) where tick is
 | ||||
|   // 250ns (datasheet value)- 0x08A on boot.
 | ||||
|   // Multiply desired steps/s/s by .137438 to get an appropriate value for this register.
 | ||||
|   // This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
 | ||||
|   float temp = stepsPerSecPerSec * 0.137438; | ||||
|   if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF; | ||||
|   else return (unsigned long) long(temp); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| unsigned long L6470::DecCalc(float stepsPerSecPerSec){ | ||||
|   // The calculation for DEC is the same as for ACC. Value is 0x08A on boot.
 | ||||
|   // This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
 | ||||
|   float temp = stepsPerSecPerSec * 0.137438; | ||||
|   if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF; | ||||
|   else return (unsigned long) long(temp); | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::MaxSpdCalc(float stepsPerSec){ | ||||
|   // The value in the MAX_SPD register is [(steps/s)*(tick)]/(2^-18) where tick is
 | ||||
|   // 250ns (datasheet value)- 0x041 on boot.
 | ||||
|   // Multiply desired steps/s by .065536 to get an appropriate value for this register
 | ||||
|   // This is a 10-bit value, so we need to make sure it remains at or below 0x3FF
 | ||||
|   float temp = stepsPerSec * .065536; | ||||
|   if( (unsigned long) long(temp) > 0x000003FF) return 0x000003FF; | ||||
|   else return (unsigned long) long(temp); | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::MinSpdCalc(float stepsPerSec){ | ||||
|   // The value in the MIN_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is
 | ||||
|   // 250ns (datasheet value)- 0x000 on boot.
 | ||||
|   // Multiply desired steps/s by 4.1943 to get an appropriate value for this register
 | ||||
|   // This is a 12-bit value, so we need to make sure the value is at or below 0xFFF.
 | ||||
|   float temp = stepsPerSec * 4.1943; | ||||
|   if( (unsigned long) long(temp) > 0x00000FFF) return 0x00000FFF; | ||||
|   else return (unsigned long) long(temp); | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::FSCalc(float stepsPerSec){ | ||||
|   // The value in the FS_SPD register is ([(steps/s)*(tick)]/(2^-18))-0.5 where tick is
 | ||||
|   // 250ns (datasheet value)- 0x027 on boot.
 | ||||
|   // Multiply desired steps/s by .065536 and subtract .5 to get an appropriate value for this register
 | ||||
|   // This is a 10-bit value, so we need to make sure the value is at or below 0x3FF.
 | ||||
|   float temp = (stepsPerSec * .065536)-.5; | ||||
|   if( (unsigned long) long(temp) > 0x000003FF) return 0x000003FF; | ||||
|   else return (unsigned long) long(temp); | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::IntSpdCalc(float stepsPerSec){ | ||||
|   // The value in the INT_SPD register is [(steps/s)*(tick)]/(2^-24) where tick is
 | ||||
|   // 250ns (datasheet value)- 0x408 on boot.
 | ||||
|   // Multiply desired steps/s by 4.1943 to get an appropriate value for this register
 | ||||
|   // This is a 14-bit value, so we need to make sure the value is at or below 0x3FFF.
 | ||||
|   float temp = stepsPerSec * 4.1943; | ||||
|   if( (unsigned long) long(temp) > 0x00003FFF) return 0x00003FFF; | ||||
|   else return (unsigned long) long(temp); | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::SpdCalc(float stepsPerSec){ | ||||
|   // When issuing RUN command, the 20-bit speed is [(steps/s)*(tick)]/(2^-28) where tick is
 | ||||
|   // 250ns (datasheet value).
 | ||||
|   // Multiply desired steps/s by 67.106 to get an appropriate value for this register
 | ||||
|   // This is a 20-bit value, so we need to make sure the value is at or below 0xFFFFF.
 | ||||
|    | ||||
|   float temp = stepsPerSec * 67.106; | ||||
|   if( (unsigned long) long(temp) > 0x000FFFFF) return 0x000FFFFF; | ||||
|   else return (unsigned long)temp; | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::Param(unsigned long value, byte bit_len){ | ||||
|   // Generalization of the subsections of the register read/write functionality.
 | ||||
|   // We want the end user to just write the value without worrying about length,
 | ||||
|   // so we pass a bit length parameter from the calling function.
 | ||||
|   unsigned long ret_val=0; // We'll return this to generalize this function
 | ||||
|   // for both read and write of registers.
 | ||||
|   byte byte_len = bit_len/8; // How many BYTES do we have?
 | ||||
|   if (bit_len%8 > 0) byte_len++; // Make sure not to lose any partial byte values.
 | ||||
|   // Let's make sure our value has no spurious bits set, and if the value was too
 | ||||
|   // high, max it out.
 | ||||
|   unsigned long mask = 0xffffffff >> (32-bit_len); | ||||
|   if (value > mask) value = mask; | ||||
|   // The following three if statements handle the various possible byte length
 | ||||
|   // transfers- it'll be no less than 1 but no more than 3 bytes of data.
 | ||||
|   // L6470::Xfer() sends a byte out through SPI and returns a byte received
 | ||||
|   // over SPI- when calling it, we typecast a shifted version of the masked
 | ||||
|   // value, then we shift the received value back by the same amount and
 | ||||
|   // store it until return time.
 | ||||
|   if (byte_len == 3) { | ||||
|     ret_val |= long(Xfer((byte)(value>>16))) << 16; | ||||
|     //Serial.println(ret_val, HEX);
 | ||||
|   } | ||||
|   if (byte_len >= 2) { | ||||
|     ret_val |= long(Xfer((byte)(value>>8))) << 8; | ||||
|     //Serial.println(ret_val, HEX);
 | ||||
|   } | ||||
|   if (byte_len >= 1) { | ||||
|     ret_val |= Xfer((byte)value); | ||||
|     //Serial.println(ret_val, HEX);
 | ||||
|   } | ||||
|   // Return the received values. Mask off any unnecessary bits, just for
 | ||||
|   // the sake of thoroughness- we don't EXPECT to see anything outside
 | ||||
|   // the bit length range but better to be safe than sorry.
 | ||||
|   return (ret_val & mask); | ||||
| } | ||||
| 
 | ||||
| byte L6470::Xfer(byte data){ | ||||
|   // This simple function shifts a byte out over SPI and receives a byte over
 | ||||
|   // SPI. Unusually for SPI devices, the dSPIN requires a toggling of the
 | ||||
|   // CS (slaveSelect) pin after each byte sent. That makes this function
 | ||||
|   // a bit more reasonable, because we can include more functionality in it.
 | ||||
|   byte data_out; | ||||
|   digitalWrite(_SSPin,LOW); | ||||
|   // SPI.transfer() both shifts a byte out on the MOSI pin AND receives a
 | ||||
|   // byte in on the MISO pin.
 | ||||
|   data_out = SPI.transfer(data); | ||||
|   digitalWrite(_SSPin,HIGH); | ||||
|   return data_out; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| void L6470::SetParam(byte param, unsigned long value){ | ||||
|   Xfer(SET_PARAM | param); | ||||
|   ParamHandler(param, value); | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::GetParam(byte param){ | ||||
|   // Realize the "get parameter" function, to read from the various registers in
 | ||||
|   // the dSPIN chip.
 | ||||
|   Xfer(GET_PARAM | param); | ||||
|   return ParamHandler(param, 0); | ||||
| } | ||||
| 
 | ||||
| long L6470::convert(unsigned long val){ | ||||
|   //convert 22bit 2s comp to signed long
 | ||||
|   int MSB = val >> 21; | ||||
|    | ||||
|   val = val << 11; | ||||
|   val = val >> 11; | ||||
|    | ||||
|   if(MSB == 1) val = val | 0b11111111111000000000000000000000; | ||||
|   return val; | ||||
| } | ||||
| 
 | ||||
| unsigned long L6470::ParamHandler(byte param, unsigned long value){ | ||||
|   // Much of the functionality between "get parameter" and "set parameter" is
 | ||||
|   // very similar, so we deal with that by putting all of it in one function
 | ||||
|   // here to save memory space and simplify the program.
 | ||||
|   unsigned long ret_val = 0; // This is a temp for the value to return.
 | ||||
|   // This switch structure handles the appropriate action for each register.
 | ||||
|   // This is necessary since not all registers are of the same length, either
 | ||||
|   // bit-wise or byte-wise, so we want to make sure we mask out any spurious
 | ||||
|   // bits and do the right number of transfers. That is handled by the dSPIN_Param()
 | ||||
|   // function, in most cases, but for 1-byte or smaller transfers, we call
 | ||||
|   // Xfer() directly.
 | ||||
|   switch (param) | ||||
|   { | ||||
|     // ABS_POS is the current absolute offset from home. It is a 22 bit number expressed
 | ||||
|     // in two's complement. At power up, this value is 0. It cannot be written when
 | ||||
|     // the motor is running, but at any other time, it can be updated to change the
 | ||||
|     // interpreted position of the motor.
 | ||||
|     case ABS_POS: | ||||
|       ret_val = Param(value, 22); | ||||
|       break; | ||||
|     // EL_POS is the current electrical position in the step generation cycle. It can
 | ||||
|     // be set when the motor is not in motion. Value is 0 on power up.
 | ||||
|     case EL_POS: | ||||
|       ret_val = Param(value, 9); | ||||
|       break; | ||||
|     // MARK is a second position other than 0 that the motor can be told to go to. As
 | ||||
|     // with ABS_POS, it is 22-bit two's complement. Value is 0 on power up.
 | ||||
|     case MARK: | ||||
|       ret_val = Param(value, 22); | ||||
|       break; | ||||
|     // SPEED contains information about the current speed. It is read-only. It does
 | ||||
|     // NOT provide direction information.
 | ||||
|     case SPEED: | ||||
|       ret_val = Param(0, 20); | ||||
|       break; | ||||
|     // ACC and DEC set the acceleration and deceleration rates. Set ACC to 0xFFF
 | ||||
|     // to get infinite acceleration/decelaeration- there is no way to get infinite
 | ||||
|     // deceleration w/o infinite acceleration (except the HARD STOP command).
 | ||||
|     // Cannot be written while motor is running. Both default to 0x08A on power up.
 | ||||
|     // AccCalc() and DecCalc() functions exist to convert steps/s/s values into
 | ||||
|     // 12-bit values for these two registers.
 | ||||
|     case ACC: | ||||
|       ret_val = Param(value, 12); | ||||
|       break; | ||||
|     case DEC: | ||||
|       ret_val = Param(value, 12); | ||||
|       break; | ||||
|     // MAX_SPEED is just what it says- any command which attempts to set the speed
 | ||||
|     // of the motor above this value will simply cause the motor to turn at this
 | ||||
|     // speed. Value is 0x041 on power up.
 | ||||
|     // MaxSpdCalc() function exists to convert steps/s value into a 10-bit value
 | ||||
|     // for this register.
 | ||||
|     case MAX_SPEED: | ||||
|       ret_val = Param(value, 10); | ||||
|       break; | ||||
|     // MIN_SPEED controls two things- the activation of the low-speed optimization
 | ||||
|     // feature and the lowest speed the motor will be allowed to operate at. LSPD_OPT
 | ||||
|     // is the 13th bit, and when it is set, the minimum allowed speed is automatically
 | ||||
|     // set to zero. This value is 0 on startup.
 | ||||
|     // MinSpdCalc() function exists to convert steps/s value into a 12-bit value for this
 | ||||
|     // register. SetLowSpeedOpt() function exists to enable/disable the optimization feature.
 | ||||
|     case MIN_SPEED: | ||||
|       ret_val = Param(value, 12); | ||||
|       break; | ||||
|     // FS_SPD register contains a threshold value above which microstepping is disabled
 | ||||
|     // and the dSPIN operates in full-step mode. Defaults to 0x027 on power up.
 | ||||
|     // FSCalc() function exists to convert steps/s value into 10-bit integer for this
 | ||||
|     // register.
 | ||||
|     case FS_SPD: | ||||
|       ret_val = Param(value, 10); | ||||
|       break; | ||||
|     // KVAL is the maximum voltage of the PWM outputs. These 8-bit values are ratiometric
 | ||||
|     // representations: 255 for full output voltage, 128 for half, etc. Default is 0x29.
 | ||||
|     // The implications of different KVAL settings is too complex to dig into here, but
 | ||||
|     // it will usually work to max the value for RUN, ACC, and DEC. Maxing the value for
 | ||||
|     // HOLD may result in excessive power dissipation when the motor is not running.
 | ||||
|     case KVAL_HOLD: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     case KVAL_RUN: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     case KVAL_ACC: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     case KVAL_DEC: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     // INT_SPD, ST_SLP, FN_SLP_ACC and FN_SLP_DEC are all related to the back EMF
 | ||||
|     // compensation functionality. Please see the datasheet for details of this
 | ||||
|     // function- it is too complex to discuss here. Default values seem to work
 | ||||
|     // well enough.
 | ||||
|     case INT_SPD: | ||||
|       ret_val = Param(value, 14); | ||||
|       break; | ||||
|     case ST_SLP: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     case FN_SLP_ACC: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     case FN_SLP_DEC: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     // K_THERM is motor winding thermal drift compensation. Please see the datasheet
 | ||||
|     // for full details on operation- the default value should be okay for most users.
 | ||||
|     case K_THERM: | ||||
|       ret_val = Xfer((byte)value & 0x0F); | ||||
|       break; | ||||
|     // ADC_OUT is a read-only register containing the result of the ADC measurements.
 | ||||
|     // This is less useful than it sounds; see the datasheet for more information.
 | ||||
|     case ADC_OUT: | ||||
|       ret_val = Xfer(0); | ||||
|       break; | ||||
|     // Set the overcurrent threshold. Ranges from 375mA to 6A in steps of 375mA.
 | ||||
|     // A set of defined constants is provided for the user's convenience. Default
 | ||||
|     // value is 3.375A- 0x08. This is a 4-bit value.
 | ||||
|     case OCD_TH: | ||||
|       ret_val = Xfer((byte)value & 0x0F); | ||||
|       break; | ||||
|     // Stall current threshold. Defaults to 0x40, or 2.03A. Value is from 31.25mA to
 | ||||
|     // 4A in 31.25mA steps. This is a 7-bit value.
 | ||||
|     case STALL_TH: | ||||
|       ret_val = Xfer((byte)value & 0x7F); | ||||
|       break; | ||||
|     // STEP_MODE controls the microstepping settings, as well as the generation of an
 | ||||
|     // output signal from the dSPIN. Bits 2:0 control the number of microsteps per
 | ||||
|     // step the part will generate. Bit 7 controls whether the BUSY/SYNC pin outputs
 | ||||
|     // a BUSY signal or a step synchronization signal. Bits 6:4 control the frequency
 | ||||
|     // of the output signal relative to the full-step frequency; see datasheet for
 | ||||
|     // that relationship as it is too complex to reproduce here.
 | ||||
|     // Most likely, only the microsteps per step value will be needed; there is a set
 | ||||
|     // of constants provided for ease of use of these values.
 | ||||
|     case STEP_MODE: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     // ALARM_EN controls which alarms will cause the FLAG pin to fall. A set of constants
 | ||||
|     // is provided to make this easy to interpret. By default, ALL alarms will trigger the
 | ||||
|     // FLAG pin.
 | ||||
|     case ALARM_EN: | ||||
|       ret_val = Xfer((byte)value); | ||||
|       break; | ||||
|     // CONFIG contains some assorted configuration bits and fields. A fairly comprehensive
 | ||||
|     // set of reasonably self-explanatory constants is provided, but users should refer
 | ||||
|     // to the datasheet before modifying the contents of this register to be certain they
 | ||||
|     // understand the implications of their modifications. Value on boot is 0x2E88; this
 | ||||
|     // can be a useful way to verify proper start up and operation of the dSPIN chip.
 | ||||
|     case CONFIG: | ||||
|       ret_val = Param(value, 16); | ||||
|       break; | ||||
|       // STATUS contains read-only information about the current condition of the chip. A
 | ||||
|       // comprehensive set of constants for masking and testing this register is provided, but
 | ||||
|       // users should refer to the datasheet to ensure that they fully understand each one of
 | ||||
|       // the bits in the register.
 | ||||
|     case STATUS: // STATUS is a read-only register
 | ||||
|       ret_val = Param(0, 16); | ||||
|       break; | ||||
|     default: | ||||
|       ret_val = Xfer((byte)(value)); | ||||
|     break; | ||||
|   } | ||||
|   return ret_val; | ||||
| } | ||||
							
								
								
									
										286
									
								
								ArduinoAddons/Arduino_1.6.x/libraries/L6470/L6470.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								ArduinoAddons/Arduino_1.6.x/libraries/L6470/L6470.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,286 @@ | ||||
| ////////////////////////////////////////////////////////////
 | ||||
| //ORIGINAL CODE 12/12/2011- Mike Hord, SparkFun Electronics
 | ||||
| //LIBRARY Created by Adam Meyer of bildr Aug 18th 2012
 | ||||
| //Released as MIT license
 | ||||
| ////////////////////////////////////////////////////////////
 | ||||
| #ifndef L6470_h | ||||
| #define L6470_h | ||||
| 
 | ||||
| #include <Arduino.h> | ||||
| #include <SPI.h> | ||||
| 
 | ||||
| #define SLAVE_SELECT_PIN 38 // Wire this to the CSN pin
 | ||||
| // #define RESET 6 // Wire this to the STBY line
 | ||||
| #define BUSYN 7 // Wire this to the BSYN line
 | ||||
| 
 | ||||
| // constant definitions for overcurrent thresholds. Write these values to
 | ||||
| // register dSPIN_OCD_TH to set the level at which an overcurrent even occurs.
 | ||||
| #define OCD_TH_375mA 0x00 | ||||
| #define OCD_TH_750mA 0x01 | ||||
| #define OCD_TH_1125mA 0x02 | ||||
| #define OCD_TH_1500mA 0x03 | ||||
| #define OCD_TH_1875mA 0x04 | ||||
| #define OCD_TH_2250mA 0x05 | ||||
| #define OCD_TH_2625mA 0x06 | ||||
| #define OCD_TH_3000mA 0x07 | ||||
| #define OCD_TH_3375mA 0x08 | ||||
| #define OCD_TH_3750mA 0x09 | ||||
| #define OCD_TH_4125mA 0x0A | ||||
| #define OCD_TH_4500mA 0x0B | ||||
| #define OCD_TH_4875mA 0x0C | ||||
| #define OCD_TH_5250mA 0x0D | ||||
| #define OCD_TH_5625mA 0x0E | ||||
| #define OCD_TH_6000mA 0x0F | ||||
| 
 | ||||
| // STEP_MODE option values.
 | ||||
| // First comes the "microsteps per step" options...
 | ||||
| #define STEP_MODE_STEP_SEL 0x07 // Mask for these bits only.
 | ||||
| #define STEP_SEL_1 0x00 | ||||
| #define STEP_SEL_1_2 0x01 | ||||
| #define STEP_SEL_1_4 0x02 | ||||
| #define STEP_SEL_1_8 0x03 | ||||
| #define STEP_SEL_1_16 0x04 | ||||
| #define STEP_SEL_1_32 0x05 | ||||
| #define STEP_SEL_1_64 0x06 | ||||
| #define STEP_SEL_1_128 0x07 | ||||
| 
 | ||||
| // ...next, define the SYNC_EN bit. When set, the BUSYN pin will instead
 | ||||
| // output a clock related to the full-step frequency as defined by the
 | ||||
| // SYNC_SEL bits below.
 | ||||
| #define STEP_MODE_SYNC_EN 0x80 // Mask for this bit
 | ||||
| #define SYNC_EN 0x80 | ||||
| 
 | ||||
| // ...last, define the SYNC_SEL modes. The clock output is defined by
 | ||||
| // the full-step frequency and the value in these bits- see the datasheet
 | ||||
| // for a matrix describing that relationship (page 46).
 | ||||
| #define STEP_MODE_SYNC_SEL 0x70 | ||||
| #define SYNC_SEL_1_2 0x00 | ||||
| #define SYNC_SEL_1 0x10 | ||||
| #define SYNC_SEL_2 0x20 | ||||
| #define SYNC_SEL_4 0x30 | ||||
| #define SYNC_SEL_8 0x40 | ||||
| #define SYNC_SEL_16 0x50 | ||||
| #define SYNC_SEL_32 0x60 | ||||
| #define SYNC_SEL_64 0x70 | ||||
| 
 | ||||
| // Bit names for the ALARM_EN register.
 | ||||
| // Each of these bits defines one potential alarm condition.
 | ||||
| // When one of these conditions occurs and the respective bit in ALARM_EN is set,
 | ||||
| // the FLAG pin will go low. The register must be queried to determine which event
 | ||||
| // caused the alarm.
 | ||||
| #define ALARM_EN_OVERCURRENT 0x01 | ||||
| #define ALARM_EN_THERMAL_SHUTDOWN 0x02 | ||||
| #define ALARM_EN_THERMAL_WARNING 0x04 | ||||
| #define ALARM_EN_UNDER_VOLTAGE 0x08 | ||||
| #define ALARM_EN_STALL_DET_A 0x10 | ||||
| #define ALARM_EN_STALL_DET_B 0x20 | ||||
| #define ALARM_EN_SW_TURN_ON 0x40 | ||||
| #define ALARM_EN_WRONG_NPERF_CMD 0x80 | ||||
| 
 | ||||
| // CONFIG register renames.
 | ||||
| 
 | ||||
| // Oscillator options.
 | ||||
| // The dSPIN needs to know what the clock frequency is because it uses that for some
 | ||||
| // calculations during operation.
 | ||||
| #define CONFIG_OSC_SEL 0x000F // Mask for this bit field.
 | ||||
| #define CONFIG_INT_16MHZ 0x0000 // Internal 16MHz, no output
 | ||||
| #define CONFIG_INT_16MHZ_OSCOUT_2MHZ 0x0008 // Default; internal 16MHz, 2MHz output
 | ||||
| #define CONFIG_INT_16MHZ_OSCOUT_4MHZ 0x0009 // Internal 16MHz, 4MHz output
 | ||||
| #define CONFIG_INT_16MHZ_OSCOUT_8MHZ 0x000A // Internal 16MHz, 8MHz output
 | ||||
| #define CONFIG_INT_16MHZ_OSCOUT_16MHZ 0x000B // Internal 16MHz, 16MHz output
 | ||||
| #define CONFIG_EXT_8MHZ_XTAL_DRIVE 0x0004 // External 8MHz crystal
 | ||||
| #define CONFIG_EXT_16MHZ_XTAL_DRIVE 0x0005 // External 16MHz crystal
 | ||||
| #define CONFIG_EXT_24MHZ_XTAL_DRIVE 0x0006 // External 24MHz crystal
 | ||||
| #define CONFIG_EXT_32MHZ_XTAL_DRIVE 0x0007 // External 32MHz crystal
 | ||||
| #define CONFIG_EXT_8MHZ_OSCOUT_INVERT 0x000C // External 8MHz crystal, output inverted
 | ||||
| #define CONFIG_EXT_16MHZ_OSCOUT_INVERT 0x000D // External 16MHz crystal, output inverted
 | ||||
| #define CONFIG_EXT_24MHZ_OSCOUT_INVERT 0x000E // External 24MHz crystal, output inverted
 | ||||
| #define CONFIG_EXT_32MHZ_OSCOUT_INVERT 0x000F // External 32MHz crystal, output inverted
 | ||||
| 
 | ||||
| // Configure the functionality of the external switch input
 | ||||
| #define CONFIG_SW_MODE 0x0010 // Mask for this bit.
 | ||||
| #define CONFIG_SW_HARD_STOP 0x0000 // Default; hard stop motor on switch.
 | ||||
| #define CONFIG_SW_USER 0x0010 // Tie to the GoUntil and ReleaseSW
 | ||||
|                                                     // commands to provide jog function.
 | ||||
|                                                     // See page 25 of datasheet.
 | ||||
| 
 | ||||
| // Configure the motor voltage compensation mode (see page 34 of datasheet)
 | ||||
| #define CONFIG_EN_VSCOMP 0x0020 // Mask for this bit.
 | ||||
| #define CONFIG_VS_COMP_DISABLE 0x0000 // Disable motor voltage compensation.
 | ||||
| #define CONFIG_VS_COMP_ENABLE 0x0020 // Enable motor voltage compensation.
 | ||||
| 
 | ||||
| // Configure overcurrent detection event handling
 | ||||
| #define CONFIG_OC_SD 0x0080 // Mask for this bit.
 | ||||
| #define CONFIG_OC_SD_DISABLE 0x0000 // Bridges do NOT shutdown on OC detect
 | ||||
| #define CONFIG_OC_SD_ENABLE 0x0080 // Bridges shutdown on OC detect
 | ||||
| 
 | ||||
| // Configure the slew rate of the power bridge output
 | ||||
| #define CONFIG_POW_SR 0x0300 // Mask for this bit field.
 | ||||
| #define CONFIG_SR_180V_us 0x0000 // 180V/us
 | ||||
| #define CONFIG_SR_290V_us 0x0200 // 290V/us
 | ||||
| #define CONFIG_SR_530V_us 0x0300 // 530V/us
 | ||||
| 
 | ||||
| // Integer divisors for PWM sinewave generation
 | ||||
| // See page 32 of the datasheet for more information on this.
 | ||||
| #define CONFIG_F_PWM_DEC 0x1C00 // mask for this bit field
 | ||||
| #define CONFIG_PWM_MUL_0_625 (0x00)<<10 | ||||
| #define CONFIG_PWM_MUL_0_75 (0x01)<<10 | ||||
| #define CONFIG_PWM_MUL_0_875 (0x02)<<10 | ||||
| #define CONFIG_PWM_MUL_1 (0x03)<<10 | ||||
| #define CONFIG_PWM_MUL_1_25 (0x04)<<10 | ||||
| #define CONFIG_PWM_MUL_1_5 (0x05)<<10 | ||||
| #define CONFIG_PWM_MUL_1_75 (0x06)<<10 | ||||
| #define CONFIG_PWM_MUL_2 (0x07)<<10 | ||||
| 
 | ||||
| // Multiplier for the PWM sinewave frequency
 | ||||
| #define CONFIG_F_PWM_INT 0xE000 // mask for this bit field.
 | ||||
| #define CONFIG_PWM_DIV_1 (0x00)<<13 | ||||
| #define CONFIG_PWM_DIV_2 (0x01)<<13 | ||||
| #define CONFIG_PWM_DIV_3 (0x02)<<13 | ||||
| #define CONFIG_PWM_DIV_4 (0x03)<<13 | ||||
| #define CONFIG_PWM_DIV_5 (0x04)<<13 | ||||
| #define CONFIG_PWM_DIV_6 (0x05)<<13 | ||||
| #define CONFIG_PWM_DIV_7 (0x06)<<13 | ||||
| 
 | ||||
| // Status register bit renames- read-only bits conferring information about the
 | ||||
| // device to the user.
 | ||||
| #define STATUS_HIZ 0x0001 // high when bridges are in HiZ mode
 | ||||
| #define STATUS_BUSY 0x0002 // mirrors BUSY pin
 | ||||
| #define STATUS_SW_F 0x0004 // low when switch open, high when closed
 | ||||
| #define STATUS_SW_EVN 0x0008 // active high, set on switch falling edge,
 | ||||
|                                                     // cleared by reading STATUS
 | ||||
| #define STATUS_DIR 0x0010 // Indicates current motor direction.
 | ||||
|                                                     // High is FWD, Low is REV.
 | ||||
| #define STATUS_NOTPERF_CMD 0x0080 // Last command not performed.
 | ||||
| #define STATUS_WRONG_CMD 0x0100 // Last command not valid.
 | ||||
| #define STATUS_UVLO 0x0200 // Undervoltage lockout is active
 | ||||
| #define STATUS_TH_WRN 0x0400 // Thermal warning
 | ||||
| #define STATUS_TH_SD 0x0800 // Thermal shutdown
 | ||||
| #define STATUS_OCD 0x1000 // Overcurrent detected
 | ||||
| #define STATUS_STEP_LOSS_A 0x2000 // Stall detected on A bridge
 | ||||
| #define STATUS_STEP_LOSS_B 0x4000 // Stall detected on B bridge
 | ||||
| #define STATUS_SCK_MOD 0x8000 // Step clock mode is active
 | ||||
| 
 | ||||
| // Status register motor status field
 | ||||
| #define STATUS_MOT_STATUS 0x0060 // field mask
 | ||||
| #define STATUS_MOT_STATUS_STOPPED (0x0000)<<13 // Motor stopped
 | ||||
| #define STATUS_MOT_STATUS_ACCELERATION (0x0001)<<13 // Motor accelerating
 | ||||
| #define STATUS_MOT_STATUS_DECELERATION (0x0002)<<13 // Motor decelerating
 | ||||
| #define STATUS_MOT_STATUS_CONST_SPD (0x0003)<<13 // Motor at constant speed
 | ||||
| 
 | ||||
| // Register address redefines.
 | ||||
| // See the Param_Handler() function for more info about these.
 | ||||
| #define ABS_POS 0x01 | ||||
| #define EL_POS 0x02 | ||||
| #define MARK 0x03 | ||||
| #define SPEED 0x04 | ||||
| #define ACC 0x05 | ||||
| #define DEC 0x06 | ||||
| #define MAX_SPEED 0x07 | ||||
| #define MIN_SPEED 0x08 | ||||
| #define FS_SPD 0x15 | ||||
| #define KVAL_HOLD 0x09 | ||||
| #define KVAL_RUN 0x0A | ||||
| #define KVAL_ACC 0x0B | ||||
| #define KVAL_DEC 0x0C | ||||
| #define INT_SPD 0x0D | ||||
| #define ST_SLP 0x0E | ||||
| #define FN_SLP_ACC 0x0F | ||||
| #define FN_SLP_DEC 0x10 | ||||
| #define K_THERM 0x11 | ||||
| #define ADC_OUT 0x12 | ||||
| #define OCD_TH 0x13 | ||||
| #define STALL_TH 0x14 | ||||
| #define STEP_MODE 0x16 | ||||
| #define ALARM_EN 0x17 | ||||
| #define CONFIG 0x18 | ||||
| #define STATUS 0x19 | ||||
| 
 | ||||
| //dSPIN commands
 | ||||
| #define NOP 0x00 | ||||
| #define SET_PARAM 0x00 | ||||
| #define GET_PARAM 0x20 | ||||
| #define RUN 0x50 | ||||
| #define STEP_CLOCK 0x58 | ||||
| #define MOVE 0x40 | ||||
| #define GOTO 0x60 | ||||
| #define GOTO_DIR 0x68 | ||||
| #define GO_UNTIL 0x82 | ||||
| #define RELEASE_SW 0x92 | ||||
| #define GO_HOME 0x70 | ||||
| #define GO_MARK 0x78 | ||||
| #define RESET_POS 0xD8 | ||||
| #define RESET_DEVICE 0xC0 | ||||
| #define SOFT_STOP 0xB0 | ||||
| #define HARD_STOP 0xB8 | ||||
| #define SOFT_HIZ 0xA0 | ||||
| #define HARD_HIZ 0xA8 | ||||
| #define GET_STATUS 0xD0 | ||||
| 
 | ||||
| /* dSPIN direction options */ | ||||
| #define FWD 0x01 | ||||
| #define REV 0x00 | ||||
| 
 | ||||
| /* dSPIN action options */ | ||||
| #define ACTION_RESET 0x00 | ||||
| #define ACTION_COPY 0x01 | ||||
| 
 | ||||
| 
 | ||||
| class L6470{ | ||||
| 
 | ||||
|   public: | ||||
| 
 | ||||
|     L6470(int SSPin); | ||||
|     void init(int k_value); | ||||
|     void setMicroSteps(int microSteps); | ||||
|     void setCurrent(int current); | ||||
|     void setMaxSpeed(int speed); | ||||
|     void setMinSpeed(int speed); | ||||
|     void setAcc(float acceleration); | ||||
|     void setDec(float deceleration); | ||||
|     void setOverCurrent(unsigned int ma_current); | ||||
|     void setThresholdSpeed(float threshold); | ||||
|     void setStallCurrent(float ma_current); | ||||
|      | ||||
|     unsigned long ParamHandler(byte param, unsigned long value); | ||||
|     void SetLowSpeedOpt(boolean enable); | ||||
|     void run(byte dir, float spd); | ||||
|     void Step_Clock(byte dir); | ||||
|     void goHome(); | ||||
|     void setAsHome(); | ||||
|     void goMark(); | ||||
|     void move(long n_step); | ||||
|     void goTo(long pos); | ||||
|     void goTo_DIR(byte dir, long pos); | ||||
|     void goUntil(byte act, byte dir, unsigned long spd); | ||||
|     boolean isBusy(); | ||||
|     void releaseSW(byte act, byte dir); | ||||
|     float getSpeed(); | ||||
|     long getPos(); | ||||
|     void setMark(); | ||||
|     void setMark(long value); | ||||
|     void resetPos(); | ||||
|     void resetDev(); | ||||
|     void softStop(); | ||||
|     void hardStop(); | ||||
|     void softFree(); | ||||
|     void free(); | ||||
|     int getStatus(); | ||||
| 	void SetParam(byte param, unsigned long value); | ||||
| 
 | ||||
|   private: | ||||
|     long convert(unsigned long val); | ||||
|     unsigned long GetParam(byte param); | ||||
|     unsigned long AccCalc(float stepsPerSecPerSec); | ||||
|     unsigned long DecCalc(float stepsPerSecPerSec); | ||||
|     unsigned long MaxSpdCalc(float stepsPerSec); | ||||
|     unsigned long MinSpdCalc(float stepsPerSec); | ||||
|     unsigned long FSCalc(float stepsPerSec); | ||||
|     unsigned long IntSpdCalc(float stepsPerSec); | ||||
|     unsigned long SpdCalc(float stepsPerSec); | ||||
|     unsigned long Param(unsigned long value, byte bit_len); | ||||
|     byte Xfer(byte data); | ||||
|     int _SSPin; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										53
									
								
								ArduinoAddons/Arduino_1.6.x/libraries/L6470/keywords.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								ArduinoAddons/Arduino_1.6.x/libraries/L6470/keywords.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| ####################################################### | ||||
| # keywords.txt - keywords file for the L6470 library | ||||
| # | ||||
| # ORIGINAL CODE 12/12/2011- Mike Hord, SparkFun Electronics | ||||
| # Library by Adam Meyer of bildr Aug 18th 2012 | ||||
| # | ||||
| # Released as MIT license | ||||
| ####################################################### | ||||
| 
 | ||||
| ####################################### | ||||
| # Datatypes (KEYWORD1) | ||||
| ####################################### | ||||
| 
 | ||||
| L6470 KEYWORD1 | ||||
| 
 | ||||
| ####################################### | ||||
| # Methods and Functions (KEYWORD2) | ||||
| ####################################### | ||||
| 
 | ||||
| L6470 				KEYWORD2 | ||||
| init 				KEYWORD2 | ||||
| setMicroSteps 		KEYWORD2 | ||||
| setCurrent 			KEYWORD2 | ||||
| setMaxSpeed 		KEYWORD2 | ||||
| setMinSpeed 		KEYWORD2 | ||||
| setAcc 				KEYWORD2 | ||||
| setDec 				KEYWORD2 | ||||
| setOverCurrent 		KEYWORD2 | ||||
| setThresholdSpeed 	KEYWORD2 | ||||
| setStallCurrent 	KEYWORD2 | ||||
| ParamHandler 		KEYWORD2 | ||||
| SetLowSpeedOpt 		KEYWORD2 | ||||
| run 				KEYWORD2 | ||||
| Step_Clock 			KEYWORD2 | ||||
| goHome 				KEYWORD2 | ||||
| goMark 				KEYWORD2 | ||||
| move 				KEYWORD2 | ||||
| goTo 				KEYWORD2 | ||||
| goTo_DIR 			KEYWORD2 | ||||
| goUntil 			KEYWORD2 | ||||
| isBusy 				KEYWORD2 | ||||
| releaseSW 			KEYWORD2 | ||||
| resetPos			KEYWORD2 | ||||
| resetDev 			KEYWORD2 | ||||
| softStop			KEYWORD2 | ||||
| hardStop 			KEYWORD2 | ||||
| softHiZ 			KEYWORD2 | ||||
| hardHiZ 			KEYWORD2 | ||||
| getStatus 			KEYWORD2 | ||||
| 
 | ||||
| ####################################### | ||||
| # Constants (LITERAL1) | ||||
| ####################################### | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user