Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Reputation Activity

  1. Like
    krzyk2 reacted to RobG in General use triac boards   
    The BOM will depend on what you want to use this board for and on the triacs.
    Here's my BOM (post #2,) for non-inductive loads, light bulbs for example:
    Triac - BTA16-600BW - you can use BTA06, BTA12, and 600, 800, but use BTA (insulated) and W (snubberless.)
    Opto - MOC3023 - this is a random phase opto-triac, good for for dimming/PWM applications. If you want to just switch on and off, you can use MOC3043/MOC3063 which has zero crossing detector built-in.
    R13, R14 - 180ohm ( 1/4W or 1/2W is the best, but 1/8W should be no problem.)
    R1, R3 - 180ohm SMD0805 (can be higher, up to 300ohm should work OK.)
    R2, R4 - 270ohm SMD0805 (depends on the LED)
    LED - SMD0805
    Terminal - DG300 or DG301
    All other parts are optional and depend on the application.
    Except for LEDs, all of those parts are available from Tayda (non W triacs like BTA16-600B are OK.)
  2. Like
    krzyk2 reacted to rbasoalto in Garage door opener   
    Very nice!
    Maybe you can have a look at http://en.wikipedia.org/wiki/HOTP for security. It's the kind of cryptographically-secure unpredictable sequence generators that banks use for two-factor authentication. Google's two-factor authentication uses it too.
    The idea is that you apply an HMAC function (some kind of hash involving a private key) to a counter. Both transmitter and receiver need to store this counter. Since both will usually be in sync, the HMAC received can be compared to the expected value, based on the shared private key, and the counter. If it fails, it can also try a few counts ahead too, in case the button was pressed accidentally out of the receiver's range.
    Although banks and Google use a time-based algorithm, it's essentially the same, but using the count of 30-second ticks instead of an event counter. I think I've seen a version for the Chronos that is compatible with Google Authenticator. Should be trivial to adapt.
    Since you will need to store a counter, FRAM would be ideal for zero-power-standby. But you can also use flash, or just have the MSP sleeping in LPM4 the whole time and wake it, with an interrupt from the button, for transmission (at a few uA it shouldn't be noticeable).
    In this last case, you could use a three-way handshake, much like TCP/IP sockets, for keeping the counters in sync. Something like

    [*:3rhtxy43]Remote: HEY, the current code is 123456.
    [*:3rhtxy43]Receiver: OK, please come in.
    [*:3rhtxy43]Remote: Thanks! Increment the counter! (I will increment it too)
    I could continue giving ideas for centuries, it's a very interesting topic.
    Cheers! I hope you're not locked out!
  3. Like
    krzyk2 got a reaction from bluehash in MTK3339 GPS   
    I mentioned this in other data logger thread, wouldn't it be better to add a SD (micro?) card to this better than using a memory chip? If it would store the data directly to the card, (without any FS, just write from the first bit, and add some marker at the end) it wouldn't use much more memory of 2553 and it would definitely by easier to get the data out of it, not to mention the amount of data that could be stored.
  4. Like
    krzyk2 reacted to spirilis in TI boost converter - TPS61221   
    Thought I'd share some thoughts on this chip since it's an obvious choice for powering low-power MSP430 type apps off a battery in some remote location.
    The TI TPS6122x series are boost converter chips, i.e. you have to add capacitors and an inductor around it, which take a battery voltage from 0.7V-5.5V and boost it to the appropriate output -- 61220 is an adjustable model where you build a resistor network on the Feedback line to specify the voltage, 61221 is fixed to 3.3V, 61222 is fixed to 5.0V. Peak output is technically 200mA although you should keep it lower than that, maybe 120mA or lower to account for performance while the battery drains down.
    TI's product page: http://www.ti.com/product/tps61221
    The chip is tiny and only comes in surface-mount packages, the DCK package (0.65mm pitch, 6-pins). The pitch of the pins is similar to the pitch of the surface-mount MSP430 TSSOP packages, at least for the value line. Definitely DIY'able although I'd suggest soldering the TPS61221 chip first (so you have clear access to all the pins without other junk getting in the way of your iron) before you solder the rest of the components.
    Anyway I've made 2 test boards (single-sided toner-transfer PCBs) to measure the actual characteristics of the chip. I've mainly only measured its current draw from the battery under no-load conditions, but I've confirmed it can power an LED (blue) drawing about 35mA with no limiting resistor. (The battery input side was showing weird results, about 220mA, which I suspect has to do with the 200mA switching current it uses to do its work... I'd probably need an oscilloscope to properly measure what's going on there. It's supposed to draw what it needs + 5.5uA in terms of net current draw, but does so using periodic/frequent 200-400mA swings in current across the inductor)
    At zero load, my multimeter's uA range shows about 9-10uA draw from the battery, just about what the datasheet suggests. My first experimental board I used some Tantalum capacitors I had and I think they were a mistake; no-load power draw ranged from 400uA-3mA with those. I've had similar problems with them in past boards where they'd short circuit causing upwards to 1A draw off the power supply, so I have since thrown them away and stuck with ceramics instead. Using a 10uF ceramic cap on the input side (+Vbatt to GND), and a 1uF (close to the chip) + 10uF ceramic cap on the output side (Vout to GND) it behaves like the datasheet suggests. FWIW, I used a 4.7uH SMD inductor rated up to 650mA.
    The datasheet mentions that if you switch the EN (enable) line off, to GND, it lets battery voltage pass through the onboard MOSFET's bypass diode. This seems to be the case, but it does net a ~0.3-0.5V voltage drop between Vbatt+ and what you see on Vout under those circumstances. Additionally, I noticed a ~10-11uA current draw from the battery with that EN line grounded. Seems like it's pointless to design a circuit where an MCU can shut off the boost converter (say, to save power while the MCU runs off the direct battery voltage bleeding through the boost converter)--because the voltage is dropped a bit and it's still sipping power anyhow. The boost converter OTOH can give the MSP430 a usable voltage until the battery's voltage is around 0.7V (and then, as I saw with a CR2032 + several LEDs toasting the thing, it still outputs some ~1.8V even with the battery run down to 0.4V)
    Anyway that's my 2 cents on this chip. I'm going to use it in a design I'm coming up with (uses thermocouple amplifiers that require 3.0-3.6V), more on that later.
    PS- Leaving the EN line floating doesn't sound like a good idea, my cheap 10uF ceramic caps seem to make noise (ceramic piezoelectric effect?) when a lot of switching is going on and while I hear it sometimes under normal operation with load (like that blue LED), they go bonkers and the LED flickers like crazy with the jumper removed from the EN line altogether (not GND'ing it). Guessing that destabilizes the switcher.
  5. Like
    krzyk2 reacted to alsenin in WS6318 GSM Booster Pack   
    Okay. There is the yet another LP booster pack. It is for communication over GSM network.


    Now I have several working prototypes. PCB has couple of bugs but booster pack has full functionality. Soon, I will correct all the errors and give a full description. Schematic is in the attachment. If anyone suggest any modification or expansion of the functionality - this is a chance to introduce them into the final PCB tracerouting.
  6. Like
    krzyk2 reacted to RobG in Serial SPI memory functions   
    Here is the set of functions needed to read and write serial SPI memory, SRAM & EEPROM.
    EEPROM: Microchip 25AAxxx series
    SRAM: Microchip 23Kxxx series
    Included are byte and sequence read and write functions (page boundaries must be handled by user.)
    Test functions are also included. Additional functions will be added later on.
    Those functions can be used with some of my booster packs, like CC2500, Universal Color LCD, and few other.
    Test example

    // setup SPI pins, which can be shared with other devices // setup memory specific pins P1OUT |= SRAM_CS_PIN + SRAM_HOLD_PIN; P1DIR |= SRAM_CS_PIN + SRAM_HOLD_PIN; P2OUT |= EEPROM_CS_PIN; P2DIR |= EEPROM_CS_PIN; // setup display // run tests drawString(0,0,"Test SRAM:"); drawString(64, 0, (testSRAM() == 'O' ? "Pass" : "Fail")); drawString(0,10,"Test EEPROM:"); drawString(76, 10, (testEEPROM() == 'O' ? "Pass" : "Fail"));

  7. Like
    krzyk2 reacted to cde in How to power a board   
    Most 3.3v will run at 3.0v as a recommended minimum, but can run a bit lower as well, the manufacturer just won't support undervolting it, you can always just try it.
    That tps61097-33 is a good idea as it only needs two caps and a common inductor, but only gives you about 100ma. Microchip MCP1253 is similar, but needs no inductor, can provided 3.3 or 5v out and 120ma.
  8. Like
    krzyk2 reacted to voodoofish in Data Logger board   
    I received the datalogger board today and after multiple hw tests to verify that board functioned as expected, I completed the first of 3 test boards. The last test is to verify that the memory chip is recording correctly, and until then I can't say that this board is 100% functional. though the current 80% has me pretty excited. Now I'm waiting for the addon board that is breaks out the datalogging pins plus a couple other pins to a usable 3 pin configuration.
    Images included in this set have the button 1 switch which allows for it to be a reset or action button, and the male header pins. The other image shows the board pre switch and header mockup and also conected to the lp which allows me to do the uploading of programs. Very happy so far. Tonight and tomorrow I'll work on getting the memory chip tested as well as doing some initial tests on the data input ports(adc channels)and communications port(hw uart).

  9. Like
    krzyk2 reacted to RobG in TI MSP430 Family Eagle library   
    I was little annoyed by the existing MSP430 libraries so I decided to modify them and create my own.
    Here's my first version of it. Let me know what you think.

    Updated May 7 2012
    Added 2210 & 2230

    Updated May 16 2012
    Added FR5739 (TSSOP 38)

    Updated June 20 2012
    Fixed two 14 pin devices. Pin 8 was assigned to pin 10 and vice versa.
    Affected devices: MSP430G2X31-14PW14 and MSP430G2X21-14PW14
    Updated March 26 2013
    G2x55 TSSOP 38 DA
    G2x44 TSSOP 38 DA
    G2x44 PDIP 40 N

  10. Like
    krzyk2 reacted to Maddox in Stock Tank Filler   
    Hi - first post to the forum, but I wanted to share a project I just finished that uses an MSP430G2553 with a DRV8833 H-Bridge, DC solenoid, float switch that is powered from a 9v battery. The goal of the project was to sense when the water level in the livestock tank need to be replenished and activate an irrigation valve and of course turn it off when the level is right.
    Was a fun project where I made my first pcb, built a reflow oven with PID control, and made the whole thing waterproof. Links to the design files and software are available on our blog posting, but I don't have enough seniority on the forum to post the link - admin said he could add it to the post.
    Link: Stock Tank Filler
    Thanks for all the valuable insight from the form!
  11. Like
    krzyk2 reacted to cubeberg in nanoPad - MSP430G target board   
    One thought - It'd be interesting to see something like this turned into an eTextile board - something like the LilyPad. I integrated some AVRs into costumes for my kids last year and it would be awesome to use an MSP430 instead.
  12. Like
    krzyk2 got a reaction from bluehash in [Group Buy-5][D]MTK3339 GPS + BoosterPack - $14.26   
    BTW the datasheet for this module is here http://www.gtop-tech.com/ShowAttach?UNID=fa8848c22dbfbff87dedfe3352971bf08e6e88e6
    I couldn't find the datasheet for the chipset itself.
  13. Like
    krzyk2 reacted to nimblemotors in Tractor Engine Control   
    Hello again my friends,
    I posted the video of the full msp430 based EFI system running my tractor.
    You can see the waterproof box that holds the fuses and all the connections.
    Originally this tractor did not have a single fuse.

    The fuel injector is a TBI unit from a Geo Metro, just using the injector portion of the TB.
    The throttle plate is from a Prius, and is an electronic controlled throttle.
    Processor is a msp4301232, with two high-side mosfets (previously used to charge NiMH batterys),
    one used to control the throttle, the other controls the fuel injector. The ADC inputs from the 430 are used to read the analog sensor inputs (GM parts) the o2 sensor, the MAP, the water temp.
    The Tach input signal of course is the msp430 based coil-on-plug ignition I showed earlier.
    Also here is the dashboard I built for it, using msp430 processors that drive bargraphs on the LCDs
    for the readings. Fuel level, Water Temp, Battery Voltage, Oil Pressure, and RPM.

  14. Like
    krzyk2 reacted to RobG in Ethernet Booster Pack   
    If all goes well with the booster pack, a standalone version will follow.
    The one below is 2" x 1", has MSP430G2553, LDO, 8 GPIOs, and a programming header.

  15. Like
    krzyk2 got a reaction from larsie in LCD 16x2 in 4 bit mode   
    I bought a 16x2 LCD from ebay and wanted to use it in 4 bit mode, with no shift register (I'm waiting for them to come).
    Maybe it will be useful to someone.
    The LCD is LMB162ABC-1 which uses ST7066U but it should work on HD44780 drivers.
    There is a bug in ST7066U documentation regarding 4 bit operation that was very annoying (looked for it about 2 hours). When initializing the 4 bit mode, in documentation it says that DB7/6/5/4 should be set to 0011, but actually DB4 should be set to 0, so nibble should be 0010.
    The interface is quite simple, just three public functions demonstrated in main.c:

    lcd_init(); lcd_goto(0,4); lcd_show("Hello"); lcd_goto(1,9); lcd_show("world");
    The connections to the uC:

    * RS - P1.0 * R/W - P2.0 * E - P1.1 * DB4 - P1.2 * DB5 - P1.3 * DB6 - P1.4 * DB7 - P1.5
    I didn't use R/W, probably I should connect it to the GND, but maybe I should try to read the busy state instead of using delay functions it would be more robust.
    BTW. I didn't know that TP1 and TP3 can be used to get 5v from the USB, useful for 3.3v logic, 5v BL LCD
  16. Like
    krzyk2 got a reaction from lvagasi in Dallas/Maxim One Wire Library   
    Thanks to pointers from Rickta59 here's code tuned to work in msp430-gcc.
    I've used it in my project to read temperature from DS sensor and it works correctly.
  17. Like
    krzyk2 reacted to oPossum in Software Real Time Clock (RTC) - two methods   
    The Launchpad comes with a 32.768 kHz crystal that can be used when timing more precise than the DCO is needed. The crystal frequency is useful for simple timing tasks, such as a RTC, because it is a power of 2. That allows a simple cascade of 15 flip-flops to create a 1 pulse per second time base. It is common for microcontroller timers to have prescalers, postscalers and/or preset divisors that are simply a tap on the flip-flip chain. The watchdog timer in the MSP430 is an example of a timer with power of 2 presets (64, 512, 8192, 32768). TimerA units have a prescaler with power of 2 presets (1, 2, 4, 8).
    The sample code in this post uses the watchdog timer to create an interrupt that occurs once per second. TimerA can also be used to do this. One of the advantages of using TimerA is the ability to change the preset +/- 1 every N cycles to allow for calibration and temperature compensation of the crystal. I chose to use the watchdog timer so that TimerA was free to be used for alarm tones or PWM backlight control.

    Using the C standard library time functions for a RTC
    The C standard library provides several functions for working with real time. The function prototypes are in time.h. The type time_t is typically an integer type that is in units of 1 second. It doesn't have to be that, but usually is. The epoch is usually January 1, 1970 for "unix time." Be aware that CCS uses an epoch of January 1, 1900 and time_t is unsigned rather than signed. I assume GCC uses the more common unix time epoch and time_t is signed.
    Since time_t is in units of 1 second, the ISR for timekeeping is trivial...

    #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // ++tt; // Increment time_t } //
    To display the time it can be converted to a tm structure that has elements for hours, minutes, day, month, ect. There are two functions to do this: gmtime() and localtime(). gmtime() converts to UTC, and localtime converts to the time zone for the set locale. Both functions take a time_t and return a pointer to a static tm struct.
    To set the time the mktime() function will convert a tm struct to a time_t value. It will also determine day of week and day or year for you.
    Tivial ISR. Simple and efficient.
    Portable code - the C standard library time functions work on almost any device with a C compiler.
    Easy to calulate time deltas - use ordinary integer math on time_t values.
    Easy to compare times using <, >, ==, etc.
    Compact representation of time (32 bit time_t typically) is good for timestamps of data logs.
    Some file systems (not FAT unfortunately) use time_t as for timestamps.
    Converting from time_t to tm struct takes quite a few clock cycles, so not good for low power (battery powered) systems.
    Time functions take up quite a bit of flash - will not fit in G2211 for example.
    Software model of a hardware RTC
    Hardware real time clocks typically have counters for seconds, minutes, hours, ect. Each counter will reset at the appropriate
    limit - 60 seconds, 24 hours, ect. This approch can be use for a software RTC. The ISR has more code than the previous version...

    #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // if(++t.tm_sec > 59) { // Increment seconds, check for overflow t.tm_sec = 0; // Reset seconds if(++t.tm_min > 59) { // Increment minutes, check for overflow t.tm_min = 0; // Reset minutes if(++t.tm_hour > 23) { // Increment hours, check for overflow t.tm_hour = 0; // Reset hours ++t.tm_yday; // Increment day of year if(++t.tm_wday > 6) // Increment day of week, check for overflow t.tm_wday = 0; // Reset day of week // Increment day of month, check for overflow if(++t.tm_mday > dim[t.tm_mon][is_leap_year(t.tm_year + 1900)]) { t.tm_mday = 1; // Reset day of month if(++t.tm_mon > 11) { // Increment month, check for overflow t.tm_mon = 0; // Reset month t.tm_yday = 0; // Reset day of year ++t.tm_year; // Increment year } // - year } // - month } // - day } // - hour } // - minute } //
    Most of the time the ISR will just increment the seconds member and return. The worst case is at the end of the year when the year is incremented and all other counters are reset to inital values.
    There is no need for any conversion for display of the time or setting the time. Be aware that day of week and day of year must be explicity set and can be out-of-sync if not properly set.
    No conversion function needed for display of time or setting of time.
    Small code size. Fits in G2211.
    High efficiency is good for battery powered applications.
    Use of tm struct provides some familiarity to those who have used the C standard library functions.
    No easy to way calulate time delta.
    No support for time zones / localization.
    Time comparison (for alarms) requires more MCU cycles because several structure members require comparason rather than just a long integer.

    This sample code can be configured to use either of the two methods descibed by (un)commenting the "#define USE_STDLIB_TIME" in main.c

    #include #include #include #include "rtc.h" #include "lcd.h" //#define USE_STDLIB_TIME // Use functions in time.h void show_time(const struct tm *t) // Show time on LCD { static const char *dow[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; int x, w; const char *d; if(t->tm_hour < 10) { x = -1; lcd_fill(0, 1, 10, 2, 0); } else { x = 4; lcd_fill(0, 1, 4, 2, 0); lcd_pd12(t->tm_hour / 10, x, 1); } lcd_pd12(t->tm_hour % 10, x + 11, 1); lcd_pd12(11, x + 22, 1); lcd_pd12(t->tm_min / 10, x + 27, 1); lcd_pd12(t->tm_min % 10, x + 38, 1); lcd_pd12(11, x + 49, 1); lcd_pd12(t->tm_sec / 10, x + 54, 1); lcd_pd12(t->tm_sec % 10, x + 65, 1); lcd_fill(x + 76, 1, 8 - x, 2, 0); if(t->tm_mon < 9) { x = -4; lcd_fill(0, 3, 7, 2, 0); } else { x = 1; lcd_fill(0, 3, 1, 2, 0); lcd_pd12((t->tm_mon + 1) / 10, x, 3); } lcd_pd12((t->tm_mon + 1) % 10, x + 11, 3); lcd_pd12(13, x + 22, 3); lcd_pd12(t->tm_mday / 10, x + 30, 3); lcd_pd12(t->tm_mday % 10, x + 41, 3); lcd_pd12(13, x + 52, 3); lcd_pd12(t->tm_year %100 / 10, x + 60, 3); lcd_pd12(t->tm_year % 10, x + 71, 3); lcd_fill(x + 82, 3, 2 - x, 2, 0); d = dow[t->tm_wday]; w = strlen(d) * 6; x = (84 - w) >> 1; lcd_fill(0, 5, x, 1, 0); lcd_print(d, x, 5); x += w; lcd_fill(x, 5, 84 - x, 1, 0); } // struct tm ts; // Time structure time_t tt; // Time in seconds since epoch // // #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // #ifdef USE_STDLIB_TIME // ++tt; // Increment time_t #else // rtc_tick(&ts); // Increment tm struct #endif // __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // // void main(void) // { // WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset // lcd_init(); // Init LCD lcd_clear(0); // lcd_print("MSP430 RTC", 12, 0); // // // 32 kHz xtal loading //BCSCTL3 = XCAP_1; // 6 pF (default) BCSCTL3 = XCAP_2; // 10 pF //BCSCTL3 = XCAP_3; // 12.5 pF // WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | WDTSSEL; // Use WDT as interval timer IE1 |= WDTIE; // Enable WDT interrupt _EINT(); // Enable interrupts // // Set initial time - there is no UI for this ts.tm_hour = 13; // Hour ts.tm_min = 37; // Minute ts.tm_sec = 42; // Second ts.tm_mon = 3; // Month (0 based!) ts.tm_mday = 20; // Day of Month ts.tm_year = 2012 - 1900; // Year ts.tm_wday = 5; // Day of Week - Not used by mktime() ts.tm_yday = 0; // Not used by mktime() ts.tm_isdst = 0; // DST flag - Not used by rtc_tick() // #ifdef USE_STDLIB_TIME // Convert tm struct to time_t tt = mktime(&ts); // #endif // // for(; { // for-ever #ifdef USE_STDLIB_TIME // show_time(localtime(&tt)); // Convert time_t to tm struct and show on LCD #else // show_time(&ts); // Show time on LCD #endif // __bis_SR_register(LPM0_bits + GIE); // Sleep until WDT interrupt } // } //

    void rtc_tick(struct tm *t);
    rtc.c - Software model of hardware RTC

    #include static int is_leap_year(const int y) { if(y & 3) return 0; // Not divisible by 4 switch(y % 400) { // Divisible by 100, but not by 400 (1900, 2100, 2200, 2300, 2500, 2600) case 100: case 200: case 300: return 0; } return 1; // Divisible by 4 and !(100 and !400) } void rtc_tick(struct tm *t) { static const signed char dim[12][2] = { // Number of days in month for non-leap year and leap year 31, 31, // January 28, 29, // February 31, 31, // March 30, 30, // April 31, 31, // May 30, 30, // June 31, 31, // July 31, 31, // August 30, 30, // September 31, 31, // October 30, 30, // November 31, 31 // December }; // // if(++t->tm_sec > 59) { // Increment seconds, check for overflow t->tm_sec = 0; // Reset seconds if(++t->tm_min > 59) { // Increment minutes, check for overflow t->tm_min = 0; // Reset minutes if(++t->tm_hour > 23) { // Increment hours, check for overflow t->tm_hour = 0; // Reset hours ++t->tm_yday; // Increment day of year if(++t->tm_wday > 6) // Increment day of week, check for overflow t->tm_wday = 0; // Reset day of week // Increment day of month, check for overflow if(++t->tm_mday > dim[t->tm_mon][is_leap_year(t->tm_year + 1900)]) { t->tm_mday = 1; // Reset day of month if(++t->tm_mon > 11) { // Increment month, check for overflow t->tm_mon = 0; // Reset month t->tm_yday = 0; // Reset day of year ++t->tm_year; // Increment year } // - year } // - month } // - day } // - hour } // - minute } //

    typedef enum { lcd_command = 0, // Array of one or more commands lcd_data = 1, // Array of one or more bytes of data lcd_data_repeat = 2 // One byte of data repeated } lcd_cmd_type; void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type); void lcd_home(void); void lcd_pos(unsigned char x, unsigned char y); void lcd_clear(unsigned char x); void lcd_init(void); void lcd_fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z); void lcd_print(const char *s, unsigned x, unsigned y); void lcd_pd12(unsigned n, unsigned x, unsigned y);

    #include #include "lcd.h" //static const unsigned TXD = BIT1; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; static const unsigned LCD_CLK = BIT5; static const unsigned LCD_BACKLIGHT = BIT6; static const unsigned LCD_DATA = BIT7; static const unsigned LCD_DC = BIT0; // PORT2 static const unsigned LCD_CE = BIT1; // PORT2 void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; P2OUT &= ~LCD_CE; do { mask = 0x0080; do { if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; mask >>= 1; } while(!(mask & 1)); if(!type) P2OUT &= ~LCD_DC; if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; P2OUT |= LCD_DC; if(!(type & 2)) ++cmd; } while(--len); P2OUT |= LCD_CE; } static const unsigned char home[] = { 0x40, 0x80 }; void lcd_home(void) { lcd_send(home, sizeof(home), lcd_command); } void lcd_pos(unsigned char x, unsigned char y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); } void lcd_clear(unsigned char x) { lcd_home(); lcd_send(&x, 504, lcd_data_repeat); lcd_home(); } void lcd_init(void) { static const unsigned char init[] = { 0x20 + 0x01, // function set - extended instructions enabled 0x80 + 64, // set vop (contrast) 0 - 127 0x04 + 0x02, // temperature control 0x10 + 0x03, // set bias system 0x20 + 0x00, // function set - chip active, horizontal addressing, basic instructions 0x08 + 0x04 // display control - normal mode }; P1REN = RXD | SWITCH; P1DIR = LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P1OUT = LCD_CLK | RXD | SWITCH | LCD_BACKLIGHT; P2REN = 0; P2DIR = LCD_DC | LCD_CE; P2OUT = LCD_CE; __delay_cycles(20000); P2OUT |= LCD_DC; __delay_cycles(20000); lcd_send(init, sizeof(init), lcd_command); } void lcd_fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z) { unsigned yy = y + h; unsigned char c[2]; c[0] = 0x80 | x; for(;y < yy; ++y) { c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); lcd_send(&z, w, lcd_data_repeat); } } static const unsigned char font6x8[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 20 32 0x00, 0x00, 0x5F, 0x00, 0x00, // 21 33 ! 0x00, 0x07, 0x00, 0x07, 0x00, // 22 34 " 0x14, 0x7F, 0x14, 0x7F, 0x14, // 23 35 # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // 24 36 $ 0x23, 0x13, 0x08, 0x64, 0x62, // 25 37 % 0x36, 0x49, 0x56, 0x20, 0x50, // 26 38 & 0x00, 0x08, 0x07, 0x03, 0x00, // 27 39 ' 0x00, 0x1C, 0x22, 0x41, 0x00, // 28 40 ( 0x00, 0x41, 0x22, 0x1C, 0x00, // 29 41 ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // 2A 42 * 0x08, 0x08, 0x3E, 0x08, 0x08, // 2B 43 + 0x00, 0x40, 0x38, 0x18, 0x00, // 2C 44 , 0x08, 0x08, 0x08, 0x08, 0x08, // 2D 45 - 0x00, 0x00, 0x60, 0x60, 0x00, // 2E 46 . 0x20, 0x10, 0x08, 0x04, 0x02, // 2F 47 / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 30 48 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 31 49 1 0x42, 0x61, 0x51, 0x49, 0x46, // 32 50 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 33 51 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 34 52 4 0x27, 0x45, 0x45, 0x45, 0x39, // 35 53 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 36 54 6 0x41, 0x21, 0x11, 0x09, 0x07, // 37 55 7 0x36, 0x49, 0x49, 0x49, 0x36, // 38 56 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 39 57 9 0x00, 0x00, 0x14, 0x00, 0x00, // 3A 58 : 0x00, 0x00, 0x40, 0x34, 0x00, // 3B 59 ; 0x00, 0x08, 0x14, 0x22, 0x41, // 3C 60 < 0x14, 0x14, 0x14, 0x14, 0x14, // 3D 61 = 0x00, 0x41, 0x22, 0x14, 0x08, // 3E 62 > 0x02, 0x01, 0x51, 0x09, 0x06, // 3F 63 ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // 40 64 @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // 41 65 A 0x7F, 0x49, 0x49, 0x49, 0x36, // 42 66 B 0x3E, 0x41, 0x41, 0x41, 0x22, // 43 67 C 0x7F, 0x41, 0x41, 0x41, 0x3E, // 44 68 D 0x7F, 0x49, 0x49, 0x49, 0x41, // 45 69 E 0x7F, 0x09, 0x09, 0x09, 0x01, // 46 70 F 0x3E, 0x41, 0x49, 0x49, 0x7A, // 47 71 G 0x7F, 0x08, 0x08, 0x08, 0x7F, // 48 72 H 0x00, 0x41, 0x7F, 0x41, 0x00, // 49 73 I 0x20, 0x40, 0x41, 0x3F, 0x01, // 4A 74 J 0x7F, 0x08, 0x14, 0x22, 0x41, // 4B 75 K 0x7F, 0x40, 0x40, 0x40, 0x40, // 4C 76 L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // 4D 77 M 0x7F, 0x04, 0x08, 0x10, 0x7F, // 4E 78 N 0x3E, 0x41, 0x41, 0x41, 0x3E, // 4F 79 O 0x7F, 0x09, 0x09, 0x09, 0x06, // 50 80 P 0x3E, 0x41, 0x51, 0x21, 0x5E, // 51 81 Q 0x7F, 0x09, 0x19, 0x29, 0x46, // 52 82 R 0x26, 0x49, 0x49, 0x49, 0x32, // 53 83 S 0x01, 0x01, 0x7F, 0x01, 0x01, // 54 84 T 0x3F, 0x40, 0x40, 0x40, 0x3F, // 55 85 U 0x1F, 0x20, 0x40, 0x20, 0x1F, // 56 86 V 0x3F, 0x40, 0x38, 0x40, 0x3F, // 57 87 W 0x63, 0x14, 0x08, 0x14, 0x63, // 58 88 X 0x03, 0x04, 0x78, 0x04, 0x03, // 59 89 Y 0x61, 0x51, 0x49, 0x45, 0x43, // 5A 90 Z 0x00, 0x7F, 0x41, 0x41, 0x41, // 5B 91 [ 0x02, 0x04, 0x08, 0x10, 0x20, // 5C 92 '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // 5D 93 ] 0x04, 0x02, 0x01, 0x02, 0x04, // 5E 94 ^ 0x80, 0x80, 0x80, 0x80, 0x80, // 5F 95 _ 0x00, 0x03, 0x07, 0x08, 0x00, // 60 96 ' 0x20, 0x54, 0x54, 0x54, 0x78, // 61 97 a 0x7F, 0x28, 0x44, 0x44, 0x38, // 62 98 b 0x38, 0x44, 0x44, 0x44, 0x28, // 63 99 c 0x38, 0x44, 0x44, 0x28, 0x7F, // 64 100 d 0x38, 0x54, 0x54, 0x54, 0x18, // 65 101 e 0x00, 0x08, 0x7E, 0x09, 0x02, // 66 102 f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // 67 103 g 0x7F, 0x08, 0x04, 0x04, 0x78, // 68 104 h 0x00, 0x44, 0x7D, 0x40, 0x00, // 69 105 i 0x00, 0x20, 0x40, 0x40, 0x3D, // 6A 106 j 0x00, 0x7F, 0x10, 0x28, 0x44, // 6B 107 k 0x00, 0x41, 0x7F, 0x40, 0x00, // 6C 108 l 0x7C, 0x04, 0x78, 0x04, 0x78, // 6D 109 m 0x7C, 0x08, 0x04, 0x04, 0x78, // 6E 110 n 0x38, 0x44, 0x44, 0x44, 0x38, // 6F 111 o 0xFC, 0x18, 0x24, 0x24, 0x18, // 70 112 p 0x18, 0x24, 0x24, 0x18, 0xFC, // 71 113 q 0x7C, 0x08, 0x04, 0x04, 0x08, // 72 114 r 0x48, 0x54, 0x54, 0x54, 0x24, // 73 115 s 0x04, 0x04, 0x3F, 0x44, 0x24, // 74 116 t 0x3C, 0x40, 0x40, 0x20, 0x7C, // 75 117 u 0x1C, 0x20, 0x40, 0x20, 0x1C, // 76 118 v 0x3C, 0x40, 0x30, 0x40, 0x3C, // 77 119 w 0x44, 0x28, 0x10, 0x28, 0x44, // 78 120 x 0x4C, 0x90, 0x90, 0x90, 0x7C, // 79 121 y 0x44, 0x64, 0x54, 0x4C, 0x44, // 7A 122 z 0x00, 0x08, 0x36, 0x41, 0x00, // 7B 123 { 0x00, 0x00, 0x77, 0x00, 0x00, // 7C 124 | 0x00, 0x41, 0x36, 0x08, 0x00, // 7D 125 } 0x02, 0x01, 0x02, 0x04, 0x02, // 7E 126 ~ 0x00, 0x06, 0x09, 0x09, 0x06, // 7F 127 degrees }; void lcd_print(const char *s, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); while(*s) { lcd_send(&font6x8[*s - 32][0], 5, lcd_data); lcd_send(&font6x8[0][0], 1, lcd_data); ++s; } } static const unsigned char num11x16[19][11 * 2] = { 0x00,0xF0,0xFC,0xFE,0x06,0x02,0x06,0xFE,0xFC,0xF0,0x00, // 0 0x00,0x07,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x07,0x00, 0x00,0x00,0x08,0x0C,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00, // 1 0x00,0x20,0x20,0x20,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x00, 0x00,0x0C,0x0E,0x06,0x02,0x02,0x86,0xFE,0x7C,0x38,0x00, // 2 0x00,0x30,0x38,0x3C,0x36,0x33,0x31,0x30,0x30,0x38,0x00, 0x00,0x0C,0x0E,0x86,0x82,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 3 0x00,0x18,0x38,0x30,0x20,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x00,0xC0,0x20,0x18,0x04,0xFE,0xFE,0xFE,0x00,0x00, // 4 0x00,0x03,0x02,0x02,0x02,0x22,0x3F,0x3F,0x3F,0x22,0x02, 0x00,0x00,0x7E,0x7E,0x46,0x46,0xC6,0xC6,0x86,0x00,0x00, // 5 0x00,0x18,0x38,0x30,0x20,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0xC0,0xF0,0xF8,0xFC,0x4C,0xC6,0xC2,0x82,0x00,0x00, // 6 0x00,0x0F,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0x06,0x06,0x06,0x06,0x06,0xC6,0xF6,0x3E,0x0E,0x00, // 7 0x00,0x00,0x00,0x30,0x3C,0x0F,0x03,0x00,0x00,0x00,0x00, 0x00,0x38,0x7C,0xFE,0xC6,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 8 0x00,0x0E,0x1F,0x3F,0x31,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x78,0xFC,0xFE,0x86,0x02,0x86,0xFE,0xFC,0xF8,0x00, // 9 0x00,0x00,0x00,0x21,0x21,0x31,0x1D,0x1F,0x0F,0x03,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : 0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . 0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x00,0x00,0x00,0x00, // / 0x00,0x30,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, // - 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x00,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xF0,0xF8,0x0C,0x06,0x02,0x02,0x02,0x02,0x0E,0x0C,0x00, // C 0x03,0x07,0x0C,0x18,0x10,0x10,0x10,0x10,0x1C,0x0C,0x00, 0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, // F 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0x40,0xE0,0xB0,0x18,0x0C,0x06,0x02,0x00,0x00, // K 0x1F,0x1F,0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x10,0x00 }; void lcd_pd12(unsigned n, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n], 11, lcd_data); c[1] = 0x41 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n] + 11, 11, lcd_data); }
  18. Like
    krzyk2 reacted to oPossum in Anaren TI CC110L RF AIR Booster Pack   
    ADC input 11 is the supply voltage (Vcc) divided by 2. So using the 1.5V reference allows measuring up to 3V and using the 2.5V reference allows measuring up to 5V (more than the max allowed for the MSP430).
    If you want units of millivolts, here is the math... (integer for speed and compactness)

    unsigned read_batt_mv(void) { ADC10CTL0 = 0; ADC10CTL1 = INCH_11 | ADC10DIV_3; ADC10CTL0 = SREF_1 | ADC10SHT_3 | REF2_5V | REFON | ADC10ON | ADC10IE; ADC10CTL0 |= (ENC | ADC10SC); // Start conversion __bis_SR_register(LPM0_bits + GIE); // Sleep while ADC active - much less noise this way! //return ((192188L * ADC10MEM) + 32768) >> 16; // 1.5 V ref return ((320314L * ADC10MEM) + 32768) >> 16; // 2.5 V ref } #pragma vector = ADC10_VECTOR __interrupt void ADC10_ISR(void) { __bic_SR_register_on_exit(LPM0_bits); }
  19. Like
    krzyk2 reacted to CorB in Anaren TI CC110L RF AIR Booster Pack   
    Hi Cuberg,
    I am using the same basic code as Larsie and have had the same issue as you report some time ago. Ive added some additional code (see below) and I dont have any issues anymore. In my test-setup I have currently 3 Sensors (2 on batteries, 2xAAA or CR3025) and 1 Hub, they send data (mainly battery level as I am testing how long a setup can run from batteries) every 10 seconds. All sensors are at sleep most of the time and wake-up every 10 seconds, send a package and go to sleep again. Every 5th package asks for an ACK from the Hub, sensors wait for the ACK to come back (not sleeping). In the ACK-reply from the HUB every sensor learns how strong its signal is when received by the Hub, sensors do self power up/down (paTable) to minimize transmission energy whilst keeping a good connection.
    Here;s the modified code for RFSendPacket
    void RFSendPacket(char *txBuffer, char size)
    // added 20120123 based on ANAREN code
    TI_CC_SPIStrobe(TI_CCxxx0_SIDLE); // set to IDLE
    TI_CC_SPIStrobe(TI_CCxxx0_SFRX); // Flush RX
    TI_CC_SPIStrobe(TI_CCxxx0_SFTX); // Flush TX
    // end new 20120123
    TI_CC_SPIWriteBurstReg(TI_CCxxx0_TXFIFO, txBuffer, size); // Write TX packet structure data
    TI_CC_SPIStrobe(TI_CCxxx0_STX); // Change state to TX, initiating data transfer
    while (!(TI_CC_GDO0_PxIN&TI_CC_GDO0_PIN)); // Wait GDO0 to go hi -> sync TX'ed
    while (TI_CC_GDO0_PxIN&TI_CC_GDO0_PIN); // Wait GDO0 to clear -> end of pkt
    TI_CC_SPIStrobe(TI_CCxxx0_SRX); // Change state to RX after sending
    TI_CC_GDO0_PxIFG &= ~TI_CC_GDO0_PIN; // After pkt TX, this interrupt flag is set.
    // Has to be cleared before exiting
  20. Like
    krzyk2 reacted to alvarop in CC2500 with mspgcc   
    NOTE: This only applies to people trying to get TI's cc2500 radio libraries compiling under mspgcc.
    While helping someone out earlier, I realized other people might have the same problem, so I figured I'd post it here.
    For some reason, the SPI timing wasn't entirely working, I 'documented' my problem here: http://e2e.ti.com/support/rf__digital_radio/etc_rf/f/228/t/127759.aspx
    Also, if you want a fully working mspgcc version of the cc2500 radio libraries, check out: https://github.com/alvarop/cc430bsn/tree/ez430-rf2500
    (NOTE: most of the 'good' code is on the ez430-rf2500 branch, not under master.)
    Look at the readme to see how to build projects and automatically program devices (and assign them addresses!)
    The code under the network/ folder should be a good example of a working master + multiple slaves.
  21. Like
    krzyk2 reacted to RobG in CC2500 Breakout/BoosterPack   
    Here's the tutorial

  22. Like
    krzyk2 reacted to kff2 in CC2500 Breakout/BoosterPack   
    In case anyone wants to start tinkering with their radios before the boards arrive, try sticking 22 AWG solid wire into the small holes on the module. The fit is almost perfect.

  23. Like
    krzyk2 reacted to V0JT4 in Universal Ripple Control Receiver   
    The goal of my project is to build ripple control receiver with some additional functions, main request was to receive massages and sent them via UART but current plan includes many more functions:
    - receive and decode messages
    - 4 relays triggered by certain message content
    - message logging to EEPROM with date and time from RTC
    - configuration will be stored on RTC DS1338 user memory
    - simple CLI via UART
    - 4 buttons and 20x4 character LCD interface
    - listing recorded messages with filtering
    Ripple control messages are transmitted to electricity distribution network, usually at 110kV or 22kV level and pass transformers down to end user 230V mains line. It is used to signal low and high tariff to electricity meters and high non-critical loads to optimize power distribution. The signal uses low modulation frequency, most common in Czech Republic is 216.7Hz. One message takes about 63 seconds to transmit. This allows one transmitter to cover large area. So far I'm getting around 200 messages a day with first receiver prototype.
    I plan to use these components:
    - MSP430G2553
    - modified old receiver ZPA FMX-100 for signal extraction from mains, opto-coupled connection
    - AT24C512 I2C EEPROM, 64Kx8 bit
    - DS1338 I2C RTC
    - 20x4 character LCD HD44780 with shift register 74HCT164
    - ULN2803 for relay switching with shift register 74HC595
    - USB to UART module with FTDI or CP2102 chip, opto-coupled UART
    Does someone have good experience with DS1338 or would you recommend other RTC? I need 3.3V operation and battery backup, square wave output is welcomed.
  24. Like
    krzyk2 reacted to bluehash in [Group Buy-2][D]CC2500 RF Module - GB2   
    -----------Shipped from Vendor----------
    This was our second most successful group buy. Thanks for participating! Please let me know if you are interested in anything else. Doing this also helps get products to the store.
    Ok people.. Price for each radio is going to be $1.58. To see what you are going to have to pay, please visit this google spreadsheet link and verify my math.
    Shipping is via DHL($45) with tracking(3-4 days, within a week). This is where a GB comes most handy along with lower prices. Thanks for participating.
    Payment email: g s e q . b u s i n e s s (at) g m a i l . c o m
    Remove the spaces.
    For those who have not yet paid, please select "gift"...and I would be grateful if you pay the fee. It is ~5% for each transaction. Eg: for a $10 transaction, it will be a 0.50 fee. This adds up.
    Bluehash ------25(PAID)(SHIPPED)
    Lars------------10(I)(PAID)( Thanks for the beer! )(SHIPPED)
    Since many people are asking about it, I'm ready to start another one. The previous group buy can be viewed here. It will be nice to get to 20 pieces. I can match it upto 50 for the Store. Your chance to get it at a much lower price. These are the modules.
    I'll try to keep the same price range depending on the deal they give me. It may fluctuate upto a $1.50 upward.
  25. Like
    krzyk2 reacted to RobG in CC2500 Breakout/BoosterPack   
    After going back and forth all weekend on what jumpers to include, here's the "final" design.
    The board includes:
    1 Booster pack
    2 G2xx3/CC2500 boards
    2 breakout boards compatible with booster pack
    1 breakout board with single row header
    (I know this is one board too many, so if Seeed rejects it, I will remove single row breakout.)
    Booster pack is designed to work with G2xx3 chips (is there any need for G2xx1/2 compatibility?)
    Port mapping:
    P1.1 - MISO (CC2500/SPI 2)
    P1.2 - MOSI (CC2500/SPI 2)
    P1.4 - SCLK (CC2500/SPI 2)
    P1.5 - SCLK (CC2500/SPI 1, Memory)
    P1.6 - MISO (CC2500/SPI 1, Memory)
    P1.7 - MOSI (CC2500/SPI 1, Memory)
    P2.0 - CS (CC2500/SPI 1)
    P2.1 - GDO0 (CC2500/SPI 1)
    P2.2 - GDO2 (CC2500/SPI 1)
    P2.3 - GDO2 (CC2500/SPI 2) or Memory Hold
    P2.4 - GDO0 (CC2500/SPI 2) or Memory CS
    P2.5 - CS (CC2500/SPI 2)
    When memory is not used, CS should be jumpered to Vcc, same with Hold.
    What thickness are we going with?
    1.0mm would be great for MCU boards, but might be too thin for the booster pack. 1.2mm should be perfect.
    I will post the complete set of files later today.

  • Create New...