Commit beabe09a authored by Jake Read's avatar Jake Read

add video link

parent 5fc67d3b
...@@ -33,10 +33,10 @@ UsedLibrary="D:/Dropbox (Personal)/CBA/doc/libraries_jake/eagle/marekr/borkedlab ...@@ -33,10 +33,10 @@ UsedLibrary="D:/Dropbox (Personal)/CBA/doc/libraries_jake/eagle/marekr/borkedlab
[Win_1] [Win_1]
Type="Schematic Editor" Type="Schematic Editor"
Loc="0 0 1919 1039" Loc="0 0 1919 1039"
State=1 State=3
Number=2 Number=2
File="mkbldcdriver.sch" File="mkbldcdriver.sch"
View="-18.3248 -28.0797 297.35 80.9142" View="57.8709 -13.4537 277.09 62.2366"
WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524" WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524"
PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0"
PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6" PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6"
...@@ -75,16 +75,16 @@ ArcDirection=0 ...@@ -75,16 +75,16 @@ ArcDirection=0
AddLevel=2 AddLevel=2
PadsSameType=0 PadsSameType=0
Layer=91 Layer=91
Views=" 1: -18.3248 -28.0797 297.35 80.9142" Views=" 1: 57.8709 -13.4537 277.09 62.2366"
Sheet="1" Sheet="1"
[Win_2] [Win_2]
Type="Board Editor" Type="Board Editor"
Loc="0 0 1919 1039" Loc="0 0 1919 1039"
State=1 State=3
Number=1 Number=1
File="mkbldcdriver.brd" File="mkbldcdriver.brd"
View="-7.02111 10.2916 81.0333 66.2425" View="18.3898 11.659 106.444 67.6099"
WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524" WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524"
PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0"
PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6" PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6"
......
...@@ -219,16 +219,103 @@ OK. Long road ahead. Here's my list ...@@ -219,16 +219,103 @@ OK. Long road ahead. Here's my list
I'm using the ATSAM's SPI Peripheral. I am *really* swimming in the datasheet at the moment. There's a lot to configure! I'm using the ATSAM's SPI Peripheral. I am *really* swimming in the datasheet at the moment. There's a lot to configure!
Although I've double checked through the layers, it seems like I'm getting my MOSI output on the CLK line... ah, I was reading my labels incorrectly. Here we go, some code.
```C
void setupspi(void){
// using SPI0, PID 21
// MISO, PD20, Peripheral B
// MOSI, PD21, Peripheral B
// SPCK, PD22, Peripheral B
// NPCS, PA31, Peripheral A
PMC->PMC_PCER0 = 1 << ID_SPI0;
PIOD->PIO_PDR |= PIO_PER_P20 | PIO_PER_P21 | PIO_PER_P22;
PIOA->PIO_PDR |= PIO_PER_P31;
SPI0->SPI_CR |= SPI_CR_SPIEN;
SPI0->SPI_MR |= SPI_MR_MSTR | SPI_MR_PCS(1);
SPI0->SPI_CSR[1] |= SPI_CSR_BITS_16_BIT | SPI_CSR_NCPHA | SPI_CSR_SCBR(200);
}
```
Turned out to be kind of boring.
So SPI is *really fast* - i.e. I can run this at ~5MBPS no problem, and I'm only doing a 32 bit transfer each time. What's more, SPI is like synchronous duplex, as in during the same time shift out 32 bits, 32 bits come in. This is the major advantage of a clocked / master:slave relationship. This means that for a total of 64 bit transferred, we take only 6.4us. Holy heck. I'm not even going to bother writing non-blocking code.
```C
void readencoder(uint16_t *data){
while(!(SPI0->SPI_SR & SPI_SR_TXEMPTY)); // wait 4 ready
SPI0->SPI_TDR = SPI_TDR_TD(0xFFFF);// | SPI_TDR_PCS(1);
while(!(SPI0->SPI_SR & SPI_SR_TXEMPTY)); // wait 4 ready
SPI0->SPI_TDR = SPI_TDR_TD(0x0000);// | SPI_TDR_PCS(1);
*data = SPI0->SPI_RDR & SPI_RDR_RD_Msk;
//uint16_t pard = data >> 15;
*data = *data << 2; // shift parity and error bit out
*data /= 4;
}
```
OK - I've got this set up properly. Now I'll try plugging the encoder in an reading some values! OK - I've got this set up properly. Now I'll try plugging the encoder in an reading some values!
Great, and with a shift in some setting (I was wrong) I'm reading SPI values nicely. Next test is to see if these values get all messed up when I turn the motor on (update: nope, yay), introducing lots of EMF and noise into the system... Then I'll write some open-loop commutation using the encoder values (update: done). Then I'll think about writing a simple PID position loop. If I get through all of that tonight, I'll go to bed (haha). Great, and with a shift in some setting (I was wrong) I'm reading SPI values nicely. Next test is to see if these values get all messed up when I turn the motor on (update: nope, yay), introducing lots of EMF and noise into the system... Then I'll write some open-loop commutation using the encoder values (update: done). Then I'll think about writing a simple PID position loop. If I get through all of that tonight, I'll go to bed (haha).
But what's the larger goal here? I have one more day. OK - I got closed-loop commutation working. This is where I take a position reading on the rotor and use that to advance the sinusoidal voltage I am sending to the phases such that *roughly* I get a magnetic field that is 90deg out of phase from the rotor's magnetic field. This is the max torque scenario.
```C
uint16_t encoder;
readencoder(&encoder);
if(reverse){
encoder = resolution - encoder;
}
uint16_t elecpos = (encoder + offset) % modulo; // 0 -> 2*PI in rads
// to update, must use duty update register, not just 'duty'
if(dir){
phaseu = elecpos/(modulo / 1024);
phasev = elecpos/(modulo / 1024) + 341;
phasew = elecpos/(modulo / 1024) + 682;
} else {
phaseu = elecpos/(modulo / 1024) + 682;
phasev = elecpos/(modulo / 1024) + 341;
phasew = elecpos/(modulo / 1024);
}
if (phaseu > 1023){
phaseu -= 1023;
}
if(phasev > 1023){
phasev -= 1023;
}
if(phasew > 1023){
phasew -= 1023;
}
```
Pretty slick, the key is adjusting the offset.
[Here](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver/raw/master/video/clcomm.m4v) is a video of the motor turning *nicely* using closed-loop commutation. Not sure why this is upside-down, but that doesn't seem important. Also - you'll hear the 10KHz pwm buzz - this is something I plan on eliminating (it's simple - I just push the PWM frequency out of the audible range) but I have left it just in the audible range so that I can be sure when the gate-drivers are on (I don't want to fry anything!).
# The EMI Problem
Below, a log of me writing notes when I find this intermittent, horrible, reset condition.
Also: a note, I'm having odd reset events occasionally. Related to the earlier issue w/ usb power. I think I need to revisit the 'bfpsu' issue - wherein I want a 24V PSU that will deliver nice consistent power ~ 65 amps (that's about as much juice as is possible to pull out of a wall socket). I may need to build this, as these don't seem readily available. My other thought is to find a big switching PSU, and hook up a *giant* capacitor to the output to smooth it out. Also: a note, I'm having odd reset events occasionally. Related to the earlier issue w/ usb power. I think I need to revisit the 'bfpsu' issue - wherein I want a 24V PSU that will deliver nice consistent power ~ 65 amps (that's about as much juice as is possible to pull out of a wall socket). I may need to build this, as these don't seem readily available. My other thought is to find a big switching PSU, and hook up a *giant* capacitor to the output to smooth it out.
OMG it's the SWITCH is being super intermittent. Don't use a switch rated for 7.5 amps past 7.5 amps. Heck! OMG it's the SWITCH is being super intermittent. Don't use a switch rated for 7.5 amps past 7.5 amps. Heck!
OK - like 8th loop on this. I fixed that wiring and was still having a reset issue. Back at it now, added extra capacitance to the 5V output, and a diode that I had previously omitted soldering on. Seems better, but I make no promises to myself. OK - like 8th loop on this. I fixed that wiring and was still having a reset issue. Back at it now, added extra capacitance to the 5V output, and a diode that I had previously omitted soldering on. Seems better, but I make no promises to myself.
\ No newline at end of file
Another update on this - I've shortened the motor lead wires and this seems to have killed the problem. Again, no expectations - I've been wrong a few times. But I suspect EMI was the issue, and shorter lines (smaller antennas) could be the solution! Hurray, maybe :| .
![emi](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver/raw/master/images/emi.jpg)
So this shortened motor wires did seem to really kill the problem. Fin.
\ No newline at end of file
...@@ -244,6 +244,9 @@ void readencoder(uint16_t *data){ ...@@ -244,6 +244,9 @@ void readencoder(uint16_t *data){
*data /= 4; *data /= 4;
} }
#define IS_ENCODER_COM 0
#define IS_OPENLOOP_COM 1
int main (void) int main (void)
{ {
/* Insert system clock initialization code here (sysclk_init()). */ /* Insert system clock initialization code here (sysclk_init()). */
...@@ -265,7 +268,7 @@ int main (void) ...@@ -265,7 +268,7 @@ int main (void)
uint8_t maxscalar = 64; uint8_t maxscalar = 64;
uint8_t scalar = 24; // 0 -> 255 (these will be chars from serial) uint8_t scalar = 45; // 0 -> 255 (these will be chars from serial)
uint8_t period = 20; // us between ++ in phase uint8_t period = 20; // us between ++ in phase
uint32_t phaseu = 0; // 0 -> 1023 uint32_t phaseu = 0; // 0 -> 1023
...@@ -333,6 +336,7 @@ int main (void) ...@@ -333,6 +336,7 @@ int main (void)
} // end message handler } // end message handler
#if IS_ENCODER_COM
uint16_t encoder; uint16_t encoder;
readencoder(&encoder); readencoder(&encoder);
...@@ -369,12 +373,31 @@ int main (void) ...@@ -369,12 +373,31 @@ int main (void)
tp_putchar(&tp2, phasew / (1024 / 255)); tp_putchar(&tp2, phasew / (1024 / 255));
} }
*/ */
#endif
#if IS_OPENLOOP_COM
phaseu ++;
phasev ++;
phasew ++;
if (phaseu > 1023){
phaseu = 0;
}
if(phasev > 1023){
phasev = 0;
}
if(phasew > 1023){
phasew = 0;
}
#endif
PWM1->PWM_CH_NUM[1].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phaseu] * scalar / 255); PWM1->PWM_CH_NUM[1].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phaseu] * scalar / 255);
PWM1->PWM_CH_NUM[2].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phasev] * scalar / 255); PWM1->PWM_CH_NUM[2].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phasev] * scalar / 255);
PWM1->PWM_CH_NUM[3].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phasew] * scalar / 255); PWM1->PWM_CH_NUM[3].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phasew] * scalar / 255);
delay_us(200); // nets about 4khz loop, granting 2 pwm cycles per update. lots! delay_us(500); // nets about 4khz loop, granting 2 pwm cycles per update. lots!
if(pin_get_state(&stlb)){ // ? if(pin_get_state(&stlb)){ // ?
pin_clear(&stlb); pin_clear(&stlb);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment