Skip to main content

I count the number of rising edges using counter0counter0 and counter5counter5 (on Arduino Mega 2560), which works fine by itself, but when I combine that code with other parts of my code, many things stop working and I can't figure out why. My current guess is that it is related to timer0.

Edit:Edit: Here's more information about the project:
In

In the project, I use a behavior based controller to build a differential drive robot that goes to some goal coordinates while avoiding obstacles.
The

The speed measurement is done using speed encoders and optocouplers. those values are also used for updating the position and heading of the robot. It runs every 210 milliseconds. The

The obstacle distance is measured using 7 ultrasonic sensors that are controlled using pin change interrupts.
The

The only external libraries that I use are TimerOne.hTimerOne.h and TimerThree.hTimerThree.h (which do not use timer0timer0) and I made sure not to use timer0 timer0 (at least directly) in the parts that I wrote myself.
My

My code is interrupt-driven, so I wonder if that could also be a cause for the wrong behavior.

I count the number of rising edges using counter0 and counter5 (on Arduino Mega 2560), which works fine by itself, but when I combine that code with other parts of my code, many things stop working and I can't figure out why. My current guess is that it is related to timer0.

Edit: Here's more information about the project:
In the project, I use a behavior based controller to build a differential drive robot that goes to some goal coordinates while avoiding obstacles.
The speed measurement is done using speed encoders and optocouplers. those values are also used for updating the position and heading of the robot. It runs every 210 milliseconds. The obstacle distance is measured using 7 ultrasonic sensors that are controlled using pin change interrupts.
The only external libraries that I use are TimerOne.h and TimerThree.h (which do not use timer0) and I made sure not to use timer0 (at least directly) in the parts that I wrote myself.
My code is interrupt-driven, so I wonder if that could also be a cause for the wrong behavior.

I count the number of rising edges using counter0 and counter5 (on Arduino Mega 2560), which works fine by itself, but when I combine that code with other parts of my code, many things stop working and I can't figure out why. My current guess is that it is related to timer0.

Edit: Here's more information about the project:

In the project, I use a behavior based controller to build a differential drive robot that goes to some goal coordinates while avoiding obstacles.

The speed measurement is done using speed encoders and optocouplers. those values are also used for updating the position and heading of the robot. It runs every 210 milliseconds.

The obstacle distance is measured using 7 ultrasonic sensors that are controlled using pin change interrupts.

The only external libraries that I use are TimerOne.h and TimerThree.h (which do not use timer0) and I made sure not to use timer0 (at least directly) in the parts that I wrote myself.

My code is interrupt-driven, so I wonder if that could also be a cause for the wrong behavior.

#include "definitions.h"    // contains constants that should be accessible by many files
#include "diff_cntrl.h"     // controls the wheels (left and right speed) uses timer0 and timer5 for speed measurement
#include <TimerThree.h>     // used for generating timer interrupts for the differential control
#include "A7.h"             // used for commmunication using an A7 module through Serial1
#include "M_Ultrasonics.h"  // measures distance from 7 ultrasonic sensors using pin change interrupts on A8 - A14 (PORTK) and TimerOne.h
#include "FuzzyBBC.h"       // a fuzzy logic behavior-based controller (does only floating point computations

volatile double dists[NUM_US]; // array where the obstacle distances will be stored
volatile uint8_t   done = 0;   // flag set by M_Ultrasonics.h when all 7 seven distances are measured
FuzzyBBC fbbc;                 // reference to the behavior based controller

volatile double xG = 0, yG = 0; // coordinates of the goal


volatile double v = 0, w = 0;   // desired velocity and angular velocity. set by fbbc and used by the differential controller

// variables holding the current state of the
volatile double x = 0, y = 0, phi = 0; // coordinates and heading

volatile double dx, dy, dphi;   // changes in coordinates and heading (used for debugging

// variables used for the speed control of the motors: reference speed, actual speed, counter value, output voltage for left and right motors
volatile double l_ref = 0, l_spd = 0, r_ref = 0, r_spd = 0;
volatile uint8_t l_ctr = 0, r_ctr = 0;
volatile uint8_t l_volt = 0, r_volt = 0;

volatile boolean newvolt = true;  // flag set when a new voltage value is computed

volatile boolean updated = false; // flag set to allow transmission of data to the remote machine
volatile uint8_t update_count = 0;

//------------debug variables-----------------
volatile double dvl, dvr;
//--------------------------------------------
void setup()
{
  delay(5000);
  A7begin();    // starts up the A7 module and connects to a predefined remote machine
  initMotors(); // initialize the pins for the motor control (I use an LM293D motor driver)
  setup_cntr(); // set the registers for timer0 and timer5
//  vw2lr();

  fbbc.begin(&xG, &yG, NUM_US, dists, &x, &y, &phi, &v, &w);  // starting the fuzzy logic controller, it has direct access to the provided variables
  HCRS04.begin(T_US, dists, &done);   // starting the ultrasonic sensors controller (it runs every 30 millisecond
  
  Timer3.initialize(T_MOTOR*1000L);   // timer interrupts for the speed control (T_MOTOR = 210 milliseconds)
  Timer3.attachInterrupt(cntrISR);
}

void loop() {
  if(done)    // wait for obstacle distances to be updated
  {
    arbiter();  // update v and w
    if(updated && !waiting){    // send data to the remote machine 
      String info = "v: " + String(v) + "\tw: " + String(w) +
                    "\t\tvl: " + String(l_spd) + "\tlref: " + String(l_ref) + "\tlvolt: " + String(l_volt) +
                    "\t\tvr: " + String(r_spd) + "\trref: " + String(r_ref) + "\trvolt: " + String(r_volt) +
                    "\t\tx: " + String(x) + "\ty: " + String(y) + "\txG: " + String(xG) + "\tyG: " + String(yG);
      LogInfo(info);
      updated = false;
 
    }
    done = false;
  }
  if (A7_STREAM.available() > 0) {    // receive input from the A7 module (Serial1)
    String msg = "";
    if(waiting){
      get_A7_resp();  // read the message (function in A7.h)
      msg = resp;     // save the message (variable in A7.h)
      resp = "";
    }
    else{
      msg = readStr();
    }
    if (msg.length() > 2)   // process the received message
    {
      if (msg.substring(0, 2).equals("xy")) {
        readXYG(msg);
        resp = "";
      }
      else if(msg.equals("stop")){
        xG = x;
        yG = y;

        resp = "";
      }
      else if(msg.equals("+TCPCLOSE:0")){
        disconnected();
      }
    }
  }

}
inline void arbiter(){
  fbbc.arbiter();
  newvolt = true;
  vw2lr();  // convert v and w to left speed and right speed
}
inline void cntrISR() // ISR that runs every 210 milliseconds (for speed control)
{
  // compute the speed of the car
  read_rm();
  read_lm();
  ctr2lr();   // convert counter values to centimeter/second
  if (newvolt){
    spd2volt_init();
    newvolt = false;
  }
  else
    spd2volt();
  // update motor values
  analogWrite(L_PWM_PIN, l_volt);
  analogWrite(R_PWM_PIN, r_volt);

  updatePos();
}

