Hello All,
I am trying to use the CTC Output Compare Interrupt to update sensor values for a robot that I am building. I am trying to troubleshoot an issue that I am having where the ISR will not work if the functions pulseIn() and compass.ReadRawAxis() are called within the ISR (see attached code). I have functions heading() and ping_ultrasonic_sensors() being called inside the ISR. These functions in turn call the functions pulseIn() and compass.ReadRawAxis(). If I don't comment these two functions out, the program will not run and get stuck in the ISR. If I comment the two functions out, the program will work just fine. Of course, I have the option to move the functions heading() and ping_ultrasonic_sensors() inside the loop function, but I would like to get these guys working within an ISR. Any suggestions?
Note: I apologize the half commented code. However, most of it should be pretty easy to interpret.
[#include <HMC5883L.h>
#include <Wire.h>
#include<Serial.h>
HMC5883L compass;
float initial_heading=0;
float heading=0;
float headingDegrees=0;
unsigned long Ave1 = 0;
unsigned long Ave2 = 0;
unsigned long Ave3 = 0;
unsigned long Time_L = 0; //Variable for the time reading of the left sonic sensor
unsigned long Time_R = 0; //Variable for the time reading of the right sonic sensor
void ping_ultrasonic_sensors()
{
unsigned long sum1 = 0;
unsigned long sum2 = 0;
unsigned long sum3 = 0;
int test = 1;
do{
DDRD|=_BV(0); //Sets pin 6 of PORTD to output
PORTD&=~_BV(0); //Sets the voltage on pin 6 of PORTD to low
delayMicroseconds(100); //Delays for 2 microseconds
PORTD|=_BV(0); //Sets the voltage on pin 6 of PORTD to high
delayMicroseconds(20); //Delays for 5 microseconds
PORTD&=~_BV(0); //Sets the voltage on pin 6 of PORTD to low
DDRD&=~_BV(0); //Sets pin 6 of PORTD to input
Time_L = pulseIn(0, HIGH); //Waits for the returning pulse, stores time
sum1 = sum1 + Time_L;
Ave1 = sum1/test;
DDRD|=_BV(1); //Sets pin 6 of PORTD to output
PORTD&=~_BV(1); //Sets the voltage on pin 6 of PORTD to low
delayMicroseconds(100); //Delays for 2 microseconds
PORTD|=_BV(1); //Sets the voltage on pin 6 of PORTD to high
delayMicroseconds(20); //Delays for 5 microseconds
PORTD&=~_BV(1); //Sets the voltage on pin 6 of PORTD to low
DDRD&=~_BV(1); //Sets pin 6 of PORTD to input
Time_R = pulseIn(1, HIGH); //Waits for the returning pulse, stores time
sum2 = sum2 + Time_R;
Ave2 = sum2/test;
DDRD|=_BV(2); //Sets pin 6 of PORTD to output
PORTD&=~_BV(2); //Sets the voltage on pin 6 of PORTD to low
delayMicroseconds(100); //Delays for 2 microseconds
PORTD|=_BV(2); //Sets the voltage on pin 6 of PORTD to high
delayMicroseconds(20); //Delays for 5 microseconds
PORTD&=~_BV(2); //Sets the voltage on pin 6 of PORTD to low
DDRD&=~_BV(2); //Sets pin 6 of PORTD to input
Time_L = pulseIn(2, HIGH); //Waits for the returning pulse, stores time
sum3 = sum3 + Time_L;
Ave3 = sum3/test;
test = test + 1;
}while(test < 5);
}
void get_heading()
{
MagnetometerRaw raw = compass.ReadRawAxis();
MagnetometerScaled scaled = compass.ReadScaledAxis();
heading = atan2(raw.YAxis, raw.XAxis);
if(heading < 0)
heading += 2*PI;
headingDegrees = heading * 180/M_PI;
}
void cancle_PWM()
{
analogWrite(5,0); //Cancles all motor PWM's
analogWrite(6,0);
analogWrite(9,0);
analogWrite(10,0);
}
void cancle_signals()
{
PORTB&=~(_BV(4) | _BV(5)); //Cancles all transistor signals
PORTD&=~(_BV(4) | _BV(7));
}
void turn_left()
{
cancle_signals();
PORTB |= _BV(4);
PORTD |= _BV(7);
cancle_PWM();
analogWrite(11,255); //Enables right side motor
analogWrite(5,150); //Enables left side motor
}
void turn_right()
{
cancle_signals();
PORTB |= _BV(4);
PORTD |= _BV(7);
cancle_PWM();
analogWrite(11,150); //Enables right side motor
analogWrite(5,255); //Enables left side motor
}
void go_back()
{
cancle_signals();
PORTB |= _BV(5);
PORTD |= _BV(4);
cancle_PWM();
analogWrite(9,255); //Enables right side motor
analogWrite(6,255); //Enables left side motor
}
void go_straight()
{
cancle_signals();
PORTB |= _BV(4);
PORTD |= _BV(7);
cancle_PWM();
analogWrite(11,255); //Enables right side motor
analogWrite(5,255); //Enables left side motor
}
ISR(TIMER1_COMPA_vect)
{
//Serial.println("A");
ping_ultrasonic_sensors();
get_heading();
}
void AD_setup(void)
{
ADMUX=_BV(5) | _BV(6); //left aligned conv., 5V ref
ADCSRA=_BV(0) | _BV(1) | _BV(2) | _BV(4) | _BV(7); //128 Prescalar, clear ADC flag, enables AD conversions
}
void Timer1_ISR_setup(void)
{
cli();
TCCR1A= 0;
TCCR1B=_BV(1) | _BV(3); //Sets a prescalar of 8 and puts timer in CTC mode
OCR1A=20000; //Sets OCR1A register to give 10 ms delay
TIFR1=_BV(1); //Clears compare flag
TIMSK1|=_BV(1); //Sets output compare interrupt
sei();
}
void setup()
{
delay(5000);
Serial.begin(9600);
DDRB = 0xFF; //Sets all ports in PORTB to outputs
DDRD = 0xFF; //Sets all ports in PORTD to outputs
PORTB|=_BV(0);
Timer1_ISR_setup();
AD_setup();
Wire.begin();
compass = HMC5883L();
compass.SetScale(1.3);
MagnetometerRaw raw = compass.ReadRawAxis();
MagnetometerScaled scaled = compass.ReadScaledAxis();
heading = atan2(raw.YAxis, raw.XAxis);
if(heading < 0)
heading += 2*PI;
initial_heading = heading * 180/M_PI;
}
void loop()
{
Serial.println(initial_heading);
Serial.println(headingDegrees);
Serial.println(" ");
/*
if((heading - initial_heading) < -5){
turn_right();
}else if((heading - initial_heading > 5)){
turn_left();
}else{
go_straight();
}
if(Ave2 < 800){
cancle_PWM();
}*/
}]