Jump to content
43oh

Bounty: $20,- to solve a simple project (OPEN )


Recommended Posts

All, ( Closed )

 

I was offering a $50,- to some one who could fix the provided code. Below is the original message. 

 

I explain in message #11 what I did to make it happen.

 

----

 

Note: modified source code Jan 19 2012

 

I have spent over two months now trying to get a simple I2C communication going and to display the string send from the master to the slave. I HAVE FAILED.

 

Here is a chance to easily earn $50,- ( That is good for 12 Launch Pads .. )

 

What do I want:

1) I want to learn from this, that is why I would like you to get my current code to work

2) I should be able to push the button on the master and repeatedly send data over the wire and display it on my LCD device

3) We should be able to assume my code for the LCD works and it uses Bit0-Bit5 of the slave

4) It should work on two msp430g2231 devices

5) I should be able to compile it using mspgcc on my Linux box

 

What does my current code do:

It establishes communication between master and slave and displays the text sent over the wire.

 

What does the code not do:

I can't re-send data once the initial string is sent.

 

Where is the source code:

http://www.movingsatellites.com/i2c.tar.gz

 

I offer two payment options

1) PayPal to you

2) PayPal donation in your name to a charitable organization ( Such as E.g. www.Hart90.com - pick your pet to sponsor )

 

Another hint: Here is the output of i2c_explorer.

 

i2c> [ 0x04 0xAA 0x02 0x43 0x43 ]

i2c START
WRITE: 0x04 Ack -> Slave Address
WRITE: 0xAA Ack -> Marker ( my protocol )
WRITE: 0x02 Ack -> ( Size of text to send )
WRITE: 0x43 Ack -> First Letter
WRITE: 0x43 Ack -> second letter
i2c STOP
 
i2c> [ 0x04 0xaa 0x02 0x44 0x44 ]
i2c START
WRITE: 0x04 Nack!
WRITE: 0xAA Nack!
WRITE: 0x02 Nack!
WRITE: 0x44 Nack!
WRITE: 0x44 Nack!
i2c STOP
 
Link to post
Share on other sites

I will surely post the results here, if I get them. I may do a writeup.

 

here is the link to the short video how it currently looks with the code from the above link.

 

As you can see the red LED1 turns off after the initial send, then pressing the button it turns on for a short period, as expected before the program gets into the I2CMaster_Transmit function and then starts to flicker ( line 185 in m_i2c.c )

 

... m_master.c ...

 

 

 while ( 1 )  {
    P1OUT &= ~LED1;
    // Send out some information to the slave
    I2CMaster_Transmit ( array1, 16 );
    P1OUT |=  LED1;
    for ( t=0; t<50; t++ )
      pause ( 10000 );
    P1OUT &= ~LED1;

    LPM0;  // Wait for button push
    P1OUT |=  LED1;
    for ( t=0; t<50; t++ )
      pause ( 10000 );

    I2CMaster_Transmit ( array2, 16 );
    P1OUT &= ~LED1;

    LPM0;  // wait for button push
  }
Link to post
Share on other sites

Divide and conquer is the method you should use to find this problem(s).

 

What does your schematic look like?

Did you assemble it that way?

Do you have any solder or board shorts?

How good is your power supply?

Have you measured it with a DVM or 'Oscope?

Does it have enough current to drive your LCD?

 

What dev environment are you using?

Can you inspect the CPU registers?

Can you single step the program?

Can you inspect them with break points?

 

Do you have a logic analyzer?

What does the I2C port do when you try to run this?

What is it supposed to do?

What do the wave forms look like?

Do they look like the wave forms in the data sheets?

 

Have you proven to yourself that you have a working CPU?

Have you unknowingly zapped your CPU or circuit with ESD?

Do you have a second board that you know works?

Can you use it as a reference standard?

Can you measure it and compare signals to your un-working board?

 

Can you go grab the TI sample code for your CPU and attempt to use the I2C Master and Slave routines that are in the archive?

See if you can pass one byte back and forth with their code.

If you can then you have working hardware and flawed software.

Compare your configurations, pin assignments, interrupt vectors, variable type assignments and widths.

Single step through their code to see the flow then single step through yours to see it fly off the rails.

If not then you probably don't have working hardware.

 

In my opinion, the sample I2C Master/Slave code from TI is your friend right now. It's either that or the board member who created the Henry the Robot project. He must be an I2C Guru by now.

Link to post
Share on other sites

(First off, I'm not fishing for the bounty as I don't have a 2231)

 

The send stop condition within the master i2c looks very much like the 'restart' posted elsewhere on this forum.  It seems like you are trying a:

 

start -> write -> incomplete/partial stop -> restart. ( not start -> write -> stop )

 

It looks like you commented out the actual stop code but this is likely leaving your state as started from the restart.  You should remove any restart code as it isn't necessary within the scope of this project.  You are leaving your I2C in a start as you leave and prepare for the next when you want to have stopped.

 

I highly recommend printing/dumping your i2c state variable to see where things are finally stopping.  What you are hoping to do on the master side can be achieved entirely with a start, write and stop command.  Have faith in that and lift some existing code that is known to do that.

 

(I would recommend removing the state machine altogether and have this project as a simple non-interrupt synchronous loop.  As a simple project it would be soooo much simpler, then build it up from there).  Some of the functions you have copied are blocking synchronous style where the majority and framework is interrupt based.  Some of the flags being blocked upon might be read or set by the interrupt handler.

 

So what do I recommend:

 

