• AVR Freaks

Hot!Help using MCC generated I2C functions

Page: 12 > Showing page 1 of 2
Author
jgreenmt
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2020/10/19 12:11:40
  • Location: 0
  • Status: offline
2020/10/19 15:41:22 (permalink)
0

Help using MCC generated I2C functions

Hello all,
 
I have been programming with 8-bit PICs for a little over three years now. I only recently started using the MCC to set up peripherals and I have run into an issue using the I2C functions generated. I will try to provide a good summary of what I am trying to do and the problems I have run into. This is my first post on the forum so I'm sure I will forget to leave out certain information that will be helpful for troubleshooting so please bear with me.
 
I am using a PIC16f1705 to communicate to an AM2315 Humidity/Temp sensor from Adafruit. I wrote an application a couple of years ago that uses a self-made driver for the I2C peripheral that works well. The problem is that the driver employs the "polling" method and thus blocks further execution if the sensor doesn't respond or is disconnected. Also over time I have realized that my driver is pretty outdated and amateur. I would like to be able to use the MCC generated functions. While I understand there are pros and cons for using MCC, the purpose of this post is to use MCC to communicate to the sensor.
 
According to the datasheet and an example program written for an Arduino, I was able to determine the commands to successfully retrieve the Humidity and Temp values from the sensor. This is a rough step-by-step:
 
//Wake up the sensor
Open transmission
wait 2ms
Close transmission
 
//Ask for sensor values
Open transmission
i2c write 0x03 //read register
i2c write 0x00 //starting address to read from
i2c write 0x04 //request 4 registers (8 bytes)
Close transmission
 
wait 10ms
 
//Receive sensor values
Open transmission
i2c read 8 bytes starting at register 0x00
Close transmission
 
I have tried several different methods using the functions generated by the MCC, but I will post the one I believe is closest. I believe this also uses a blocking method due to the while loops, but I'm not for sure.
 
My MCC settings for the MSSP are:
Interrupt Driven: checked
I2C Master
100,000 Hz I2C clock
SM Bus Input Enable: not checked
Slew Rate: Standard speed
SDA Hold Time: 100ns
Enable I2C Interrupt: checked
 

//initialize SendData values
SendData[0] = 0x03;
SendData[1] = 0x00;
SendData[2] = 0x04;
 
while(1) {
 
//Wake sensor
    while(!I2C_Open(0x5C));
    __delay_ms(2);
    while(I2C_BUSY == I2C_Close());
 
//Ask for data
    I2C_WriteNBytes(0x5C, SendData, 3);
    __delay_ms(10);
//Retrieve data
    I2C_ReadNBytes(0x5C, RecData, 0x08);
 
    __delay_ms(2000);
}

 
I made sure to un-comment the global and peripheral interrupt lines in the main.c file. I don't want to let the initial post get too long, but I realize more code might be helpful so please let me know what you would like to see. If it will be helpful I can also include my old drivers. Or I can post my entire main.c file.
 
Thank you in advance for your time and help, and I look forward to learning.
#1

