-
Notifications
You must be signed in to change notification settings - Fork 0
/
AutoDriverConfig_Due.cpp
214 lines (183 loc) · 7.67 KB
/
AutoDriverConfig_Due.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#include "AutoDriver_Due.h"
// Setup the SYNC/BUSY pin to be either SYNC or BUSY, and to a desired
// ticks per step level.
void AutoDriver_Due::configSyncPin(byte pinFunc, byte syncSteps)
{
// Only some of the bits in this register are of interest to us; we need to
// clear those bits. It happens that they are the upper four.
byte syncPinConfig = (byte)getParam(STEP_MODE);
syncPinConfig &= 0x0F;
// Now, let's OR in the arguments. We're going to mask the incoming
// data to avoid touching any bits that aren't appropriate. See datasheet
// for more info about which bits we're touching.
syncPinConfig |= ((pinFunc & 0x80) | (syncSteps & 0x70));
// Now we should be able to send that byte right back to the dSPIN- it
// won't corrupt the other bits, and the changes are made.
setParam(STEP_MODE, (unsigned long)syncPinConfig);
}
// The dSPIN chip supports microstepping for a smoother ride. This function
// provides an easy front end for changing the microstepping mode.
void AutoDriver_Due::configStepMode(byte stepMode)
{
// Only some of these bits are useful (the lower three). We'll extract the
// current contents, clear those three bits, then set them accordingly.
byte stepModeConfig = (byte)getParam(STEP_MODE);
stepModeConfig &= 0xF8;
// Now we can OR in the new bit settings. Mask the argument so we don't
// accidentally the other bits, if the user sends us a non-legit value.
stepModeConfig |= (stepMode&0x07);
// Now push the change to the chip.
setParam(STEP_MODE, (unsigned long)stepModeConfig);
}
// This is the maximum speed the dSPIN will attempt to produce.
void AutoDriver_Due::setMaxSpeed(float stepsPerSecond)
{
// We need to convert the floating point stepsPerSecond into a value that
// the dSPIN can understand. Fortunately, we have a function to do that.
unsigned long integerSpeed = maxSpdCalc(stepsPerSecond);
// Now, we can set that paramter.
setParam(MAX_SPEED, integerSpeed);
}
// Set the minimum speed allowable in the system. This is the speed a motion
// starts with; it will then ramp up to the designated speed or the max
// speed, using the acceleration profile.
void AutoDriver_Due::setMinSpeed(float stepsPerSecond)
{
// We need to convert the floating point stepsPerSecond into a value that
// the dSPIN can understand. Fortunately, we have a function to do that.
unsigned long integerSpeed = minSpdCalc(stepsPerSecond);
// MIN_SPEED also contains the LSPD_OPT flag, so we need to protect that.
unsigned long temp = getParam(MIN_SPEED) & 0x00001000;
// Now, we can set that paramter.
setParam(MIN_SPEED, integerSpeed | temp);
}
// Above this threshold, the dSPIN will cease microstepping and go to full-step
// mode.
void AutoDriver_Due::setFullSpeed(float stepsPerSecond)
{
unsigned long integerSpeed = FSCalc(stepsPerSecond);
setParam(FS_SPD, integerSpeed);
}
// Set the acceleration rate, in steps per second per second. This value is
// converted to a dSPIN friendly value. Any value larger than 29802 will
// disable acceleration, putting the chip in "infinite" acceleration mode.
void AutoDriver_Due::setAcc(float stepsPerSecondPerSecond)
{
unsigned long integerAcc = accCalc(stepsPerSecondPerSecond);
setParam(ACC, integerAcc);
}
// Same rules as setAcc().
void AutoDriver_Due::setDec(float stepsPerSecondPerSecond)
{
unsigned long integerDec = decCalc(stepsPerSecondPerSecond);
setParam(DECEL, integerDec);
}
void AutoDriver_Due::setOCThreshold(byte threshold)
{
setParam(OCD_TH, 0x0F & threshold);
}
// The next few functions are all breakouts for individual options within the
// single register CONFIG. We'll read CONFIG, blank some bits, then OR in the
// new value.
// This is a multiplier/divider setup for the PWM frequency when microstepping.
// Divisors of 1-7 are available; multipliers of .625-2 are available. See
// datasheet for more details; it's not clear what the frequency being
// multiplied/divided here is, but it is clearly *not* the actual clock freq.
void AutoDriver_Due::setPWMFreq(int divisor, int multiplier)
{
unsigned long configVal = getParam(CONFIG);
// The divisor is set by config 15:13, so mask 0xE000 to clear them.
configVal &= ~(0xE000);
// The multiplier is set by config 12:10; mask is 0x1C00
configVal &= ~(0x1C00);
// Now we can OR in the masked-out versions of the values passed in.
configVal |= ((0xE000&divisor)|(0x1C00&multiplier));
setParam(CONFIG, configVal);
}
// Slew rate of the output in V/us. Can be 180, 290, or 530.
void AutoDriver_Due::setSlewRate(int slewRate)
{
unsigned long configVal = getParam(CONFIG);
// These bits live in CONFIG 9:8, so the mask is 0x0300.
configVal &= ~(0x0300);
//Now, OR in the masked incoming value.
configVal |= (0x0300&slewRate);
setParam(CONFIG, configVal);
}
// Single bit- do we shutdown the drivers on overcurrent or not?
void AutoDriver_Due::setOCShutdown(int OCShutdown)
{
unsigned long configVal = getParam(CONFIG);
// This bit is CONFIG 7, mask is 0x0080
configVal &= ~(0x0800);
//Now, OR in the masked incoming value.
configVal |= (0x0800&OCShutdown);
setParam(CONFIG, configVal);
}
// Enable motor voltage compensation? Not at all straightforward- check out
// p34 of the datasheet.
void AutoDriver_Due::setVoltageComp(int vsCompMode)
{
unsigned long configVal = getParam(CONFIG);
// This bit is CONFIG 5, mask is 0x0020
configVal &= ~(0x0200);
//Now, OR in the masked incoming value.
configVal |= (0x0200&vsCompMode);
setParam(CONFIG, configVal);
}
// The switch input can either hard-stop the driver _or_ activate an interrupt.
// This bit allows you to select what it does.
void AutoDriver_Due::setSwitchMode(int switchMode)
{
unsigned long configVal = getParam(CONFIG);
// This bit is CONFIG 4, mask is 0x0010
configVal &= ~(0x0100);
//Now, OR in the masked incoming value.
configVal |= (0x0100&switchMode);
setParam(CONFIG, configVal);
}
// There are a number of clock options for this chip- it can be configured to
// accept a clock, drive a crystal or resonator, and pass or not pass the
// clock signal downstream. Theoretically, you can use pretty much any
// frequency you want to drive it; practically, this library assumes it's
// being driven at 16MHz. Also, the device will use these bits to set the
// math used to figure out steps per second and stuff like that.
void AutoDriver_Due::setOscMode(int oscillatorMode)
{
unsigned long configVal = getParam(CONFIG);
// These bits are CONFIG 3:0, mask is 0x000F
configVal &= ~(0x000F);
//Now, OR in the masked incoming value.
configVal |= (0x000F&oscillatorMode);
setParam(CONFIG, configVal);
}
// The KVAL registers are...weird. I don't entirely understand how they differ
// from the microstepping, but if you have trouble getting the motor to run,
// tweaking KVAL has proven effective in the past. There's a separate register
// for each case: running, static, accelerating, and decelerating.
void AutoDriver_Due::setAccKVAL(byte kvalInput)
{
setParam(KVAL_ACC, kvalInput);
}
void AutoDriver_Due::setDecKVAL(byte kvalInput)
{
setParam(KVAL_DEC, kvalInput);
}
void AutoDriver_Due::setRunKVAL(byte kvalInput)
{
setParam(KVAL_RUN, kvalInput);
}
void AutoDriver_Due::setHoldKVAL(byte kvalInput)
{
setParam(KVAL_HOLD, kvalInput);
}
// Enable or disable the low-speed optimization option. With LSPD_OPT enabled,
// motion starts from 0 instead of MIN_SPEED and low-speed optimization keeps
// the driving sine wave prettier than normal until MIN_SPEED is reached.
void AutoDriver_Due::setLoSpdOpt(boolean enable)
{
unsigned long temp = getParam(MIN_SPEED);
if (enable) temp |= 0x00001000; // Set the LSPD_OPT bit
else temp &= 0xffffefff; // Clear the LSPD_OPT bit
setParam(MIN_SPEED, temp);
}