Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 22 of 22

Thread: Teensy 4.0 and Adafruit BNO055

  1. #1
    Junior Member
    Join Date
    Sep 2019
    Posts
    2

    Teensy 4.0 and Adafruit BNO055

    Hi,
    I was wondering if somebody has also problems with the teensy 4.0 board. Trying to run the Adafruit BNO055 on a Teensy 4.0 with the standard Adafruit examples in Arduino/Teensyduino, it firstly doesn't get into the loop part until I remove the check for the BNO055 is present and then it doesn't get any values and shows only zeros.

    Using my Teensy 3.6 board, it perfectly runs, like on my Arduino Nano.
    Apologies if someone thinks this is better placed in the Adafruit forum, but then it a difference between two teensy boards I don't understand.

    Thank you a lot in advance.

    Mike

  2. #2
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @Maikeru - @PaulStoffregen

    No. This is the place to ask abou the BNO055. The problem with the BNO055 is a known problem that was hightlighted in this thread:

    https://forum.pjrc.com/threads/57353...ghlight=BNO055

  3. #3
    Junior Member
    Join Date
    Sep 2019
    Posts
    2
    Thank you!, indeed commenting the Reset section in the library does make it work. Now is this a teensy 4.0 or an Adafruit problem?

  4. #4
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    I found the issue on the bosch site and the work around. Also just saw something on the Adafruit site about something like it and resetting. So think the issue is probably on the Adafruit side.

  5. #5
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    Just as a test - I had found this on the adafruit forum: https://forums.adafruit.com/viewtopi...133511#p664391
    Simply hook up the reset line to a spare GPIO line on your controller and toggle it low for at least 20 nsec, then drive it high and keep it there for at least 650 msec before you start initialization (yes, that long!).
    which equates to this instead of the write8
    Code:
      pinMode(3, OUTPUT);
      digitalWrite(3, LOW);
      delayNanoseconds(20);
      digitalWrite(3, HIGH);
      delay(650);
    Haven't done exhaustive testing on this but the raw example does run. There may be other problems. I also haven't tested with i2c_t3 to see if that helped

  6. #6
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @Maikeru - @PaulStoffregen

    Just as a quick test I hooked up the BNO055 to a T3.6 with the reset command uncommented:
    Code:
      write8(BNO055_SYS_TRIGGER_ADDR, 0x20);
    and the examples work without a problem. So may or may not be a BNO055 problem but a T4 problem. Think Paul needs to do his debugging to get the correct answer.

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    For the heck of it, went to my display and sensors box and found an BNO055 and hooked up the same as Paul.

    Ran Wire example scanner:
    Code:
    Scanning...
    Device found at address 0x28  (BNO055,EM7180,CAP1188)
    done
    And running the same test, I see the same hang. It appears to kill the system totally, that is I updated the test program:
    Code:
    while (!Serial && millis() < 5000) ;
      Serial.begin(9600);
      Serial.println("Orientation Sensor Test"); Serial.println("");
      Serial.flush();
      delay(500);
    ...
    And nothing shows up in the display. Commenting out the above line and it appears to run...
    Will hook up Logic Analyzer and see if it shows anything...

  8. #8
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @KurtE

    Thanks for checking - Mike

    Edit: I did put some prints and delays in write function in wire but it hangs on that one command but not on the T3.6?

  9. #9
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    I also looked at it with Logic Analyzer and it outputs the reset command, which I did not notice anything unusual...

    Then it tried to output the next command, which it NAKEd once and that was the last I2C output.
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	9 
Size:	49.4 KB 
ID:	17538
    Showed both Analog and digital values here..

    Will look at it more later, got some other stuff needing to get done.
    Last edited by KurtE; 09-09-2019 at 01:08 AM.

  10. #10
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    I did a quick look at running the same sketch with a T3.0 (I thought I was grabbing a 3.2, but...)

    So ran it again and the with the Reset function in place, sure enough the next output Was Setup to write to 50 NAK, Setup RED 51 NAK.

    Which was the LAST output on T4. But here this sequence repeats something like 47 Times until we get a
    Setup Write 50 ACK Write 0, SETUP Read 51 ... If I look at how long it took between the output of the Reset until I got a valid ACK it was about .5 seconds. There was about a 10ms gap between the retries.

    And then continues and runs again.

    This feels like the WireIMXRT code is not properly handling the NAK and doing the retries.


    That is all for now... Will try to look again tomorrow.

    Kurt

  11. #11
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @KurtE

    Not sure if this will help but I uncommented the printf's in endtransmission in wireIMXRT.cpp:
    Code:
    Orientation Sensor Raw Data Test
    
    Chip ID
    m=1
    MSR=1, MFSR=0
    t=0
    start 50
    Switch Mode
    m=3000101
    MSR=3000101, MFSR=1
    t=1
    start 50
    t=3
    BNO055_SYS_TRIGGER_ADDR
    m=301
    MSR=301, MFSR=0
    t=0
    start 50
    m=301
    MSR=301, MFSR=0
    t=0
    start 50
    NACK, f=2, i=3
    status timeout = 1000
    status timeout = 1000
    status timeout keeps repeating infinitely...……

  12. #12
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    @mjs513 - Good morning, I decided to instrument the code as well with digitalWriteFast calls. I knew that the BNO055 code was hanging after the reset was sent, and it did one query and got a NAK... Should repeat the query until it received a valid response of it's id...

    That is this code in their begin method:
    Code:
    /* Reset */
      write8(BNO055_SYS_TRIGGER_ADDR, 0x20);
      /* Delay incrased to 30ms due to power issues https://tinyurl.com/y375z699 */
      delay(30);
      while (read8(BNO055_CHIP_ID_ADDR) != BNO055_ID) {
        delay(10);
      }
    So I put some writes in their read8 code:
    Code:
    byte Adafruit_BNO055::read8(adafruit_bno055_reg_t reg) {
      byte value = 0;
      digitalWriteFast(0, HIGH);
      digitalWriteFast(1, HIGH);
      _wire->beginTransmission(_address);
    #if ARDUINO >= 100
      _wire->write((uint8_t)reg);
    #else
      _wire->send(reg);
    #endif
      _wire->endTransmission();
      digitalWriteFast(1, LOW);
      _wire->requestFrom(_address, (byte)1);
    #if ARDUINO >= 100
      value = _wire->read();
    #else
      value = _wire->receive();
    #endif
      digitalWriteFast(0, LOW);
    
      return value;
    }
    And Capturing this, I see:
    Click image for larger version. 