22 Replies Related Threads

    ric
    Super Member
    • Total Posts : 28941
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/19 16:01:11 (permalink)
    0
    Good luck with MCC :)
    If you would like to revisit your own code, I suspect you never implemented ACK/NAK checking.
    With that done correctly, you would know immediately if the sensor was not connected.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    Mysil
    Super Member
    • Total Posts : 3946
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Help using MCC generated I2C functions 2020/10/19 16:41:38 (permalink)
    4 (3)
    Hi,
    There was a larger Rewrite started for I2C code in MCC about a year ago. 
    I do not know if there is any significant change in the latest MCC release v4.0.2.
     
    The current I2C code generated by MCC is based on earlier Foundation Services and Click board library examples.
    Driver code for I2C is based around a table of 6 Callback functions,
    that will be called when something happen,
    e.g. when a transfer is completed, or when a NACK response is observed.
    This may have been a good idea for the MCC developers,
    but require careful documentation of how it is intended to work, and good examples of how it should be used.
    Otherwise, it only push responsibility for how to handle tricky cases back to Application developers.
     
    There is little explaination in code or documentation, but there are a number of examples among Click Board library. 
     
    Even if it is not default in the driver code, all examples I have seen,
    set up  to retry without limitation when NACK response occur, in case a device is disconnected or not responding.
    This make program hang, with no possibility for application code to regain control. 
     
    The driver code is written with the aim, that the same code may be used both in polling loop,
    or in Interrupt mode.
    Whether this is a good idea, or make the simple cases complicated, may be a matter of opinion.
    However, all examples I have seen, are based on polling mode.
     
    There are some explaination and examples in this thread:
    https://www.microchip.com/forums/FindPost/1117381
     
        Mysil
     
     
    post edited by Mysil - 2020/10/19 17:23:02
    #3
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/20 10:25:05 (permalink)
    0
    Mysil,
     
    Thank you for your response. I have looked at the thread you linked but it has led me down a path of more questions.
     I would also like to add that I am using MCC version 4.0.2. To my knowledge there haven't been any substantial changes to the i2c libraries.
    1. Is there a downside to using interrupt over polling? If so, what are some situations in which the interrupt method would be preferred?
    2. I know you touched on this. Do I need to add the ack/nak checking regardless of interrupt vs polling method, or is it already present? If it is present in both methods, do I need to change what the nak condition response does?
    3. I am under the impression that I am using the interrupt method because I selected it in the MCC gui. I have not altered the code in any way. I am using functions created in the i2c_master_example library. Is this correct implementation of the interrupt method?
    4. Perhaps this is due to the use of interrupts, but the "wake_sensor" section of my code will run and not block any subsequent code whether the sensor is connected or not. However the writing and reading to the sensor, blocks the code regardless of whether the sensor is connected or not. What would be the simplest way to use the functions provided to communicate with the sensor properly? Could you lay them out in a step by step type procedure?
    My immediate goal is to be able to use the MCC libraries/functions to communicate to the sensor, but my ultimate goal is to learn about the libraries. I'm afraid I will have to learn in small steps, but if I can learn and make adjustments to the libraries to make them more usable, that would be great.
     
    I appreciate your patience and time.
    #4
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/20 10:38:25 (permalink)
    0
    Ric,
     
    Thank you for your response as well. At a later date I'm sure I would be interested in re-visiting my own code :)
    #5
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/20 15:30:38 (permalink)
    0
    I made a couple of discoveries today. I was manipulating the wrong MCC config file for the last couple of iterations I tested yesterday. When using the "interrupt enabled" method of I2C nothing in my code executes. I have not determined where the hang up is yet. However using polled mode, I was able to do some testing.
     
    I used the I2C spy function of a Digilent Analog Discovery 2 device to see what the pins are doing.
     
    The following is from using the MCC "polled" method. This makes use of the WriteNBytes, and ReadNBytes functions.

    Start, hB8 [ h5C | WR ] NAK, Stop
    Start, hB9 [ h5C | RD ], h00, h00, h00, h00, h00, h00, h00, h00 NAK, Stop

     
    The following is from using my own code that retrieves information from the sensor correctly.

    Start, hB8 [ h5C | WR ], h03 NAK, h00 NAK, h04 NAK, Stop
    Start, hB8 [ h5C | WR ], h00,
    Restart, hB9 [ h5C | RD ], h03, h04, h01, h72, h00, hE5, h91, h84, Error!!! Stop

     
    This is confusing to me because the MCC version doesn't appear to send any data after the write. I'm not sure if this is because it immediately receives a NAK or not. It is also interesting that when using my own code, which retrieves the data correctly, there are still several NAKs and even an "Error!!!".
     
    My new questions are:
    1. Why isn't the MCC code sending the correct data? / Why is it getting an immediate NAK?
    2. If I am receiving data properly using my own code, why is there still NAKs and an error present?
    The Analog Discovery 2 also has a logic analyzer but I couldn't get my settings quite right to view the transmissions properly. I will try to adjust accordingly so I can post screenshots.
    #6
    Mysil
    Super Member
    • Total Posts : 3946
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Help using MCC generated I2C functions 2020/10/20 15:37:39 (permalink)
    5 (2)
    Hi,
    I am not surprised that you have questions.
    In my opinion, there are errors and loose ends in the current I2C code generated by MCC.
     
    In my opinion, there are several different ways of making software:
    Blocking: When something is started, software will wait inside function,  until the task is completed.
    Polled:    Start something, and then come back later to check if operation is complete.
                 Thus  work may be split up into many small steps,
                 one increment of work will be done each time the function is called,
                if previous steps have been completed.
    Interrupt:  Start something, and return to the calling program without waiting for work to be done.
                 Interrupt handling will proceed thru sequence of task,
                 and proceed with next step whenever previous step is completed.
                 There may be a way to ask if task is completed, and if it was successfull.
    Operating system:
                 Make program as with Blocking code,
                 but be prepared that work may be suspended at random times, to perform other tasks.
     
    These may be combined in various ways.
    There will be a need to know if task have been completed, and if it was successfull.
    Polling may be used to check if Interrupt code tasks have been completed.
    If not successfull, what was the reason?
     
    Both interrupt driven, and polled code will need more logic and checking than blocking code,
    to keep track of progress, and handle eventual disturbances.
     
    Interrupt may be best when there are  time-critical tasks that need to be done at unpredictable times. 
    Example is Receiving characters from asynchronous serial port.
     
    When there is a long sequence of actions stretching out with waiting time inbetween,
    both Interrupt driven code, and polling code may work.
    If there is a lot of work to be done in main program, then polling may cause too much delay between steps.
    With interrupts, the next step is started when the previous was complete.
     
    Do you have code that somewhat show what you are trying to do,
    and how you are trying to do it?
    I may be able to help sort out what are mistakes in code generated by MCC, and what changes may be needed in application code.
    I will need a complete program that can be compiled and debugged:
    All files generated by MCC, all your code and header files, and MPLAB X project.
     
    In MPLAB X there is a 'Package' facility, to collect all files needed to restore a project.
    In 'Projects' panel, upper left part of window, point to root of project tree,
    Right-Click for a pop-up menu, and select 'Package'.
    The resulting .zip file may be attached to a Forum message, use 'Open Full Version'.
     
        Mysil
     
    post edited by Mysil - 2020/10/20 15:52:11
    #7
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/21 11:57:03 (permalink)
    0
    I have attached a simplified version of my project. The basic premise is reading data from a sensor over I2C, then sending it to a serial terminal over EUSART. I believe this is a good starting point to keep things from getting messy.
     
    Thank you for looking this over and I look forward to reviewing your changes.
    #8
    Mysil
    Super Member
    • Total Posts : 3946
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Help using MCC generated I2C functions 2020/10/21 22:54:32 (permalink)
    0
    Hi,
    Here are some preliminary comments based on previous messages, before studying the problem code in message #8.
     
    Sequence in message #1 will not serve to activate the sensor:
    //Wake sensor
        while(!I2C_Open(0x5C));
        __delay_ms(2);
        while(I2C_BUSY == I2C_Close());

    As this will Not do any signaling on the bus, it will not even check whether bus signal lines are free or busy.
    It will only initialze internal datastructures and the MSSP peripheral,
    and close everything down again.
     
    Capture in message #6 show that sensor is Not awake, and is not responding to the first transfer.
    NAK from slave when master is sending address, indicate that slave is not awake, 
    busy with internal operations, not connected, or that the address is wrong.
    When this happen, there is no point to continue trying to send data.
    There must be Stop, new Start and Address, or possibly a Restart signal and Address, 
    before slave will be able to receive data.
    So MCC code actually behave correctly in terminating the transfer and sending Stop signal.
    There is however bug in MCC code that problem is not reported to application code.
    while(I2C_BUSY == I2C_Close()); // sit here until finished.

    Never return a status of I2C_FAIL,
    and function:   void I2C_WriteNBytes(...);   have no way of reporting a problem.
     
    Capture in message #6 also reveal that there are mistakes in your existing code,
    When NAK is returned from slave, there is no point in sending data.
    So setup data for the sensor is likely ignored.
    The following transfer is accepted by the slave, and is returning data when reading.
    There is a Error message from the communication analyzer,
    be aware that when reading data from a slave,
    there shall be NAK signal from master to slave in the Last byte transferred, before Stop signal.
     
    Regardless of whether MCC driver for I2C is configured for Interrupt or Polled operation,
    while(I2C_BUSY == I2C_Close()); 

    will make the whole transfer into a blocking operation.
     
        Mysil
    #9
    Mysil
    Super Member
    • Total Posts : 3946
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Help using MCC generated I2C functions 2020/10/22 06:39:16 (permalink)
    0
    Hi,
    You may try to change the wakeup sequence like this:
     
            // Wake sensor by finding it on bus
    //        while(!I2C_Open(am2315));
    //        __delay_ms(2);
    //        while(I2C_BUSY == I2C_Close());

            // Make a dummy write to Wake the sensor
            I2C_WriteNBytes(am2315, SendData, 1);
            __delay_ms(2);

            // Write commands to initiate sensor read
            I2C_WriteNBytes(am2315, SendData, 3);
            
            // Wait for sensor read to finish
            __delay_ms(10);
            
            // Retrieve sensor data
            I2C_ReadNBytes(am2315, RecData, 0x08);
       ...

    There is a bug in MCC code, such that a message with 0 data bytes will make the code hang,
    thus 1 bytes in the first message.
     
        Mysil
    #10
    BroadwellConsultingInc
    Super Member
    • Total Posts : 66
    • Reward points : 0
    • Joined: 2020/06/09 06:07:55
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/22 08:19:02 (permalink)
    4 (1)
    As a general comment, if you aren't using one already pick up one of the really cheap USB logic analyzers off of Amazon.  It will do you a world of good seeing what your I2C bus is doing using the Sigrok Pulseview software.  If you've got more dough to spend the Saleae Logic system is really top notch for low-ish voltage mixed dc signals.  It will decode your packets and mark Nack / Acks.  You can see the tool at work about 14 minutes into the video below.
     
    I just did a project a couple of days ago using a PIC16F15214 to act as a bridge from UART to I2C (master).  All of the low-level interrupt driven I2C code and state machine came straight out of MCC.  
    Project video:  https://youtu.be/dhzYJGVzSiU
     
    I'm going to post the code to Github soon after I figure out a strategy for making my custom stuff releasable using MIT license without stepping on the Microchip copyright claims on the MCC generated code.
    #11
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/22 16:08:20 (permalink)
    0
    This is going to be a long post as I have many questions and the troubleshooting is starting to fracture off into different sections. I will try to keep them compartmentalized as best as I can.
     
    I would first like to address the assessment of the capture in post #6. This will pertain to the MCC code.
    • The "wake sensor" routine will not work:
      • While I am not disagreeing, I'm confused why my own code has a similar "wake up" routine but I receive data from the sensor?
      • I used a github library for Arduino to model/port my own code. In their library the "wake up" routine consists of "begin transmission, wait 2ms, end transmission". I assumed performing an I2C_Open and I2C_Close corresponded to the begin and end transmission routines in the Arduino library.
      • Here is a link to the github: https://github.com/adafruit/Adafruit_AM2315/blob/master/Adafruit_AM2315.cpp
     
    • Re-writing the "wake" routine:
      • I tried the code you posted and I got a different result. I will post my new results in a later section. I have a troubling update that is related.
      • Since you state in the initial read the NAK shows that the sensor is not awake, would sending a "dummy" read, not just return a NAK as well? Would this wake the sensor for the next read even if a NAK is observed?
     
    This section is a continuation of the capture in post #6, but this pertains to my own code that correctly receives data from the sensor.
    • There are mistakes in my existing code:
      • If I understand you correctly, in the first transfer of 0x00, 0x03, 0x04 each of these bytes are followed by a NAK in the capture in post #6. But then the following transfer is accepted and that's why the sensor is still sending data? If this is what you are saying, it does not make sense to me because if the first transfer was not accepted, how would the sensor know what information to send back?
      • To state it differently, to be able to receive the correct data from the sensor, the sensor has to be sent the correct commands. So if the commands are received by the sensor correctly, why does a NAK follow each byte?
    • Error message from the communication analyzer:
      • What causes there to be an error from the communication analyzer? Before I connected the communication analyzer I assumed everything was fine with the communication because I was receiving the correct information from the sensor. Is the error something to be concerned about, despite proper values being received from the sensor?
     
    This section deals with the blocking loop.
    • Since the "while(I2C_BUSY == I2C_Close());" creates an automatic blocking loop, how would you recommend changing this in the i2c_master.c file?
    • Once I implement the change above, what would be the best practice to check the status of the I2C for failures or problems?
     
    This section expounds on the troubling update I mentioned earlier.
    • I changed my wake up routine to the one suggested in post #10
      • When I made this change and ran the code, my communication analyzer returned the following:

    Error!!!
    Error!!!
    Start,

      • Then if I keep the communication analyzer running but I turn power to the PIC off, I receive a massive jumble of text. I will post a snippet as it appears to repeat.

    Error!!!
    Error!!!
    Error!!!
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, Stop
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Error!!!
    Start, h00 [ h00 | WR ], h00, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], Error!!! Stop
    Start, Stop
    Error!!!
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], h00, Error!!! Stop
    Error!!!
    Error!!!
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ], Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Start, Stop
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start, Stop
    Error!!!
    Start, Stop
    Error!!!
    Start, Error!!! Stop
    Start, Stop
    Start, Error!!! Stop

      • While power to the PIC is on, only the first section posted shows up on the analyzer. It is odd that once power is removed from the PIC the rest of the transmission attempts seem to come through. While I understand that something is blocking the transmissions, why do they come through once power is turned off?
      • This makes me doubt my feedback from the logic analyzer. But the analyzer still reads correctly when I deploy my custom code that works correctly.
    • To further investigate this issue I returned my wake up routine to the same I attached in post #8.
      • When I ran this code I no longer saw the response I got in post #6, but instead it was almost identical to the long stream above.
      • Another check I performed out of desperation was I commented out my entire while loop minus the 2000ms delay. To my surprise I saw a very similar stream to the above. I can't think of anywhere else in my code that should send data across the I2C bus. Perhaps I'm reading too much into this, and it is a product of the logic analyzer. However, It makes it difficult to troubleshoot my code if I'm not getting realistic feedback, so any explanation as to why this is happening will help.
    Kudos to anyone who made it this far. I hope dividing the post into sections helped to make it easier to digest and respond to.
    #12
    Mysil
    Super Member
    • Total Posts : 3946
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Help using MCC generated I2C functions 2020/10/22 17:00:47 (permalink)
    0
    Hi,
    The code generated by MCC work differently,
    from what is used in Arduino library.
    I believe the Arduino library you have used as pattern,
    send Start signal and  device Address in the  "begin transmission" function.
     
    AOSONG  datasheet for the AM2315 Humidity/Temp sensor,
    have some rather peculiar requirements for the "Wakeup" signal.
    It should be possible to perform that sequence using a tailored AddressNack() callback function with the i2c_master.c  driver.
     
    I do not have the same sensor and PIC here, so I have to emulate some of the response in other ways.
    I will test it here as far as possible, before sending any more code.
     
    I have no possibility to know the reason for your instrumentation problem,
    are you able to get pictures of the waveforms at all?
     
    Edit, about how NACK/ACK signals should be exchanged,
    see I2C Specification and User Manual on NXP website:
    https://www.nxp.com/docs/en/user-guide/UM10204.pdf
     
        Mysil
    post edited by Mysil - 2020/10/23 02:02:45
    #13
    Mysil
    Super Member
    • Total Posts : 3946
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Help using MCC generated I2C functions 2020/10/26 21:13:17 (permalink)
    0
    Hi,
    Transfer shown in the second capture in message #6, from your own code,
    do a different transfer from what will be done by code shown in message #1
     
    Transfer as shown in message #6, may be created with MCC code like this:
        I2C_ReadDataBlock(am2315, 0x00, RecData, 0x08); 

    Datasheet for the sensor is rather fuzzy about this part of the protocol.
     
    Datasheet also have a strange requirement for delay between Read Address and Read data.
    Code will have some delay in this step, but that is due to code execution,
    and will be different if processor clock frequency is changed.
    Both alternatives are available in the code.
     
    A modified program is attached.
    Note that the project as attached, will run in Simulator,
    to run on microconntroller, you will have to go into 'Project Properties' and change to PICkit 3.
     
        Mysil
     
    post edited by Mysil - 2020/10/27 03:25:12
    #14
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/27 10:55:45 (permalink)
    0
    I have deployed the code you attached to the microcontroller and I am still not receiving any data from the sensor.
     
    Using the logic analyzer in I2C spy mode, the following is returned when I turn on power to the microcontroller:

    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ], Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ], Stop
    Error!!!
    Start, h00 [ h00 | WR ], Error!!! Stop
    Start, h00 [ h00 | WR ], Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start,
    Restart, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], h00, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, Stop
    Start, Error!!! Stop
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Stop
    Error!!!
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ],
    Restart, h00 [ h00 | WR ] NAK,
    Restart, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Error!!!
    Start, Stop
    Start, Stop
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Error!!!
    Start,
    Restart, Error!!! Stop
    Error!!!
    Start, Error!!! Stop
    Start,
    Restart, Error!!! Stop
    Start, Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], h00, Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ], Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ], h00, h00,
    Restart, h00 [ h00 | WR ], Error!!! Stop
    Start, Error!!! Stop
    Start, Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ], Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], h00, h00, h00, Error!!! Stop
    Start, h00 [ h00 | WR ], h00, Stop
    Start, Stop
    Error!!!
    Start, h00 [ h00 | WR ], h00, h00, h00,
    Restart, h00 [ h00 | WR ], h00, h00, h00, h00, Error!!! Stop
    Error!!!
    Start, h00 [ h00 | WR ], Error!!! Stop
    Error!!!
    Error!!!
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], h00, Error!!! Stop
    Start, Error!!! Stop
    Start, h00 [ h00 | WR ], h00, h00, h00, h00, h00, Error!!! Stop
    Error!!!
    Error!!!
    Start, h00 [ h00 | WR ], h01, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00, h00,

     
    It appears that the code is sending h00 over and over again. I will try to get a waveform capture of what is happening but I am having trouble scaling my analyzer to see a correct waveform.
    #15
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/27 11:38:07 (permalink)
    0
    This may not be a good enough image but I have attached an image of the logic analyzer. And a csv file with the I2C events. Hopefully this will help some. Based on the information I am seeing using the analyzer, it appears something is still very wrong. It is either with the code, or the instrumentation, however I am leaning toward the code since the instrumentation can read my custom code (that doesn't use MCC) just fine.
     
    Let me know what you think or what I can do to provide more information to help. If I need to scale the image better or change how I'm exporting it, let me know. This is my first time exporting my analyzer images/data to someone else.

    Attached Image(s)

    #16
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/27 11:54:11 (permalink)
    0
    I just noticed that at the end of the I2C Spy Data.txt file it appears there was a successful transfer of data. It only happened one time.

    Start, hB8 [ h5C | WR ], h03 NAK, h00 NAK, h04 NAK, Stop
    Start, hB8 [ h5C | WR ], h00,
    Restart, hB9 [ h5C | RD ], h03, h04, h01, h72, h00, hE5, h91, h84, Error!!! Stop

    I plugged this into the equations to make them sensor readings and they are believable. But this code is still not good enough to give me consistent sensor readings at the UART output. All I see in the serial terminal is 0's.
     
    We are closer than I thought to finding a working solution. But I'm still not sure why the communication is so sporadic.
    #17
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/27 13:16:50 (permalink)
    0
    Sorry for posting several things at once. I get excited at breakthroughs and post too soon. Also, with the difference in time zones I know it is almost impossible to get more than one exchange per day. I have an important update.
     
    I went back to the original project that I attached in post #8. The only thing I changed is I do a dummy read to wake up the sensor as described in post #10, and I changed the I2C_ReadNBytes to I2C_ReadDataBlock. This now gives me an accurate exchange of data. So my MCC version is now caught up to speed with the code I had written not using MCC.
     
    I changed the MCC configuration to "Interrupt Driven" and this worked successfully also. I unplugged the sensor and my code continued to execute. I believe this has also solved the issue of not blocking the rest of the code when the sensor doesn't read or isn't present.
     
    I am fairly happy with this if I am correct in my above statement about not blocking. My application involves turning pumps on and off at certain timing intervals and while the timing itself isn't critical, making sure the pumps turn on and off is. So if the I2C code will cause the rest of the execution to "hang" for any reason it would not be good.
     
    While I am happy, I would like to push further and see if there is a simple way to detect if the sensor is present or not. I'm assuming a NAK/ACK check is all that is required? If so, could someone help show me how to implement this?
     
    I have attached the latest revision of my project with the interrupt driven code. If someone could verify there is no blocking, and also help me implement a check to see if the sensor is present or not, I would be completely satisfied with the state of the project. Thank you to everyone who has already helped so far.
    #18
    Mysil
    Super Member
    • Total Posts : 3946
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Help using MCC generated I2C functions 2020/10/27 18:31:23 (permalink)
    0
    Hi  Micah,
     
    Good that you are making progress.
    If you look in the Wakeup(); function, there is a NackFlag that is passed to the NackDelayHandler as a pointer.
    If there is a NACK event, NackDelayHandler(void *Ptr)   will be called inside MCC driver code,
    and the NackFlag  will be set. 
    You may pass this flag value back to the calling function.
     
    It is possible to make a similar Callback function also for other I2C_Write...  and  I2C_Read...  functions.
     
    Actually all the driver interface functions:
         I2C_Open(),  I2C_MasterWrite(), I2C_MasterRead()  and I2C_Close();
    will return a status value that may be I2C_NOERR, I2C_BUSY, or I2C_FAIL.
     
    However, there is bug in code generated by MCC,   such that a problem is never reported, and status is always I2C_NOERR, even if no data was transferred at all.  I have solved some of those problems, but there may be more testing needed.
     
    I will do more testing with the Interrupt configuration, 
    but if you use functions in:    examples/i2c_master_example.c 
    then there is not much point in using Interrupt configuration.
    Program will wait in: 
        while(I2C_BUSY == I2C_Close()); // sit here until finished. 

    anyway.
     
        Mysil
     
     
     
     
    post edited by Mysil - 2020/10/27 18:36:09
    #19
    jgreenmt
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2020/10/19 12:11:40
    • Location: 0
    • Status: offline
    Re: Help using MCC generated I2C functions 2020/10/28 08:58:40 (permalink)
    0
    Thank you Mysil and others who have helped get me this far. I feel like I'm getting my bearings.
     
    If I understand you correctly, the NackFlag will be set when a Nack event occurs. So if I write an interrupt routine that is looking for the NackFlag to be set, do I need to clear it manually in that routine, or does the I2C driver clear it for me? Would it make sense to reset a timer when the NackFlag is set, and if the timer times out then I trigger a "device not detected" state?
     
    I have two questions about the block in:

    while(I2C_Busy == I2C_Close()); // sit here until finished.

    1. Under what circumstances will this not be true and cause the code to hang? From what I can tell, even if I leave the sensor unplugged the code will still execute without getting hung up.
    2. Is there a convenient way to modify the I2C_Master_Example.c file to avoid the blocking routine?
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2020 APG vNext Commercial Version 4.5