Jump to content
43oh

# EngIP

Members

120

3

## Reputation Activity

1. EngIP reacted to username in Reflow Oven Booster Pack
Hey all, thanks for the comments. Video added, source will be added later if any interest.

2.
Seriously consider using an IR oven. We're doing this already with a convection oven, and for leadfree solder profiles it is a PiTA( thats right -> pain in the A . .  .backside )

As it stands we have to either find a suitable way to insulate our oven, or just scrap it for an IR oven. Our oven also has upper, and lower elements, so it is not for lack of having enough elements. Although I suppose that wattage on said elements could be on the low side. Just from watching as few trial runs though while experimenting, I would have to say that max temp of the oven is 260C, where 240C is a reasonable peak stage profile for lead free solder paste.
3.
Eh, I implemented a simple PID control loop on the G2553 with a Triac for power control (and MOC3063 optoisolated triac driver driven by the MSP430) based on @@wulfman / @@yyrkoon 's reflow control board.  Project thread: http://forum.43oh.com/topic/3945-solder-reflow-skillet-w-wulfmans-control-board/

The floating point math does add like 4KB to the program size, so keep that in mind.  It's probably possible to do it with integer math only but I didn't feel like figuring that out.
4.
#include <msp430.h> #include <stdint.h> const unsigned RXD = BIT1; const unsigned TXD = BIT2; const unsigned SW2 = BIT3; const unsigned long smclk_freq = 16000000; // SMCLK frequency in hertz const unsigned long bps = 9600; // Async serial bit rate // Output char to UART static inline void putc(const unsigned c) { while(UCA0STAT & UCBUSY); UCA0TXBUF = c; } // Output string to UART void puts(const char *s) { while(*s) putc(*s++); } // CR LF void crlf(void) { puts("\r\n"); } // Output binary array to UART void putb(const uint8_t *b, unsigned n) { do putc(*b++); while(--n); } // Print unsigned int void print_u(unsigned x) {     static const unsigned dd[] = { 10000, 1000, 100, 10, 1 };     const unsigned *dp = dd; unsigned d;     if(x) { while(x < *dp) ++dp;         do { d = *dp++; char c = '0'; while(x >= d) ++c, x -= d; putc(c); } while(!(d & 1));     } else putc('0'); } // Print signed int void print_i(const int x) { if(x < 0) putc('-'); print_u((x < 0) ? -x : x); } // Print hex nibble static inline void puth(const unsigned x) { putc("0123456789ABCDEF"[x & 15]); } // Print hex byte void print_hb(const unsigned x) { puth(x >> 4); puth(x); } // Print hex word void print_hw(const unsigned x) { print_hb(x >> 8); print_hb(x); } void main(void) { WDTCTL = WDTPW + WDTHOLD; // No watchdog reset // DCOCTL = 0; // Run at 16 MHz BCSCTL1 = CALBC1_16MHZ; // DCOCTL = CALDCO_16MHZ; // // P1DIR = ~(RXD | SW2); // Setup I/O for UART and switch P1OUT = P1REN = RXD | SW2; // P1SEL = P1SEL2 = RXD | TXD; // // const unsigned long brd = (smclk_freq + (bps >> 1)) / bps; // Bit rate divisor 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 for(; { // int n = 1; // do (P1IN & BIT3) ? --n : (n = 5000); while(n); do (P1IN & BIT3) ? n = 5000 : --n; while(n); puts("Poke me with a Stick\r\n"); // for(n = -5; n <= 5;) print_i(n++), putc(' '); crlf(); n = 0xDEAD; print_hw(n); putc(' '); // n += 0xE042; print_hw(n); crlf(); // crlf(); // } // } //
5. EngIP reacted to rebeltaz in Coffee Pot Fish Tank
My girlfriend wanted a Betta fish for Valentine's Day. When we got it home, I realized that it was a Tropical fish needing warm water - a slight problem in the winter. Using a coffee pot and the MSP430, I hacked together a (I think) pretty cool fish tank that not only looks good, but keep the little guy at a happy 75-80 degrees. Rather than rewrite everything, I am just going to link to my web page - I hope that is ok?

http://www.robotsandcomputers.com/robots/projects/cpfishtank.htm

6.
The msp430 was my first micro. At \$4.30 and free shipping any newbie is willing to "take the risk" into the world of microcontrollers. I don't think \$10 is outrageous but I can guarantee I would look around on the internet more to see what else I could get for \$10 first before i picked up an msp430.
7.
Hi 43oh community,

