Error en el uso de Timer0 para interrupciones.

Buenas tardes.

He hecho el sketch necesario para el manejo de un brazo robótico, con la placa Arbotix-M Robocontroller que utiliza el core ATMega644, pero al comprobar su funcionamiento, aunque funcionaba de manera correcta, me percaté de que el robot tardaba en reaccionar y el buffer se me colapsaba y petaba el programa, puesto que leía la posición de los servos en el loop y se sobrecargaba. El sketch los conforman 4 archivos, el archivo principal y 3 librerías implementadas a mano por mi profesor para el manejo de los Servos.

Entonces decidí hacer un Timer, en este caso el Timer0 (Timer2 ya estaba en uso en una de las librerías ya implementadas) tomando como ejemplo el Timer ya implementado por el profesor que me dijo que utilizó el datasheet del ATMega644, pero al ejecutarlo me sale el siguiente error, que no tengo ni idea de que me quiere decir.

wiring.c.o (symbol from plugin): In function `__vector_18':

(.text+0x0): multiple definition of `__vector_18'

sketch\PhamtonX_Arduino.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compilación en tarjeta ArbotiX Std.

Pondré aquí el código de interés (setup e interrupción) del sketch principal y os adjuntare todo el sketch y las 3 librerías en el post, por si algún alma caritativa quiere probar suerte.

#include <ax12.h>

#define CLOCK_MAIN 16000
#define TIM0_PRESCALER 0X05
#define TIM0_COUNT 99

#define EXTRAPRESCALER0 3

void MenuOptions();
void TestAllJoints ();
void P1Solution ();
void Home ();
void ROBOT_ConfigTimer0 ();
void ISR_lecturaServos();
int8_t MoveSpecificJoint ();
char comando;
float angulo;
#include "poses.h"
#include "robot.h"
#include <avr/interrupt.h> 
#include <avr/io.h>


String readString; //main captured String 
 String q1; //data String
 String q2;
 String q3;
 String q4;
 String q5;
String orden;

uint16_t m_unTimer0ExtraPrescaler = 0;
int ind1; // , locations
int ind2;
int ind3;
int ind4;int ind5;int ind6;

/*******************************************
 *******************************************/

  unsigned int  tmp[SERVOCOUNT-1];
  double        tmpJointAngles[DOFs];
  double        tmpCoords[3];
  char * pch;
  boolean m_bTimer0OnFlag;



void ROBOT_ConfigTimer0 (void) {

// m_bTimer0OnFlag = FALSE;
  
  //Disbale Timer0 while we set it up
  TCCR0B = 0x00;        
  TCNT0  = TIM0_COUNT;      //Set Count to 10ms  
  TIFR0  = 0x00;            //Timer2 INT Flag Reg: Clear Timer Overflow Flag
  TIMSK0 = 0x01;            //Timer2 INT Reg: Timer0 Overflow Interrupt Enable
  TCCR0A = 0x00;   

}

ISR (TIMER0_OVF_vect) {
   m_unTimer0ExtraPrescaler++;
  if ( m_unTimer0ExtraPrescaler >= EXTRA_PRESCALER0 )
  {
    ROBOT_GetJointsPos(tmpJointAngles);
        Serial.print("[");
        Serial.print(tmpJointAngles[0]);
        Serial.print(",");
        Serial.print(tmpJointAngles[1]);
        Serial.print(",");
        Serial.print(tmpJointAngles[2]);
        Serial.print(",");
        Serial.print(tmpJointAngles[3]);
        Serial.print(",");
        Serial.print(tmpJointAngles[4]);
        Serial.println("]");
        delay(20);

        m_unTimer0ExtraPrescaler  = 0;
  }
  TCNT0 = TIM0_COUNT;    //Reset Timer to TIM2_COUNT
  TIFR0 = 0x00;          //Timer2 INT Flag Reg: Clear Timer Overflow Flag
}

Muchas Gracias de antemano.

Saludos

Sergio

PhamtonX_Arduino.ino (7.49 KB)

poses.h (1.58 KB)

robot.h (15.3 KB)

servos.h (2.82 KB)

Resuelto, el timer0 solo sirve para temporizar... use el timer1 y me compila.

Mañana lo intento subir a la placa y os cuento

Buenas chicos,

al subirlo a la placa se me sube sin problemas, pero no pinta nada por el puerto serie. Lo único que he cambiado son las variables del ConfigTimer() para que concuerde con los valores deseados para el Timer1 (según datasheet ATMega 644 http://www.atmel.com/images/doc2593.pdf)

Estos son:

void ROBOT_ConfigTimer0 (void) {

// m_bTimer0OnFlag = FALSE;
  
  //Disbale Timer0 while we set it up
  TCCR0B = 0x00;        
  TCNT0  = TIM0_COUNT;      //Set Count to 10ms  
  TIFR0  = 0x00;            //Timer2 INT Flag Reg: Clear Timer Overflow Flag
  TIMSK0 = 0x01;            //Timer2 INT Reg: Timer0 Overflow Interrupt Enable
  TCCR0A = 0x00;

Alguna idea?

Muchas gracias de antemano.

Sergio_1993:
al subirlo a la placa se me sube sin problemas, pero no pinta nada por el puerto serie.

USART o "puerto serial" casualmente también necesita de interrupciones para funcionar. Lo que pasa es que son de menor prioridad que las de un timer.

Lo más inteligente sería acumular los resultados en variables o arrays, y dejar que el loop se encargue de imprimirlos.

Ya lo arreglé y me imprime por puerto serie, solo que valores desfasados. Deberia de imprimir unos valores entre -2 y 2 aproximadamente. Pero me imprime lo siguiente:

[332.48,333.79,331.18,331.72,334.05]
[332.48,333.79,331.18,331.72,334.05]
[332.48,333.79,331.18,331.72,334.05]
[332.48,333.79,331.18,331.72,334.05]

Es un vector de tamaño 5, cada posicion del vector guarda la posicion actual de dicho servo (en teoria)

Alguna idea?