throw away the master  i2c code

use cde's i2c code from the latest i2c explorer

write your  I2CMaster_Transmit ( ) in terms of blocking start-write-write...write,stop with maybe some modest delays in-between.  I'm pretty sure that can be done with either no or minimal interrupts

 

(For the master side I see no reason why the i2c_explorer itself wouldn't be the quickest way to test)

 

then when that is working get fancy :smile:

Link to post
Share on other sites

As I like the post by grodius, I am reminded of an embedded course I recently watched on yourtube. Where the instructor was telling the class he had two students in his previous semester that consistently took about 2-3 times less time finishing projects than the others. The key the instructor noted, was coding in small steps, test, and move on.

 

*That* can be taken as a hybrid form of TDD ( test driven development ), and is how I personally write code myself. I'll write a function, compile and test it, then move on to the next step / problem. Once you finish a function / method, you *know* it is working, and do not have to worry about it any more. At least, until it comes time to refactor.

Link to post
Share on other sites

Will look into re-using the master code to get one side working first.

 

I tried to compile i2c_explorer but for a 2231 device I run out of rom.

 

I am busy this week but I definitively will try to get things working a small step at a time. The problem I have dealt with were on multiple fronts TDD is what I have spent the most part of my time trying to get things to work. Unfortunately once I drilled down on one side. another side which used to work stopped working. I believe I stumbled over some compiler issues when code optimization is turned on. I tried using CCS under Linux, and a whole lot of other things.

 

Thanks for all of your feedback and help.

Link to post
Share on other sites

So I spent the past 7h trying to figure out what is going on.

 

I used i2c_explorer and I think the problem is the mix of USI interrupt handler and LPM0.

 

All works except when I try to exit the interrupt routine and continue with my main program ( LPM0_EXIT; ) 

The USI interrupt routing is called from there on constantly.

 

If I don't exit LPM0, I can repeatedly send commands to the slave.

 

The question is, How can I gracefully exit LPM0 and reset the msp430g2231 such that the USI interrupt is no longer called ?

 

Here is the pseudo code

 

main ( )
{
  // First run
  initUSI ( );
  LPM0;
  _NOP ( );


  // Second run 
  initUSI ( );
  LPM0;
  _NOP ( );
}


void initUSI ( ){
  P1OUT  = BIT7 + BIT6;
// Not needed if using external pull-up resistors
  P1DIR |= SCL | SDA;
  P1REN |= SCL | SDA;
  P2OUT  = 0;
  P2DIR  = 0xFF;


  // enable SDA, SCL, hold in reset
  USICTL0 = USIPE6 | USIPE7 | USISWRST;
  // enable  I2C Mode, counter interrupt, Start interrupt
  USICTL1 = USII2C | USIIE | USISTTIE;
  USICKCTL =  USICKPL;
  USICNT  |=  USIIFGCC; // Disable automatic clear control
  USICTL0 &= ~USISWRST;
  USICTL1 &= ~USIIFG;


//#define SET_SDA_AS_OUTPUT USICTL0 |=  USIOE;
  SET_SDA_AS_INPUT
  _EINT ( );
}

void stopUSI ( )
{
  USICTL0 |= USISWRST;  USICTL0 &= ~( USIPE7 | USIPE6 | USIOE );
  // disable  I2C Mode, counter interrupt, Start interrupt, Stop interrupt  
  USICTL1 &= ~( USII2C | USIIE | USISTTIE );
  USICTL0 &= ~USISWRST;
}

#pragma vector = USI_VECTOR
__interrupt void intI2CStateEngine (void)
{
  ... state engine ...
 case ( iState )  {

 

  ...
    stopUSI ( );
    LPM0_EXIT;
   } // end case      
}

 

 
Link to post
Share on other sites

After a long back and forth I finally gave up on my original software design, which was:

 

main()

{

  initUSI();        // state engine in callback

  while ( 1 )  {

    enterLPM0();  // After all bytes are received in USI callback this will be released

    resetStateEngine ();

    display ( string );

  }

}

 

I am now handling the display of the text from within the USI callback ( state engine ). This works quite nicely, however I was stumped to have to change the SW in this way, as it will not allow me to build more complex designs.

 

I was also surprised to see so much code out there in the open with had all the same issue. I have tried 14 different designs in all and I experimented with hundreds of variations ( I don't give up easily, and I was at it for two months ).

 

The good part is that I got the i2c_explorer to work on the msp430g2231, which helped me a lot getting this to work. As for the Master I went with the bitbang code ( state engine not handled in USI callback) from

http://processors.wiki.ti.com/index.php/I2C_Communication_with_USI_Module

 

UPDATE: See Comment#14

Link to post
Share on other sites

Varol, for what its worth, I have been reading about, and experimenting with the hardware ( Launchpad v1.5 ), for the last 8 months. Off and on, since sometimes my time is limited. So yeah, here lately in the last couple days I have been getting serious, and have been able to make much greater headway.

 

So what I am saying here. Is that you're not alone. Also, for what it is worth, I have been writing software for PC's in one language or another since the early 90's As a serious hobby.

Link to post
Share on other sites

Thanks,

 

I tried this and it works. This was the single line change I have been hunting for about two weeks. It exits LPM0 mode and stops the USI callback from being called relentlessly.

Now I have two working i2c slave versions.

 

I know that there is a lot of i2c code out there where they commented out the line LPM0_EXIT; in the i2c slave code and they handle this differently.

What I am asking here is how can this be improved ?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...