Jump to content
43oh

roadrunner84

Members
  • Content Count

    1,370
  • Joined

  • Last visited

  • Days Won

    33

Reputation Activity

  1. Like
    roadrunner84 got a reaction from zeke in Stupidest Thing you had to Troubleshoot?   
    printf and friends are very hungry beasts, for integer to hex string and vice versa I prefer manual conversions.
    const char *const hex = "0123456789ABCDEF"; unsigned long input = 10; char output[9]; char *result = output; for(unsigned int ctr = 28; ctr; ctr -= 4) *result++ = hex[(input >> ctr) & 0xF]; *result = '\0'; something like this.
  2. Like
    roadrunner84 got a reaction from MSPLife in Problem with msp430g2553   
    Read my signature.
  3. Like
    roadrunner84 got a reaction from Simeon in Cant install Energia on ubuntu help   
    Note that Linux filenames are case sensitive, so
    /home/simeon/downloads/energia-0101E00XYZ-linux64.tgz
    and
    /home/simeon/Downloads/energia-0101E00XYZ-linux64.tgz
    are not the same file! Note the capital D in Downloads.
  4. Like
    roadrunner84 got a reaction from greeeg in Neural network code   
    You need to buy a controller with the DWIM module built in, choose any of the MSP430G7xxx chips and you'll be fine.
  5. Like
    roadrunner84 got a reaction from ike in Neural network code   
    You need to buy a controller with the DWIM module built in, choose any of the MSP430G7xxx chips and you'll be fine.
  6. Like
    roadrunner84 got a reaction from spirilis in Neural network code   
    You need to buy a controller with the DWIM module built in, choose any of the MSP430G7xxx chips and you'll be fine.
  7. Like
    roadrunner84 got a reaction from gsutton in Products using MSP430   
    That's a cool IR transmitter. Reading the report (I think this is a school project) you can see it's quite out-dated; the references name nothing more recent than 2002.
    If I'd build a similar thing nowadays there are some things I'd do different and make it significantly cheaper. First he's using the MSP430F1101A, which goes at $1.06, while an MSP430G2001 would do the thrick too and goes at $0.34.
    Second, the more recent MSP430 support pull-up to be configured in I/O lines, so that saves us 5 resistors (and reduces component placing to single sided, this saves a lot of money in real production).
    The 10-pin 0.5mm pitch zif socket (ouch, pricey!) for JTAG can be replaced by a 0.05" pitch quartet of holes, allowing programming with spy-bi-wire.
    For some reason he uses a FET to power his LED, I don't think that's necessary at all.
    He uses 2x 1uF + 10nF power decoupling on a battery, I think a single capacitor would do the trick at well. (but we need another 2.2nF capacitor on RST).
    He estimates his fobs at a price of about $21,- of which $11,- are for PCB manufacturing, at current prices you could easily go to $3,-, then $2,- for the casing, fine with me, and the components would go at.... well.... the battery and battery clip, plus a few cents. I think a "remake" would go for under 7$, cutting the price in three!
  8. Like
    roadrunner84 got a reaction from bluehash in Pi day - 3.14 USD freight on all TI store orders today (03/14)   
    @@greeeg as explained by the nice Vi Hart.
  9. Like
    roadrunner84 got a reaction from greeeg in Pi day - 3.14 USD freight on all TI store orders today (03/14)   
    @@greeeg as explained by the nice Vi Hart.
  10. Like
    roadrunner84 got a reaction from cde in Stupidest Thing you had to Troubleshoot?   
    Pin direction is a pain in the *ss. I've learned so far that the I/O direction description is mostly more informative than the net name....
  11. Like
    roadrunner84 got a reaction from Fmilburn in Parsing "strings" in C - Attempting to parse MQTT payload   
    You suggested returning a struct instead of passing out parameters, you could rewrite things like this
    #include <stdio.h> #include <string.h> const char *test[] = {   "cmd=led&color=red&state=on",   "cmd=&bla=true",   "cmd==false&blue=grey",   "x&&&&&g=t",   "cmd=load&&&&&&&&&&&&&color=red&bg=blueα=0.56&&blah=&&&&=wtf&&&&" }; struct key_value { const char *key; int key_len; const char *value; int value_len; const_char *next; }; struct key_value getKeyValue(const char *const input) { struct key_value result; const char *iter; result.value = input; result.key = input; for (iter = input; (*iter != '&') && (*iter != '\0'); ++iter) { if (*iter == '=') { if (result.value != input) // second '=' found, abort parsing { result.key_len = 0; result.value_len = 0; result.next = NULL; return result; } result.key_len = iter - input; result.value = iter + 1; } } result.value_len = iter - result.value; if (result.value == input) { result.key_len = result.value_len; result.value_len = 0; } result.next = *iter == '\0' ? NULL : iter + 1; return result; } int main() {   struct key_value result;   char key_str[20], value_str[20];   int n;   for(n = 0; n < 5; ++n)   {     result.next = test[n];     printf("%s\n", result.next);     do     {       const char *current = result.next;       result = getKeyValue(current);       memcpy(key_str, result.key, result.key_len);       key_str[result.key_len] = '\0';       memcpy(value_str, result.value, result.value_len);       value_str[result.value_len] = '\0';       printf("%s, %s\n",key_str, value_str);     } while (result.next != NULL);   }   return 0; } But you need to bear in mind that the key, value and next properties are pointers, not strings. So you can read them, but changing them will alter the input string too!
     
    The drawback of this solution is that in embedded systems it takes more memory and more time. You see, the function now needs to allocate memory to store the result variable, as well as the return value. Then when the function returns it copies the result from result to the return value. Then the main function would copy the return value to a local variable again. So that's three times memory for the struct and two memcpy calls done in the dark. So if speed or size is of the essence, this method is less appropriate.
    Add to that the issue of keeping track of pointers all the time and it's just not worth it most of the time.
  12. Like
    roadrunner84 got a reaction from Fmilburn in Parsing "strings" in C - Attempting to parse MQTT payload   
    Returning structs is a bit tricky in C, this is because the way parameters are assigned. You cannot assign a struct to another struct the naive way; it will work though, if you do not have any pointers or char* things in the struct.
    If you do have pointers or strings (char*) inside your struct, you must bear in mind that the struct does only carry a pointer to the "member" array, so altering one copy will also alter the other.
    struct foo { char *text; } struct foo bar; struct foo baz; int main() { bar.text = "hello"; baz = bar; printf("%s\n", baz.text); // prints "hello" bar.text[1] = 'a'; // change "hello" into "hallo" printf("%s\n", baz.text); // prints "hallo" baz.text = "olla"; // changes the pointer in baz, so bar is unaltered printf("%s\n", bar.text); // prints "hallo" return 0; } So you need to keep watch over the internals of your struct constantly.
     
    I do feel your juggling problem. Since you need to be more aware of slip-ups you cannot approach stuff the naive way. Things like "could this pointer point to invalid memory" or "am I sure I handle cases for an empty string" are essential to writing sound code. Your compiler or runtime will not (always) notify you if you screw things up.
    To take my own code as an example, this case is not covered:
    getKeyValue(NULL, &key_len, &value, &value_len); Oops, passing a null pointer to the function will not be caught. My function assumes all four pointers are valid, if they're not, well, things go sour.
     
    My code is intended to be plain C code, so no C++ tricks there. I started out with an old C book too, but I mostly learned just by doing things. Note that I debugged my function on a PC, not in the msp430 itself. Almost all behaviour wourks out fine in both. There's just tiny differences, like the size of a pointer (2 bytes in the msp430 and 8 bytes in my 64 bit linux machine), but they do not matter for good C code. I could do ugly things like assign a pointer to an integer or the other way around, which would work on the msp430 since both integers and pointers are 2 bytes, but not on my pc, since integers are 4 bytes but pointers are 8 bytes. Better steer clear from tricks like that.
    Well.. I don't assign pointers to integers, but I do assign pointer differences to integers! in C++ those should be ptrdiff_t not int! But I want a string length to result, which is an integer. C++ is a bit more picky on types than C, which is a good thing, because simple errors are more easily detected.
  13. Like
    roadrunner84 got a reaction from bluehash in Parsing "strings" in C - Attempting to parse MQTT payload   
    You suggested returning a struct instead of passing out parameters, you could rewrite things like this
    #include <stdio.h> #include <string.h> const char *test[] = {   "cmd=led&color=red&state=on",   "cmd=&bla=true",   "cmd==false&blue=grey",   "x&&&&&g=t",   "cmd=load&&&&&&&&&&&&&color=red&bg=blueα=0.56&&blah=&&&&=wtf&&&&" }; struct key_value { const char *key; int key_len; const char *value; int value_len; const_char *next; }; struct key_value getKeyValue(const char *const input) { struct key_value result; const char *iter; result.value = input; result.key = input; for (iter = input; (*iter != '&') && (*iter != '\0'); ++iter) { if (*iter == '=') { if (result.value != input) // second '=' found, abort parsing { result.key_len = 0; result.value_len = 0; result.next = NULL; return result; } result.key_len = iter - input; result.value = iter + 1; } } result.value_len = iter - result.value; if (result.value == input) { result.key_len = result.value_len; result.value_len = 0; } result.next = *iter == '\0' ? NULL : iter + 1; return result; } int main() {   struct key_value result;   char key_str[20], value_str[20];   int n;   for(n = 0; n < 5; ++n)   {     result.next = test[n];     printf("%s\n", result.next);     do     {       const char *current = result.next;       result = getKeyValue(current);       memcpy(key_str, result.key, result.key_len);       key_str[result.key_len] = '\0';       memcpy(value_str, result.value, result.value_len);       value_str[result.value_len] = '\0';       printf("%s, %s\n",key_str, value_str);     } while (result.next != NULL);   }   return 0; } But you need to bear in mind that the key, value and next properties are pointers, not strings. So you can read them, but changing them will alter the input string too!
     
    The drawback of this solution is that in embedded systems it takes more memory and more time. You see, the function now needs to allocate memory to store the result variable, as well as the return value. Then when the function returns it copies the result from result to the return value. Then the main function would copy the return value to a local variable again. So that's three times memory for the struct and two memcpy calls done in the dark. So if speed or size is of the essence, this method is less appropriate.
    Add to that the issue of keeping track of pointers all the time and it's just not worth it most of the time.
  14. Like
    roadrunner84 got a reaction from Fmilburn in Parsing "strings" in C - Attempting to parse MQTT payload   
    I made this version, it doesn't take a callback, instead it returns a pointer to the value (the key is always at the start of a token anyway) and the key and value lengths in parameters, as well as the start of the next token as return value.
    It may be easier to use in a state machine. Also, keys without values are allowed, as well as values without keys, but two = signs cause abortion of the function. empty tokens result in a key and value length of 0.
    const char *getKeyValue(const char *const input, int *key_len, const char **value, int *value_len) { const char *iter; *value = input; for (iter = input; (*iter != '&') && (*iter != '\0'); ++iter) { if (*iter == '=') { if (*value != input) // second '=' found, abort parsing { *key_len = 0; *value_len = 0; return NULL; } *key_len = iter - input; *value = iter + 1; } } *value_len = iter - *value; if (*value == input) { *key_len = *value_len; *value_len = 0; } return *iter == '\0' ? NULL : iter + 1; } #include <stdio.h> #include <string.h> char *test[] = { "cmd=led&color=red&state=on", "cmd=&bla=true", "cmd==false&blue=grey", "x&&&&&g=t", "cmd=load&&&&&&&&&&&&&color=red&bg=blueα=0.56&&blah=&&&&=wtf&&&&" }; int main() { int key_len, value_len; const char *key, *value, *next; char key_str[20], value_str[20]; int n; for(n = 0; n < 5; ++n) { next = test[n]; printf("%s\n", next); do { const char *current = next; next = getKeyValue(current, &key_len, &value, &value_len); memcpy(key_str, current, key_len); key_str[key_len] = '\0'; memcpy(value_str, value, value_len); value_str[value_len] = '\0'; printf("%s, %s\n",key_str, value_str); } while (next != NULL); } return 0; } Oh, and it doesn't touch the input string at all and uses practically no memory at all, it does require the user to iterate over all tokens though, but that's by design (since, no callback).
  15. Like
    roadrunner84 got a reaction from bluehash in Parsing "strings" in C - Attempting to parse MQTT payload   
    I made this version, it doesn't take a callback, instead it returns a pointer to the value (the key is always at the start of a token anyway) and the key and value lengths in parameters, as well as the start of the next token as return value.
    It may be easier to use in a state machine. Also, keys without values are allowed, as well as values without keys, but two = signs cause abortion of the function. empty tokens result in a key and value length of 0.
    const char *getKeyValue(const char *const input, int *key_len, const char **value, int *value_len) { const char *iter; *value = input; for (iter = input; (*iter != '&') && (*iter != '\0'); ++iter) { if (*iter == '=') { if (*value != input) // second '=' found, abort parsing { *key_len = 0; *value_len = 0; return NULL; } *key_len = iter - input; *value = iter + 1; } } *value_len = iter - *value; if (*value == input) { *key_len = *value_len; *value_len = 0; } return *iter == '\0' ? NULL : iter + 1; } #include <stdio.h> #include <string.h> char *test[] = { "cmd=led&color=red&state=on", "cmd=&bla=true", "cmd==false&blue=grey", "x&&&&&g=t", "cmd=load&&&&&&&&&&&&&color=red&bg=blueα=0.56&&blah=&&&&=wtf&&&&" }; int main() { int key_len, value_len; const char *key, *value, *next; char key_str[20], value_str[20]; int n; for(n = 0; n < 5; ++n) { next = test[n]; printf("%s\n", next); do { const char *current = next; next = getKeyValue(current, &key_len, &value, &value_len); memcpy(key_str, current, key_len); key_str[key_len] = '\0'; memcpy(value_str, value, value_len); value_str[value_len] = '\0'; printf("%s, %s\n",key_str, value_str); } while (next != NULL); } return 0; } Oh, and it doesn't touch the input string at all and uses practically no memory at all, it does require the user to iterate over all tokens though, but that's by design (since, no callback).
  16. Like
    roadrunner84 got a reaction from spirilis in Parsing "strings" in C - Attempting to parse MQTT payload   
    I made this version, it doesn't take a callback, instead it returns a pointer to the value (the key is always at the start of a token anyway) and the key and value lengths in parameters, as well as the start of the next token as return value.
    It may be easier to use in a state machine. Also, keys without values are allowed, as well as values without keys, but two = signs cause abortion of the function. empty tokens result in a key and value length of 0.
    const char *getKeyValue(const char *const input, int *key_len, const char **value, int *value_len) { const char *iter; *value = input; for (iter = input; (*iter != '&') && (*iter != '\0'); ++iter) { if (*iter == '=') { if (*value != input) // second '=' found, abort parsing { *key_len = 0; *value_len = 0; return NULL; } *key_len = iter - input; *value = iter + 1; } } *value_len = iter - *value; if (*value == input) { *key_len = *value_len; *value_len = 0; } return *iter == '\0' ? NULL : iter + 1; } #include <stdio.h> #include <string.h> char *test[] = { "cmd=led&color=red&state=on", "cmd=&bla=true", "cmd==false&blue=grey", "x&&&&&g=t", "cmd=load&&&&&&&&&&&&&color=red&bg=blueα=0.56&&blah=&&&&=wtf&&&&" }; int main() { int key_len, value_len; const char *key, *value, *next; char key_str[20], value_str[20]; int n; for(n = 0; n < 5; ++n) { next = test[n]; printf("%s\n", next); do { const char *current = next; next = getKeyValue(current, &key_len, &value, &value_len); memcpy(key_str, current, key_len); key_str[key_len] = '\0'; memcpy(value_str, value, value_len); value_str[value_len] = '\0'; printf("%s, %s\n",key_str, value_str); } while (next != NULL); } return 0; } Oh, and it doesn't touch the input string at all and uses practically no memory at all, it does require the user to iterate over all tokens though, but that's by design (since, no callback).
  17. Like
    roadrunner84 reacted to pine in Stupidest Thing you had to Troubleshoot?   
    Keep getting error message in CCS saying unable to program the LP (not exactly but something very similar to that meaning). 100% sure the board is connected. Unplugged the USB and plugged in again, restarted CCS and restarted PC. Turns out I tried to program a non-existent 2553 as I moved it out from the LP to a breadboard 
  18. Like
    roadrunner84 reacted to veryalive in Using 5volt LCDs on 3.3volt MSP430s - with no extra power supply   
    Hi forum,     I have many 5 volt LCDs.   Here's an idea for using them on 3.3 volt MSP430 systems, other 3 volt systems and LaunchPads.   Let's think of the typical 16 char  x 2 row LCD, with a 16 pin connector (pin 1 = GND, pin 2 = Vcc, pin 3 = Vee, etc) and operate the MSP and LCD off only one 3volt source.    No extra power supplies.   I've been using this technique for a long while, its nothing new, you may have already seen it.      PROBLEM STATEMENT - how to use a 5volt LCD unit on a 3.3 volt system without creating a separate 5v supply.     SOLUTION  SUMMARY - use a simple circuit to create a negative voltage from the MSP 430 ACLK.  This negative voltage then drives the LCD Vee on pin 3.   The ACLK ***must*** be enabled in your software.   You can enable ACLK in either CCS or Energia.      Current measurements and waveforms are shown below.   Clearly, you have to sacrifice use of the PORT P1_0 (red LED) pin, but this can be a reasonable trade off.   If you can't do this, then you can use another MSP output to generate the negative voltage.       HARDWARE -   a-- create a simple negative voltage charge pump (two capacitors, 2 diodes). - input is from MSP ACLK pin +- 12 KHz. - output is to LCD Vee, which is almost always pin 3.   b-- here is a simple charge pump circuit:       (please do google this if you've a question, it is really simple)                | |                    || ACLK -->---| |---------O----------||<|------O--------->---- to Vee, pin3 on LCD.             | |         |          ||        |             C1         |        D2          |                        |                    |                       ===                 =====                 D1    \ /             C2  =====                     =======                 |                        |                    |                        |                    |                        |                    |                      GROUND               GROUND     Typical component values are not critical. I used:  C1 = C2 = 1 uF.   D1 = D2 = Germanium 1N569. Results are below.   c--  then connect the LCD module as follows: - pin1 to GROUND - pin2 to +3.3 volts (same line as the MSP430 positive supply) - pin3 to the charge pump inverter circuit, above in para 'b'. - all the other pins (RS   R/W    E   DATA0-7) to PORT pins suitable for your application.   d--  the scope output of the waveform in actual operation is shown in the scope screen shot below.     SOFTWARE -  you must enable the ACLK / VLO to be output from the MSP430:   P2SEL |= 0x07; // aclk P2_0 pin8.  smclk P2_1 pin9.   ta0 3 P2DIR |= 0x07; BCSCTL3 = LFXT1S_2; // aclk = vloclk abt 12khz   This can be done in CCS or in Energia 'SETUP'.     CURRENT CONSUMPTION -  .... With this configuration: - MSP430F2272 at 1MHz,  PORTs 1,3,4 all set to OUTPUT LOW.  PORT 2 set up as above.     4 x 20 LCD with blue backlight (powered by 3.3volts to a reasonable back light output)   ....  here is the typical current consumption I measured:   - MSP430F2272 running tight loop, 1MHz    1.1  mA - loop + charge pump                      1.55 mA   <<<< so, only 0.45 mA for the charge pump - loop + charge pump + LCD backlight      9.44 mA    (these are high efficiency blue LEDs)     PLUS POINTS -  - only one power supply needed for a simple 430 + LCD project. - rather low current consumption - even lower current consumption by switching ACLK off (but then you should turn off the LCD Vcc +3.3 - use another PORT pin as the LCD Vcc)   MINUS POINTS -  - you have to use a MSP430 port pin   ALTERNATIVES -  - use a timer / int driven PORT pin to replace the ACLK. - LCD too much contrast? :       - insert series resistor to LCD Vee from charge pump to reduce neg volts - LCD not enough contrast? :       - use a negative voltage triple / quadrupler.       Hope someone can use this idea.....   Cheers.      
     
     
     
     
     

  19. Like
    roadrunner84 reacted to cde in Running straight off Battery vs LDO   
    Found a nice app note by TI, and wrote some thoughts on it:
     
    Just recently read an app note that targets your same circumstances. Using power solutions to extend battery life in MSP430 applications By TI's Michael Day. While it uses the MSP430 as its target, the same applies to any MCU.
     
    Depending on the MCU's Current vs Voltage, and Voltage vs Clock Speed, using an LDO with a low Quiescent Current will be much better than powering the MCU directly off the battery. The example uses 2x AA, and a TPS780xx regulator with 0.5
  20. Like
    roadrunner84 got a reaction from energia in MSP430 ===> FDC1004 using wire.h   
    The resistors for I2C should go from the SDA/SCL lines to Vcc, not in series on the SDA/SCL lines between the msp430 and the fdc1004
  21. Like
    roadrunner84 reacted to greeeg in GPS logger for a local Beagle club   
    Ran the enclosures through my Mill, made a little jig to aid in positioning.


     
    There are a few issues left to sort out.
    PCB is not retained downward in the enclosure, when removing USB the PCB lifts upwards. LEDs leak light between their corresponding holes in the enclosure Button needs a mechanism to reach up through the case. I plan to solve these issues by creating 2 custom parts.
    Part A:
    This part will wedge between the PCB and top of the enclosure. Have holes over the LEDs to create light pipes out of the enclosure. A channel around the button to house a switch cap, part B. Part B:
    Switch cap, poke through the cutout in the enclosure  
    I decided to use my CNC to make molds to form the parts out of polyurethane. Straight from the CNC. You can see the switch part took a few attempts to get the tolerance right.

     
    Fitted


     
    Button fits perfectly flush with the case to avoid accidental presses.



     
     
  22. Like
    roadrunner84 reacted to Fmilburn in Getting Started with Printed Circuit Board (PCB) Design   
    This is the first PCB that I have designed and sent off to be manufactured.  Yesterday I received the boards, soldered them up, and they work!

    This write-up outlines the process I used in the hope that it will be useful to other hobbyists and builders.  There are links at the end which provide additional detail. 
     
    Selecting a Project
    The project consists of a small board with a MSP430G2553 microcontroller and an nRF24L01 radio.  I started with a radio attached with jumpers to a LaunchPad quite some time back and then built one on a proto-board.  The photograph below shows a G2553 with radio powered by a buck-boost converter attached to a super capacitor and solar panel.  I used it for a while with my weather station which never was quite completed.

    Although I could have started with that, I actually chose to start with something simpler.  The goal was to focus on the PCB design process and to minimize the issues associated with a new or technically challenging project.  The objectives, strategies, and constraints I decided on included the following:
    Inexpensive






  23. Like
    roadrunner84 reacted to greeeg in Getting Started with Printed Circuit Board (PCB) Design   
    Glad your first PCB worked!!
    (my first few boards never worked without a decent number of bodge wires.)
     
    Nice to see you got dug straight into Kicad. Here's a very useful tip, try switching the canvas to openGL or Cario. (Cario is slower). This will enable the new routing tools, including obstacle avoidance and push-shove routing.

     
    Hopefully you will find this useful
  24. Like
    roadrunner84 got a reaction from energia in How to build and add Precompiled Header files in energia   
    Do you mean precompiled objects or binaries, because as far as I know, you cannot precompile headers; headers must be in plain text to be able to include them.
    If the header itself is containing a lot of classes that take time, you could consider moving the class method bodies to a separate C++ file and precompiling that, but be sure to use the exact same compiler and compiler settings when doing that, or you'll end up with ABI incompatibilities!
  25. Like
    roadrunner84 got a reaction from energia in Serial print problem   
    You're printing your output value and commenting text in the wrong order:
    Serial.println(average2); Serial.print("GUIDE_PIN_2="); Will print the value first, then a new-line, then the commenting text
    So assuming average1,2,3,4 are 1,2,3,4 respectively, you print
    1 GUIDE_PIN_1=2 GUIDE_PIN_2=3 GUIDE_PIN_3=4 GUIDE_PIN_4= So, in each clause, swap those two print lines like this
    Serial.print("GUIDE_PIN_2="); Serial.println(average2); Oh, and use the code block next time, it's the < > symbol above the edit window.
×
×
  • Create New...