Code debug

Luca

Active member
Hi, I found a library that allows a teensy to comunicate with an sbus receiver. I need to pass the data received (an array of integers) to another board with I2C. I can see things happening on the board connected to the SBUS receiver but nothing on the board that's supposed to receive the array of data via I2C. Hope that makes sense.

I've also other i2c devices connected to the same bus (don't know if that can cause problems).

Here are the 2 programs:

Transmitter:
Code:
#include "sbus.h"
#include <Wire.h>

/* SBUS object, reading SBUS */
bfs::SbusRx sbus_rx(&Serial2);
bfs::SbusData data;

const int channelNumber = 16;
int channels[channelNumber];

void setup() {
  /* Serial to display data */
  Serial.begin(115200);
  while (!Serial);
  sbus_rx.Begin();
  Wire.begin();
}

void loop () {
  if (sbus_rx.Read()) {
    /* Grab the received data */
    data = sbus_rx.data();
    /* Display the received data */
    for (int8_t i = 0; i < data.NUM_CH; i++) {
      channels[i] = data.ch[i];
      Serial.print(data.ch[i]);
      Serial.print("\t");
    }
    Serial.println();
  }

  Wire.beginTransmission(8);
  for(int i = 0; i < channelNumber; i++){
    Wire.write(channels[i]);
  }
  Wire.endTransmission();
}

Receiver:
Code:
#include<Wire.h>

const int channelNumber = 16;
int receiverChannels[channelNumber];

void setup() {
Wire.begin(8);
Wire.onReceive(receiveEvent);
Serial.begin(115200);
while(!Serial);
}

void loop() {
}

void receiveEvent(int byteCount){
  if(Wire.available()){
    byte b = 0;
    for(int i = 0; i < channelNumber; i++){
      b = Wire.read();
      receiverChannels[i] = b;

      Serial.print(receiverChannels[i]); Serial.print(" ");
    }
    Serial.println();
  }
}
 
Last edited:
I have no familiarity with sbus or I2C slave mode so this is all very generic but a couple of things stick out as possibly causing issues in your receiver code.

Code:
void receiveEvent(int byteCount){
  if(Wire.available()){
    byte b = 0;
    for(int i = 0; i < channelNumber; i++){
        b = Wire.read();

This is checking if any data is available and then assumes that there will be channelNumber bytes waiting.
You could well get a call that data is there when there is only 1 byte waiting. The variable name is implying that you will in fact have byteCount bytes waiting.
Trying to read bytes that aren't there will likely cause the code to block.

Which brings us to issue two, this is an interrupt event. Never have anything slow or blocking in an interrupt.

printf (which is what most print commands will be using under the covers) is not thread safe, if it gets called in an interrupt half way through a call in the main code all sorts of nasty things can happen.
Both of these mean that printing to a serial port in an interrupt is a very bad idea. In this case (no background loop and using a USB serial) you may just about be able to get away with it but it's still not a good idea.
 
The transmitter is always sending eatch time 1 component of the array channels by time. i thought that when the first has arrived to the receiver the others would be coming directly after that. In total it's passing all the 16 integers of the array
 
Is the other board also a Teensy? I can tell you I've personally verified Teensy (I2C master) to Teensy (I2C slave) many times. Many people have also successfully used Teensy in either mode, so I'm pretty sure the Teensy side works.

So as a starting point for the sake of troubleshooting, maybe try just the I2C stuff without sbus. If it still doesn't work, those of us without sbus hardware would at least give your I2C-only code a try on our hardware to try helping. To help with the code shown in msg #1 requires getting sbus.h somewhere and probably also having specific sbus hardware, which realistically means most of us can't really help with the I2C part. If you post I2C-only code, really opens up the possibility for me and others that try helping more than just guesswork.

If the other device isn't Teensy, maybe for the sake of troubleshooting try Teensy-to-Teensy I2C communication. I know this is getting farther from your goal to have everything working together, but usually when you're stuck on troubleshooting a difficult problem the path forward is to whittle it down and test simpler first. When each simple piece is confirmed, work back up to your original more complex goal.
 
In your code you have been mixing up bytes and integers.

In your send routint you have Wire.write(channels); where channels is an integer and Wire.write accepts a byte ( as I understand it ).

In your receive routine you have
byte b = Wire.read();
receiverChannels = b; <<--- assigning a byte to an int

I have massaged (though NOT tested) your code to take account of the different types. Have a look below.

Transmiter:
Code:
#include "sbus.h"
#include <Wire.h>

/* SBUS object, reading SBUS */
bfs::SbusRx sbus_rx(&Serial2);
bfs::SbusData data;

const int channelNumber = 16;
union dataType {
    int channels[channelNumber];
    uint8_t transmitData[sizeof(channels)];
};

dataType d;

void setup() {
    /* Serial to display data */
    Serial.begin(115200);
    while (!Serial);
    sbus_rx.Begin();
    Wire.begin();
}

void loop() {
    if (sbus_rx.Read()) {
        /* Grab the received data */
        data = sbus_rx.data();
        /* Display the received data */
        for (int8_t i = 0; i < data.NUM_CH; i++) {
            d.channels[i] = data.ch[i];
            Serial.print(data.ch[i]);
            Serial.print("\t");
        }
        Serial.println();
    };

    Wire.beginTransmission(8);
    for (int i = 0; i < sizeof(d.transmitData); i++) {
        Wire.write(d.transmitData[i]);
    }
    Wire.endTransmission();
}

Receiver:
Code:
#include<Wire.h>

const int channelNumber = 16;
union dataType {
    int receiverChannels[channelNumber];
    uint8_t transmitData[sizeof(receiverChannels)];
};

dataType d;

void setup() {
    Wire.begin(8);
    Wire.onReceive(receiveEvent);
    Serial.begin(115200);
    while (!Serial);
}

void loop() {
}

void receiveEvent(int byteCount) {
    if (Wire.available()>= sizeof(d.transmitData)) {

        for (int i = 0; i < sizeof(d.transmitData); i++) {
            d.transmiData[i] = Wire.read();
        }
        for (int i = 0; i < channelNumber; i++) {
            Serial.print(d.receiverChannels[i]); Serial.print(" ");
        }
        Serial.println();
    }
}
 
Back
Top