After speaking to a few folks that expressed an interest in the MMMM workshop, it became apparent (a) most folks were newbs who want to learn the basics and (b) everyone wants to control motors. Excellent! We’ll do that.
Although motor control is potentially a vast and complex topic, with highly specialized branches, the basics are fairly easy to learn — and they’ll take you pretty far. Â So … we’ll be prepared to present the following items:
- DC motors
- H-bridge circuits — these let puny microcontrollers run fairly powerful motors
- Stepper motors — just a little more complex to program than DC motors and they use H-bridge circuits too
- Quadrature Encoders — these are a simple and accurate way to read the position of something
We’ll also try to discuss some organizational items — like the logistics of future workshops and the use of the MMMM GitHub, so that we can build up assets collectively, share them with the world and manage changes and contributions in a free-and-easy-but-organized way.
If you are coming , please bring:
- Yourself — If you’re a newb, welcome — If you’re an MCU Yoda, then attend you must and wisdom to newbs impart
- Some ideas
- A laptop if you have one
- You may want to install VMWare Player or VMWare Fusion before you arrive
- An MCU development kit if you have one or …
- Some money if you don’t. We’ll have some development kits that you can buy. Plan on at least $10 for the kits and some parts that you can use for small learning projects.
- A bread-board if you want to build some live circuits to keep. We’ll have breadboards to loan, but if you want to take one home, it has to be one that arrived with you.
That’s about it — see you all Monday. To whet your appetite, there is some prototype code below for reading a quadrature encoded position detector (not really elegant enough for a final effort, but it’s a start). We’ll have you writing stuff like this in no-time.
This code is part of an effort to turn salvaged InkJet printers into motion controllers. Most of these positioners let you position an InkJet head to within 1/600 inch — they’re fast, accurate, compact, surprisingly strong … and dirt-cheap.
#include <msp430x20x2.h> #define LED0 BIT0 #define LED1 BIT6 #define PHASE1 BIT1 #define PHASE2 BIT2 #define PHASE_MASK 6 #define PHASE_SHIFT 1 int state; // used to hold current state of encoder bits (00, 01, 10 or 11) int lastState; // used to hold previous state of encoder bits (00, 01, 10 or 11) int pos; // used to count steps. A 1/150" encoder (the most common kind) yields 600 steps per inck. // -- prototype of common bit of code used to compute the present state value void updateState(void); int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer // --- set up some initial values pos = 0; P1DIR &= ~(PHASE1 + PHASE2); // Set P1.1 and P1.2 as inputs P1DIR |= (LED0 + LED1); // Set P1.0 and P1.6 to outputs. These are the LEDs on a LaunchPad. // --- get initial conditions so that the first interrupt // has the right "edge" values and so that position calculations are based on feasible transitions updateState(); lastState = state; P1IFG &= ~(PHASE1 | PHASE2); // clear interrupt flags for P1.1 and P1.2 P1IE |= (PHASE1 | PHASE2); // P1.1 and P1.2 interrupt enabled __enable_interrupt(); // enable all interrupts for(;;) { /* just loop forever and let the interrupts do all the work */ } } // updateState() calculates updates for the edge detectors used in the interrupts // and also updates the "lastState" variable void updateState(void){ state = P1IN & PHASE_MASK; if (state & PHASE1) P1IES |= PHASE1; // PHASE1 high, then interrupt on falling edge else P1IES &= ~PHASE1; // PHASE1 low, then interrupt on rising edge if (state & PHASE2) P1IES |= PHASE2; // PHASE2 high, then interrupt on falling edge else P1IES &= ~PHASE2; // PHASE2 low, then interrupt on rising edge // ---"right-justify" state so that it is in the range 0..3 state = (state >> PHASE_SHIFT); } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { updateState(); // --- test for all clockwise incremental cases // if we stepped clockwise, then increment the position if ( (lastState == 0 & state == 2) ||(lastState == 2 & state == 3) ||(lastState == 3 & state == 1) ||(lastState == 1 & state == 0)){ pos++; } // --- If we didn't move clockwise, then we must have moved counter-clockwise // so decrement the position else{ pos--; } // --- record last state lastState = state; // --- update LEDs just to help debug // use "state" as intermediate variable so that we can see the output value in the debugger easily // This is just so that we can see the encoder signal. No functional purpose. state = state + ((state << 5) & 0x40); P1OUT = state; // --- clear the interrupt flags P1IFG &= ~(PHASE1 | PHASE2); // clear interrupt flags for P1.1 and P1.2 }
Hey Hive76, Monthly Monday Microcontroller Madness was awesome. Lindsay and I planned on coming Wednesday but got caught up with work. We’ll definitely be back though, you guys are super nice and it was a relaxed and inviting atmosphere. I learned a lot, and I’m looking forward to seeing you guys again soon. Keep up the good work
Sincerely,
Daniel and Lindsay
Hi Dan,
Thanks for the kind words and hope you become a regular at the MMMM. Do you still have the Computron? If so, it might be an awesome MCU project to lovingly up-cycle it (e.g. COMPUTRON twitter feed).
Hi Pez,
Thanks yeah we’ll definitely come by more often — what Computron are you referring to?
I found your e-mail address a little intriguing, so I googled, hoping to find that you had an advice column or something equally .. whatever .., and found this instead:
http://kenfager.com/wordpress/index.php/archives/195
… and that made me think that a Computron might be excellent starting material for a hack of some sort …