Jessters 3 Posted October 18, 2010 Share Posted October 18, 2010 Well, after some researching and input from a couple people I have actually gotten off to a fairly good start on a basic motor controller using the MSP430G2231 which came with the Launchpad. Currently the controller takes input from three buttons, one for direction, the other two for increasing and decreasing the speed. Simple yes, but I am actually fairly happy with it so far, as this is my first time using anything other than the BasicATOM or BasicStamp MCU's. As such I had a bit of a learning curve transitioning from Basic to C. The end goal of the project is to have the controller accept inputs from a RC radio/reciever and do the calculations necessary for a Proportional Steering system for a robot my business partner and I are working on. So still a long ways off. Also, being a newbie at this, my code may be bloated... frankly I'm just glad it works, but any input would be fantastic. #include //variables #define BUTTON BIT1 // Button on P1.1 #define BUTTON2 BIT3 // Button on P1.3 #define BUTTON3 BIT5 // Button on P1.5 unsigned int PWM = 100; unsigned int Freq = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1DIR |= (BIT0) + (BIT4) + (BIT2) + (BIT6); // Set P1.0 P1.2 P1.4 AND P1.6 as Output Pins; P1SEL |= (BIT2); // Tie TA0.1 to P1.2 //Set Up Button P1.1 P1DIR &= ~BUTTON; P1OUT |= BUTTON; P1REN |= BUTTON; P1IES |= BUTTON; P1IFG &= ~BUTTON; P1IE |= BUTTON; //Set Up Button P1.4 P1DIR &= ~BUTTON2; P1OUT |= BUTTON2; P1REN |= BUTTON2; P1IES |= BUTTON2; P1IFG &= ~BUTTON2; P1IE |= BUTTON2; //Set Up Button P1.5 P1DIR &= ~BUTTON3; P1OUT |= BUTTON3; P1REN |= BUTTON3; P1IES |= BUTTON3; P1IFG &= ~BUTTON3; P1IE |= BUTTON3; //PWM Generation on P1.2 CCR0 = 1000-1; // PWM Period CCTL1 = OUTMOD_7; // CCR1 reset/set TACTL = TASSEL_2 + MC_1; _BIS_SR(LPM0_bits + GIE); } #pragma vector=PORT1_VECTOR __interrupt void Port1_ISR(void){ //Direction switch(P1IFG & BUTTON) { case BUTTON: P1OUT ^= BIT4; P1IFG = 0; } //Increase Speed switch(P1IFG & BUTTON2) { case BUTTON2: if (Freq < 11) { Freq++; CCR1 = PWM*Freq; P1OUT &= ~BIT0; P1OUT |= BIT6; P1IFG = 0; } else { P1OUT |= BIT0; P1OUT &= ~BIT6; P1IFG = 0; } } //Decrease speed switch(P1IFG & BUTTON3) { case BUTTON3: if (Freq > 0) { Freq--; CCR1 = PWM*Freq; P1OUT &= ~BIT0; P1OUT |= BIT6; P1IFG = 0; } else { P1OUT |= BIT0; P1OUT &= ~BIT6; P1IFG = 0; } } } Feel free to comment away, use the code, etc. I do have some questions though, which may seem apparent, but I just can't seem to figure out. 1. I will actually need a total of 2 PWM signals, one per motor. Is this possible with this chip? I don't want to get to far in to it only to find out I need to switch MCU's. 2. I am at an absolute loss as to how to program the MCU to decode the RC signals. Basically, I need the MCU to measure the length of the pulses being sent by the receiver. (ie: 1.6ms = forward/10% Duty Cycle, 1.5ms = full stop, 1.4ms = Revers/10% Duty Cycle.) ANY input on this would be greatly appreciated. Anyway, this forum has been awesome, probably the best source I have found along with NJC's blog. I just hope to be an additive part of it to some extent. EDIT: On a side note, I also purchased a MSP-FET430U64 Target Board and Programmer, which this project will most likely fall back on if the Launchpad and Value Line MCU's aren't up to the task. So again, if you much more experienced people don't think this this platform will work, please let me know. Quote Link to post Share on other sites
cde 334 Posted October 18, 2010 Share Posted October 18, 2010 As far as the code bloat goes, you can cut that down by setting up all three buttons at the same time, instead of repeating the same commands three times. Here's the bit manipulation tutorial I use. http://www.avrfreaks.net/index.php?name ... ic&t=37871 //Set Up Buttons P1DIR &= ~BUTTON & ~BUTTON2 & ~BUTTON3; P1OUT |= BUTTON | BUTTON2 | BUTTON3; P1REN |= BUTTON | BUTTON2 | BUTTON3; P1IES |= BUTTON | BUTTON2 | BUTTON3; P1IFG &= ~BUTTON & ~BUTTON2 & ~BUTTON3; P1IE |= BUTTON | BUTTON2 | BUTTON3; Additionally, I don't think that's the best use of a case/switch function. Case is best when you have multiple results from a test, essentially a long if,elseif,elseif,elseif,else sequence. You should have a single switch and four cases. Finally, you should disable the interrupt before processing the flag, and clear the flag before reenable the interrupt and lpm. disable interrupt code; switch(P1IFG) { case BUTTON: Direction code; break; case BUTTON2: Increase code; break; case BUTTON3: Decrease code; break; default: error catching, etc; } P1IFG = 0; //Clear flag reenable interrupt/lpm code; As far as pwms, I think the short answer depends on the msp430 chip you have, is only one easy to set one. Possibly more if you play with the code. The launchpad's included chips, the msp430G value line don't have alot of comparators/timers. But other, launchpad compatible chips do. http://e2e.ti.com/support/microcontroll ... 56142.aspx http://www.msp430launchpad.com/2010/07/ ... oh-my.html There is also Binary Code Modulation (Or Pulse Code Modulation) if you can use that. http://blog.hodgepig.org/2010/09/12/577/ Quote Link to post Share on other sites
Jessters 3 Posted October 19, 2010 Author Share Posted October 19, 2010 Hehe, oh how I love to miss the obvious. Anyway, thanks for the feedback on the bloated code. However.... I am actually in the process of rewriting the whole thing. After doing some more research regarding PWM on the MSP430G2231 series, I decided to step away from the LaunchPad all together, and jump up to the MSP430F417 and/or F2619. Though I have a couple of both MCU's I am leaning towards the F417 as it is quite a bit cheaper than the F2619. Anyway, one I get this recoded and working on the new chip I'll post an update. Quote Link to post Share on other sites
jsolarski 94 Posted October 19, 2010 Share Posted October 19, 2010 you can only have 2 separate PWM outputs on selected pins using the timer a as the PWM source for the msp430 value line. but i know if you have a SW driven PWM, you can easily hook up 5 with out a problem, more is possible depending on how much time you want to give to the interrupt. as for the MSP430F417 seems like a good choice if you need the HW PWM. I would personaly start with getting the basics working on the launchpad before moving to the bigger chip. How many sensors, and motors are you planning to connect to your bot? Quote Link to post Share on other sites
Jessters 3 Posted October 19, 2010 Author Share Posted October 19, 2010 Well.... in regards to focusing on the LaunchPad for the time being, you are probably right. In regards to the bot, everything other than the motor control will be handled via an on board laptop. (sensors etc) As for the motor controller, I need to drive 2 12v Brushed DC motors off a powered wheelchair. Yes there are plenty of off the shelf options for this, but it's the design and implementation of home brewed components that peak my interest. Anyway, a bit of background, I am actually working on 2 separate projects, one being the bot, the other being a "hopefully" soon to be available automation machine for the restaurant industry. I have completely functional and viable control systems already developed for both, including the motor controller. But they rely on the BasicATOM from Basic Micro. In the interest of production cost on the commercial project (1 dollar per TI MCU versus 70+ for the Atom) my business partner and I made the decision to switch. The motor controller for the bot is basically my version of "Getting my feet wet" before trying to tackle the other project, which has 17 motors for repeating actuation of various belts, control arms, etc. In addition to various optical and proximity sensors. My problem has been this: I'm a PHP developer and electronics hobbyist, the embedded world is a whole new ball game for me. I chose the Atom initially due to it's ease of use, and very minor learning curve. The Basic Micro Studio IDE and Basic programming language made throwing control routines together a snap. The MSP Value Line however has proven to be a completely different monster. Let alone the F series chips. As such I am starting with a basic motor controller prior to even getting started on the "machine". At this juncture I have decided to break the motor controller project in to individual segments. Starting with decoding the PPM signal from the receiver. Now if you have managed to last through that whole diatribe, here's where I am at, and hopefully some of you may be able to help. The incoming signal from the receiver is PPM and has a pulse width of approx 1-2ms based on the location of the control stick. All I need the MCU to do is measure the length of the pulse width, then set the outbound PWM Duty Cycle accordingly. The PWM I have down, it's the measuring of the pulse width that has me stuck. On the Atom, there was a predefined Basic command to do this for you, but that's not the case with the MSP430's. I understand I can use Timer_A in continuous mode and the CCRx registers to do it, but as of yet have not been able to implement it. Nor have I been able to find anything in the TI Example Code database that can help. Any input or a point in the right direction would be great. Quote Link to post Share on other sites
jsolarski 94 Posted October 19, 2010 Share Posted October 19, 2010 I would look at the metronome code for inspiration http://blog.hodgepig.org/2010/09/08/571/ it has a way to measure between button presses, to set the tempo. I am sure that it can be modified for your purpose this might be a good spot for you to start. also this PPM hack may help as well http://hackaday.com/2010/10/02/rc-ppm-hacked/ but sounds like you have some impressive projects coming along - Good luck and let me know is you need any more help Quote Link to post Share on other sites
Jessters 3 Posted October 20, 2010 Author Share Posted October 20, 2010 I have fallen back to the Launchpad for the time being to work on individual pieces of the code I'll need. Was a good idea doing so actually, lol. After a bit of trial and error I was able to get the MSP430G2231 am developing on to interpret the PPM signal being sent out from the Spektrum AR7000 Receiver I am using. #include "msp430g2231.h" volatile unsigned int sample1 = 0; volatile unsigned int sample2 = 0; volatile unsigned int ppm1 = 0; volatile unsigned int count1 = 0; volatile unsigned int totalCount1 = 0; volatile unsigned int totalPulse1 = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz DCOCTL = CALDCO_1MHZ; P1DIR |= (BIT0) + (BIT6); // Configure LEDS P1OUT &= ~BIT0; // SET P1.0 TO LOW P1SEL |= (BIT1) + (BIT2); // P1.1 AND P1.2 TO TA0.0/0.1 P1DIR &= ~(BIT1) + ~(BIT2); // P1.1 AND P1.2 TO INPUT TACTL = TASSEL_2 + MC_2 + ID_3; // SMCLK, contmode TACCTL0 = CM_3+CCIS_0+SCS+CAP+CCIE; // Capture on Both Edge + CCIxA + // Synchronous Capture + Capture + Interrupt Enabled _BIS_SR(LPM0_bits + GIE); // ENTER LPMO W/ INTERRUPTS while(1); } #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { count1++; totalCount1++; totalPulse1 = (totalCount1 / 2); if (count1 == 1){ // Store sample 1 P1OUT ^= BIT0; // Toggle LED on P1.0 sample1 = TACCR0; TACCR0 = 0; } if (count1 == 2){ // Store sample 2 P1OUT ^= BIT0; // Toggle LED on P1.0 sample2 = TACCR0; ppm1 = (sample2 - sample1); // PPM pulse width count1 = 0; TACCR0 = 0; } } In this code, the variable ppm1 comes out between 110 and 210 depending on the location of the control stick on the DX7 Radio. It shouldn't be hard at all to use those numbers to set the Duty Cycle for outbound PWM's to the H bridge. One question I do have though is this: Is it possible to use the same timer to measure pulse width on a second I/O Pin? I will be needing to watch two different signals when it is all said and done. If I am understanding things correctly I am at this point only using a single CCRx? If so cant he second one be used in capture mode to analyze the second PPM signal? Quote Link to post Share on other sites
bluehash 1,581 Posted October 20, 2010 Share Posted October 20, 2010 If I am understanding things correctly I am at this point only using a single CCRx? If so cant he second one be used in capture mode to analyze the second PPM signal? You can use the other compare register to look at the other pin using the same timer block. This is good news. Keep at it. Quote Link to post Share on other sites
paradug 4 Posted November 5, 2010 Share Posted November 5, 2010 The MSP430 clock project instructable below generates 2 independent pwm signals from a MSP430G2211 (Launchpad part). http://www.instructables.com/id/MSP430-Based-Chronulator-using-Launchpad-chip The code could be used to drive DC motors with the correct transistor drivers. Quote Link to post Share on other sites
bluehash 1,581 Posted November 6, 2010 Share Posted November 6, 2010 The MSP430 clock project instructable below generates 2 independent pwm signals from a MSP430G2211 (Launchpad part). http://www.instructables.com/id/MSP430-Based-Chronulator-using-Launchpad-chip The code could be used to drive DC motors with the correct transistor drivers. Funny, I just found it yesterday and was writing a blog post. Thanks for the link and welcome to the forums - looks like you just joined. Are you the author of the instructable? You may want to enter it for the "Project of the month Contest - Nov 2010" Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.