Name:	screenshot.jpg 
Views:	8 
Size:	30.4 KB 
ID:	17539

    So the code makes it throught the first read8 call, delays 10ms and calls again, which hangs in the write code, probably for sure in the endTransmission call

  13. #13
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @KurtE

    Yeah that's pretty much what I am seeing as well.

    It will make it through the first read8 which gets the CHIP ID. The next write8 is to Switch Mode's to Configuration mode. The third write is for the rest with the BNO055_SYS_TRIGGER_ADDR, 0x20 which gets stuck in endTransmission it seems.

    EDIT: A couple of other things. This might also be related to the MPL3115 issue I was having: https://forum.pjrc.com/threads/54711...l=1#post207003. The solution to that was to add a delay before endtransmission. I did try that but no luck for this one.

    Also, early on (beginning of this year) I had a problem with i2cscanner not working - Paul put in a fix for 1.46-beta4 and that seemed to resolve it - not sure what the fix was though - didn't look at the time.

    Issue: https://forum.pjrc.com/threads/54711...l=1#post194081
    Last edited by mjs513; 09-09-2019 at 02:31 PM.

  14. #14
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    @mjs513 @PaulStoffregen - I think one hint is what you printed out:
    Code:
    status timeout = 1000
    At first I thought the 1000 was simply the timeout value, then saw that it is the value from the MSR

    So 1000 -> FEF is FIFO ERROR FLAG -
    FIFO Error Flag
    Detects an attempt to send or receive data without first generating a (repeated) START condition. This
    can occur if the transmit FIFO underflows when the AUTOSTOP bit is set. When FIFO Error Flag is set,
    the LPI2C master will send a STOP condition (if busy), and will not initiate a new START condition until
    FIFO Error Flag has been cleared.
    0b - No error
    1b - Master sending or receiving data without a START condition
    Next up try to detect this flag and clear it and see what happens?

    EDIT: It still hangs...

  15. #15
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @KurtE @PaulStoffregen

    fifo_used always seems to be = 4. Not sure if that means anything.

  16. #16
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    @...

    I also updated the code to print out everything (like @mjs513 did earlier) plus add a printf at start of endTransmission and requestFrom to get ideas of what is going on...
    Code:
    endTransmission 2 (00000050 00000000 00000000) 00000001
    m=00000001
    MSR=00000001, MFSR=00000000
    t=0
    start 00000050
    
    requestFrom 00000028 00000001 00000001
    idle2, msr=00000301
    MSR=00000301, MFSR=00000000
    t=0
    r=1
    
    endTransmission 3 (00000050 0000003D 00000000) 00000001
    m=00000301
    MSR=00000301, MFSR=00000000
    t=0
    start 00000050
    
    endTransmission 3 (00000050 0000003F 00000020) 00000001
    m=00000301
    MSR=00000301, MFSR=00000000
    t=0
    start 00000050
    
    endTransmission 2 (00000050 00000000 00000020) 00000001
    m=00000301
    MSR=00000301, MFSR=00000000
    t=0
    start 00000050
    NACK, f=2, i=3
    
    requestFrom 00000028 00000001 00000001
    idle2, msr=00000701
    MSR=00000701, MFSR=00000001
    t=1
    Status = 00001100
    Status = 00001100
    Status = 00001100
    Status = 00001100
    Status = 00001100
    Status = 00001100
    Status = 00001100
    Status = 00001100
    In this case it appears to have hung in request from:
    Interesting info: MSR is 701(NDF-NACK, SDF-Stop Detect, EPF-End Packet, TDF-Transmit Dat)
    Most of the others were 301 which does not have NACK which makes sense.

    BUT: MFSR=1 says that there is something already in TX FIFO, So maybe this needs to be cleared? otherwise we end up with 1100 or
    Fifo Error flag, EPF...

  17. #17
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @KurtE

    That seems to make sense - fifo_used comes in at 4 so the fifo prints never seem to hit.

  18. #18
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    @PaullStoffregen @mjs513 ...

    I used a few sledge hammers and I got it to not stick... But not sure if correct to do?

    The main thing is I clear out FIFO queue and clear FTF

    Here are the two functions. Note: with the sketch in this thread, I receiving back all zeros...

    Code:
    uint8_t TwoWire::endTransmission(uint8_t sendStop)
    {
    	//printf("\nendTransmission %d (%x %x %x) %x\n", txBufferLength,txBuffer[0], txBuffer[1], txBuffer[2], sendStop);
    	uint32_t i=0, len, status;
    
    	len = txBufferLength;
    	if (!len) return 4; // no data to transmit
    
    	// wait while bus is busy
    	while (1) {
    		status = port->MSR; // pg 2899 & 2892
    		if (!(status & LPI2C_MSR_BBF)) break; // bus is available
    		if (status & LPI2C_MSR_MBF) break; // we already have bus control
    		// TODO: timeout...
    	}
    	//printf("m=%x\n", status);
    
    	// Wonder if MFSR we should maybe clear it?
    	if ( port->MFSR & 0x7) {
    		port->MCR = LPI2C_MCR_MEN | LPI2C_MCR_RTF;  // clear the FIFO
    		port->MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF | LPI2C_MSR_FEF; // clear flags
    		//printf("Clear TX Fifo %lx %lx\n", port->MSR, port->MFSR);
    	}
    	// TODO: is this correct if the prior use didn't send stop?
    	//port->MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF; // clear flags
    	port->MSR = status;
    
    	//printf("MSR=%lX, MFSR=%lX\n", status, port->MFSR);
    	//elapsedMillis timeout=0;
    
    	while (1) {
    		// transmit stuff, if we haven't already
    		if (i <= len) {
    			uint32_t fifo_used = port->MFSR & 0x07; // pg 2914
    			//if (fifo_used < 4) printf("t=%ld\n", fifo_used);
    			while (fifo_used < 4) {
    				if (i == 0) {
    					//printf("start %x\n", txBuffer[0]);
    					port->MTDR = LPI2C_MTDR_CMD_START | txBuffer[0];
    					i = 1;
    				} else if (i < len) {
    					port->MTDR = LPI2C_MTDR_CMD_TRANSMIT | txBuffer[i++];
    				} else {
    					if (sendStop) port->MTDR = LPI2C_MTDR_CMD_STOP;
    					i++;
    					break;
    				}
    				fifo_used = fifo_used + 1;
    			}
    		}
    		// monitor status
    		status = port->MSR; // pg 2899 & 2892
    		if (status & LPI2C_MSR_ALF) {
    			//printf("arbitration lost\n");
    			return 4; // we lost bus arbitration to another master
    		}
    		if (status & LPI2C_MSR_NDF) {
    			//printf("NACK, f=%d, i=%d\n", port->MFSR & 0x07, i);
    			// TODO: check that hardware really sends stop automatically
    			port->MCR = LPI2C_MCR_MEN | LPI2C_MCR_RTF;  // clear the FIFO
    			// TODO: is always sending a stop the right way to recover?
    			port->MTDR = LPI2C_MTDR_CMD_STOP;
    			return 2; // NACK for address
    			//return 3; // NACK for data TODO: how to discern addr from data?
    		}
    		//if (status & LPI2C_MSR_PLTF) {
    			//printf("bus stuck - what to do?\n");
    			//return 4;
    		//}
    
    		//if (timeout > 100) {
    			//printf("status = %x\n", status);
    			//timeout = 0;
    		//}
    
    		if (sendStop) {
    			if (status & LPI2C_MSR_SDF) {
    				// master automatically sends stop condition on some
    				// types of errors, so this flag only means success
    				// when all comments in fifo have been fully used
    				uint32_t fifo = port->MFSR & 0x07;
    				if (fifo == 0) return 0;
    			}
    		} else {
    			uint32_t fifo_used = port->MFSR & 0x07; // pg 2914
    			if (fifo_used == 0) {
    				//digitalWriteFast(15, HIGH);
    				//delayMicroseconds(2);
    				//digitalWriteFast(15, LOW);
    				// TODO: this returns before the last data transmits!
    				// Should verify every byte ACKs, arbitration not lost
    				//printf("fifo empty, msr=%x\n", status);
    				return 0;
    			}
    		}
    	}
    }
    
    uint8_t TwoWire::requestFrom(uint8_t address, uint8_t length, uint8_t sendStop)
    {
    	uint32_t cmd=0, status, fifo;
    
    	// wait while bus is busy
    	//printf("\nrequestFrom %x %x %x\n", address, length, sendStop);
    	while (1) {
    		status = port->MSR; // pg 2899 & 2892
    		if (!(status & LPI2C_MSR_BBF)) break; // bus is available
    		if (status & LPI2C_MSR_MBF) break; // we already have bus control
    		// TODO: timeout...
    	}
    	//printf("idle2, msr=%x\n", status);
    
    	// TODO: is this correct if the prior use didn't send stop?
    	port->MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF | LPI2C_MSR_FEF; // clear flags
    
    	//printf("MSR=%lX, MCR:%lx, MFSR=%lX\n", status, port->MCR, port->MFSR);
    
    	// Wonder if MFSR we should maybe clear it?
    	if ( port->MFSR & 0x7) {
    		port->MCR = LPI2C_MCR_MEN | LPI2C_MCR_RTF;  // clear the FIFO
    		port->MSR = LPI2C_MSR_PLTF | LPI2C_MSR_ALF | LPI2C_MSR_NDF | LPI2C_MSR_SDF | LPI2C_MSR_FEF; // clear flags
    		//printf("Clear TX Fifo %lx %lx\n", port->MSR, port->MFSR);
    	}
    	address = (address & 0x7F) << 1;
    	if (length < 1) length = 1;
    	if (length > 255) length = 255;
    	rxBufferIndex = 0;
    	rxBufferLength = 0;
    
    	//elapsedMillis timeout=0;
    
    	while (1) {
    		// transmit stuff, if we haven't already
    		if (cmd < 3) {
    			fifo = port->MFSR & 0x07; // pg 2914
    			//if (fifo < 4) printf("t=%ld\n", fifo);
    			while (fifo < 4 && cmd < 3) {
    				if (cmd == 0) {
    					port->MTDR = LPI2C_MTDR_CMD_START | 1 | address;
    				} else if (cmd == 1) {
    					// causes bus stuck... need way to recover
    					//port->MTDR = LPI2C_MTDR_CMD_START | (length - 1);
    					port->MTDR = LPI2C_MTDR_CMD_RECEIVE | (length - 1);
    				} else {
    					if (sendStop) port->MTDR = LPI2C_MTDR_CMD_STOP;
    				}
    				cmd++;
    				fifo = fifo + 1;
    			}
    		}
    		// receive stuff
    		if (rxBufferLength < sizeof(rxBuffer)) {
    			fifo = (port->MFSR >> 16) & 0x07;
    			//if (fifo > 0) printf("r=%ld\n", fifo);
    			while (fifo > 0 && rxBufferLength < sizeof(rxBuffer)) {
    				rxBuffer[rxBufferLength++] = port->MRDR;
    				fifo = fifo - 1;
    			}
    		}
    		// monitor status
    		status = port->MSR; // pg 2899 & 2892
    		if (status & LPI2C_MSR_ALF) {
    			//printf("arbitration lost\n");
    			break;
    		}
    		if (status & LPI2C_MSR_NDF) {
    			//printf("got NACK\n");
    			// TODO: how to make sure stop is sent?
    			break;
    		}
    
    		//if (timeout > 250) {
    			//printf("Status = %x\n", status);
    			//timeout = 0;
    		//}
    
    		if (rxBufferLength >= length && cmd >= 3) break;
    	}
    	//digitalWriteFast(15, HIGH);
    	//delayMicroseconds(2);
    	//digitalWriteFast(15, LOW);
    	return rxBufferLength;
    }

  19. #19
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,213
    @KurtE @PaullStoffregen

    Sorry - been repairing holes in walls today and grouting tile. Anyway I tested your changes with the BNO055 and the propshield with the MPL3115 that I was having a problem with.

    The fix you put in place works with the BNO055 as well as fixing the issue with MPL3115.

    Also tested i2cscanner and that works with issue as well.

  20. #20
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,586
    @PaulStoffregen - I put in PR: https://github.com/PaulStoffregen/Wire/pull/16

    Not sure if this is the best solution or not, but???

  21. #21
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,232
    FWIW, I notice the mbed lib for BNO055 has a much longer delay after issuing reset
    Code:
    void BNO055::reset(){
    //Perform a power-on-reset
        readchar(BNO055_SYS_TRIGGER_ADDR);
        rx = rx | 0x20;
        writechar(BNO055_SYS_TRIGGER_ADDR,rx);
    //Wait for the system to come back up again (datasheet says 650ms)
        wait_ms(675);
    }
    EDIT: As per datasheet, I changed delay after reset in Adafruit_BNO055.cpp to 700 ms, and BNO055 examples worked on Teensy 4.
    Code:
    ...
      /* Reset */
      write8(BNO055_SYS_TRIGGER_ADDR, 0x20);
      /* Delay incrased to 30ms due to power issues https://tinyurl.com/y375z699 */
      delay(700);
      while (read8(BNO055_CHIP_ID_ADDR) != BNO055_ID) {
    ...
    As noted, examples work on T3* with delay(30)
    Last edited by manitou; 09-17-2019 at 11:16 AM.

  22. #22
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,686
    Teensyduino 1.48 has been released, with Kurt's fix for this problem.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •