0

So I have a teensy and an arduino uno connected together via I2C, however some very odd behavior is occurring, when monitoring the serial connection for shorter data sent over I2C I receive the expected serial output. However if the data is longer I only receive 2 characters. More strange even is that if I send the longer data again I receive none, but if I send the shorter data I receive the expected output. After sending the shorter data again sending the longer data will result is the odd 2 characters.

Uno code //#include

 #include <Wire.h>

boolean pinout = 0;
byte current[512];

void setup() {
  // put your setup code here, to run once:
  Wire.begin(1);
  Serial.begin(115200);
  Wire.onReceive(data);
  //DmxSimple.usePin(3);
  //DmxSimple.maxChannel(30);
}

void loop() {

}

void data(int numBytes){
//Serial.println("DATA RECIVED");

 delay(500);

 char input[20];
 int pos = 0;

 while(Wire.available()){
   input[pos++] = Wire.read();
  }
  input[pos++] = '\0';

  Serial.print("Recived \"");
  Serial.print(input);
  Serial.println("\"");

  char* next = strchr(input, ',');
  while(next != 0){  
  *next = 0;
  next++;
  char* splitter = strchr(next, ':');
  if(splitter != 0){
  *splitter = 0;
  splitter++;
  int channel = atoi(next);
  int value = atoi(splitter);
      //DmxSimple.write(channel,value);
      Serial.print(channel); Serial.print(":"); Serial.println(value);
    }
  } 
}

Teensy code

            #include <i2c_t3.h>
            //#include <ArduinoPebbleSerial.h>

     /*
    static const uint16_t SERVICE_ID = 0x1001;
static const uint16_t UPTIME_ATTRIBUTE_ID = 0x0002;
static const size_t UPTIME_ATTRIBUTE_LENGTH = 4;
static const uint16_t LAMP_ATTRIBUTE_ID = 0x0003;
static const size_t LAMP_ATTRIBUTE_LENGTH = 20;

static const uint16_t SERVICES[] = {SERVICE_ID};
static const uint8_t NUM_SERVICES = 1;

static const uint8_t PEBBLE_DATA_PIN = 1;
static uint8_t buffer[GET_PAYLOAD_BUFFER_SIZE(4)];

typedef struct __attribute__((packed)){
  uint8_t channel;
  uint8_t value;
} DMXP;*/

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Wire.begin();
  Serial.begin(9600);
  /*
 #if defined(__MK20DX256__) || defined(__MK20DX128__)
  // Teensy 3.0/3.1 uses hardware serial mode (pins 0/1) with RX/TX shorted together
 ArduinoPebbleSerial::begin_hardware(buffer, sizeof(buffer), Baud57600, SERVICES, NUM_SERVICES);
#elif defined(__AVR_ATmega32U4__)
 // Teensy 2.0 uses the one-wire software serial mode
 ArduinoPebbleSerial::begin_software(PEBBLE_DATA_PIN, buffer, sizeof(buffer), Baud57600, SERVICES,
                                  NUM_SERVICES);
#else
#error "This example will only work for the Teensy 2.0, 3.0, or 3.1 boards"
#endif
*/
/*for(int i = 1; i < 8; i++){
  sendChannel(i,0);
}
*/

}

/*
void handle_dmx_request(RequestType type, size_t length) {
if (type != RequestTypeWrite) {
  return;
}

DMXP cmd = *(DMXP*)buffer;
sendChannel(cmd.channel, cmd.value);

// ACK that the write request was received
ArduinoPebbleSerial::write(true, NULL, 0);
ArduinoPebbleSerial::notify(SERVICE_ID, UPTIME_ATTRIBUTE_ID);
}
*/

void loop() {

  /*
  if (ArduinoPebbleSerial::is_connected()) {
  digitalWrite(13,true);
} else {
  digitalWrite(13,false);
}

uint16_t service_id;
uint16_t attribute_id;
size_t length;
RequestType type;
if (ArduinoPebbleSerial::feed(&service_id, &attribute_id, &length, &type)) {
  // process the request
  if (service_id == SERVICE_ID) {
    switch (attribute_id) {
      case LAMP_ATTRIBUTE_ID:
        handle_dmx_request(type, length);
        break;
      default:
        break;
    }
  }
}
*/

}

void serialEvent(){
  if(Serial.read() == 't'){
  digitalWrite(13,true);
  Serial.println("Starting Controller");
  int chans[8] = {1,2,3,4,5,6,7,8};
  int vals[8] = {2,4,6,8,16,32,64,128};
  sendChannel(chans,vals,4);
  } else {
    sendChannel(1,1);
  }
  while(Serial.available()){
    Serial.println(Serial.read());
  }
}


