Teensy 4.1 I2C slave crashing after data request

Status
Not open for further replies.

Mano1979

Active member
I have a Teensy 4.1 hooked up to a Raspberry Pi. I have communication working with an example sketch (arduino IDE) and i can request data with the Raspberry pi multiple times without any problem. I'm using this library instead of the default "Wire" because it has a 'slave' function: https://github.com/Richard-Gemmell/teensy4_i2c

i then put this exact code in my other code project, and a data request from the pi gives the wanted result, but only the first time!
after that, the I2C slave (Teensy) cannot be found by the raspberry pi and i need to manually reset it by pressing the button before it starts working again.

I have no idea what can cause this and why, so any help is greatly appreciated.

Example sketch (Working always):
Code:
// Wire Slave Sender
// by Nicholas Zambetti <http://www.zambetti.com>
// Modified by Richard Gemmell Oct 2019

// Demonstrates use of the Wire library
// Sends data as an I2C/TWI slave device
// Refer to the "Wire Master Reader" example for use with this
// To use it, connect a master to the Teensy on pins 18 and 19.
//
// Consider using the I2CRegisterSlave class instead of Wire to
// create an I2C slave.

// Created 29 March 2006

// This example code is in the public domain.

#include <Arduino.h>
#include <i2c_driver.h>
#include <i2c_driver_wire.h>

void requestEvent();

int led = LED_BUILTIN;

void setup()
{
  pinMode(led, OUTPUT);
  Wire1.begin(8);        // join i2c bus with address #8
  Wire1.onRequest(requestEvent); // register event
}

void loop()
{
  delay(100);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
  uint16_t gotArray[13] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
  digitalWrite(led, HIGH);      // briefly flash the LED
  Wire1.write(gotArray[13]);     // respond with message of 6 bytes
                                // as expected by master
  digitalWrite(led, LOW);
}

Sketch with my other code added but identical I2C code (Working once then crashes):
Code:
#include <Arduino.h>
#include "AdvServo.h"
#include "FootSensor.h"
#include "InverseKinematics.h"
#include "Util.h"
#include <Servo.h>
//MANO'S REMOTE STUFF
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(37, 38); // CE, CSN
const byte address[6] = "00001"; // CHANGE TO A UNIQUE ADDRESS (SAME AS ON THE REMOTE)
uint16_t gotArray[13];
// END OF MANO'S REMOTE STUFF
//I2C STUFF BELOW
#include <i2c_driver.h>
#include <i2c_driver_wire.h>
// END I2C STUFF

using namespace std;

String serialResponse = "";
char msg0[] = "0,-999.9,-999.9,-999.9"; // general structure for normal position command
char msg1[] = "0,-999.9,-999.9,-999.9,-999.9,-999.9,-999.9"; // general structure for normal position/speed command
bool ESTOPPED = false;
int max_speed = 500; // deg / sec


AdvServo BR_Hip, BR_Shoulder, BR_Wrist, BL_Hip, BL_Shoulder, BL_Wrist, FR_Hip, FR_Shoulder, FR_Wrist, FL_Hip, FL_Shoulder, FL_Wrist;
FootSensor FL_sensor, FR_sensor, BL_sensor, BR_sensor;
AdvServo * hips[4] = {&FL_Hip, &FR_Hip, &BL_Hip, &BR_Hip};
AdvServo * shoulders[4] = {&FL_Shoulder, &FR_Shoulder, &BL_Shoulder, &BR_Shoulder};
AdvServo * wrists[4] = {&FL_Wrist, &FR_Wrist, &BL_Wrist, &BR_Wrist};
Util util;
InverseKinematics ik;

void attach_servos() {
  // HIPS
  FL_Hip.init(4, 135, -2);
  FR_Hip.init(11, 135, 0);
  BL_Hip.init(7, 135, 0);
  BR_Hip.init(8, 135, -3);

  //SHOULDERS
  FL_Shoulder.init(2, 180, -3);
  FR_Shoulder.init(13, 90, -14);
  BL_Shoulder.init(5, 180, 5); // +
  BR_Shoulder.init(10, 90, 0); // -

  //WRISTS
  FL_Wrist.init(3, 0, 2);
  FR_Wrist.init(12, 270, -2);
  BL_Wrist.init(6, 0, 2);
  BR_Wrist.init(9, 270, -1);

  //FL_sensor.init(A9, 17);
  //FR_sensor.init(A8, 16);
  //BL_sensor.init(A7, 15);
  //BR_sensor.init(A6, 14);

  setLegJointIDS();

  delay(1000);
}

