Showing posts with label MSP430. Show all posts
Showing posts with label MSP430. Show all posts

Saturday, 15 September 2007

Bus stops

The I²C bus not working was more of a problem. I had some issues when I just had the spindle controller connected, see bodge-it-and-move-on, but at that time I did not have a storage scope so I could not get to the bottom of it. In the meantime I bought a cheap 100 MHz 2 channel USB scope so I was able to find out what was going wrong.



As I have indicated above, the clock line has two glitches where it should have a proper clock pulse. The master generates the clock but the slave is allowed to stretch it by extending the low portion. Normally it is hard to tell which device is driving the bus but in this case it is obvious because I got the pull up resistors too small for the MSP430. I forgot that the MSP430 is aimed at low power applications so has an unusually low drive capability.

I still wasn't sure which end was the problem so I coded the host end in software so I could see exactly what the slave was doing. It is relatively easy to do an I²C master in software because it does not have any strict timing deadlines. The slave does, so it is more difficult to implement purely in software.

It turns out the problem lies with the mask revision of the MSP430F2013s that I am using. Revision B has several I²C bugs such as pulling the clock low when it shouldn't and no workarounds. I have had my chips for some time, long before I started this project. Two are actually labeled with a mask revision of X which is undocumented. It seems to have at least all the bugs in mask B. The other is labeled as mask B, so none are of any use for I²C!

Very disappointing that these days a device has to have three or four mask revisions just to get something as simple as an I²C module working. This seems to be the way things are going: hardware is becoming just as buggy as software. I wasted some time at work recently discovering that the UART in a PIC18F65J10 occasionally inserts zero bytes in the middle of your packet. These things were lab exercises when I was an undergraduate, now big companies can't get them right.

Fortunately, I had some MSP430F2012s that were mask revision B and the I²C bugs were fixed one revision earlier on that chip. They are slightly different in that they have a 10 bit SAR ADC instead of a 16 bit sigma-delta ADC. This is actually more appropriate for my application but it has a completely different software interface and voltage range.

Once I had swapped to the MSP430F2012 and modified the firmware for the new ADC, the I²C bus sprang into life. That was until I started to run the motor whereupon I got occasional bus lockups. This is due to the massive amount of noise coming from the brushes of the DC motor. I get about 2.5V of noise on the I²C lines

Using I²C without buffers for anything other than inter IC comms is a really bad design decision, I am not sure what came over me. I normally use RS485 differential comms when linking boards that drive motors or other high current loads and have never had a problem with noise. I even think I have publicly criticized the RepRap design for converting the RS232 to 5V signals before sending it around the ring of control boards. It was tempting to give I²C a try because I already had micros that support it, and didn't have UARTs, and my screened cable is only about a foot long. I²C is particularly susceptible to noise though because it is only actively driven low and because it is edge sensitive. Also the data rate I chose is five times faster than RepRap uses and I am using 3.3V logic rather than 5V. I²C also has the nasty feature that corruption can cause the bus to lock up which doesn't happen with asynchronous comms.

One thing I noticed was that earthing the can of the motor made things a lot worse by coupling the noise onto the ground rail. I established that the noise is conducted rather than radiated by running the motor from a separate bench PSU. I also managed to get it to run reliably by adding some 2200pF capacitors to the I²C lines, but that is a horrible bodge! Other things I will try :-
  1. Change the pullup resistors from 1K to 2K2 so that the MSP430 can pull them fully low. That will increase the logic low noise immunity but make the logic high immunity worse.
  2. See if I can program the master to clear the bus lockup.
  3. Add a CRC and packet sequence flags so I can detect errors and do retries.
  4. See if I can suppress the motor better.
If that doesn't fix it I may have to rethink the design. There are such things as high voltage I²C buffers but I expect they are SMT only. I could switch to differential comms or use a better DC motor, or replace it with a small stepper motor. That would also eliminate the need for a shaft encoder but I may struggle for torque.

Thursday, 7 June 2007

Torque talk

I updated my motor control circuit to use a 0.1Ω current sense resistor to give me a full scale current of about 0.6A and then set up the ADC to provide negative feedback to control the speed. I read up on the classical control method which is PID, finding a good article on it here www.embedded.com. Before embarking on that complexity I decided to try a simple more intuitive method. I wrote a program which turns the motor on and monitors the current until it falls to a specified level, indicating that the motor is generating the correct back e.m.f. i.e. running at the correct speed. It then turns the motor off and waits for the start of another cycle.