void sendChannel(int chan, int val){
 char chno[8];
  itoa(chan,chno,10);
  char vano[8];
 itoa(val,vano,10);
 char message[20];
 int messagei = 0;
 for(int i = 0; i < 7; i++){
 if(chno[i] == '\0'){
   break;
  }
 message[messagei++] = chno[i];
}
 message[messagei++] = ':';
 for(int i = 0;i < 7; i++){
 if(vano[i] == '\0'){
  break;
 }
 message[messagei++] = vano[i];
 }
  //message[messagei++] = '\n';
//message[messagei++] = '\r';
message[messagei++] = '\0';

Serial.println(message);

Wire.beginTransmission(1);
Wire.write(message);
Wire.endTransmission();
}

void sendChannel(int chan[], int val[], int num){
 char message[20*num + 1];
 int at = 0;

 for(int i = 0; i < num; i++){
char chno[8];
itoa(chan[i],chno,10);
char vano[8];
itoa(val[i],vano,10);
for(int i = 0; i < 7; i++){
  if(chno[i] == '\0'){
    break;
  }
  message[at++] = chno[i];
}
message[at++] = ':';
for(int i = 0;i < 7; i++){
  if(vano[i] == '\0'){
    break;
  }
  message[at++] = vano[i];
  }
  if(i+1!=num){
  message[at++] = ',';
  } else {
  message[at++] = 0;
 }
 }

 char finalMessage[at+1];
 for(int i = 0; i <= at; i++){
finalMessage[i] = message[i];
 }

 Serial.println(finalMessage);

Wire.beginTransmission(1);
Wire.write(message);
Wire.endTransmission();

}

(If modifying the teensy code to run on a second arduino replace the line #include <i2c_t3.h> with #include <Wire.h> no other changes should be necessary)

To use the Teensy code open a serial terminal to access it, press 't' to send a long packet, or any other character to send a shorter one.

  • In future please use "code quoting" for referencing include directives. As you can see from your post (unless it is fixed now) things in angled brackets are treated as HTML and don't render properly. – Nick Gammon Sep 11 '15 at 5:42
  • Your code is short enough to include in the post. Please post it rather than sending people of to GitHub for short amounts of simple code. Use "code formatting" - select the code and hit Ctrl+K to indent if four spaces and then it should be very readable. – Nick Gammon Sep 11 '15 at 5:44
1

Your code which I will reproduce here as it wasn't in the question has a major issue:

//#include <DmxSimple.h>

#include <Wire.h>

boolean pinout = 0;
byte current[512];

void setup() {
  // put your setup code here, to run once:
  Wire.begin(1);
  Serial.begin(115200);
  Wire.onReceive(data);
  //DmxSimple.usePin(3);
  //DmxSimple.maxChannel(30);
}

void loop() {

}

void data(int numBytes){
  //Serial.println("DATA RECIVED");

  delay(500);

  char input[20];
  int pos = 0;

  while(Wire.available()){
    input[pos++] = Wire.read();
  }
  input[pos++] = '\0';

  Serial.print("Recived \"");
  Serial.print(input);
  Serial.println("\"");

  char* next = strchr(input, ',');
  while(next != 0){  
   *next = 0;
   next++;
    char* splitter = strchr(next, ':');
    if(splitter != 0){
      *splitter = 0;      Wire.onReceive(data);
  //DmxSimple.usePin(3);
  //DmxSimple.maxChannel(30);
}

Your function data does Serial.prints. It is called as an interrupt service routine effectively, and thus should not do serial prints:

      Wire.onReceive(data);
    }

    void loop() {

    }

    void data(int numBytes){

...

      Serial.print("Recived \"");
      Serial.print(input);
      Serial.println("\"");

More strange even is that if I send the longer data again I receive none, ...

Yep, that will definitely happen. The serial printing "blocks" if you print a lot, and thus the code will hang indefinitely.


  delay(500);

You definitely should not use delay in an interrupt routine. It will almost certainly hang because the timer interrupts which are needed for delay to work are not being serviced.


  Wire.begin(1);

You should not be choosing to use I2C address 1. It is reserved. See:

7-bit, 8-bit, and 10-bit I2C Slave Addressing and I2C specification (pdf)

Slave Address   R/W Bit     Description
000 0000    0   General call address
000 0000    1   START byte(1)
000 0001    X   CBUS address(2)
000 0010    X   Reserved for different bus format (3)
000 0011    X   Reserved for future purposes
000 01XX    X   Hs-mode master code
111 10XX    X   10-bit slave addressing
111 11XX    X   Reserved for future purposes

(1) No device is allowed to acknowledge at the reception of the START byte.

(2) The CBUS address has been reserved to enable the inter-mixing of CBUS compatible and I2C-bus compatible devices in the same system. I2C-bus compatible devices are not allowed to respond on reception of this address.

(3) The address reserved for a different bus format is included to enable I2C and other protocols to be mixed. Only I2C-bus compatible devices that can work with such formats and protocols are allowed to respond to this address.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.