void detach_servos() {
  // HIPS
  FL_Hip.detach();
  FR_Hip.detach();
  BR_Hip.detach();
  BL_Hip.detach();

  // SHOULDER
  FL_Shoulder.detach();
  FR_Shoulder.detach();
  BR_Shoulder.detach();
  BL_Shoulder.detach();

  // WRIST
  FL_Wrist.detach();
  FR_Wrist.detach();
  BR_Wrist.detach();
  BL_Wrist.detach();
}

void update_servos(){
  // HIPS
  FL_Hip.update_clk();
  FR_Hip.update_clk();
  BR_Hip.update_clk();
  BL_Hip.update_clk();

  // SHOULDER
  FL_Shoulder.update_clk();
  FR_Shoulder.update_clk();
  BR_Shoulder.update_clk();
  BL_Shoulder.update_clk();

  // WRIST
  FL_Wrist.update_clk();
  FR_Wrist.update_clk();
  BR_Wrist.update_clk();
  BL_Wrist.update_clk();
}

void update_sensors() {
  FL_sensor.update_clk();
  FR_sensor.update_clk();
  BL_sensor.update_clk();
  BR_sensor.update_clk();
}

void setLegJointIDS() {
  // HIPS
  FL_Hip.setType(0, 0);
  FR_Hip.setType(1, 0);
  BL_Hip.setType(2, 0);
  BR_Hip.setType(3, 0);

  //SHOULDERS
  FL_Shoulder.setType(0, 1);
  FR_Shoulder.setType(1, 1);
  BL_Shoulder.setType(2, 1);
  BR_Shoulder.setType(3, 1);

  //WRISTS
  FL_Wrist.setType(0, 2);
  FR_Wrist.setType(1, 2);
  BL_Wrist.setType(2, 2);
  BR_Wrist.setType(3, 2);

}

void readRemote(){
  while(radio.available()){ 
    radio.read( &gotArray, sizeof(gotArray) ); 
    //Serial.print("Recieved array:\n"); 
    //for (byte i=0; i<13; i++){
      //Serial.print(gotArray[i]);
      //Serial.print(",");
    //}
    //Serial.println("\n");
  }
}

void requestEvent();

void setup() {
  // SETUP RADIO FOR MANO'S REMOTE
  SPI1.setCS(38);
  SPI1.setMISO(39);
  SPI1.begin();
  //Serial.begin(2000000);
  //Serial.println("starting....");
  radio.begin();
  radio.openReadingPipe(0, address);   //Setting the address at which we will receive the data
  radio.setPALevel(RF24_PA_MAX);       //You can set this as minimum or maximum depending on the distance between the transmitter and receiver.
  radio.setDataRate(RF24_2MBPS);
  radio.startListening();              //This sets the module as receiver
  //END
  //I2C initialization
  Wire1.begin(8);        // join i2c bus with address #8
  Wire1.onRequest(requestEvent); // register event
  // END I2C

  Serial1.begin(500000);
  ik.init(8.7, 59, 107, 130); // hip offset 0, hip_offset 1, shoulder length, wrist length
  FL_Hip.init(4, 135, -2);
  FR_Hip.init(11, 135, 0);
  BL_Hip.init(7, 135, 0);
  BR_Hip.init(8, 135, -3);

  //SHOULDERS
  FL_Shoulder.init(2, 180, -3);
  FR_Shoulder.init(13, 90, -14);
  BL_Shoulder.init(5, 180, 5); // +
  BR_Shoulder.init(10, 90, 0); // -

  //WRISTS
  FL_Wrist.init(3, 0, 2);
  FR_Wrist.init(12, 270, -2);
  BL_Wrist.init(6, 0, 2);
  BR_Wrist.init(9, 270, -1);

  FL_sensor.init(A9, 17);
  FR_sensor.init(A8, 16);
  BL_sensor.init(A7, 15);
  BR_sensor.init(A6, 14);

  setLegJointIDS();

  delay(1000);
  //attach_servos();
}