inline void updatePos()   // compute new position (using differential drive kinematic equations)
{
  lr2xyphi();
}

inline void readXYG(String cmd) // get the new goal coordinates
{
  int sp1 = cmd.indexOf(' ');
  int sp2 = cmd.indexOf(' ', sp1 + 1);
  xG = (double)cmd.substring(sp1 + 1, sp2).toInt();
  yG = (double)cmd.substring(sp2 + 1, cmd.indexOf('~',sp2+1)).toInt();
}
#include "definitions.h"    // contains constants that should be accessible by many files
#include "diff_cntrl.h"     // controls the wheels (left and right speed) uses timer0 and timer5 for speed measurement
#include <TimerThree.h>     // used for generating timer interrupts for the differential control
#include "A7.h"             // used for commmunication using an A7 module through Serial1
#include "M_Ultrasonics.h"  // measures distance from 7 ultrasonic sensors using pin change interrupts on A8 - A14 (PORTK) and TimerOne.h
#include "FuzzyBBC.h"       // a fuzzy logic behavior-based controller (does only floating point computations

volatile double dists[NUM_US]; // array where the obstacle distances will be stored
volatile uint8_t   done = 0;   // flag set by M_Ultrasonics.h when all 7 seven distances are measured
FuzzyBBC fbbc;                 // reference to the behavior based controller

volatile double xG = 0, yG = 0; // coordinates of the goal


volatile double v = 0, w = 0;   // desired velocity and angular velocity. set by fbbc and used by the differential controller

// variables holding the current state of the
volatile double x = 0, y = 0, phi = 0; // coordinates and heading

volatile double dx, dy, dphi;   // changes in coordinates and heading (used for debugging

// variables used for the speed control of the motors: reference speed, actual speed, counter value, output voltage for left and right motors
volatile double l_ref = 0, l_spd = 0, r_ref = 0, r_spd = 0;
volatile uint8_t l_ctr = 0, r_ctr = 0;
volatile uint8_t l_volt = 0, r_volt = 0;

volatile boolean newvolt = true;  // flag set when a new voltage value is computed

volatile boolean updated = false; // flag set to allow transmission of data to the remote machine
volatile uint8_t update_count = 0;

//------------debug variables-----------------
volatile double dvl, dvr;
//--------------------------------------------
void setup()
{
  delay(5000);
  A7begin();    // starts up the A7 module and connects to a predefined remote machine
  initMotors(); // initialize the pins for the motor control (I use an LM293D motor driver)
  setup_cntr(); // set the registers for timer0 and timer5
//  vw2lr();

  fbbc.begin(&xG, &yG, NUM_US, dists, &x, &y, &phi, &v, &w);  // starting the fuzzy logic controller, it has direct access to the provided variables
  HCRS04.begin(T_US, dists, &done);   // starting the ultrasonic sensors controller (it runs every 30 millisecond
  
  Timer3.initialize(T_MOTOR*1000L);   // timer interrupts for the speed control (T_MOTOR = 210 milliseconds)
  Timer3.attachInterrupt(cntrISR);
}

void loop() {
  if(done)    // wait for obstacle distances to be updated
  {
    arbiter();  // update v and w
    if(updated && !waiting){    // send data to the remote machine 
      String info = "v: " + String(v) + "\tw: " + String(w) +
                    "\t\tvl: " + String(l_spd) + "\tlref: " + String(l_ref) + "\tlvolt: " + String(l_volt) +
                    "\t\tvr: " + String(r_spd) + "\trref: " + String(r_ref) + "\trvolt: " + String(r_volt) +
                    "\t\tx: " + String(x) + "\ty: " + String(y) + "\txG: " + String(xG) + "\tyG: " + String(yG);
      LogInfo(info);
      updated = false;
  
    }
    done = false;
  }
  if (A7_STREAM.available() > 0) {    // receive input from the A7 module (Serial1)
    String msg = "";
    if(waiting){
      get_A7_resp();  // read the message (function in A7.h)
      msg = resp;     // save the message (variable in A7.h)
      resp = "";
    }
    else{
      msg = readStr();
    }
    if (msg.length() > 2)   // process the received message
    {
      if (msg.substring(0, 2).equals("xy")) {
        readXYG(msg);
        resp = "";
      }
      else if(msg.equals("stop")){
        xG = x;
        yG = y;

        resp = "";
      }
      else if(msg.equals("+TCPCLOSE:0")){
        disconnected();
      }
    }
  }

}
inline void arbiter(){
  fbbc.arbiter();
  newvolt = true;
  vw2lr();  // convert v and w to left speed and right speed
}
inline void cntrISR() // ISR that runs every 210 milliseconds (for speed control)
{
  // compute the speed of the car
  read_rm();
  read_lm();
  ctr2lr();   // convert counter values to centimeter/second
  if (newvolt){
    spd2volt_init();
    newvolt = false;
  }
  else
    spd2volt();
  // update motor values
  analogWrite(L_PWM_PIN, l_volt);
  analogWrite(R_PWM_PIN, r_volt);

  updatePos();
}

inline void updatePos()   // compute new position (using differential drive kinematic equations)
{
  lr2xyphi();
}

inline void readXYG(String cmd) // get the new goal coordinates
{
  int sp1 = cmd.indexOf(' ');
  int sp2 = cmd.indexOf(' ', sp1 + 1);
  xG = (double)cmd.substring(sp1 + 1, sp2).toInt();
  yG = (double)cmd.substring(sp2 + 1, cmd.indexOf('~',sp2+1)).toInt();
}
inline void setup_cntr()
{
  pinMode(CTR0_PIN, INPUT_PULLUP);
  pinMode(CTR5_PIN, INPUT_PULLUP);
  TCNT5H = 0;
  TCNT5L = 0;
  TCCR5B = 0X07;
  TCNT0 = 0;
  TCCR0B = 0X07;
}

inline void initMotors(){
  pinMode(L_FWD_PIN, OUTPUT);
  pinMode(L_BACK_PIN, OUTPUT);
  pinMode(L_PWM_PIN, OUTPUT);
  pinMode(L_EN_PIN, OUTPUT);
  digitalWrite(L_EN_PIN, HIGH);
  digitalWrite(L_FWD_PIN, HIGH);
  digitalWrite(L_BACK_PIN, LOW);

  pinMode(R_FWD_PIN, OUTPUT);
  pinMode(R_BACK_PIN, OUTPUT);
  pinMode(R_PWM_PIN, OUTPUT);
  pinMode(R_EN_PIN, OUTPUT);
  digitalWrite(R_EN_PIN, HIGH);
  digitalWrite(R_FWD_PIN, HIGH);
  digitalWrite(R_BACK_PIN, LOW);
}
inline void setup_cntr()
{
  pinMode(CTR0_PIN, INPUT_PULLUP);
  pinMode(CTR5_PIN, INPUT_PULLUP);
  TCNT5H = 0;
  TCNT5L = 0;
  TCCR5B = 0X07;
  TCNT0 = 0;
  TCCR0B = 0X07;
}

