momemarian
Member
I am trying to read the data off of an IMU3000 Gyro and KXTF9 accelerometer chip through I2C using teensy 3.1. Teensy and the IMU do communicate, however the data read is wrong. The exact same code runs fine on arduino Uno and Leonardo. I have tried both the wire library for Teensy and the i2c_t3 library provided by nox771 and they both have the same issue. I have looked at the SDA/SCL signals on the scope on both arduino and Teensy and one difference that I noticed was that, with the arduino, the scl line is pulled high for two to three clocks after the 7 bit address is sent. After the delay, the 8bit data byte shows up on the SDA line. However for the teensy that 2 or 3 clocks delay does not exits and the data byte comes up on the SDA line in the next clock cycle after the ACK bit of the 7bit address. I have tried both 400kHz and 100kHz. I also tried 24Mhz and 48MHz CPU clocks and nothing made a difference. Below is my code. The code is setup to read the sensors at 80Hz. I am really out of troubleshooting ideas for this.
Code:
#define GYRO 0x68 // gyro I2C address
#define IMU3000_SLAVE_ACC_ADR 0x14 // IMU-3000 Register address for the Acc sensor addrees
#define IMU3000_SAMPLE_RATE 0x15 // IMU-3000 Register address for the sampling rate divider
#define IMU3000_DATA_RANGE 0x16 // IMU-3000 Register address for analog sample rate and data range
#define IMU3000_ACC_DATA_START_ADR 0x18 // IMU-3000 Register address for acc semsor data start address
#define IMU3000_AUX_DMP_CONTROL 0x3D // IMU-3000 Register address for controling digital motion processor and the aux device
#define IMU3000_X_DATA 0x1D // IMU-3000 Register address for GYRO_XOUT_H
#define ACCEL 0x0F // Accel I2c Address
#define KXTF9_FILT_REG 0x21 // Data control reg addr
#define KXTF9_HPFHZ_50 0x00 // HPF roll off at 100 Hz
#define KXTF9_LPFHZ_400 0x06 // LPF roll off at 25 hz
#define KXTF9_POWER_CTL 0x1B // Power control reg addr
#define KXTF9_PC0 0x80 // Operating mode bit
#define KXTF9_RES 0x40 // Resolution bit
#define KXTF9_GS2G 0x00 // bits for 2G mode
#define KXTF9_GS4G 0x08 // bits for 4G mode
#define KXTF9_GS8G 0x10 // bits for 8G mode
IntervalTimer syncTimer;
byte buffer[12]; // Array to store ADC values
int gyro_x;
int gyro_y;
int gyro_z;
int accel_x;
int accel_y;
int accel_z;
boolean stopRun = false;
boolean valveState = false;
const int stopSwitch = 7;
const int valvePin = 11;
const int scopeDebug = 8;
unsigned int controlTime = 0;
unsigned int controlTime2 = 0;
volatile boolean Tik = false;
boolean preTik = false;
int i;
int machine = 0;
char str[64];
#include <i2c_t3.h>
void setup()
{
Serial.begin(115200);
Serial.write('S');
while(Serial.available() == 0)
{
}
pinMode(valvePin, OUTPUT);
pinMode(stopSwitch, INPUT);
pinMode(scopeDebug,OUTPUT);
// initialize timer1 on arduino
// noInterrupts(); // disable all interrupts
// TCCR1A = 0;
// TCCR1B = 0;
// TCNT1 = 0;
// //78
// OCR1A = 75; // compare match register 16MHz/256/2Hz
// TCCR1B |= (1 << WGM12); // CTC mode
// TCCR1B |= (1 << CS12); // 256 prescaler
// TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
// interrupts(); // enable all interrupts
//
// initialize timer1 on Teensy 3.1
syncTimer.begin(timerCallback1,12500);
Wire.begin();
// Set Gyro settings
writeTo(GYRO, IMU3000_SLAVE_ACC_ADR, ACCEL); // set accel i2c slave address
writeTo(GYRO, IMU3000_SAMPLE_RATE, 0x09); // set gyro sampling rate to 800Hz
writeTo(GYRO, IMU3000_DATA_RANGE, 0x18); // Analog Sample Rate 8kHz, Gyro Range 2000 d/s
writeTo(GYRO, IMU3000_ACC_DATA_START_ADR , 0x06); // set accel register data address
writeTo(GYRO, IMU3000_AUX_DMP_CONTROL, 0x08); // Set passthrough mode to Accel so we can turn it on
writeTo(ACCEL, KXTF9_POWER_CTL, KXTF9_PC0); // set KXTF9 to opertaing mode, set to measure +/- 8G
writeTo(ACCEL, KXTF9_POWER_CTL, KXTF9_PC0 | KXTF9_RES| KXTF9_GS8G); // set LPF to 25 hz and HPF to 100
writeTo(ACCEL, KXTF9_FILT_REG, KXTF9_HPFHZ_50 | KXTF9_LPFHZ_400);
writeTo(GYRO, IMU3000_AUX_DMP_CONTROL, 0xEE); //cancel pass through to accel, gyro will now read accel for us
}
//ISR(TIMER1_COMPA_vect){
// Tik = !Tik;
//}
void timerCallback1() {
Tik = !Tik;
}
void loop()
{
if(digitalRead(stopSwitch))
{
stopRun = true;
Serial.write("FFFFFFFFFFFF");
}
else if(!stopRun)
{
if (Tik != preTik)
{
digitalWrite(scopeDebug,LOW);
// First set the register start address for X on Gyro
Wire.beginTransmission(GYRO);
Wire.write(IMU3000_X_DATA); //Register Address GYRO_XOUT_H
Wire.endTransmission();
// New read the 12 data bytes
Wire.beginTransmission(GYRO);
Wire.requestFrom(GYRO,12); // Read 12 bytes
i = 0;
while(Wire.available())
{
buffer[i] = Wire.read();
// Serial.write(buffer[i]);
i++;
}
Wire.endTransmission();
Serial.write(buffer,12);
controlTime ++;
preTik = Tik;
digitalWrite(scopeDebug,HIGH);
}
if (controlTime>80)
{
if (!valveState)
{
valveState = true;
digitalWrite(valvePin,HIGH);
}
else
{
valveState = false;
digitalWrite(valvePin,LOW);
}
controlTime = 0;
}
}
}
// Write a value to address register on device
void writeTo(int device, byte address, byte val) {
Wire.beginTransmission(device); // start transmission to device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); // end transmission
}