This algorithm works reasonably well after playing with a few numbers to get it relatively stable. It does however suffer from a beating problem. I am not sure exactly why but I think it must be the PWM pulse rate beating with the commutation of the motor. Here is a video of a scope trace of the current waveform. You can hear the motor in the background as the speed is swept from maximum to minimum and you can see the current pulses getting shorter and higher. Just to to confuse matters the scope trace is beating with the camera frame rate.



I don't think the beating will matter much but it is a bit annoying. Playing with the PWM frequency has a big effect on it. In the end I settled for 200Hz, but I may play about with it a bit more.

One thing that I hadn't realised, but is obvious really, is that when you slow down a motor with PWM it loses a lot of torque at low speeds but when you add feedback it gets it all back again.

Here is the simple piece of code :-
#include "msp430x20x3.h"

#define LED BIT0
#define MOTOR BIT2
#define FLOATING (BIT1 + BIT3)
#define CURRENT BIT4
#define GND BIT5
#define I2CPINS (BIT6 + BIT7)

#define OUTPUTS (I2CPINS + MOTOR + LED + FLOATING)

typedef unsigned int word;
typedef char bool;
#define true 1
#define false 0

int main( void )
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
//
// Set MCLK to 16 MHz, SMCLK = 2 MHz
//
BCSCTL2 = SELM_0 | DIVM_0 | DIVS_3; // MCLK = DCO, SMCLK = DCO / 8
BCSCTL1 = CALBC1_16MHZ | XT2OFF;
DCOCTL = CALDCO_16MHZ;
//
// Set up I/0
//
P1OUT = MOTOR; // Motor off
P1DIR = OUTPUTS; // Define output pins
SD16AE = CURRENT + GND; // Configure analogue inputs
//
// Set up ADC
//
SD16CTL = SD16XDIV_2 + SD16DIV_0 + SD16REFON; // MCLK / 16 = 1MHz
SD16CCTL0 = SD16DF + SD16OSR_32 + SD16IE + SD16SC; // OSR = 32
SD16INCTL0 = SD16INTDLY_0 + SD16INCH_2; // Delay 4 clocks; channel A2
//
// Enable interrupts and wait forever
//
_BIS_SR(GIE);
for(;;);
}

int current;
int target_current = 5000;
#define CYCLE 200

#pragma vector=SD16_VECTOR
__interrupt void ADC_int(void)
{
static int count;

int adc = SD16MEM0;
current += (adc - current) >> 1; // Moving average filter
if(++count >= CYCLE) {
count = 0;
P1OUT &= ~MOTOR; // Motor on
P1OUT |= LED;
if(target_current < 0)
target_current = 5000;
target_current += 10;
}
if(count > 30 && current < target_current) {
P1OUT |= MOTOR; // Turn the motor off
P1OUT &= ~LED;
}
}
Note that in the end I am not using the PWM capability of the MSP430 timer as I did the motor control in the ADC interrupt handler.

The next task is to get it talking to the rest of HydraRaptor using an I²C bus.

Sunday, 3 June 2007

PIC your micro

The official RepRap project uses Microchip PIC micro controllers. I have done several projects at work with these because they have such a wide range of parts that they often have the best fit price wise. However, I have never liked them very much. They have a horrible instruction set which does not lend itself to running C efficiently. Also, the development kit is a bit primitive by today's standards. When doing a home project ease of use and development kit cost becomes more important than part price. I have been following the RepRap forums and people are having lots of problems with a buggy open source PIC compiler and programmer.

I recently did a project at work which needed a micro with a very low power consumption so we used a Texas Instruments MSP430 series micro. I was very impressed with the USB key development kit which only costs $20. For that you get an IAR C compiler, assembler, simulator and debugger. The instruction set of the chip is very small but has just the right instructions to run C efficiently and the C compiler does a good job of using them. The code size is limited to 4K but, as I am only using a 2K part, that doesn't matter. The USB key contains a programmer / "Spy Bi-Wire" in circuit debugger and a little detachable target board. The chip is surface mount but the target board brings all the pins out to a 0.1 inch header so you can incorporate it into a through-hole board and you can get additional target boards at $10 for three.





So for $30 I get a development kit and micros to control four of HydraRaptor's heads.

The smaller parts don't have UARTs but they do have I²C which is easier to make a multi-drop bus with.