inline void initMotors(){
  pinMode(L_FWD_PIN, OUTPUT);
  pinMode(L_BACK_PIN, OUTPUT);
  pinMode(L_PWM_PIN, OUTPUT);
  pinMode(L_EN_PIN, OUTPUT);
  digitalWrite(L_EN_PIN, HIGH);
  digitalWrite(L_FWD_PIN, HIGH);
  digitalWrite(L_BACK_PIN, LOW);

  pinMode(R_FWD_PIN, OUTPUT);
  pinMode(R_BACK_PIN, OUTPUT);
  pinMode(R_PWM_PIN, OUTPUT);
  pinMode(R_EN_PIN, OUTPUT);
  digitalWrite(R_EN_PIN, HIGH);
  digitalWrite(R_FWD_PIN, HIGH);
  digitalWrite(R_BACK_PIN, LOW);
}
#include "M_Ultrasonics.h"

M_Ultrasonics HCRS04;
void measISR();
void trigISR();
M_Ultrasonics::M_Ultrasonics()
{
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT); // trigs: array containing the trigger pins of the ultrasonic sensors
    digitalWrite(trigs[i],LOW);
  }
}
void M_Ultrasonics::begin(uint32_t period, volatile double *dists_, volatile uint8_t *done_)
{ 
  Timer1.initialize(period*1000);
  Timer1.attachInterrupt(trigISR);
  dists = dists_;
  done = done_;
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT);
    digitalWrite(trigs[i],LOW);
    dists[i] = MAX_DIST;
  }
  enable_pci();
}
void M_Ultrasonics::end()
{ 
  Timer1.stop();
  Timer1.detachInterrupt();
  PCICR = 0;
}
inline void M_Ultrasonics::trig() // send the trigger signal to the sensor
{
  pinIndex ++;
  if(pinIndex == NUM_US)
  {
    pinIndex = 0;
    *done = 1;
  }
  set_pci();
  digitalWrite(trigs[pinIndex], HIGH);
  delayMicroseconds(ping);
  digitalWrite(trigs[pinIndex], LOW);
}
inline void M_Ultrasonics::enable_pci() // enable pin change interrupts on PORTK
{
  PCICR = 0x04;
}
inline void M_Ultrasonics::set_pci()  // activate interrupts for the current pin
{
  PCMSK2 = (1<<pinIndex);
}
inline unsigned long M_Ultrasonics::read_time() // convert the timer value to microseconds
{
  return (/*(TCNT1H<<8) | */TCNT1L) * F_CLOCK;
}
inline void M_Ultrasonics::meas()
{
  if(PINK & (1<<pinIndex)) {  // check if the pin is high
    s_echo = /*micros();/*/read_time();
    dists[pinIndex] = MAX_DIST*DOBST_COEFF;
  }
  else
  {
    f_echo =/* micros();/*/read_time();
//    d = (f_echo-s_echo)*soundSpeed/2E4;
    if(d < MAX_DIST) {
      dists[pinIndex] = d/**DOBST_COEFF*/;
    }
//    dists[pinIndex] = d; // (double)(f_echo - s_echo);
  }
}
ISR (PCINT2_vect) // handle pin change interrupt for A8 to A14 here
{
  measISR();
}
void measISR() // ISR called on rising or falling edge on the current pin
{
  HCRS04.meas();
}
void trigISR()  // function called every 30 millisecond to trigger the next ultrasonic sensor
{
  HCRS04.trig();
}
#include "M_Ultrasonics.h"

M_Ultrasonics HCRS04;
void measISR();
void trigISR();
M_Ultrasonics::M_Ultrasonics()
{
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT); // trigs: array containing the trigger pins of the ultrasonic sensors
    digitalWrite(trigs[i],LOW);
  }
}
void M_Ultrasonics::begin(uint32_t period, volatile double *dists_, volatile uint8_t *done_)
{ 
  Timer1.initialize(period*1000);
  Timer1.attachInterrupt(trigISR);
  dists = dists_;
  done = done_;
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT);
    digitalWrite(trigs[i],LOW);
    dists[i] = MAX_DIST;
  }
  enable_pci();
}
void M_Ultrasonics::end()
{ 
  Timer1.stop();
  Timer1.detachInterrupt();
  PCICR = 0;
}
inline void M_Ultrasonics::trig() // send the trigger signal to the sensor
{
  pinIndex ++;
  if(pinIndex == NUM_US)
  {
    pinIndex = 0;
    *done = 1;
  }
  set_pci();
  digitalWrite(trigs[pinIndex], HIGH);
  delayMicroseconds(ping);
  digitalWrite(trigs[pinIndex], LOW);
}
inline void M_Ultrasonics::enable_pci() // enable pin change interrupts on PORTK
{
  PCICR = 0x04;
}
inline void M_Ultrasonics::set_pci()  // activate interrupts for the current pin
{
  PCMSK2 = (1<<pinIndex);
}
inline unsigned long M_Ultrasonics::read_time() // convert the timer value to microseconds
{
  return (/*(TCNT1H<<8) | */TCNT1L) * F_CLOCK;
}
inline void M_Ultrasonics::meas()
{
  if(PINK & (1<<pinIndex)) {  // check if the pin is high
    s_echo = /*micros();/*/read_time();
    dists[pinIndex] = MAX_DIST*DOBST_COEFF;
  }
  else
  {
    f_echo =/* micros();/*/read_time();
//    d = (f_echo-s_echo)*soundSpeed/2E4;
    if(d < MAX_DIST) {
      dists[pinIndex] = d/**DOBST_COEFF*/;
    }
//    dists[pinIndex] = d; // (double)(f_echo - s_echo);
  }
}
ISR (PCINT2_vect) // handle pin change interrupt for A8 to A14 here
{
  measISR();
}
void measISR() // ISR called on rising or falling edge on the current pin
{
  HCRS04.meas();
}
void trigISR()  // function called every 30 millisecond to trigger the next ultrasonic sensor
{
  HCRS04.trig();
}
#include "definitions.h"    // contains constants that should be accessible by many files
#include "diff_cntrl.h"     // controls the wheels (left and right speed) uses timer0 and timer5 for speed measurement
#include <TimerThree.h>     // used for generating timer interrupts for the differential control
#include "A7.h"             // used for commmunication using an A7 module through Serial1
#include "M_Ultrasonics.h"  // measures distance from 7 ultrasonic sensors using pin change interrupts on A8 - A14 (PORTK) and TimerOne.h
#include "FuzzyBBC.h"       // a fuzzy logic behavior-based controller (does only floating point computations

volatile double dists[NUM_US]; // array where the obstacle distances will be stored
volatile uint8_t   done = 0;   // flag set by M_Ultrasonics.h when all 7 seven distances are measured
FuzzyBBC fbbc;                 // reference to the behavior based controller

volatile double xG = 0, yG = 0; // coordinates of the goal


volatile double v = 0, w = 0;   // desired velocity and angular velocity. set by fbbc and used by the differential controller

// variables holding the current state of the
volatile double x = 0, y = 0, phi = 0; // coordinates and heading

volatile double dx, dy, dphi;   // changes in coordinates and heading (used for debugging

