Jump to content


  • Content Count

  • Joined

  • Last visited

Posts posted by leomar01

  1. Hello @@JapiMostert,


    I just read this thread and your questions. Since I just finished my masters degree, I can well imagine how overwhelmed you feel facing the requirements of your project. As it's already been said, try to draw a graph of the components, how they interact and which functions you want to accomplish. Don't try to overaccomplish what's asked. Try to find the easiest ways.


    Don't be afraid of the term "data logging". If you just send the time of the stopwatch over UART, that's everything you need. On the MSP430G2 launchpad you have a UART->USB bridge (just in case you didn't know that already). On your computer you just open a serial console / terminal program like "hterm". Everything your MSP430 sends over UART will be on your computer screen. Actually that's allready some sort of "data logging". Then, you'll just save the output to a text file (hterm has a buttong "save output") and you're done. 


    You don't need a dedicated RTC module. The launchpad has a watch crystal on boad (actually you maybe have to solder it on). I think that's the reason why your professor thinks this wohle project is logical and easy to do. 


    Regarding the button debuncing: adding a capacitor would do the trick and will propably save you some headache with software debouncing.


    Since you are using CCS you could also use "Grace" to configure things like UART peripheral, timers, button interrupts, clocks etc.




  2. In workEvents(), first store the value of millis() in a local variable and use that in your compares. If you do not, the trigger millisecond might have elapsed before you reach it, and thus miss an event.

    that's a good point, thanks @@roadrunner84

    If I change the check to "eventArray[i].nextTime <= millis()" the problem is also gone and saves the 4 bytes for another variable ;-)


    I just had a look at Energia source code.

    Energia spends quite some time to do the millis(); alone:

    void watchdog_isr (void)
    	// copy these to local variables so they can be stored in registers
    	// (volatile variables must be read from memory on every access)
    	unsigned long m = wdt_millis;
    	unsigned int f = wdt_fract;
    	m += sleeping ? SMILLIS_INC:MILLIS_INC;
    	f += sleeping ? SFRACT_INC:FRACT_INC;
    	if (f >= FRACT_MAX) {
    		f -= FRACT_MAX;
    		m += 1;
    	wdt_fract = f;
    	wdt_millis = m;
            /* Exit from LMP3 on reti (this includes LMP0) */

    calling a millis() ISR every millisecond is the easiest way to do tings like this, but it also means your controller will spend a significant amount of time not in low power. You could set a timer to fire at the time the first LED should go off. Thenlet tha one schedule the next timer, etc.


    Your solution is overly complex for the scetched scenario; you allow looping in your timers, you allow different time intervals. If you drop these two features you could use a single ringbuffer to add timeouts to, and use the solution I described above without ever having to iterate the whole buffer.


    I measured my current implementation to be 97,7% of the time in sleep state. Not optimal, but ok. 

    Actually, in my real use case low power won't matter that much, rather the ability to do other things in the meantime without having to worry about the timings. Hence, the ability to stop the whole event timer engine and go completely down to LPM4 until a external interrupt from the wireless module fires.



    To sum it all up, I'm aiming on compiling my own library of portable code snippets to get such things done the easier way in future (see my portable ringbuffer approach).

  3. Erm, I think I've got it:




     * EventTimer.h
     *  Created on: 07.07.2014
     *      Author: Leo_2
    #include <msp430.h>
    #include "../types.h"
    #ifndef EVENTTIMER_H_
    #define EVENTTIMER_H_
    #define MAXEVENTS 10
    #define EVENTTIMER_TxR 		TBR 	// Timer_B counter
    #define EVENTTIMER_CTL		TBCTL	// Timer_B control
    #define EVENTTIMER_MC0		MC0		// Mode control 0
    #define EVENTTIMER_MC1		MC1		// Mode control 1
    int AddTimerEvent(void (*function)(void), unsigned int millis, bool infinite);
    void initEventTimer(void);
    void startEventTimer(void);
    void stopEventTimer(void);
    bool getTimerRunning(void);
    unsigned long millis(void);
    void incMillis(void);
    void workEvents(void);
    unsigned int deleteEvent(void (*function)(void));
    #endif /* EVENTTIMER_H_ */


    #include "EventTimer.h"
    int getFreeArrayIndex(void);
    unsigned long milliseconds;					// 2^32 -> max. ~49 Days
    // struct that holds events
    struct timedEvent{
    	void (*function)(void);		// pointer to function to be executed
    	unsigned long nextTime;		// time when function will be executed next
    	bool infinite;				// will it be executed over and over?
    	unsigned int interval;		// time interval between executions
    }eventArray[MAXEVENTS];			// array of timedEvent-structs
    void initEventTimer(void)
    	milliseconds = 0;
    	for(int i=0; i<MAXEVENTS; i++)
    		eventArray[i].function = NULL;
    		eventArray[i].infinite = false;
    		eventArray[i].nextTime = 0;
    		eventArray[i].interval = 0;
    void incMillis(void)
    void startEventTimer(void)
    	// reset counter of timer
    	EVENTTIMER_TxR = 0;
    	// start timer in up mode
    void stopEventTimer(void)
    	// switch off timer to conserve power
    unsigned long millis(void)
    	return milliseconds;
    int getFreeArrayIndex(void)
    	for(int i=0; i < MAXEVENTS; i++)
    		if(eventArray[i].function == NULL)
    			return i;
    	// we didn't find a free spot
    	return -1;
    void workEvents(void)
    	for(int i=0; i < MAXEVENTS; i++)
    		if(eventArray[i].nextTime == millis())
    			if(eventArray[i].infinite == true)
    				eventArray[i].nextTime = millis() + eventArray[i].interval;
    				eventArray[i].function = NULL;
    				eventArray[i].nextTime = 0;
    unsigned int deleteEvent(void (*function)(void))
    	for(int i=0; i < MAXEVENTS; i++)
    		if(eventArray[i].function == function)
    			eventArray[i].function = NULL;
    			eventArray[i].nextTime = 0;
    			return 0;
    	return 1;
    int AddTimerEvent(void (*function)(void), unsigned int mils, bool infinite)
    	int arrayIndex = getFreeArrayIndex();
    	if(arrayIndex < 0)
    		return -1;
    	eventArray[arrayIndex].function = function;
    	eventArray[arrayIndex].interval = mils;
    	eventArray[arrayIndex].nextTime = millis() + mils;
    	eventArray[arrayIndex].infinite = infinite;
    	return 0;
    bool getTimerRunning(void)

    I configured Timer B in Grace like this:




    The corresponding ISR looks like this:

     *  ======== Timer_B3 Interrupt Service Routine ======== 
    #pragma vector=TIMERB0_VECTOR
    __interrupt void TIMERB0_ISR_HOOK(void)
        /* USER CODE START (section: TIMERB0_ISR_HOOK) */
        /* USER CODE END (section: TIMERB0_ISR_HOOK) */


    int main(void)
        Grace_init();                   // Activate Grace-generated configuration

    These 4 functions just toggle output pins like so:


    Don't know how embedding a Youtube video works, here's the link.





    PS: maybe worth moving this into the code vault?

  4. Hi there,


    I'm in the process of developing some wireless system. I want to have more than one transmitter - behaving just a little bit different from each other.

    Using Code Composer Studio I've discovered the ability to have different "build configurations". I made three different "main.c" files:






    In build config 1 the second and third are excluded from build. In build config 2 the first and third are excluded... I think you get it.


    Now my question:


    To configure the peripherals I used Grace. Now I have a new idea where I need to change some of that Grace configuration in transmitter1 but not in the others.


    Is there a possibility to make the Grace config dependent of the current build config?




  5. Hi there,


    I've got something in my mind and need your advice :)


    Let's imagine we've got 8 LED's and 8 buttons attached to MSP430. (actually, it doesn't matter how many LED's or buttons, or which port they're attached to)

    We want a solution where a press of button one causes the first LED to light up for 1 second. After that time it'll switch off automatically.

    For now that's nothing special. Now, let's say every LED lights up when the corresponding button has been pressed, but every one of these LEDs switches off

    after a different amount of time. Moreover this whole mechanism should be independent of when which button has been pressed. It should be somehow interrupt-driven

    and low power (using low power modes between the interrupts). OR: use the spare processing power inbetween status changes for something else.


    My first thoughts were:


    1. functions for each LED like "LED1_on();", "LED1_off();" etc.

    2. a timer function like "millis();" in Arduino IDE

    3. a array or struct that will hold a function pointer and the amount of time (millis) it should take until the function will be executed

    4. a function to allocate i.e. "LED1_off();" to this array with the desired amount of time

    5. timer-ISR checks every ms if there exists a function in the array that needs to be serviced and if so, executes it


    my program could look something like this:

    if(button1 pressed)
        AddTimerEvent(LED1_off, 500); // after 500ms it should "fire"
    // move on doing other stuff

    Adding this to a port ISR makes it completely independet of my main program code.



    What do you think about my approach? Any advice? Does it already exist and I missed it?






    PS: I have to admit I never used function pointers. I only read "The C programming language" (Kernighan & Richie) some days ago and thought this would be a good match.

  6. Hello @@igor,


    I had another night of trial and error ;)

    As you correctly pointed out, the first byte got discarded by BufferOut. That was my solution to overcome the problem caused by directly transmitting the first byte in buffered_send_SPI.


    I have corrected this behaviour and again, had the problem of first byte getting sent double. Then I discovered the UCBUSY bit in UCxSTAT. Instead of directly sending the first byte to get the peripheral running...

    	else if(in == send_toSPI_buffer.index_reading)
    		//IFG2 |= UCB0TXIFG;
    		UCB0TXBUF = ch;

    ... I fired an artificial interrupt to get things going:

    	if(!(UCA0STAT & UCBUSY))
    		// ...initiate an artificial interrupt to get things going
    		IFG2 |= UCB0TXIFG;

    This seemed to work well until I tested this ISR:

    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCI0RX_ISR_HOOK(void)
        /* USER CODE START (section: USCI0RX_ISR_HOOK) */
    	unsigned char receivedByte;
    		// UART RX Interrupt
    	    if (IFG2 & UCA0RXIFG) {
    	    	receivedByte = UCA0RXBUF;
    	        IFG2 &= ~UCA0RXIFG;

    Main thing in this example is: The through UART received char gets directly transmitted through that whole ringbuffer logic.


    The result looked like this:




    Sometimes it even looked more weird:




    This happens because UCBUSY is 1 while the peripheral is TXing OR RXing .... 


    This led me to add another variable to the RINGBUFFER struct to indicate if currently a transmission is running:

    typedef struct ringbuffer{
    	unsigned char ringbuffer[BUFFERLENGTH];
    	unsigned int index_reading; // indicates the field to be read next
    	unsigned int index_writing; // indicates field to be written to next
    	bool ringbuffer_running;    // indicates if output peripheral is allready running

    The corresponding part in buffered_send_SPI changed to this (here I think is the first time I clearly have to disable the interrupts):

    		// ...initiate an artificial interrupt to get things going
    		IFG2 |= UCB0TXIFG;
    		send_toSPI_buffer.ringbuffer_running = true;

    In BufferOut it now looks like this:

    	if(buffer->index_reading == buffer->index_writing)
    		buffer->ringbuffer_running = false;
    		// buffer is empty, nothing to read
    		return 1;

    Now I get the intended behaviour:




    Now the ringbuffer logic is working with a interrupt triggered peripheral and also "standalone" in code.


    As you mentioned I've also added a few accompanying functions:

    unsigned char CountFreeBytesInBuffer(RINGBUFFER *buffer);
    bool IsBufferEmpty(RINGBUFFER *buffer);
    int printstrBuffer(unsigned char *str, RINGBUFFER *buffer);
    int ReadBuffer(unsigned char *dest, RINGBUFFER *buffer);

    I'm getting towards a more portable solution ... as I intended in first place :)


    Comments and suggestions welcome :)





    PS: I've attached source files








  7. Hello @@igor,


    up until now I only used it to send data over a peripheral like SPI or UART. In this case only the ISR triggers BufferOut(). If the buffer is empty no new value gets written in the output buffer register of the peripheral. Thereby no ISR will fire anymore and the two indices will remain the same. Thats the reason why BufferIn() checks if the two indices were the same and if so, writes the current char directly to the register of the peripheral. If only one char has been sent to the buffer the ISR again will do nothing except increasing the reading index the thereby leading to same indices. 


    If on the other hand the buffer is full, BufferIn() will discard the char. At this point actually on char of the buffer gets wasted if I'm not mistaken :)


    Thanks for the wiki link, I've read it in the beginning, but maybe it's worth a reread with my in the meantime gained knowledge :)



  8. I read that wikipedia article - I just can't make the transition to my actual case :)


    I'm now adding my current code (please excuse the german comments).


    First I have a layer that abstracts the ringbuffer logic:


    #ifndef RINGBUFFER_H_#define RINGBUFFER_H_#define BUFFERLENGTH 64 // Must be 2^n#define BUFFER_MASK (BUFFERLENGTH-1) // Klammern auf keinen Fall vergessentypedef struct ringbuffer{	unsigned char ringbuffer[BUFFERLENGTH];	unsigned int index_reading; // zeigt auf das Feld das zuletzt gelesen wurde	unsigned int index_writing; // zeigt auf das Feld in welches das n
  9. Hello,


    the last two days I've implemented a portable ringbuffer for use with UART, SPI or even different microcontrollers (minor changes required). 

    I grabbed some ideas from here and there and mixed it all together in my own solution. 

    I tested the functionality with some code that writes in unregular time distances into the buffer while the SPI TX interrupt is reading from it.

    It _seems_ to work well, but a friend of mine told me I definately have to deactivate the interrupt in "critical sections" of my code.

    Now I'm a little bit stuck. How do I identify what a critical section is? I don't want you guys to review my code. I just wanted to ask if there's a general approach on identifying such possible problems. My friend also said I should draw a timing diagram on what's going on, but again, I have no idea how you do that.

    Any advice?


    Best regards,


  10. Wow thanks for the quick answer oPossum :)


    I think I've misunderstood the purpose of UCxSTE.

    On the eZ430-RF2500T target board UCB0STE (Port 3.0) is connected to CSn of the CC2500.

    Therefore I thought UCxSTE is some kind of auto hardware controlled chip select that's being driven low when transmitting.


    Ok, if got it right, I have to use 3-pin mode and use P3.0 as a normal output that I manually drive low during communication with the attached cc2500, right?



  11. Hello,


    after years of abstinence I'm back to playing with TI hardware. 

    I'm using the eZ430-RF2500 Development Tool with CCS and Grace.

    While implementing a ringbuffer for SPI I ran into an unexpected behaviour. (using USCI_B )


    By writing a byte to UCB0TXBUF the UCB0TXIFG Interrupt should fire, right?


    Ok, I made a minimal example with Grace, only clocks and the SPI interface configured.

    I placed a _NOP(); in the ISR and a breakpoint on it.


    In main I add the line 

    UCB0TXBUF = 'a';

    When the SPI interface is configured as 3-Pin it does halt at the breakpoint.

    If I configure it as 4-Pin it never reaches the ISR.


    Can someone explain that behaviour?





    PS: I've attached my testproject


  12. Up until now I didn't put anything in sleep. I did the measurement with the original supplied firmware on the MSP430G2553 that came with the anaren booster pack. Since I didn't have any success in getting the supplied code from anaren to work, I even don't know what they are doing in their firmware. That's why I asked in my initial post: "Did Anaren really miss the low power (sleep) modes of the components?"


    This weekend I'll be trying to understand the code CorB attached. If it meets my requirements, I'll stick to it. If not, my next step will be simpliciTI.


    @larsie: To make things clear, I didn't do the measurement with your code.

    I think I'll buy anaren modules with U-FL connector for the final "product". What I'm not shure about is the antenna. Which antenna do you mean with "thread antenna"?

  13. thanks for the code, CorB


    I'm still trying to understand it. I'll ask my questions when I'm able to :)

    But, this code isn't simpliciTI, am right? As far as I can tell, it's based on mobilars' code. That code is again, based on the TI library "MSP430 Interface to CC1100/2500 Code Library" (slaa325a). And (you guessed it) that one is based on the old "Application Note N049" from chipcon.

    In that list I don't see simpliciTI mentioned.


    Maybe I'm completely wrong (still didn't have the time to read the simpliciTI docs).

  14. Dear forum members,


    As a X-Mas gift for my dad, I want to build a wireless thermometer with four transmitters. He allready has something cheap, but it doesn't work so well over the ~30m distance from the garden to the living room. Therefore I want to build something accurate, long distance, "endless battery life" (the transmitter will end in some rubber enclosure, so it can withstand the weather - therefore, ideally it shouldn't be nescessary to change batteries for the next 10 years or so) and rssi readout to determine if the wireless connection is good.

    Ok, that's my goal.


    This weekend I've started to evaluate some of the wireless modules I have at hand. Since I'm a big victim of tideals, I have the eZ430-RF2500-SEH solar energy harvesting kit with three eZ430-RF2500 modules. On the other hand, I have two Anaren AIR booster packs.

    On the first try, with the stock firmware of these kits, I got way better range out of the anaren modules. These modules are quite cheap, so that's ok. But, as I want to have a very long battery life, power consumption must be checked.


    First, I want to discuss the eZ430-RF2500T module:


    Please have a look at page 13 in http://www.ti.com/lit/an/slaa378d/slaa378d.pdf

    I did the same measurement with my DS1052E and a 30 Ohm resistor (didn't have anything else at hand).

    My measurement looks like this:


    On the right side there's more, until the transmission ends:



    I calculate the current like follows:

    measured voltage on the scope divided by 30 (Ohms of my resistor)


    The capacity is beeing calculated by:

    current times measured time


    My measurement is as follows:

    1. 1,6ms , 20mV -> 0,67mA --> 1,072


  15. I'm relatively new to tinkering with electronics. Soon I felt like I would need an oscilloscope. I'm also still a student and thus, money is always a problem. My parents got me the above mentioned DS1052E from Rigol as a birthday gift (man I'm lucky). Not much time went by until I was sure I would also need a logic analyser. Of course I bought that very good Saleae Logic. Now (after 3 months) I can say that I should've bought the Logic first. I can check almost everything I need with the Logic. I really recommend you to buy the Logic first. Then, please do yourself that favour, save your money for a real o'scope like the DS1052E or better. Don't waste any more time on even thinking about something like the DPScope.

    I hope this helps :)

  16. I think they should go with female headers and include the aforementioned male-male headers. So you have female headers at both ends (launchpad and boosterpacks) and the male headers that get sometimes damaged (I often bend pins accidentially when removing shield/booster packs) are easily replaceable. Also there are no problems with shorts. And you're still compatible to all kinds of boosterpacks regardless of male or female headers.

    I allready do it like that on my launchpad :)

  17. Hi there,


    today I received my booster pack. I'm a little bit confused on how the booster pack has to be inserted into the launchpad. Directly on the launchpad it says "this side up" written on the arrow. But, with that side up it can't be put into the launchpad.

    Is it correct that the anaren rf module has to face down when the booster pack is inserted into the launchpad?







    aaawww I see ... after watching this video: http://www.anaren.com/content/Media/Boo ... Anaren.wmv

    I've got the wrong headers in my launchpad :D Glad I investigated deeper than just trying it out and probably would have killed something :)

  • Create New...