I2C between Arduino Mega and Pololu A-Star 32U4 Mini LV delay function

Hi All,

I am trying to run I2C between an Arduino Mega and a Pololu A-Star 32U4 Mini LV board. I have the Arduino Mega configured as a master and the Pololu board as a slave. I am sending a string through the Wire library to the Pololu board, which the Pololu board then parses to find a number, converts it to an int and passes to the delay() function. The Pololu board is hooked up to a DC motor and I am using the delay() function to control how long the motor stays on for.

The problem is, when I do input the same string (with the same formatting) over Serial, the motor rotates for the proper period of time. When I do the same thing but pass the string over I2C, the motor turns on for a fraction of a second then turns off (its supposed to be on for around 1 or 2 seconds). If I try to do the same thing using the millis() function and a while loop to control the motor's turning duration, I have the opposite problem of the motor running infinitely long and never stopping. Does anyone have any ideas as to why this may be? I've been stumped on this for a week and would really appreciate any help!

Thanks!

Sounds like your transmogrifier isn't frobbing the bits right. You should post your code so we can check that first. :smiley:

Seriously though, it's really difficult to debug code without being able to look at it.

josh_d:
Sounds like your transmogrifier isn't frobbing the bits right. You should post your code so we can check that first. :smiley:

Seriously though, it's really difficult to debug code without being able to look at it.

Are you sure it wasn't the Framistat? :o

Chuck.

Sorry about that. The code I am using is as follows for the master (Arduino Mega):

# include <Wire.h>

String data="2000";

void setup() {
  // put your setup code here, to run once:
  Wire.begin(); //join I2C as master
}

void loop() {
  // put your main code here, to run repeatedly:
  Wire.beginTransmission(4);
  Wire.write(data.c_str());
  Wire.endTransmission();
  delay(5000);
}

and for the slave (Pololu board):

# include <Wire.h>

long value=0;

void setup() {
  // put your setup code here, to run once:
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
  pinMode(12, OUTPUT);
}

void loop() {
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  String data = "";
  while(Wire.available()) {
    data += (char)Wire.read();
    Serial.println(data);
  }

  Serial.println(data);
  
  value=data.toInt();
//  value=long(data.toInt());
  Serial.print("value = ");
  Serial.println(value);      // print the integer
  digitalWrite(12, HIGH);
  delay(value);
  digitalWrite(12, LOW);
}

The serial monitor output is as follows:

2
20
200
2000
2000
value = 2000
2
20
200
2000
2000
value = 2000
2
20
200
2000
2000
value = 2000

So, clearly the master is sending the string to the slave. The slave receives it and is successfully converting it to an integer BUT when I pass it into the delay function, the LED that I have hooked up to pin 12 blinks for an instant then turns off (definitely not for 2 seconds).

Solved!

I’ll post this so that it helps anyone else who has the same question. When working with an Interrupt Handler Function (like the receiveEvent() function in my code), care should be taken so that the function runs for as short as possible. So, I modified my slave (Pololu) side code as follows:

# include <Wire.h>
# include <limits.h>

volatile int value=0;
volatile long int TimeLEDWentOn=ULONG_MAX;

void setup() {
  // put your setup code here, to run once:
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
  pinMode(12, OUTPUT);
}

void loop() {
  // Check if it is time to turn the LED off
  if (millis()-TimeLEDWentOn >= value) {
    digitalWrite(12, LOW);  
  }
  Serial.println(millis()-TimeLEDWentOn);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  String data = "";
  while(Wire.available()) {
    data += (char)Wire.read();
  }

  Serial.print("data = ");
  Serial.println(data);
  
  value=data.toInt();
  Serial.print("value = ");
  Serial.println(value, DEC);      // print the integer

  digitalWrite(12, HIGH);
  TimeLEDWentOn=millis();
}

I bet the Save was more from this

volatile

which you didn't mention changing, than from making the ISR short.