// variables used for the speed control of the motors: reference speed, actual speed, counter value, output voltage for left and right motors
volatile double l_ref = 0, l_spd = 0, r_ref = 0, r_spd = 0;
volatile uint8_t l_ctr = 0, r_ctr = 0;
volatile uint8_t l_volt = 0, r_volt = 0;

volatile boolean newvolt = true;  // flag set when a new voltage value is computed

volatile boolean updated = false; // flag set to allow transmission of data to the remote machine
volatile uint8_t update_count = 0;

//------------debug variables-----------------
volatile double dvl, dvr;
//--------------------------------------------
void setup()
{
  delay(5000);
  A7begin();    // starts up the A7 module and connects to a predefined remote machine
  initMotors(); // initialize the pins for the motor control (I use an LM293D motor driver)
  setup_cntr(); // set the registers for timer0 and timer5
//  vw2lr();

  fbbc.begin(&xG, &yG, NUM_US, dists, &x, &y, &phi, &v, &w);  // starting the fuzzy logic controller, it has direct access to the provided variables
  HCRS04.begin(T_US, dists, &done);   // starting the ultrasonic sensors controller (it runs every 30 millisecond
  
  Timer3.initialize(T_MOTOR*1000L);   // timer interrupts for the speed control (T_MOTOR = 210 milliseconds)
  Timer3.attachInterrupt(cntrISR);
}

void loop() {
  if(done)    // wait for obstacle distances to be updated
  {
    arbiter();  // update v and w
    if(updated && !waiting){    // send data to the remote machine 
      String info = "v: " + String(v) + "\tw: " + String(w) +
                    "\t\tvl: " + String(l_spd) + "\tlref: " + String(l_ref) + "\tlvolt: " + String(l_volt) +
                    "\t\tvr: " + String(r_spd) + "\trref: " + String(r_ref) + "\trvolt: " + String(r_volt) +
                    "\t\tx: " + String(x) + "\ty: " + String(y) + "\txG: " + String(xG) + "\tyG: " + String(yG);
      LogInfo(info);
      updated = false;
 
    }
    done = false;
  }
  if (A7_STREAM.available() > 0) {    // receive input from the A7 module (Serial1)
    String msg = "";
    if(waiting){
      get_A7_resp();  // read the message (function in A7.h)
      msg = resp;     // save the message (variable in A7.h)
      resp = "";
    }
    else{
      msg = readStr();
    }
    if (msg.length() > 2)   // process the received message
    {
      if (msg.substring(0, 2).equals("xy")) {
        readXYG(msg);
        resp = "";
      }
      else if(msg.equals("stop")){
        xG = x;
        yG = y;

        resp = "";
      }
      else if(msg.equals("+TCPCLOSE:0")){
        disconnected();
      }
    }
  }

}
inline void arbiter(){
  fbbc.arbiter();
  newvolt = true;
  vw2lr();  // convert v and w to left speed and right speed
}
inline void cntrISR() // ISR that runs every 210 milliseconds (for speed control)
{
  // compute the speed of the car
  read_rm();
  read_lm();
  ctr2lr();   // convert counter values to centimeter/second
  if (newvolt){
    spd2volt_init();
    newvolt = false;
  }
  else
    spd2volt();
  // update motor values
  analogWrite(L_PWM_PIN, l_volt);
  analogWrite(R_PWM_PIN, r_volt);

  updatePos();
}

inline void updatePos()   // compute new position (using differential drive kinematic equations)
{
  lr2xyphi();
}

inline void readXYG(String cmd) // get the new goal coordinates
{
  int sp1 = cmd.indexOf(' ');
  int sp2 = cmd.indexOf(' ', sp1 + 1);
  xG = (double)cmd.substring(sp1 + 1, sp2).toInt();
  yG = (double)cmd.substring(sp2 + 1, cmd.indexOf('~',sp2+1)).toInt();
}
inline void setup_cntr()
{
  pinMode(CTR0_PIN, INPUT_PULLUP);
  pinMode(CTR5_PIN, INPUT_PULLUP);
  TCNT5H = 0;
  TCNT5L = 0;
  TCCR5B = 0X07;
  TCNT0 = 0;
  TCCR0B = 0X07;
}

inline void initMotors(){
  pinMode(L_FWD_PIN, OUTPUT);
  pinMode(L_BACK_PIN, OUTPUT);
  pinMode(L_PWM_PIN, OUTPUT);
  pinMode(L_EN_PIN, OUTPUT);
  digitalWrite(L_EN_PIN, HIGH);
  digitalWrite(L_FWD_PIN, HIGH);
  digitalWrite(L_BACK_PIN, LOW);

  pinMode(R_FWD_PIN, OUTPUT);
  pinMode(R_BACK_PIN, OUTPUT);
  pinMode(R_PWM_PIN, OUTPUT);
  pinMode(R_EN_PIN, OUTPUT);
  digitalWrite(R_EN_PIN, HIGH);
  digitalWrite(R_FWD_PIN, HIGH);
  digitalWrite(R_BACK_PIN, LOW);
}
#include "M_Ultrasonics.h"

M_Ultrasonics HCRS04;
void measISR();
void trigISR();
M_Ultrasonics::M_Ultrasonics()
{
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT); // trigs: array containing the trigger pins of the ultrasonic sensors
    digitalWrite(trigs[i],LOW);
  }
}
void M_Ultrasonics::begin(uint32_t period, volatile double *dists_, volatile uint8_t *done_)
{ 
  Timer1.initialize(period*1000);
  Timer1.attachInterrupt(trigISR);
  dists = dists_;
  done = done_;
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT);
    digitalWrite(trigs[i],LOW);
    dists[i] = MAX_DIST;
  }
  enable_pci();
}
void M_Ultrasonics::end()
{ 
  Timer1.stop();
  Timer1.detachInterrupt();
  PCICR = 0;
}
inline void M_Ultrasonics::trig() // send the trigger signal to the sensor
{
  pinIndex ++;
  if(pinIndex == NUM_US)
  {
    pinIndex = 0;
    *done = 1;
  }
  set_pci();
  digitalWrite(trigs[pinIndex], HIGH);
  delayMicroseconds(ping);
  digitalWrite(trigs[pinIndex], LOW);
}
inline void M_Ultrasonics::enable_pci() // enable pin change interrupts on PORTK
{
  PCICR = 0x04;
}
inline void M_Ultrasonics::set_pci()  // activate interrupts for the current pin
{
  PCMSK2 = (1<<pinIndex);
}
inline unsigned long M_Ultrasonics::read_time() // convert the timer value to microseconds
{
  return (/*(TCNT1H<<8) | */TCNT1L) * F_CLOCK;
}
inline void M_Ultrasonics::meas()
{
  if(PINK & (1<<pinIndex)) {  // check if the pin is high
    s_echo = /*micros();/*/read_time();
    dists[pinIndex] = MAX_DIST*DOBST_COEFF;
  }
  else
  {
    f_echo =/* micros();/*/read_time();
//    d = (f_echo-s_echo)*soundSpeed/2E4;
    if(d < MAX_DIST) {
      dists[pinIndex] = d/**DOBST_COEFF*/;
    }
//    dists[pinIndex] = d; // (double)(f_echo - s_echo);
  }
}
ISR (PCINT2_vect) // handle pin change interrupt for A8 to A14 here
{
  measISR();
}
void measISR() // ISR called on rising or falling edge on the current pin
{
  HCRS04.meas();
}
void trigISR()  // function called every 30 millisecond to trigger the next ultrasonic sensor
{
  HCRS04.trig();
}
#include "definitions.h"    // contains constants that should be accessible by many files
#include "diff_cntrl.h"     // controls the wheels (left and right speed) uses timer0 and timer5 for speed measurement
#include <TimerThree.h>     // used for generating timer interrupts for the differential control
#include "A7.h"             // used for commmunication using an A7 module through Serial1
#include "M_Ultrasonics.h"  // measures distance from 7 ultrasonic sensors using pin change interrupts on A8 - A14 (PORTK) and TimerOne.h
#include "FuzzyBBC.h"       // a fuzzy logic behavior-based controller (does only floating point computations

