Jump to content
43oh

oPossum

Members
  • Content Count

    925
  • Joined

  • Last visited

  • Days Won

    103

Reputation Activity

  1. Like
    oPossum reacted to David Bender in "spikes" in the ultrasonic reading   
    Why are you comparing TA1CCR0 to a constant? You set it only once in the code and never change it again...
    if((TA1CTL & TAIFG) && (TA1CCR0 < 0x1000)) fall += TA1CCR0;
  2. Like
    oPossum reacted to nickds1 in Tiny low power LED clock   
    I just love clocks (especially cold-cathode and similar...)... Nice project...
     
     
    That's a good capacitor but not rated for this application - you should really be using an X1 or X2-rated cap for safety... not just for shock, but fire hazard etc. "X" capacitors are flame retardant and mandatory in Europe - don't know about US but both the Microchip App note and TI blog above also specify an X2-rated cap (as they should too!).
     
    A good one here would be VISHAY - MKP3382 X2, 4n7 @ 630VAC, p/n BFC233820472, Farnell p/n 121-5463
     
    Also, you should probably have a MOV across the mains on the hot side of the cap - the cap will do its work with a nice 50Hz (and 60Hz) sinusoidal waveform, but a mains-borne transient from, say, a motor (fridge/washingmachine/nearby lightning etc.), has far higher dV/dT and will cause a DC spike, quite possibly in the 100+V region. A MOV won't be 100% effective in all cases, but its a good move.
     
    Have you measured or 'scoped the final DC voltage - is the zener doing the clipping or is the voltage below 3.9V? The two smoothing caps will also sink current - typically between 50 and 100uA each - with such a low delivery current to the uP & LEDs, these parasitics become very significant and can drop the final DC value significantly - maybe consider upping the 4n7 to 5n6 or 6n8?
     
    You can also lose one diode (D2) by replacing the lower two diodes in the bridge by 4.2V zeners and changing R11 to about 470R. With C3 at 22n you'll get a nice steady 3.6V with about 20mV ripple...
  3. Like
    oPossum reacted to greeeg in Custom EzFet Lite   
    Soldered up a new board. Works like a charm, unfortunately I don't know actually have any target boards to use this with, as it's a different pinout.
     

     
    Fuse is a 1206 footprint, but I ordered 0805's No big deal, just looks funny.
  4. Like
    oPossum got a reaction from simpleavr in RC PPM encode and decode   
    PPM (pulse position modulation) is a common protocol used with radio control. It used to be the over that air protocol, but has been mostly replaced with PCM (pulse code modulation). It lives on in the form of trainer ports, radio to tx module link, and even some modern PCM receivers can output PPM (typically on the battery connector). It is also a handy way to drive up to 8 servos using a single pin of the microcontroller (and a CD4017 decoder). PPM is sort of a concatenation of several (often 8) RC servo signals in succession. The time between narrow (a few hundred microseconds) pulses determines with width of each successive servo pulse. A duration of more than about 4000 microseconds designates the end of a frame. The typical total frame duration is 20,000 microseconds (20 ms).
     

     
    The PPM transmit code uses a single timer capture/compare unit in toggle mode. The initial state is set with OUTMOD_0 to allow for active low or active high output. The elegantly simple MSP430 timer makes this code very compact and efficient.
     

    static void init_ppm_tx(unsigned pol) // - Initialize PPM transmission { // pol = 0: idle low, pulse high // pol = 1: idle high, pulse low // P2DIR |= BIT0; // PPM output on P2.0 P2SEL |= BIT0; // Enable timer compare output P2SEL2 &= ~BIT0; // // TA1CCTL0 = OUTMOD_0 | (pol ? OUT : 0); // Set initial state of output (polarity) TA1CCTL0 = OUTMOD_4 | CCIE; // Set timer output to toggle mode, enable interrupt TA1CCR0 = TA1R + 1000; // Set initial interrupt time } // // static unsigned st[8]; // Servo transmit times // static const unsigned pulse_duration = 200; // Duration of on time of each pulse static const unsigned frame_duration = 20000; // Total duration of a complete frame // #pragma vector = TIMER1_A0_VECTOR // - ISR for PPM transmission __interrupt void isr_ccr0(void) // { // static unsigned state = 0; // State / pulse index static unsigned td = 0; // Total duration of channel pulses // if(state < (sizeof(st) / sizeof(st[0])) * 2 + 1) { // Check if not done with all times if(state & 1) { // Alternate between rising & falling edges // Setup the time until the next rising edge const unsigned t = st[state >> 1]; // Get time from array TA1CCR0 += (t - pulse_duration); // Add to falling edge time, compensate for pulse width td += t; // Update total frame duration } else { // TA1CCR0 += pulse_duration; // Add pulse duration to rising edge time } // ++state; // Increment state } else { // Final pulse in frame (off time only) TA1CCR0 += (frame_duration - pulse_duration - td); // Set rising edge time to make desired frame duration td = 0; // Reset total frame time state = 0; // Reset state } // } // // The PPM decoder is a bit more complicated. It checks for vaild pulse widths and ignores anything out of spec. Two capture/compare units are used. The first handles measuring the time between edges, and the second provides a timeout that detects an idle line (to prevent timer wraparound from creating alias pulses). Either the rising of falling edge can be used. 

    static void init_ppm_rx(unsigned edge) // - Initialize PPM reception { // edge = 0: capture on rising edge // edge = 1: capture on falling edge // P2DIR &= ~BIT1; // PPM input on P2.1 P2SEL |= BIT1; // Enable time capture input P2SEL2 &= ~BIT1; // // TA1CCTL1 = (edge ? CM_2 : CM_1) | CCIS_0 | CAP | CCIE; // CCR1 capture mode, enable interrupt TA1CCTL2 = CCIE; // CCR2 enable interrupt } // // static unsigned sr[8]; // Servo receive times static unsigned rx_frame = 0; // Incremented after every received frame // static const unsigned min_pw = 1500 - 1100; // 400 us minimum static const unsigned max_pw = 1500 + 1100; // 2600 us maximum static const unsigned min_reset = 4000; // minimum time between frames static const unsigned rx_timeout = 24000; // maximum time between pulses // #pragma vector = TIMER1_A1_VECTOR // - ISR for PPM reception __interrupt void isr_ccr12(void) // { // static unsigned pt, et; // Previous time, elapsed time static unsigned state; // Received pulse index / state static unsigned pd[8]; // Received pulse durations - the size of this array must // match what the transmitter is sending // switch(TA1IV) { // case 0x02: // - CCR1 et = TA1CCR1 - pt; // Calculate elapsed time since last edge pt = TA1CCR1; // Save current edge time if(et > min_reset) { // Check for a pulse that is too long to be a channel // Check if all pulses received, and no more if(state == sizeof(pd) / sizeof(pd[0])) { memcpy(sr, pd, sizeof(pd)); // Copy to foreground array ++rx_frame; // Increment frame count } // state = 0; // Begin next frame } else if(et < min_pw || et > max_pw) { // Check if pulse is out of range state = 0x80; // Go to idle state } else { // Save pulse if room in array if(state < sizeof(pd) / sizeof(pd[0])) pd[state] = et; // if(state < 0x40) ++state; // Next state - limit max value in case of noisy input } // TA1CCR2 = pt + rx_timeout; // Reset timeout break; // case 0x04: // - CCR2 state = 0x81; // Go to timeout state break; // } // } // // Here is a simple test program that prints the pulse times. The times are represented as the deviation from 1500 microseconds. That is the typical center time for a RC servo. Each field is a fixed width with a sign followed by 3 digits. Jumper P2.0 to P2.1 to feed the PPM output to the PPM input. 

     

    #include <msp430.h> #include <stdlib.h> static void putc(char c) // - Put char to serial { // while(!(IFG2 & UCA0TXIFG)); // UCA0TXBUF = c; // } // // static void put_pw(unsigned pw) // - Print pulse width to serial { // Sign and three digits unsigned n; // Deviation from 1500 us if(pw < 1500) { // If less than 1500 n = 1500 - pw; // Calculate deviation putc('-'); // Print sign } else { // Equal to or more than 1500 n = pw - 1500; // Calculate deviation putc((pw == 1500) ? ' ' : '+'); // Print sign } // div_t d = div(n, 100); // putc(d.quot + '0'); // First digit - hundreds d = div(d.rem, 10); // putc(d.quot + '0'); // Second digit - tens putc(d.rem + '0'); // Third digit - ones } // // static const unsigned long smclk_freq = 8000000UL; // SMCLK frequency in hertz static const unsigned long bps = 9600UL; // Async serial bit rate // int main(void) // { // const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor // WDTCTL = WDTPW | WDTHOLD; // // DCOCTL = 0; // Run DCO at 8 MHz BCSCTL1 = CALBC1_8MHZ; // DCOCTL = CALDCO_8MHZ; // // P1DIR = 0; // P1SEL = BIT1 | BIT2; // Enable UART pins P1SEL2 = BIT1 | BIT2; // // P2DIR = 0; // P2SEL = 0; // P2SEL2 = 0; // // TA1CTL = TASSEL_2 | ID_3 | MC_2; // Setup timer 1 for SMCLK / 8, continuous mode // init_ppm_rx(0); // Initialize PPM receive // init_ppm_tx(0); // Initialize PPM transmit // // Initialize UART UCA0CTL1 = UCSWRST; // Hold USCI in reset to allow configuration UCA0CTL0 = 0; // No parity, LSB first, 8 bits, one stop bit, UART (async) UCA0BR1 = (brd >> 12) & 0xFF; // High byte of whole divisor UCA0BR0 = (brd >> 4) & 0xFF; // Low byte of whole divisor UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16; // Fractional divisor, oversampling mode UCA0CTL1 = UCSSEL_2; // Use SMCLK for bit rate generator, release reset // // st[0] = 1000; // Setup servo transmit times st[1] = 1200; // st[2] = 1400; // st[3] = 1500; // st[4] = 1600; // st[5] = 1800; // st[6] = 2000; // st[7] = 1520; // // _enable_interrupts(); // Enable all interrupts // for(; { // unsigned n; // // Print received pulse times to serial for(n = 0; n < sizeof(sr) / sizeof(sr[0]); ++n) put_pw(sr[n]); // putc('\r'); putc('\n'); // } // // return 0; // } // A bargraph can be displayed with some custom software. 

    servo_test.cpp
     

  5. Like
    oPossum got a reaction from zeke in RC PPM encode and decode   
    PPM (pulse position modulation) is a common protocol used with radio control. It used to be the over that air protocol, but has been mostly replaced with PCM (pulse code modulation). It lives on in the form of trainer ports, radio to tx module link, and even some modern PCM receivers can output PPM (typically on the battery connector). It is also a handy way to drive up to 8 servos using a single pin of the microcontroller (and a CD4017 decoder). PPM is sort of a concatenation of several (often 8) RC servo signals in succession. The time between narrow (a few hundred microseconds) pulses determines with width of each successive servo pulse. A duration of more than about 4000 microseconds designates the end of a frame. The typical total frame duration is 20,000 microseconds (20 ms).
     

     
    The PPM transmit code uses a single timer capture/compare unit in toggle mode. The initial state is set with OUTMOD_0 to allow for active low or active high output. The elegantly simple MSP430 timer makes this code very compact and efficient.
     

    static void init_ppm_tx(unsigned pol) // - Initialize PPM transmission { // pol = 0: idle low, pulse high // pol = 1: idle high, pulse low // P2DIR |= BIT0; // PPM output on P2.0 P2SEL |= BIT0; // Enable timer compare output P2SEL2 &= ~BIT0; // // TA1CCTL0 = OUTMOD_0 | (pol ? OUT : 0); // Set initial state of output (polarity) TA1CCTL0 = OUTMOD_4 | CCIE; // Set timer output to toggle mode, enable interrupt TA1CCR0 = TA1R + 1000; // Set initial interrupt time } // // static unsigned st[8]; // Servo transmit times // static const unsigned pulse_duration = 200; // Duration of on time of each pulse static const unsigned frame_duration = 20000; // Total duration of a complete frame // #pragma vector = TIMER1_A0_VECTOR // - ISR for PPM transmission __interrupt void isr_ccr0(void) // { // static unsigned state = 0; // State / pulse index static unsigned td = 0; // Total duration of channel pulses // if(state < (sizeof(st) / sizeof(st[0])) * 2 + 1) { // Check if not done with all times if(state & 1) { // Alternate between rising & falling edges // Setup the time until the next rising edge const unsigned t = st[state >> 1]; // Get time from array TA1CCR0 += (t - pulse_duration); // Add to falling edge time, compensate for pulse width td += t; // Update total frame duration } else { // TA1CCR0 += pulse_duration; // Add pulse duration to rising edge time } // ++state; // Increment state } else { // Final pulse in frame (off time only) TA1CCR0 += (frame_duration - pulse_duration - td); // Set rising edge time to make desired frame duration td = 0; // Reset total frame time state = 0; // Reset state } // } // // The PPM decoder is a bit more complicated. It checks for vaild pulse widths and ignores anything out of spec. Two capture/compare units are used. The first handles measuring the time between edges, and the second provides a timeout that detects an idle line (to prevent timer wraparound from creating alias pulses). Either the rising of falling edge can be used. 

    static void init_ppm_rx(unsigned edge) // - Initialize PPM reception { // edge = 0: capture on rising edge // edge = 1: capture on falling edge // P2DIR &= ~BIT1; // PPM input on P2.1 P2SEL |= BIT1; // Enable time capture input P2SEL2 &= ~BIT1; // // TA1CCTL1 = (edge ? CM_2 : CM_1) | CCIS_0 | CAP | CCIE; // CCR1 capture mode, enable interrupt TA1CCTL2 = CCIE; // CCR2 enable interrupt } // // static unsigned sr[8]; // Servo receive times static unsigned rx_frame = 0; // Incremented after every received frame // static const unsigned min_pw = 1500 - 1100; // 400 us minimum static const unsigned max_pw = 1500 + 1100; // 2600 us maximum static const unsigned min_reset = 4000; // minimum time between frames static const unsigned rx_timeout = 24000; // maximum time between pulses // #pragma vector = TIMER1_A1_VECTOR // - ISR for PPM reception __interrupt void isr_ccr12(void) // { // static unsigned pt, et; // Previous time, elapsed time static unsigned state; // Received pulse index / state static unsigned pd[8]; // Received pulse durations - the size of this array must // match what the transmitter is sending // switch(TA1IV) { // case 0x02: // - CCR1 et = TA1CCR1 - pt; // Calculate elapsed time since last edge pt = TA1CCR1; // Save current edge time if(et > min_reset) { // Check for a pulse that is too long to be a channel // Check if all pulses received, and no more if(state == sizeof(pd) / sizeof(pd[0])) { memcpy(sr, pd, sizeof(pd)); // Copy to foreground array ++rx_frame; // Increment frame count } // state = 0; // Begin next frame } else if(et < min_pw || et > max_pw) { // Check if pulse is out of range state = 0x80; // Go to idle state } else { // Save pulse if room in array if(state < sizeof(pd) / sizeof(pd[0])) pd[state] = et; // if(state < 0x40) ++state; // Next state - limit max value in case of noisy input } // TA1CCR2 = pt + rx_timeout; // Reset timeout break; // case 0x04: // - CCR2 state = 0x81; // Go to timeout state break; // } // } // // Here is a simple test program that prints the pulse times. The times are represented as the deviation from 1500 microseconds. That is the typical center time for a RC servo. Each field is a fixed width with a sign followed by 3 digits. Jumper P2.0 to P2.1 to feed the PPM output to the PPM input. 

     

    #include <msp430.h> #include <stdlib.h> static void putc(char c) // - Put char to serial { // while(!(IFG2 & UCA0TXIFG)); // UCA0TXBUF = c; // } // // static void put_pw(unsigned pw) // - Print pulse width to serial { // Sign and three digits unsigned n; // Deviation from 1500 us if(pw < 1500) { // If less than 1500 n = 1500 - pw; // Calculate deviation putc('-'); // Print sign } else { // Equal to or more than 1500 n = pw - 1500; // Calculate deviation putc((pw == 1500) ? ' ' : '+'); // Print sign } // div_t d = div(n, 100); // putc(d.quot + '0'); // First digit - hundreds d = div(d.rem, 10); // putc(d.quot + '0'); // Second digit - tens putc(d.rem + '0'); // Third digit - ones } // // static const unsigned long smclk_freq = 8000000UL; // SMCLK frequency in hertz static const unsigned long bps = 9600UL; // Async serial bit rate // int main(void) // { // const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor // WDTCTL = WDTPW | WDTHOLD; // // DCOCTL = 0; // Run DCO at 8 MHz BCSCTL1 = CALBC1_8MHZ; // DCOCTL = CALDCO_8MHZ; // // P1DIR = 0; // P1SEL = BIT1 | BIT2; // Enable UART pins P1SEL2 = BIT1 | BIT2; // // P2DIR = 0; // P2SEL = 0; // P2SEL2 = 0; // // TA1CTL = TASSEL_2 | ID_3 | MC_2; // Setup timer 1 for SMCLK / 8, continuous mode // init_ppm_rx(0); // Initialize PPM receive // init_ppm_tx(0); // Initialize PPM transmit // // Initialize UART UCA0CTL1 = UCSWRST; // Hold USCI in reset to allow configuration UCA0CTL0 = 0; // No parity, LSB first, 8 bits, one stop bit, UART (async) UCA0BR1 = (brd >> 12) & 0xFF; // High byte of whole divisor UCA0BR0 = (brd >> 4) & 0xFF; // Low byte of whole divisor UCA0MCTL = ((brd << 4) & 0xF0) | UCOS16; // Fractional divisor, oversampling mode UCA0CTL1 = UCSSEL_2; // Use SMCLK for bit rate generator, release reset // // st[0] = 1000; // Setup servo transmit times st[1] = 1200; // st[2] = 1400; // st[3] = 1500; // st[4] = 1600; // st[5] = 1800; // st[6] = 2000; // st[7] = 1520; // // _enable_interrupts(); // Enable all interrupts // for(; { // unsigned n; // // Print received pulse times to serial for(n = 0; n < sizeof(sr) / sizeof(sr[0]); ++n) put_pw(sr[n]); // putc('\r'); putc('\n'); // } // // return 0; // } // A bargraph can be displayed with some custom software. 

    servo_test.cpp
     

  6. Like
    oPossum reacted to KatiePier in SPI 4-Pin Mode and TX Interrupt won't work, in 3-Pin Mode it works   
    Just as a side-note for others searching for help: if you get one of the parts that has the new eUSCI module (FR57xx, FR59xx, some of the F5xx/6xx parts) it has an option to set the 4th pin up as a true chip select function instead of Slave-Transmit-Enable (STE), so that you don't have to do it on your own with a separate IO anymore.
     
    www.ti.com/lit/pdf/slaa522 USCI to eUSCI migration guide
     
    Regards,
    Katie
  7. Like
    oPossum got a reaction from KatiePier in SPI 4-Pin Mode and TX Interrupt won't work, in 3-Pin Mode it works   
    Make sure UCxSTE is the proper level to allow transmission. 4 pin mode is for multi-master operation and is very rarely used.
  8. Like
    oPossum got a reaction from KatiePier in SPI 4-Pin Mode and TX Interrupt won't work, in 3-Pin Mode it works   
    Yes, you have to use 3 wire mode and a normal IO pin to select your SPI slave device.
  9. Like
    oPossum got a reaction from leomar01 in SPI 4-Pin Mode and TX Interrupt won't work, in 3-Pin Mode it works   
    Yes, you have to use 3 wire mode and a normal IO pin to select your SPI slave device.
  10. Like
    oPossum got a reaction from leomar01 in SPI 4-Pin Mode and TX Interrupt won't work, in 3-Pin Mode it works   
    Make sure UCxSTE is the proper level to allow transmission. 4 pin mode is for multi-master operation and is very rarely used.
  11. Like
    oPossum got a reaction from GeekDoc in Be aware : Launchpad can retain old code in memory   
    The lesson here is you should always explicitly init all IO. Don't assume any IO will be in a know state on power up or reset. This is not retained code, but rather retained state.
  12. Like
    oPossum reacted to emdarcher in Light Seeker robot with MSP430   
    Recently finished my first msp430 based robot, a Basic Light seeker!
     
    This was a project to get me to learn more about the MSP430 microcontroller. In this project specifically, using multiple ADC inputs and PWMs ( 2 PWMs was a little tricky on the MSP430G2452 but eventually got it ).
     
    The robot turns according to the difference between the light values on the left and right, using two Photoresistors/LDRs.
     
    The robot is powered my a set of 4 to 5 NiMH 1.2-1.4V batteries which directly power the l293d Motor Driver IC and DC motors, and is also fed into a LP2950-33 3.3V LDO to provide regulated power to the MSP430G2452 IC and Photoresistors/LDRs. Most of my robot designs use a separate power supply for control and motors for stability, but this one has been fine so far and has an abundance of filtering caps.
     
    For a better description look at my blog post here:
    http://emdinventor-blog.tk/light-seeker-robot-with-msp430/
     
    and for the code look at my github repository for the robot's code here:
    https://github.com/emdarcher/msp430_tank_robot
     
    Some pictures of the robot:

     

     

     
    Fritzing diagram ( missing 0.1uF filtering cap across Vcc and GND on the mcu ):
     

     
     
  13. Like
    oPossum got a reaction from GeekDoc in Buying an oscilloscope, need some advice.   
    TEquipment.net ships to Canada and is reputable.
     
    http://www.tequipment.net/RigolDS1074Z.html?v=7401
  14. Like
    oPossum got a reaction from Rickta59 in Tiny printf() - C version   
    This code was written when the MSP430 Lauchpad shipped with chips that had 128 bytes of RAM, 2k of flash, and no hardware serial port. So it was important to keep code very compact and a software UART was needed.
     
    Your F6137 chip has many hardware UARTS - so it would be wise to use them rather than software UART. Just write a putc() function that sends a char to the UART and you don't need the assembly code.
  15. Like
    oPossum reacted to pabigot in New BoosterPacks - CC3100 & CC3200   
    Interesting; thanks for the pointer. The big problem is that over the last couple years TI has completely failed to make the CC3000 robust enough to be deployable solution, and their support for it has diminished significantly over the last couple months. Maybe the CC3100 is intended to magically fix all the CC3000's problems, but my expectations aren't high.
  16. Like
    oPossum reacted to spirilis in New BoosterPacks - CC3100 & CC3200   
    CC3100 can serve as an Access Point per this thread- http://e2e.ti.com/support/wireless_connectivity/f/851/t/285351.aspx
     
    and 802.11n: http://e2e.ti.com/support/wireless_connectivity/f/307/p/295681/1031582.aspx#103158
  17. Like
    oPossum reacted to V0JT4 in IR remote controlled LED segment display   
    Hello,
     
    I needed a large 3 digit display with remote control. All available didn't fit my needs, were quite expensive or not flexible enough. So I decided to create my own inspired by products I found.
     
    IR remote control looked simple and cheap enough, Seeedstudio sells some nice large 7 segment LED displays and prototype PCB manufacture in China doesn't cost much.
     
    First I LaunchPad prototyped the design with 8 channel serial LED driver, like SCT2168, and generic 3 pin IR receiver. I implemented NEC IR protocol with TimerA and bit banged serial display data output. All worked nicely so I ordered 5" 7 segment LED digits from Seedstudio. I highly recommend to order one extra digit. From my batch 2 horizontal segments had visibly couple LEDs busted. Also provided datasheet doesn't match what I received. Instead of 2x6 mine are 3x7 LEDs per segment. I tore one apart to see what's inside. Dot segment doesn't even have a polarity mark and only one seemed to work, but I didn't plan to use them anyway.

     
    I designed 2 boards, one large for individual segments of 5" digit, MCU and voltage regulator and small one for various sizes of common anode LED displays. I can extend the display by daisy chaining digits or run multiple displays in parallel depending on which side I connect next digit. MCU and power supply part is placed only on 1st digit. Currently I have ordered 2.3" digits from ebay for secondary display. Boards were made by Elecrow, I fit 1 large and 2 small designs on one 10x10 PCB.



     
    Code runs on small MSP430G2 MCU and only 4 pins are needed, board is designed for MSP430G2210 SO-8 package but with little leg bending and pin reassignment TSSOP-14 may be used. I use small remote I got with DVB-T tuner I use for SDR. It has just few buttons and fairly large labels. Current code implements 4 memory slots to switch between numbers.
     
    Everything is placed in plastic box covered by gray acrylic.

    Code:
    main.ctools.htools.c
    Eagle files:
    large.schlarge.brdsmall.schsmall.brd
     
  18. Like
    oPossum got a reaction from tripwire in Tiny printf() - C version   
    This code was written when the MSP430 Lauchpad shipped with chips that had 128 bytes of RAM, 2k of flash, and no hardware serial port. So it was important to keep code very compact and a software UART was needed.
     
    Your F6137 chip has many hardware UARTS - so it would be wise to use them rather than software UART. Just write a putc() function that sends a char to the UART and you don't need the assembly code.
  19. Like
    oPossum got a reaction from agaelema in Tiny printf() - C version   
    This is a tiny printf() function that can be used with the chips that come with the Launchpad. Code size is about 640 bytes with CCS.
     
    There are 7 format specifiers:
    %c - Character
    %s - String
    %i - signed Integer (16 bit)
    %u - Unsigned integer (16 bit)
    %l - signed Long (32 bit)
    %n - uNsigned loNg (32 bit)
    %x - heXadecimal (16 bit)
     
    Field width, floating point and other standard printf() features are not supported.
     
    printf() code

    #include "msp430g2231.h" #include "stdarg.h" void putc(unsigned); void puts(char *); static const unsigned long dv[] = { // 4294967296 // 32 bit unsigned max 1000000000, // +0 100000000, // +1 10000000, // +2 1000000, // +3 100000, // +4 // 65535 // 16 bit unsigned max 10000, // +5 1000, // +6 100, // +7 10, // +8 1, // +9 }; static void xtoa(unsigned long x, const unsigned long *dp) { char c; unsigned long d; if(x) { while(x < *dp) ++dp; do { d = *dp++; c = '0'; while(x >= d) ++c, x -= d; putc(c); } while(!(d & 1)); } else putc('0'); } static void puth(unsigned n) { static const char hex[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; putc(hex[n & 15]); } void printf(char *format, ...) { char c; int i; long n; va_list a; va_start(a, format); while(c = *format++) { if(c == '%') { switch(c = *format++) { case 's': // String puts(va_arg(a, char*)); break; case 'c': // Char putc(va_arg(a, char)); break; case 'i': // 16 bit Integer case 'u': // 16 bit Unsigned i = va_arg(a, int); if(c == 'i' && i < 0) i = -i, putc('-'); xtoa((unsigned)i, dv + 5); break; case 'l': // 32 bit Long case 'n': // 32 bit uNsigned loNg n = va_arg(a, long); if(c == 'l' && n < 0) n = -n, putc('-'); xtoa((unsigned long)n, dv); break; case 'x': // 16 bit heXadecimal i = va_arg(a, int); puth(i >> 12); puth(i >> 8); puth(i >> 4); puth(i); break; case 0: return; default: goto bad_fmt; } } else bad_fmt: putc(c); } va_end(a); }
     
    test code

    #include "msp430g2231.h" void serial_setup(unsigned out_mask, unsigned in_mask, unsigned duration); void printf(char *, ...); void main(void) { char *s; char c; int i; unsigned u; long int l; long unsigned n; unsigned x; // Disable watchdog WDTCTL = WDTPW + WDTHOLD; // Use 1 MHz DCO factory calibration DCOCTL = 0; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; // Setup the serial port // Serial out: P1.1 (BIT1) // Serial in: P1.2 (BIT2) // Bit rate: 9600 (CPU freq / bit rate) serial_setup(BIT1, BIT2, 1000000 / 9600); printf("%s", "\r\n*** printf() test ***\r\n"); s = "test"; c = 'X'; i = -12345; u = 12345; l = -1234567890; n = 1234567890; x = 0xABCD; printf("String %s\r\n", s); printf("Char %c\r\n", c); printf("Integer %i\r\n", i); printf("Unsigned %u\r\n", u); printf("Long %l\r\n", l); printf("uNsigned loNg %n\r\n", n); printf("heX %x\r\n", x); printf("multiple args %s %c %i %u %l %n %x\r\n", s, c, i, u, l, n, x); printf("\r\n*** Done ***\r\n"); for(;; }

  20. Like
    oPossum reacted to greeeg in Custom EzFet Lite   
    Okay, so after a bit more poking.
     
    I found that the FW does use the BSL for it's FW updates, specifically it erases memory location 0xFFFE, then triggers a WDT reset. The MSP thinks it's erased so it runs the BSL.
     
    So I now know that the BSL wasn't flashed correctly.
    My version of mspdebug 0.22 (from source, but ~2 months old) cannot program the BSL. It reports that it is but the memory doesn't change.
     
    I then used TI's MSPflasher 1.3.1 and it worked perfectly. updated the BSL.
     
    Now when I connect via mspdebug it asks for a FW update, and actually completes it. I can connect to my target board (MSP430F5513) with no issue.
     
     
    I still have a small HW problem. When I connect a target device powered from the FET it hangs while connecting on linux, and disconnects on windows.
    My boards need to be updated with a larger capacitance on the VCC rail to support the inrush current of adding a target board.
    Or add an extra regulator to provide the ext power.
     
    In the meantime It works with powered boards, or if the board is connected before connecting USB.
     
    Looks like I have another board spin in the works.
  21. Like
    oPossum got a reaction from bluehash in Rocket Badge Not Working   
    Sparkfun's library if full of bad stuff. I know many people have been burned by it. Adafruit may be too. Best to do your own parts.
     
    Here is my battery lib with SMD & thru hole CR2032 holders drawn to mfg spec.
     
    http://www.memoryprotectiondevices.com/datasheets/BHX1-2032-SM-datasheet.pdf
     

    my_battery.lbr
  22. Like
    oPossum got a reaction from spirilis in Rocket Badge Not Working   
    Sparkfun's library if full of bad stuff. I know many people have been burned by it. Adafruit may be too. Best to do your own parts.
     
    Here is my battery lib with SMD & thru hole CR2032 holders drawn to mfg spec.
     
    http://www.memoryprotectiondevices.com/datasheets/BHX1-2032-SM-datasheet.pdf
     

    my_battery.lbr
  23. Like
    oPossum got a reaction from basil4j in Current sense layout   
    There has to be some source resistance ahead of the TVS or it's max current will be exceeded and it will fail or be damaged. TVS are tough devices, but they have limits that must not be exceeded.
  24. Like
    oPossum got a reaction from spirilis in Rocket Badge Not Working   
    Ahhh --- there should be no solder mask under the entire battery area (~25 mm dia) and the contact pad should be no larger than 8 mm dia/square to ensure good contact.
  25. Like
    oPossum got a reaction from RobG in Rocket Badge Not Working   
    Ahhh --- there should be no solder mask under the entire battery area (~25 mm dia) and the contact pad should be no larger than 8 mm dia/square to ensure good contact.
×
×
  • Create New...