This is Adrian from the TI MCU group - wanted to chime in and confirm that the price of LaunchPad will change to \$9.99. While the \$4.30 promotional price of the MSP430 LaunchPad ended on March 1, 2013, at \$9.99 it remains TI
8.
The best location systems are all using antenna arrays and phase detectors in combination with signal strength and "fingerprinting."  So, a little bit of everything.  The time-based systems are pretty good, but not as good as the method above, and usually more expensive.  The time-based methods have rigid infrastructure requirements, which is a pain.

First, you need to determine what your requirements are for location precision.  Second, you will probably make your job easier if you can go lower and lower in frequency.  There is some point where the wavelength is too long to make a realistic antenna array, and the attenuation through walls is actually too low, but if you are just going to use signal strength and nothing else fancy, the simple advice is to go as low as you can go.  Maybe the ERC 169 MHz band is a good option.  If you can go even lower, that's even better.  I certainly wouldn't use a band higher than 433 MHz.
9.
There is a lot of variability in system-implementation parameters, but the method I use is good for achieving precision of 1/4th the cell size without using extended algorithms.  With extended algorithms, precision can get to 1/10th the cell size.  With additional, special hardware, precision can get near 1/50th cell size.  Typical cell arrangement is a 20m grid of reference points.  These are relatively cheap.

The "special hardware" I'm talking about is not something you're going to be able to implement in a project of your apparent scope.  The extended algorithms are a maybe.  I've done a few thesis projects in my time, and to implement all of these things is too big a task for the limited time and resources at your disposal.

You can send me a PM if you want to get into details about your project (if they are sensitive).  Location is something everyone likes, but it's not easy to implement.  There are several methods, and each has different attributes that may make it more or less suitable for you application.  I can help you if I have more detail about what you're trying to do and what limitations you have.
10.
One of the limitations of the C language is that multiplication truncates the result to match the size of the multiplicands. So if you multiply two 16 bit numbers, the result is limited to 16 bits despite 32 bits being needed to represent all possible results. The fix for this is to cast one of the multiplicands to a larger type. Unfortunately this results in the use of a multiply library routine that is larger and slower than necessary. Division has a similar problem - the quotient, dividend, and divisor are all the same size.

The way I fix these limitations is to write assembly code that is compact, efficient, and well suited to specific tasks. The muldiv() function provided here will take 16 bit unsigned values and do a multiply to a 32 bit intermediate result and then divide back down to 16 bits. It makes some simple tests on the arguments to optimize the code path.

One specific case where this muldiv() function is useful is scaling one range of values to another. For example taking the 0 to 1023 range of a 10 bit ADC and scaling to some actual unit of measure.

A helper function function can be used to allow clearly written code...