volatile double dists[NUM_US]; // array where the obstacle distances will be stored
volatile uint8_t   done = 0;   // flag set by M_Ultrasonics.h when all 7 seven distances are measured
FuzzyBBC fbbc;                 // reference to the behavior based controller

volatile double xG = 0, yG = 0; // coordinates of the goal


volatile double v = 0, w = 0;   // desired velocity and angular velocity. set by fbbc and used by the differential controller

// variables holding the current state of the
volatile double x = 0, y = 0, phi = 0; // coordinates and heading

volatile double dx, dy, dphi;   // changes in coordinates and heading (used for debugging

// variables used for the speed control of the motors: reference speed, actual speed, counter value, output voltage for left and right motors
volatile double l_ref = 0, l_spd = 0, r_ref = 0, r_spd = 0;
volatile uint8_t l_ctr = 0, r_ctr = 0;
volatile uint8_t l_volt = 0, r_volt = 0;

volatile boolean newvolt = true;  // flag set when a new voltage value is computed

volatile boolean updated = false; // flag set to allow transmission of data to the remote machine
volatile uint8_t update_count = 0;

//------------debug variables-----------------
volatile double dvl, dvr;
//--------------------------------------------
void setup()
{
  delay(5000);
  A7begin();    // starts up the A7 module and connects to a predefined remote machine
  initMotors(); // initialize the pins for the motor control (I use an LM293D motor driver)
  setup_cntr(); // set the registers for timer0 and timer5
//  vw2lr();

  fbbc.begin(&xG, &yG, NUM_US, dists, &x, &y, &phi, &v, &w);  // starting the fuzzy logic controller, it has direct access to the provided variables
  HCRS04.begin(T_US, dists, &done);   // starting the ultrasonic sensors controller (it runs every 30 millisecond
  
  Timer3.initialize(T_MOTOR*1000L);   // timer interrupts for the speed control (T_MOTOR = 210 milliseconds)
  Timer3.attachInterrupt(cntrISR);
}

void loop() {
  if(done)    // wait for obstacle distances to be updated
  {
    arbiter();  // update v and w
    if(updated && !waiting){    // send data to the remote machine 
      String info = "v: " + String(v) + "\tw: " + String(w) +
                    "\t\tvl: " + String(l_spd) + "\tlref: " + String(l_ref) + "\tlvolt: " + String(l_volt) +
                    "\t\tvr: " + String(r_spd) + "\trref: " + String(r_ref) + "\trvolt: " + String(r_volt) +
                    "\t\tx: " + String(x) + "\ty: " + String(y) + "\txG: " + String(xG) + "\tyG: " + String(yG);
      LogInfo(info);
      updated = false;
  
    }
    done = false;
  }
  if (A7_STREAM.available() > 0) {    // receive input from the A7 module (Serial1)
    String msg = "";
    if(waiting){
      get_A7_resp();  // read the message (function in A7.h)
      msg = resp;     // save the message (variable in A7.h)
      resp = "";
    }
    else{
      msg = readStr();
    }
    if (msg.length() > 2)   // process the received message
    {
      if (msg.substring(0, 2).equals("xy")) {
        readXYG(msg);
        resp = "";
      }
      else if(msg.equals("stop")){
        xG = x;
        yG = y;

        resp = "";
      }
      else if(msg.equals("+TCPCLOSE:0")){
        disconnected();
      }
    }
  }

}
inline void arbiter(){
  fbbc.arbiter();
  newvolt = true;
  vw2lr();  // convert v and w to left speed and right speed
}
inline void cntrISR() // ISR that runs every 210 milliseconds (for speed control)
{
  // compute the speed of the car
  read_rm();
  read_lm();
  ctr2lr();   // convert counter values to centimeter/second
  if (newvolt){
    spd2volt_init();
    newvolt = false;
  }
  else
    spd2volt();
  // update motor values
  analogWrite(L_PWM_PIN, l_volt);
  analogWrite(R_PWM_PIN, r_volt);

  updatePos();
}

inline void updatePos()   // compute new position (using differential drive kinematic equations)
{
  lr2xyphi();
}

inline void readXYG(String cmd) // get the new goal coordinates
{
  int sp1 = cmd.indexOf(' ');
  int sp2 = cmd.indexOf(' ', sp1 + 1);
  xG = (double)cmd.substring(sp1 + 1, sp2).toInt();
  yG = (double)cmd.substring(sp2 + 1, cmd.indexOf('~',sp2+1)).toInt();
}
inline void setup_cntr()
{
  pinMode(CTR0_PIN, INPUT_PULLUP);
  pinMode(CTR5_PIN, INPUT_PULLUP);
  TCNT5H = 0;
  TCNT5L = 0;
  TCCR5B = 0X07;
  TCNT0 = 0;
  TCCR0B = 0X07;
}

inline void initMotors(){
  pinMode(L_FWD_PIN, OUTPUT);
  pinMode(L_BACK_PIN, OUTPUT);
  pinMode(L_PWM_PIN, OUTPUT);
  pinMode(L_EN_PIN, OUTPUT);
  digitalWrite(L_EN_PIN, HIGH);
  digitalWrite(L_FWD_PIN, HIGH);
  digitalWrite(L_BACK_PIN, LOW);

  pinMode(R_FWD_PIN, OUTPUT);
  pinMode(R_BACK_PIN, OUTPUT);
  pinMode(R_PWM_PIN, OUTPUT);
  pinMode(R_EN_PIN, OUTPUT);
  digitalWrite(R_EN_PIN, HIGH);
  digitalWrite(R_FWD_PIN, HIGH);
  digitalWrite(R_BACK_PIN, LOW);
}
#include "M_Ultrasonics.h"

