I'm trying to make a head tracker module that will use a MPU9150 IMU to measure head position, and send PPM signals to my radio transmitter via the trainer port using a 3.3V Pro Mini. The PPM timing code that I found uses Timer1, but I have a feeling that the timer is used by my I2C communication. When I comment out the section that changes Timer1, the code runs fine but I cannot get the PPM signal to generate without using the timer interrupt. Can anyone suggest a way I can get the interrupt at 22mS to run as well as I2C?
Code Below:
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#include "Wire.h"
//#include <Servo.h>
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"
// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;
int outPinPPM = 9;
int Fixed_uS = 300; // PPM frame fixed LOW phase
int pulseMin = 650;
int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;
int ch1;
int ch2;
int ch3 = 700;
int ch4 = 800;
int ch5 = 900;
int ch6 = 1000;
int ch7 = 1100;
int ch8 = 1200;
int timing = 22000;
int padding;
#define LED_PIN 13
bool blinkState = false;
unsigned long time;
unsigned long oldtime;
ISR(TIMER1_COMPA_vect) {
ppmoutput(); // Jump to ppmoutput subroutine
}
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
Wire.begin();
// initialize serial communication
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
// it's really up to you depending on your project)
Serial.begin(38400);
// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
pinMode(outPinPPM, OUTPUT); // sets the digital pin as output
oldtime = micros();
// Setup timer
TCCR1A = B00110001; // Compare register B used in mode '3'
TCCR1B = B00010010; // WGM13 and CS11 set to 1
TCCR1C = B00000000; // All set to 0
TIMSK1 = B00000010; // Interrupt on compare B
TIFR1 = B00000010; // Interrupt on compare B
OCR1A = 22000; // 22mS PPM output refresh
OCR1B = 1000;
}
void loop() {
// read raw accel/gyro measurements from device
accelgyro.getMotion9(&ax, &ay, &az, &gx, &gy, &gz, &mx, &my, &mz);
// these methods (and a few others) are also available
//accelgyro.getAcceleration(&ax, &ay, &az);
//accelgyro.getRotation(&gx, &gy, &gz);
// display tab-separated accel/gyro x/y/z values
ch1 = (map(ay, -17000, 17000, 0,1000) * 1) + pulseMin;
if(mx<=0){
ch2 = (map(my, 0, 120, 0,500) * 1) + pulseMin;
}else{
ch2 = 1000 - (map(my, 0, 120, 0,500) * 1) + pulseMin;
}
Serial.print("a/g/m:\t");
Serial.print(ch1); Serial.print("\t");
Serial.print(ch2); Serial.print("\t");
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.print(az); Serial.print("\t");
Serial.print(mx); Serial.print("\t");
Serial.print(my); Serial.print("\t");
Serial.print(mz); Serial.print("\t");
Serial.print(gx); Serial.print("\t");
Serial.print(gy); Serial.print("\t");
Serial.print(gz);Serial.print("\n");
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
void ppmoutput() { // PPM output sub
// Channel 1 - Aeleron
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch1); // Hold for Aeleron_uS microseconds
// Channel 2 - Elevator
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch2); // Hold for Elevator_uS microseconds
// Channel 3 - Throttle
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch3); // Hold for Throttle_uS microseconds
// Channel 4 - Rudder
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch4); // Hold for Rudder_uS microseconds
// Channel 5
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch5);
// Channel 6
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch6);
// Channel 7
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch7);
// Channel 8
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS); // Hold
digitalWrite(outPinPPM, HIGH);
delayMicroseconds(ch8);
digitalWrite(outPinPPM, LOW);
delayMicroseconds(Fixed_uS);
digitalWrite(outPinPPM, HIGH);
}
The part that I comment out to get it to work is:
TCCR1A = B00110001; // Compare register B used in mode '3'
TCCR1B = B00010010; // WGM13 and CS11 set to 1
TCCR1C = B00000000; // All set to 0
TIMSK1 = B00000010; // Interrupt on compare B
TIFR1 = B00000010; // Interrupt on compare B
OCR1A = 22000; // 22mS PPM output refresh
OCR1B = 1000;