uint16_t muldiv_u16(uint16_t a, uint16_t b, uint16_t c); inline uint16_t scale_u16(uint16_t in, uint16_t in_low, uint16_t in_high, uint16_t out_low, uint16_t out_high) { // For guaranteed correct results: // in_low <= in <= in_high // in_low < in_high // out_low < out_high // return out_low + muldiv_u16(in - in_low, out_high - out_low + 1, in_high - in_low + 1); } Sample usage...

// Read 10 bit ADC value - range of 0 to 1023 const uint16_t adc = readADC(); // ADC reference votlage is 2.5V, so convert to a range of 0 to 2500 mV const uint16_t mv = scale_u16(adc, 0, 1023, 0, 2500);
Note that there are constraints on the values passed to the function. All are unsinged 16 bit integers, and must fall withing the constraints to ensure a correct return value.

Signed integers can also be used because the constraints will result in unsigned values being passed to the muldiv() function...
inline int16_t scale_i16(int16_t in, int16_t in_low, int16_t in_high, int16_t out_low, int16_t out_high) { // For guaranteed correct results: // in_low <= in <= in_high // in_low < in_high // out_low < out_high // return out_low + muldiv_u16(in - in_low, out_high - out_low + 1, in_high - in_low + 1); }
The in_low <= in constraint can easily be removed if needed...

int16_t scale_i16x(int16_t in, int16_t in_low, int16_t in_high, int16_t out_low, int16_t out_high) { // For guaranteed correct results: // in_low < in_high // out_low < out_high // -32768 <= return <= 32767 // return (in < in_low) ? out_low - muldiv_u16(in_low - in, out_high - out_low + 1, in_high - in_low + 1) : out_low + muldiv_u16(in - in_low, out_high - out_low + 1, in_high - in_low + 1); }

The other constraints could be reduced or eliminated using C++ templates. (exercise for the user)
; ;    Copyright (C) 2013  Kevin Timmerman ; ;   This program is free software: you can redistribute it and/or modify ;   it under the terms of the GNU General Public License as published by ;   the Free Software Foundation, either version 3 of the License, or ;   (at your option) any later version. ; ;   This program is distributed in the hope that it will be useful, ;   but WITHOUT ANY WARRANTY; without even the implied warranty of ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the ;   GNU General Public License for more details. ; ;   You should have received a copy of the GNU General Public License ;   along with this program.  If not, see <http://www.gnu.org/licenses/>. ;     .cdecls C, LIST, "msp430.h"                 ;                                                 ;     .text                                       ;                                                 ;                                                 ; return a * b / c     .def    muldiv_u16                          ; uint16_t muldiv_u16(uint16_t a, uint16_t b, uint16_t c)     .def    muldiv_u8                           ; uint8_t muldiv_u8(uint8_t a, uint8_t b, uint8_t c)                                                 ;                                                 ; muldiv_u16:                                     ;                                                                                               ; --- Multiply ---     push    R10                                 ; Accumulator MSW     push    R11                                 ; Accumulator LSW                                                                                               ; R12 a                                                 ; R13 b                                                 ; R14 c                                                 ; R15 b shift register LSW                                                 ;     clr     R11                                 ; Clear accumulator LSW     mov     R12, R10                            ; Copy a to accumulator MSW                                                 ;  (assume multiply by zero)     tst     R13                                 ; Multiply by zero?     jeq     div16                               ; Yes, skip multiply...     cmp     R12, R13                            ; Make R12 smaller than R13 to     jhs     no_swap16                           ;  do multiply as quickly as possible     xor     R12, R13                            ;     xor     R13, R12                            ;     xor     R12, R13                            ; no_swap16:                                      ;                                                   clr     R10                                 ; Clear accumulator MSW     clr     R15                                 ; Clear MSW of b shift                                                  clrc                                        ;                                                   jmp     mul16_begin                         ; mul16_add:                                      ;     add     R13, R11                            ; Add b to accumulator     addc    R15, R10                            ; mul16_shift:                                    ;     rla     R13                                 ; Shift b     rlc     R15                                 ; mul16_begin:                                    ;     rrc     R12                                 ; Shift a, test lsb     jc      mul16_add                           ; lsb is 1, add b...     jne     mul16_shift                         ; lsb is 0, but more 1 bits remain...                                                 ;                                                 ; --- Divide ---                                                 ; R13/R10/R11 Dividend / Quotient shift register                                                 ; R14 Divisor                                                 ; R15 Bit count div16:                                          ;     mov     R10, R12                            ; Copy MSW of accumulator to result                                                 ;   (assume divide by zero)     tst     R14                                 ; Divide by zero?     jz      div16_exit                          ; Yes, all done...     mov     #1, R15                             ; 16 bit quotient div16_shift:                                    ; R10 <- R11     rla     R11                                 ; Shift     rlc     R10                                 ;                                                 ; Greater than or equal to divisor?     jc      div16_sub                           ; Yes...     cmp     R14, R10                            ;     jlo     div16_next                          ; No... div16_sub:                                      ;       sub     R14, R10                            ; Yes, subtract     bis     #1, R11                             ; Set bit in result div16_next:                                     ;     rla     R15                                 ; Dec bit count     jne     div16_shift                         ; Next bit...     mov     R11, R12                            ; Return result in R12 div16_exit:                                     ;     pop     R11                                 ;     pop     R10                                 ;     ret                                         ;
11. EngIP reacted to JWoodrell in Basic timer usage
when you set  "TACTL = MC_2;"  you are setting the entire 16 bits...  so you are in effect turning off the flags you set earlier, and TASSEL = 0 (what you are setting it back to) is looking for the TACLK signal which is an external pulse, so your timer is never pulsing

for that same reason, use | when setting multiple flags to prevent some strange behavior sometimes.
TACTL = TASSEL_2 | ID_0 | MC_0;
try writing it with a |=    (or equals)  so that you are only affecting the bits you want and leaving the rest alone

"TACTL |= MC_2;"   (enable timer, while leaving other bits alone)
"TACTL &= ~MC_2;"   (disable timer, while leaving other bits alone)
12.
Hey forum!
I always wanted to make a synthesizer , so i chose the msp430 launchpad, because it's one of the most inappropriate chip i can use for it  :grin:
When i started to make it i didn't have real goal, i just wanted to make a sound, so this project is kind if all over the place but i have learned a lot doing it so it was totally worth it.

The DAC used is a  TI TLC5615, it's not the best choice, but i only had this in my parts bin.
Probably any other SPI DAC could be used with minimal modification, or even PWM.
(I don't sound good with PWM IMO.)
The TLC5615 needs 5 volts, but it seem to run good with 3.6 volt from the launchpad,or you could use TP3 (the USB 5V) but that can be noisy, I used a separate 5V supply.

The crystal is required, because it tunes the DCO on every start up to a pre-defined value
( i ran it at 19Mhz without any problems)
If you change the frequency , you only need to change the bit rate divider for the USCI UART.

There are a lot to optimize/rewrite but i kind of grew tired of playing with variables to get a few more bytes of free ram.
Maybe i'll rewrite it on an F5510 as it would be a much better choice because it has 8 x Ram as much ram and a hardware multiplier.

This is a synth with 16 voice of polyphony. It accepts midi massages from 1-8 and 10 (for the drum sounds). Each midi channel has it's own different settings for: -MIDI program  -LFO width and speed  (CC01 for combined mod wheel control, CC02 for width,CC03 for speed -Oscillator type (simple with any waveform or with ADSR square or sine wave) -Pitch bend -Portamento on/of (CC65) -Portamento speed (CC05) -Channel volume (CC07)  It plays 8 sine/square with ADSR, 4 with any waveform (now only Saw and triangle), and 4 drum sounds simultaneously.   Here are two songs i recorded with it: Soundcloud.   I have attached the CCS Project with the source codes in a ZIP, the schematics, and a picture of how it look on my breadboard.

mSpYNTH.zip
mysy
13. EngIP got a reaction from pine in Project idea seeking comments - golf swing
Someone attempted this with the chronos.

http://processors.wiki.ti.com/index.php/Pro_Swing_Analyzer_-_Chronos_Project_Design
14.
This link shows how I uses packages to send information around:
http://forum.43oh.com/topic/1433-anaren-ti-cc110l-rf-air-booster-pack/?p=17770

Below a bit more on the secrets You can define the payload any way you wish with any data you want to transfer. As you can see my setup uses ACKs and also nodeIDs but you could do that completely different. The only mandatory thing (at least its wise) is to start with an addr part in your payloadframe since the receivers can check automatically for this. I am using 2 payload variables In_Payload and Out_Payload to do all the exchanges, next to that there are 2 buffers declared for receiving/sending payloads. Makes sure they are large enough.

After receiving a package I use the following code to decipher the package into to In_Payload variable
LoadRxBuffer((char *)&In_Payload,len); // translate rxBuffferdata into In_Payload

Sending a package is simple, you first set your packagedata in the Out_Payload structure and then call
send_Msg(xxxx)  where xxxx is a command you want to send around.

Have fun !

CorB

//PAYLOADS typedef volatile struct StatusStruct { enum TxACKMessageType { //!< Flags to ACK transfer REQUEST_NO_ACK = 0, REQUEST_ACK = 1 } TxACKMessageType; enum RxACKMessageType { //!< Flags to ACK transfer RECEIVED_NO_ACK = 0, RECEIVED_ACK = 1 } RxACKMessageType; char channel; char power; char RSSI; unsigned int msgNodeId; } StatusStruct; typedef struct PayloadFrame { char addr; // payloads need to start with char addr as the receiver can check this ! char msg; // messagetype 0x00 - 0xFF options char msgdata0; // var1 that belongs to the message char msgdata1; // var2 that belongs to the message StatusStruct Status; // USER DESIGNED PAYLOAD SECTION unsigned int data1; //unsigned int data2; char DataUnit; } PayloadFrame; PayloadFrame In_Payload; // receiving payload PayloadFrame Out_Payload; // sending payload #define maxPayload 40 // reserve space for the payloadsize in the buffers char txBuffer[maxPayload]; // sizeof(PayloadFrame) !! char rxBuffer[maxPayload]; // this routine sets default settings for payloads that will be send PayloadFrame * DefaultPayload () { Out_Payload.addr=0x01; // force adress Out_Payload.msg=DATA_PAYLOAD; Out_Payload.msgdata0=0; Out_Payload.msgdata1=0; Out_Payload.DataUnit='_'; Out_Payload.Status.RxACKMessageType=RECEIVED_NO_ACK ; Out_Payload.Status.TxACKMessageType= REQUEST_ACK; Out_Payload.Status.msgNodeId=NodeId; return &Out_Payload; } // transfer of a payload PayloadFrame * MakeTxPayload () { Out_Payload.Status.msgNodeId=NodeId; // always enforce ! return &Out_Payload; } // load a payload into the RxBuffer char LoadRxBuffer (char *buffer, char len) { int i = 0; for (i = len; i >= 0; i--) { buffer[i] = rxBuffer[i]; // Recreate Payload from received data } return 0; } // load a payload into the TxBuffer char PreparetxBuffer (char *payload, char len) { int i = 0; for (i = len; i >= 0; i--) { txBuffer[i+1] = payload[i]; // Create DataPacket from Payload } txBuffer[0]=len; // byte 0 in the pack should be the package length return 0; } // Send a payload void send_Msg(char message) { Out_Payload.addr=0x01;//force address Out_Payload.msg=message; PreparetxBuffer( (char *)(MakeTxPayload()), sizeof(PayloadFrame)); RFSendPacket(txBuffer, txBuffer[0]+1); // 1 byte larger than payloadframe due to the packagesize byte __delay_cycles(5000); //5ms waiting }
15. EngIP got a reaction from Antscran in Displaying ADC value on a 16x2 LCD
When I've done this in the past, I've use a character map and a function to translate an integer to display values.  Basically there's a variable with the LCD code for that particular number in it's indexed location.  For my LCD it's

const char charMap[10] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};

Then if I have an integer to display (say 341) I do the modulus operator to find the remainder after 10 (1 in this case), send charMap[1] to the display, then divide by 10 and repeat.

Hope this helps
16. EngIP reacted to oPossum in High resolution timing...
Use timer capture - then interrupt latency doesn't matter - the edge time is latched for you.

See SLAU144 section 12.2.4

Use 16 MHz DCO with /8 prescaler - that will meet your jitter spec.

17. EngIP got a reaction from jsolarski in POV with G2211 and little else
Just a little update with this "project".

I put the circuit on stripboard, a bit easier than frantically swinging a breadboard about in my efforts to impress the wife.

A few attempts at more than a pretty green face...

An attempt at mixing inverse and regular text...Not great

About the best picture I managed to get...

18. EngIP reacted to SugarAddict in Can't find slaa465.zip...
I'm not sure why, but here you go... SLAA465 inside SLAC525
Accompanying appnote: SLAA465
19. EngIP reacted to cubeberg in Can't find slaa465.zip...
This page: http://www.ti.com/product/cc430f6147 has a SLAA465 (Rev A) listed. It's a different ID though - not sure if it's what you're looking for. There are a bunch of broken links (including on their search page) to that document though... Might be worth posting in TI's forums to see if a TI employee could get it back on the site - especially since they're still selling the Chronos.
20. EngIP reacted to Philipp in Stellaris LaunchPad
The Stellaris Launchpad is now available at the TI e-store for preorder!

I ordered two of them, some ez430 targets and a v1.5 Launchpad for a total of ~24\$ or 20
21. EngIP reacted to pine in 2553 serial support...
Are the UART jumpers set to HW positions like the picture below, assuming a v1.5 LP board? 2553 uses build-in hardware serial, 2231 uses software serial, and the jumpers need to be set accordingly.. For pre-1.5 board i think there is a need to cross over the RX and TX for the HW uart to work.. i haven't tried pre-1.5 board, but the positions of jumper below works ok with the AnalogReadSerial example on a v1.5 board with a 2553.

22. EngIP reacted to OppaErich in FRAM for Dummies
Mouser offers FRAM for Dummies for free. Sign up here http://mou.sr/OMm5e0
23. EngIP reacted to rockets4kids in Leeching power
Yes, you could do that.
24. EngIP reacted to GeekDoc in Leeching power
This seems right to me (see sig below), but remember to just wrap one conductor of the AC line, or the two will cancel each other out. It's basically just a transformer. The supply side just happens to be powering something else as well.
25. EngIP reacted to rockets4kids in Leeching power
Just wrap some wire around a power cord, rectify and filter whatever is induced, and measure voltage drop over a known resistance. From there you can calculate current and power. If you are not getting enough, experiment with more wraps.
×
• Blog

• #### Activity

×
• Create New...