M_Ultrasonics HCRS04;
void measISR();
void trigISR();
M_Ultrasonics::M_Ultrasonics()
{
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT); // trigs: array containing the trigger pins of the ultrasonic sensors
    digitalWrite(trigs[i],LOW);
  }
}
void M_Ultrasonics::begin(uint32_t period, volatile double *dists_, volatile uint8_t *done_)
{ 
  Timer1.initialize(period*1000);
  Timer1.attachInterrupt(trigISR);
  dists = dists_;
  done = done_;
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT);
    digitalWrite(trigs[i],LOW);
    dists[i] = MAX_DIST;
  }
  enable_pci();
}
void M_Ultrasonics::end()
{ 
  Timer1.stop();
  Timer1.detachInterrupt();
  PCICR = 0;
}
inline void M_Ultrasonics::trig() // send the trigger signal to the sensor
{
  pinIndex ++;
  if(pinIndex == NUM_US)
  {
    pinIndex = 0;
    *done = 1;
  }
  set_pci();
  digitalWrite(trigs[pinIndex], HIGH);
  delayMicroseconds(ping);
  digitalWrite(trigs[pinIndex], LOW);
}
inline void M_Ultrasonics::enable_pci() // enable pin change interrupts on PORTK
{
  PCICR = 0x04;
}
inline void M_Ultrasonics::set_pci()  // activate interrupts for the current pin
{
  PCMSK2 = (1<<pinIndex);
}
inline unsigned long M_Ultrasonics::read_time() // convert the timer value to microseconds
{
  return (/*(TCNT1H<<8) | */TCNT1L) * F_CLOCK;
}
inline void M_Ultrasonics::meas()
{
  if(PINK & (1<<pinIndex)) {  // check if the pin is high
    s_echo = /*micros();/*/read_time();
    dists[pinIndex] = MAX_DIST*DOBST_COEFF;
  }
  else
  {
    f_echo =/* micros();/*/read_time();
//    d = (f_echo-s_echo)*soundSpeed/2E4;
    if(d < MAX_DIST) {
      dists[pinIndex] = d/**DOBST_COEFF*/;
    }
//    dists[pinIndex] = d; // (double)(f_echo - s_echo);
  }
}
ISR (PCINT2_vect) // handle pin change interrupt for A8 to A14 here
{
  measISR();
}
void measISR() // ISR called on rising or falling edge on the current pin
{
  HCRS04.meas();
}
void trigISR()  // function called every 30 millisecond to trigger the next ultrasonic sensor
{
  HCRS04.trig();
}
added more information about the project and code snippets
Source Link

Edit: Here's more information about the project:
In the project, I use a behavior based controller to build a differential drive robot that goes to some goal coordinates while avoiding obstacles.
The speed measurement is done using speed encoders and optocouplers. those values are also used for updating the position and heading of the robot. It runs every 210 milliseconds. The obstacle distance is measured using 7 ultrasonic sensors that are controlled using pin change interrupts.
The only external libraries that I use are TimerOne.h and TimerThree.h (which do not use timer0) and I made sure not to use timer0 (at least directly) in the parts that I wrote myself.
My code is interrupt-driven, so I wonder if that could also be a cause for the wrong behavior.

Here's the main code

#include "definitions.h"    // contains constants that should be accessible by many files
#include "diff_cntrl.h"     // controls the wheels (left and right speed) uses timer0 and timer5 for speed measurement
#include <TimerThree.h>     // used for generating timer interrupts for the differential control
#include "A7.h"             // used for commmunication using an A7 module through Serial1
#include "M_Ultrasonics.h"  // measures distance from 7 ultrasonic sensors using pin change interrupts on A8 - A14 (PORTK) and TimerOne.h
#include "FuzzyBBC.h"       // a fuzzy logic behavior-based controller (does only floating point computations

volatile double dists[NUM_US]; // array where the obstacle distances will be stored
volatile uint8_t   done = 0;   // flag set by M_Ultrasonics.h when all 7 seven distances are measured
FuzzyBBC fbbc;                 // reference to the behavior based controller

volatile double xG = 0, yG = 0; // coordinates of the goal


volatile double v = 0, w = 0;   // desired velocity and angular velocity. set by fbbc and used by the differential controller

// variables holding the current state of the
volatile double x = 0, y = 0, phi = 0; // coordinates and heading

volatile double dx, dy, dphi;   // changes in coordinates and heading (used for debugging

// variables used for the speed control of the motors: reference speed, actual speed, counter value, output voltage for left and right motors
volatile double l_ref = 0, l_spd = 0, r_ref = 0, r_spd = 0;
volatile uint8_t l_ctr = 0, r_ctr = 0;
volatile uint8_t l_volt = 0, r_volt = 0;

volatile boolean newvolt = true;  // flag set when a new voltage value is computed

volatile boolean updated = false; // flag set to allow transmission of data to the remote machine
volatile uint8_t update_count = 0;

//------------debug variables-----------------
volatile double dvl, dvr;
//--------------------------------------------
void setup()
{
  delay(5000);
  A7begin();    // starts up the A7 module and connects to a predefined remote machine
  initMotors(); // initialize the pins for the motor control (I use an LM293D motor driver)
  setup_cntr(); // set the registers for timer0 and timer5
//  vw2lr();

  fbbc.begin(&xG, &yG, NUM_US, dists, &x, &y, &phi, &v, &w);  // starting the fuzzy logic controller, it has direct access to the provided variables
  HCRS04.begin(T_US, dists, &done);   // starting the ultrasonic sensors controller (it runs every 30 millisecond
  
  Timer3.initialize(T_MOTOR*1000L);   // timer interrupts for the speed control (T_MOTOR = 210 milliseconds)
  Timer3.attachInterrupt(cntrISR);
}

void loop() {
  if(done)    // wait for obstacle distances to be updated
  {
    arbiter();  // update v and w
    if(updated && !waiting){    // send data to the remote machine 
      String info = "v: " + String(v) + "\tw: " + String(w) +
                    "\t\tvl: " + String(l_spd) + "\tlref: " + String(l_ref) + "\tlvolt: " + String(l_volt) +
                    "\t\tvr: " + String(r_spd) + "\trref: " + String(r_ref) + "\trvolt: " + String(r_volt) +
                    "\t\tx: " + String(x) + "\ty: " + String(y) + "\txG: " + String(xG) + "\tyG: " + String(yG);
      LogInfo(info);
      updated = false;
 
    }
    done = false;
  }
  if (A7_STREAM.available() > 0) {    // receive input from the A7 module (Serial1)
    String msg = "";
    if(waiting){
      get_A7_resp();  // read the message (function in A7.h)
      msg = resp;     // save the message (variable in A7.h)
      resp = "";
    }
    else{
      msg = readStr();
    }
    if (msg.length() > 2)   // process the received message
    {
      if (msg.substring(0, 2).equals("xy")) {
        readXYG(msg);
        resp = "";
      }
      else if(msg.equals("stop")){
        xG = x;
        yG = y;

        resp = "";
      }
      else if(msg.equals("+TCPCLOSE:0")){
        disconnected();
      }
    }
  }

}
inline void arbiter(){
  fbbc.arbiter();
  newvolt = true;
  vw2lr();  // convert v and w to left speed and right speed
}
inline void cntrISR() // ISR that runs every 210 milliseconds (for speed control)
{
  // compute the speed of the car
  read_rm();
  read_lm();
  ctr2lr();   // convert counter values to centimeter/second
  if (newvolt){
    spd2volt_init();
    newvolt = false;
  }
  else
    spd2volt();
  // update motor values
  analogWrite(L_PWM_PIN, l_volt);
  analogWrite(R_PWM_PIN, r_volt);

  updatePos();
}