void loop() {
  readRemote();
  //MANO'S REMOTE SERVO POWER OFF
  if(gotArray[11]==1){
    detach_servos();
  } //else {
   // attach_servos();
 // }
  
  if(!ESTOPPED){
    update_servos();
  } else {
    detach_servos();
  }
    
  //update_sensors();
  if (Serial1.available()) {
    serialResponse = Serial1.readStringUntil('\r\n');
    // Convert from String Object to String.
    char buf[sizeof(msg0)];
    serialResponse.toCharArray(buf, sizeof(buf));
    char *ptr = buf;
    char *str;
    int index = 0;
    int leg = -1; //0=FL, 1=FR, 2=BL, 3=BR
    double x = -9999;
    double y = -9999;
    double z = -9999;
    while ((str = strtok_r(ptr, ",", &ptr)) != NULL) { // delimiter is the dash
      if(strcmp(str, "e") == 0 || strcmp(str, "E") == 0) {
        ESTOPPED = true;
      }

      if(index == 0) {
        util.upper(str);
        if(strcmp(str, "0") == 0){
          leg = 0;
        }
        if(strcmp(str, "1") == 0){
          leg = 1;
        }
        if(strcmp(str, "2") == 0){
          leg = 2;
        }
        if(strcmp(str, "3") == 0){
          leg = 3;
        }
      }
      if(index == 1) {
        x = atof(str);
      }
      if(index == 2) {
        y = atof(str);
      }
      if(index == 3) {
        z = atof(str);
      }
      index++;
    }

    //COMPLETE MESSAGE CHECK
    if(leg != -9999 || x != -9999 || y != -9999 || z != -9999){
      Serial.println("complete message");
      double *p;
      p = ik.run(leg, x, y, z);

      double temp_hip = util.toDegrees(*p);

      if(leg == 1 || leg == 2){
        temp_hip *= -1;
      }

      double hip_angle = util.angleConversion(leg, 0, temp_hip);
      double shoulder_angle = util.angleConversion(leg, 1, util.toDegrees(*(p+1)));
      double wrist_angle = util.angleConversion(leg, 2, util.toDegrees(*(p+2)));

      double h_dist = abs(hip_angle - (*hips[leg]).getPosition());
      double s_dist = abs(shoulder_angle - (*shoulders[leg]).getPosition());
      double w_dist = abs(wrist_angle - (*wrists[leg]).getPosition());

      double scaling_factor = util.max(h_dist, s_dist, w_dist);

      h_dist /= scaling_factor;
      s_dist /= scaling_factor;
      w_dist /= scaling_factor;

      (*hips[leg]).setPosition(hip_angle, max_speed * h_dist);
      (*shoulders[leg]).setPosition(shoulder_angle, max_speed * s_dist);
      (*wrists[leg]).setPosition(wrist_angle, max_speed * w_dist);
    }
  }
}

//I2C Data request response
void requestEvent()
{
  Wire1.write(gotArray[0]);     // respond with message of 6 bytes
  
}

Raspberry pi Python code (Master device):
Code:
#!/usr/bin/python

import smbus

bus = smbus.SMBus(1)    # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)

#DEVICE_ADDRESS = 0x15      #7 bit address (will be left shifted to add the read$
DEVICE_REG_MODE1 = 0x00
DEVICE_REG_LEDOUT0 = 0x1d

# Read a block of 16 bytes from address 80, offset 0
count = 0
while count < 5:
        block = bus.read_i2c_block_data(8, 0, 16)
        # Returned value is a list of 16 bytes
        print(block)

What i also notice is that when i do a address scan from the pi ($ i2cdetect -y 1) it finishes in about 100ms, but when the teensy crashes that same scan takes about 10 seconds.


In the end, what i'm trying to do is send an array (uint16 gotArray[13 values]) over i2c to the pi on the pi's request.
 
Last edited:
Anyone? i'm really stuck here....

i noticed that occasionally the so called 'non crashing' sketch, also crashes.
 
Here the output from the python script:

Code:
pi@raspberrypi:~ $ python3 i2ctest.py
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[104, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Traceback (most recent call last):
  File "i2ctest.py", line 14, in <module>
    block = bus.read_i2c_block_data(8, 0, 16)
OSError: [Errno 121] Remote I/O error
pi@raspberrypi:~ $
 
Status
Not open for further replies.
Back
Top