inline void updatePos()   // compute new position (using differential drive kinematic equations)
{
  lr2xyphi();
}

inline void readXYG(String cmd) // get the new goal coordinates
{
  int sp1 = cmd.indexOf(' ');
  int sp2 = cmd.indexOf(' ', sp1 + 1);
  xG = (double)cmd.substring(sp1 + 1, sp2).toInt();
  yG = (double)cmd.substring(sp2 + 1, cmd.indexOf('~',sp2+1)).toInt();
}

the motor initialization code:

inline void setup_cntr()
{
  pinMode(CTR0_PIN, INPUT_PULLUP);
  pinMode(CTR5_PIN, INPUT_PULLUP);
  TCNT5H = 0;
  TCNT5L = 0;
  TCCR5B = 0X07;
  TCNT0 = 0;
  TCCR0B = 0X07;
}

inline void initMotors(){
  pinMode(L_FWD_PIN, OUTPUT);
  pinMode(L_BACK_PIN, OUTPUT);
  pinMode(L_PWM_PIN, OUTPUT);
  pinMode(L_EN_PIN, OUTPUT);
  digitalWrite(L_EN_PIN, HIGH);
  digitalWrite(L_FWD_PIN, HIGH);
  digitalWrite(L_BACK_PIN, LOW);

  pinMode(R_FWD_PIN, OUTPUT);
  pinMode(R_BACK_PIN, OUTPUT);
  pinMode(R_PWM_PIN, OUTPUT);
  pinMode(R_EN_PIN, OUTPUT);
  digitalWrite(R_EN_PIN, HIGH);
  digitalWrite(R_FWD_PIN, HIGH);
  digitalWrite(R_BACK_PIN, LOW);
}

ultrasonic sensors code:

#include "M_Ultrasonics.h"

M_Ultrasonics HCRS04;
void measISR();
void trigISR();
M_Ultrasonics::M_Ultrasonics()
{
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT); // trigs: array containing the trigger pins of the ultrasonic sensors
    digitalWrite(trigs[i],LOW);
  }
}
void M_Ultrasonics::begin(uint32_t period, volatile double *dists_, volatile uint8_t *done_)
{ 
  Timer1.initialize(period*1000);
  Timer1.attachInterrupt(trigISR);
  dists = dists_;
  done = done_;
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT);
    digitalWrite(trigs[i],LOW);
    dists[i] = MAX_DIST;
  }
  enable_pci();
}
void M_Ultrasonics::end()
{ 
  Timer1.stop();
  Timer1.detachInterrupt();
  PCICR = 0;
}
inline void M_Ultrasonics::trig() // send the trigger signal to the sensor
{
  pinIndex ++;
  if(pinIndex == NUM_US)
  {
    pinIndex = 0;
    *done = 1;
  }
  set_pci();
  digitalWrite(trigs[pinIndex], HIGH);
  delayMicroseconds(ping);
  digitalWrite(trigs[pinIndex], LOW);
}
inline void M_Ultrasonics::enable_pci() // enable pin change interrupts on PORTK
{
  PCICR = 0x04;
}
inline void M_Ultrasonics::set_pci()  // activate interrupts for the current pin
{
  PCMSK2 = (1<<pinIndex);
}
inline unsigned long M_Ultrasonics::read_time() // convert the timer value to microseconds
{
  return (/*(TCNT1H<<8) | */TCNT1L) * F_CLOCK;
}
inline void M_Ultrasonics::meas()
{
  if(PINK & (1<<pinIndex)) {  // check if the pin is high
    s_echo = /*micros();/*/read_time();
    dists[pinIndex] = MAX_DIST*DOBST_COEFF;
  }
  else
  {
    f_echo =/* micros();/*/read_time();
//    d = (f_echo-s_echo)*soundSpeed/2E4;
    if(d < MAX_DIST) {
      dists[pinIndex] = d/**DOBST_COEFF*/;
    }
//    dists[pinIndex] = d; // (double)(f_echo - s_echo);
  }
}
ISR (PCINT2_vect) // handle pin change interrupt for A8 to A14 here
{
  measISR();
}
void measISR() // ISR called on rising or falling edge on the current pin
{
  HCRS04.meas();
}
void trigISR()  // function called every 30 millisecond to trigger the next ultrasonic sensor
{
  HCRS04.trig();
}

Edit: Here's more information about the project:
In the project, I use a behavior based controller to build a differential drive robot that goes to some goal coordinates while avoiding obstacles.
The speed measurement is done using speed encoders and optocouplers. those values are also used for updating the position and heading of the robot. It runs every 210 milliseconds. The obstacle distance is measured using 7 ultrasonic sensors that are controlled using pin change interrupts.
The only external libraries that I use are TimerOne.h and TimerThree.h (which do not use timer0) and I made sure not to use timer0 (at least directly) in the parts that I wrote myself.
My code is interrupt-driven, so I wonder if that could also be a cause for the wrong behavior.

Here's the main code

#include "definitions.h"    // contains constants that should be accessible by many files
#include "diff_cntrl.h"     // controls the wheels (left and right speed) uses timer0 and timer5 for speed measurement
#include <TimerThree.h>     // used for generating timer interrupts for the differential control
#include "A7.h"             // used for commmunication using an A7 module through Serial1
#include "M_Ultrasonics.h"  // measures distance from 7 ultrasonic sensors using pin change interrupts on A8 - A14 (PORTK) and TimerOne.h
#include "FuzzyBBC.h"       // a fuzzy logic behavior-based controller (does only floating point computations

volatile double dists[NUM_US]; // array where the obstacle distances will be stored
volatile uint8_t   done = 0;   // flag set by M_Ultrasonics.h when all 7 seven distances are measured
FuzzyBBC fbbc;                 // reference to the behavior based controller

volatile double xG = 0, yG = 0; // coordinates of the goal


volatile double v = 0, w = 0;   // desired velocity and angular velocity. set by fbbc and used by the differential controller

// variables holding the current state of the
volatile double x = 0, y = 0, phi = 0; // coordinates and heading

volatile double dx, dy, dphi;   // changes in coordinates and heading (used for debugging

// variables used for the speed control of the motors: reference speed, actual speed, counter value, output voltage for left and right motors
volatile double l_ref = 0, l_spd = 0, r_ref = 0, r_spd = 0;
volatile uint8_t l_ctr = 0, r_ctr = 0;
volatile uint8_t l_volt = 0, r_volt = 0;

volatile boolean newvolt = true;  // flag set when a new voltage value is computed

volatile boolean updated = false; // flag set to allow transmission of data to the remote machine
volatile uint8_t update_count = 0;

//------------debug variables-----------------
volatile double dvl, dvr;
//--------------------------------------------
void setup()
{
  delay(5000);
  A7begin();    // starts up the A7 module and connects to a predefined remote machine
  initMotors(); // initialize the pins for the motor control (I use an LM293D motor driver)
  setup_cntr(); // set the registers for timer0 and timer5
//  vw2lr();

  fbbc.begin(&xG, &yG, NUM_US, dists, &x, &y, &phi, &v, &w);  // starting the fuzzy logic controller, it has direct access to the provided variables
  HCRS04.begin(T_US, dists, &done);   // starting the ultrasonic sensors controller (it runs every 30 millisecond
  
  Timer3.initialize(T_MOTOR*1000L);   // timer interrupts for the speed control (T_MOTOR = 210 milliseconds)
  Timer3.attachInterrupt(cntrISR);
}

void loop() {
  if(done)    // wait for obstacle distances to be updated
  {
    arbiter();  // update v and w
    if(updated && !waiting){    // send data to the remote machine 
      String info = "v: " + String(v) + "\tw: " + String(w) +
                    "\t\tvl: " + String(l_spd) + "\tlref: " + String(l_ref) + "\tlvolt: " + String(l_volt) +
                    "\t\tvr: " + String(r_spd) + "\trref: " + String(r_ref) + "\trvolt: " + String(r_volt) +
                    "\t\tx: " + String(x) + "\ty: " + String(y) + "\txG: " + String(xG) + "\tyG: " + String(yG);
      LogInfo(info);
      updated = false;
 
    }
    done = false;
  }
  if (A7_STREAM.available() > 0) {    // receive input from the A7 module (Serial1)
    String msg = "";
    if(waiting){
      get_A7_resp();  // read the message (function in A7.h)
      msg = resp;     // save the message (variable in A7.h)
      resp = "";
    }
    else{
      msg = readStr();
    }
    if (msg.length() > 2)   // process the received message
    {
      if (msg.substring(0, 2).equals("xy")) {
        readXYG(msg);
        resp = "";
      }
      else if(msg.equals("stop")){
        xG = x;
        yG = y;

        resp = "";
      }
      else if(msg.equals("+TCPCLOSE:0")){
        disconnected();
      }
    }
  }

}
inline void arbiter(){
  fbbc.arbiter();
  newvolt = true;
  vw2lr();  // convert v and w to left speed and right speed
}
inline void cntrISR() // ISR that runs every 210 milliseconds (for speed control)
{
  // compute the speed of the car
  read_rm();
  read_lm();
  ctr2lr();   // convert counter values to centimeter/second
  if (newvolt){
    spd2volt_init();
    newvolt = false;
  }
  else
    spd2volt();
  // update motor values
  analogWrite(L_PWM_PIN, l_volt);
  analogWrite(R_PWM_PIN, r_volt);

  updatePos();
}

inline void updatePos()   // compute new position (using differential drive kinematic equations)
{
  lr2xyphi();
}

inline void readXYG(String cmd) // get the new goal coordinates
{
  int sp1 = cmd.indexOf(' ');
  int sp2 = cmd.indexOf(' ', sp1 + 1);
  xG = (double)cmd.substring(sp1 + 1, sp2).toInt();
  yG = (double)cmd.substring(sp2 + 1, cmd.indexOf('~',sp2+1)).toInt();
}

the motor initialization code:

inline void setup_cntr()
{
  pinMode(CTR0_PIN, INPUT_PULLUP);
  pinMode(CTR5_PIN, INPUT_PULLUP);
  TCNT5H = 0;
  TCNT5L = 0;
  TCCR5B = 0X07;
  TCNT0 = 0;
  TCCR0B = 0X07;
}

inline void initMotors(){
  pinMode(L_FWD_PIN, OUTPUT);
  pinMode(L_BACK_PIN, OUTPUT);
  pinMode(L_PWM_PIN, OUTPUT);
  pinMode(L_EN_PIN, OUTPUT);
  digitalWrite(L_EN_PIN, HIGH);
  digitalWrite(L_FWD_PIN, HIGH);
  digitalWrite(L_BACK_PIN, LOW);

  pinMode(R_FWD_PIN, OUTPUT);
  pinMode(R_BACK_PIN, OUTPUT);
  pinMode(R_PWM_PIN, OUTPUT);
  pinMode(R_EN_PIN, OUTPUT);
  digitalWrite(R_EN_PIN, HIGH);
  digitalWrite(R_FWD_PIN, HIGH);
  digitalWrite(R_BACK_PIN, LOW);
}

ultrasonic sensors code:

#include "M_Ultrasonics.h"

M_Ultrasonics HCRS04;
void measISR();
void trigISR();
M_Ultrasonics::M_Ultrasonics()
{
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT); // trigs: array containing the trigger pins of the ultrasonic sensors
    digitalWrite(trigs[i],LOW);
  }
}
void M_Ultrasonics::begin(uint32_t period, volatile double *dists_, volatile uint8_t *done_)
{ 
  Timer1.initialize(period*1000);
  Timer1.attachInterrupt(trigISR);
  dists = dists_;
  done = done_;
  pinIndex = -1;
  for(int i=0; i < NUM_US; i++)
  {
    pinMode(trigs[i],OUTPUT);
    digitalWrite(trigs[i],LOW);
    dists[i] = MAX_DIST;
  }
  enable_pci();
}
void M_Ultrasonics::end()
{ 
  Timer1.stop();
  Timer1.detachInterrupt();
  PCICR = 0;
}
inline void M_Ultrasonics::trig() // send the trigger signal to the sensor
{
  pinIndex ++;
  if(pinIndex == NUM_US)
  {
    pinIndex = 0;
    *done = 1;
  }
  set_pci();
  digitalWrite(trigs[pinIndex], HIGH);
  delayMicroseconds(ping);
  digitalWrite(trigs[pinIndex], LOW);
}
inline void M_Ultrasonics::enable_pci() // enable pin change interrupts on PORTK
{
  PCICR = 0x04;
}
inline void M_Ultrasonics::set_pci()  // activate interrupts for the current pin
{
  PCMSK2 = (1<<pinIndex);
}
inline unsigned long M_Ultrasonics::read_time() // convert the timer value to microseconds
{
  return (/*(TCNT1H<<8) | */TCNT1L) * F_CLOCK;
}
inline void M_Ultrasonics::meas()
{
  if(PINK & (1<<pinIndex)) {  // check if the pin is high
    s_echo = /*micros();/*/read_time();
    dists[pinIndex] = MAX_DIST*DOBST_COEFF;
  }
  else
  {
    f_echo =/* micros();/*/read_time();
//    d = (f_echo-s_echo)*soundSpeed/2E4;
    if(d < MAX_DIST) {
      dists[pinIndex] = d/**DOBST_COEFF*/;
    }
//    dists[pinIndex] = d; // (double)(f_echo - s_echo);
  }
}
ISR (PCINT2_vect) // handle pin change interrupt for A8 to A14 here
{
  measISR();
}
void measISR() // ISR called on rising or falling edge on the current pin
{
  HCRS04.meas();
}
void trigISR()  // function called every 30 millisecond to trigger the next ultrasonic sensor
{
  HCRS04.trig();
}
Improved the formatting.
Source Link
sa_leinad
  • 3.2k
  • 2
  • 24
  • 53
Loading
Source Link
Loading