diff --git a/servo_firmware/ax12/Makefile b/servo_firmware/ax12/Makefile
index 650c609d68773066d058c9586d110aa6fb17ed7c..8f2792f73bca782f60187dbf36dcca4156803edf 100755
--- a/servo_firmware/ax12/Makefile
+++ b/servo_firmware/ax12/Makefile
@@ -2,7 +2,7 @@ PROJECT=ax12_fw
 ########################################################
 # afegir tots els fitxers que s'han de compilar aquí
 ########################################################
-SOURCES=src/main.c src/gpio.c src/dyn_slave.c src/mem.c
+SOURCES=src/main.c src/gpio.c src/dyn_slave.c src/mem.c src/motor_control.c src/adc.c src/time_base.c src/sensors.c src/comm.c
 OBJS=$(SOURCES:.c=.o)
 SRC_DIR=./src/
 INCLUDE_DIR=./include/
@@ -14,7 +14,7 @@ MMCU=atmega8
 
 CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=16000000UL -gdwarf-2 -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wstrict-prototypes
 
-LDFLAGS=-mmcu=$(MMCU) -Wl,-Map=$(PROJECT).map -DF_CPU=16000000UL
+LDFLAGS=-mmcu=$(MMCU) -Wl,-Map=$(PROJECT).map,--section-start,.eeprom=810000 -DF_CPU=16000000UL
 
 HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature
 
diff --git a/servo_firmware/ax12/include/adc.h b/servo_firmware/ax12/include/adc.h
new file mode 100644
index 0000000000000000000000000000000000000000..28ca114a091233b37e01ac8d655dd972ada1fcf4
--- /dev/null
+++ b/servo_firmware/ax12/include/adc.h
@@ -0,0 +1,17 @@
+#ifndef _ADC_H
+#define _ADC_H
+
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
+#define ADC_pote_Port               0   // Input port for potenciometer
+#define ADC_temp_Port               2   // Input port for temperature
+#define ADC_voltage_Port            3   // Input port for voltage
+
+void adc_init(void);
+void adc_start(uint8_t port);
+uint8_t adc_is_done(void);
+uint16_t adc_get_value(void);
+
+#endif
+
diff --git a/servo_firmware/ax12/include/comm.h b/servo_firmware/ax12/include/comm.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f5080049c66948d5c98b4269d3bef081c684b76
--- /dev/null
+++ b/servo_firmware/ax12/include/comm.h
@@ -0,0 +1,12 @@
+#ifndef _COMM_H
+#define _COMM_H
+
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
+void comm_init(void);
+void comm_loop(void);
+void comm_set_error(uint8_t error);
+void comm_clear_error(void);
+
+#endif
diff --git a/servo_firmware/ax12/include/dyn_slave.h b/servo_firmware/ax12/include/dyn_slave.h
index 9a8a51e3f475b8627ddbbbe29368c5176581de38..8d10a99668f2c68256b67176a953f0cad79378c6 100644
--- a/servo_firmware/ax12/include/dyn_slave.h
+++ b/servo_firmware/ax12/include/dyn_slave.h
@@ -1,6 +1,9 @@
 #ifndef DYN_SLAVE_H
 #define DYN_SLAVE_H
 
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
 // Instruction identifiers
 #define INST_PING           0x01
 #define INST_READ           0x02
diff --git a/servo_firmware/ax12/include/mem.h b/servo_firmware/ax12/include/mem.h
index 7687157738e4671e6b5b63158a45f4d9c11a31bd..aad100ccd8346653a77931825a937c3e987e44aa 100644
--- a/servo_firmware/ax12/include/mem.h
+++ b/servo_firmware/ax12/include/mem.h
@@ -26,10 +26,10 @@
 // Register Id  RAM - declared in dynamixel
 #define Torque_Enable           0X18   //24 - 0x00 R/W - Torque On/Off
 #define LED                     0X19   //25 - 0x00 R/W - LED On/Off 
-#define CW_Compliance_Margin    0X1A   //26 - 0X01 R/W - CW Compliance margin 
-#define CCW_Compliance_Margin   0X1B   //27 - 0X01 R/W - CCW Compliance margin  
-#define CW_Compliance_Slope     0X1C   //28 - 0X20 R/W - CW Compliance slope  
-#define CCW_Compliance_Slope    0X1D   //29 - 0X20 R/W - CCW Compliance Slope  
+#define KP_L                    0X1A   //26 - 0X01 R/W - CW Compliance margin 
+#define KP_H                    0X1B   //27 - 0X01 R/W - CCW Compliance margin  
+#define KI_L                    0X1C   //28 - 0X20 R/W - CW Compliance slope  
+#define KI_H                    0X1D   //29 - 0X20 R/W - CCW Compliance Slope  
 #define Goal_Position_L         0X1E   //30 - 0x00 R/W - Lowest byte of Goal Position    
 #define Goal_Position_H         0X1F   //31 - 0x00 R/W - Highest byte of Goal Position
 #define Moving_Speed_L          0X20   //32 - 0xF0 R/W - Lowest byte of Moving Speed  
@@ -48,8 +48,10 @@
 //45 no used
 #define Moving                  0X2E   //46 - 0X00 R - Means if there is any movement   
 #define Lock                    0X2F   //47 - 0x00 R/W - Locking EEPROM   
-#define Punch_L                 0X30   //48 - 0X20 R/W - Lowest byte of Punch   
-#define Punch_H                 0X31   //49 - 0X00 R/W - Highest byte of Punch  
+#define KD_L                    0X30   //48 - 0X20 R/W - Lowest byte of Punch   
+#define KD_H                    0X31   //49 - 0X00 R/W - Highest byte of Punch  
+
+extern unsigned char ram_data[50];
 
 void ram_init(void);
 uint8_t ram_read(uint8_t address, uint8_t length, uint8_t **data);
diff --git a/servo_firmware/ax12/include/motor_control.h b/servo_firmware/ax12/include/motor_control.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ad94d10ac220a588035cb0c6644c3d403e6db1d
--- /dev/null
+++ b/servo_firmware/ax12/include/motor_control.h
@@ -0,0 +1,11 @@
+#ifndef _MOTOR_CONTROL_H
+#define _MOTOR_CONTROL_H
+
+#include <avr/interrupt.h>
+#include <avr/io.h>
+
+void motor_init(void);
+void motor_set_pwm(uint16_t cw,uint16_t ccw);
+void motor_control_loop(void);
+
+#endif
diff --git a/servo_firmware/ax12/include/sensors.h b/servo_firmware/ax12/include/sensors.h
new file mode 100644
index 0000000000000000000000000000000000000000..193b4bc58954d4fe9550bfb1831f21d865001748
--- /dev/null
+++ b/servo_firmware/ax12/include/sensors.h
@@ -0,0 +1,7 @@
+#ifndef _SENSORS_H
+#define _SENSIRS_H
+
+void sensors_init(void);
+void sensors_loop(void);
+
+#endif
diff --git a/servo_firmware/ax12/include/time_base.h b/servo_firmware/ax12/include/time_base.h
new file mode 100644
index 0000000000000000000000000000000000000000..d44eea59e88597e2af87d816ddd6858c233233ab
--- /dev/null
+++ b/servo_firmware/ax12/include/time_base.h
@@ -0,0 +1,9 @@
+#ifndef _TIME_BASE_H
+#define _TIME_BASE_H
+
+#include <avr/io.h>
+
+void time_base_init(void);
+uint8_t time_base_period(void);
+
+#endif
diff --git a/servo_firmware/ax12/src/adc.c b/servo_firmware/ax12/src/adc.c
new file mode 100644
index 0000000000000000000000000000000000000000..d297347a6b5b24bb4b35b0f601fc4f2653e75d10
--- /dev/null
+++ b/servo_firmware/ax12/src/adc.c
@@ -0,0 +1,28 @@
+#include "adc.h"
+
+void adc_init(void)
+{
+  ADMUX|=(1 << REFS0);    // use AVcc as the reference
+  ADMUX&=~(1 << ADLAR);   // clear for 10 bit resolution
+  ADCSRA|=(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0)|(1 << ADEN);    // 128 prescale for 8Mhz, enable ADC
+}
+
+void adc_start(uint8_t port)
+{
+  ADMUX&=0xF0;
+  ADMUX|=port;
+  ADCSRA|=(1 << ADSC);    // Start the ADC conversion
+}
+
+uint8_t adc_is_done(void)
+{
+  if(ADCSRA & (1 << ADSC))      //   waits for the ADC to finish 
+    return 0x00;
+  else
+    return 0x01;
+}
+
+uint16_t adc_get_value(void)
+{
+  return ADCL+(ADCH << 8);    // ADCH is read so ADC can be updated again
+}
diff --git a/servo_firmware/ax12/src/comm.c b/servo_firmware/ax12/src/comm.c
new file mode 100644
index 0000000000000000000000000000000000000000..bde386a84f7f6d2a4148af68f05b5c69a8b5b9c7
--- /dev/null
+++ b/servo_firmware/ax12/src/comm.c
@@ -0,0 +1,78 @@
+#include "comm.h"
+#include "dyn_slave.h"
+#include "mem.h"
+#include "gpio.h"
+
+uint8_t dyn_error;
+
+void do_write(uint8_t address,uint8_t length,uint8_t *data)
+{
+  uint8_t i,num=0;
+
+  for(i=address;i<address+length;i++)
+  {
+    if(i==ID)
+      dyn_slave_set_id(data[num]);
+    else if(i==Baud_Rate)
+      dyn_slave_set_baudrate(data[num]);
+    else if(i==LED)
+    {
+      if(data[num]==0x00) gpio_led_off();
+      else gpio_led_on();
+    }
+    num++;
+  } 
+  ram_write(address,length,data);
+}
+
+void comm_init(void)
+{
+  dyn_error=NO_ERROR;
+}
+
+void comm_loop(void)
+{
+  uint8_t *data;
+
+  if(dyn_slave_is_packet_ready())
+  {
+    if(dyn_slave_check_id())
+    {
+      if(dyn_slave_check_checksum())
+      {
+        switch(dyn_slave_get_instruction())
+        {
+          case INST_PING: dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000);
+                          break;
+          case INST_READ: if(ram_read(dyn_slave_get_address(),dyn_slave_get_read_length(),&data))
+                            dyn_slave_send_status(dyn_error|NO_ERROR,dyn_slave_get_read_length(),data);
+                          else
+                            dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000);
+                          break;
+          case INST_WRITE: if(ram_write(dyn_slave_get_address(),dyn_slave_get_write_length(),dyn_slave_get_write_data()))
+                           {
+                             do_write(dyn_slave_get_address(),dyn_slave_get_write_length(),dyn_slave_get_write_data());
+                             dyn_slave_send_status(dyn_error|NO_ERROR,0x00,0x00000000);
+                           }
+                           else 
+                             dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000);
+                           break;
+          default: dyn_slave_send_status(dyn_error|INSTRUCTION_ERROR,0x00,0x00000000);
+                   break;
+        }
+      }
+      else
+        dyn_slave_send_status(dyn_error|CHECKSUM_ERROR,0x00,0x00000000);
+    }
+  }
+}
+
+void comm_set_error(uint8_t error)
+{
+  dyn_error|=error;
+}
+
+void comm_clear_error(void)
+{
+  dyn_error=NO_ERROR;
+}
diff --git a/servo_firmware/ax12/src/dyn_slave.c b/servo_firmware/ax12/src/dyn_slave.c
index d91c098dad529c4d044cd64bf020674de0c4ddbd..a43a39fdde5d2316bf8fa9a3676289ccae85a392 100644
--- a/servo_firmware/ax12/src/dyn_slave.c
+++ b/servo_firmware/ax12/src/dyn_slave.c
@@ -5,7 +5,8 @@
 
 uint8_t dyn_slave_id;
 uint8_t dyn_slave_data[128];
-uint8_t dyn_slave_num_bytes;
+uint8_t dyn_slave_num_rx_bytes;
+uint8_t dyn_slave_num_tx_bytes;
 uint8_t dyn_slave_packet_ready;
 uint8_t dyn_slave_send_done;
 
@@ -23,18 +24,17 @@ inline void dyn_slave_set_tx(void)
 
 ISR(USART_TXC_vect)
 {
-  UDR=dyn_slave_data[dyn_slave_num_bytes];
-  if(dyn_slave_num_bytes==dyn_slave_data[3]+4)
+  if(dyn_slave_num_tx_bytes==dyn_slave_data[3]+4)
   {
-    dyn_slave_num_bytes=0;
+    dyn_slave_num_rx_bytes=0;
     dyn_slave_set_rx();
     dyn_slave_send_done=1;
-    UCSRB&=~(1<<TXCIE);// disable tx interrutps
-    UCSRA|=0x80;// clear any pending interrupt
-    UCSRB|=(1<<RXCIE);// enable reception interrupts
   }
   else
-    dyn_slave_num_bytes++;
+  {
+    UDR=dyn_slave_data[dyn_slave_num_tx_bytes];
+    dyn_slave_num_tx_bytes++;
+  }
 }
 
 ISR(USART_RXC_vect)
@@ -42,30 +42,25 @@ ISR(USART_RXC_vect)
   static uint8_t length;
 
   cli();// disable any other interrupt
-  dyn_slave_data[dyn_slave_num_bytes]=UDR;
-  switch(dyn_slave_num_bytes)
+  dyn_slave_data[dyn_slave_num_rx_bytes]=UDR;
+  switch(dyn_slave_num_rx_bytes)
   {
-    case 0: if(dyn_slave_data[dyn_slave_num_bytes]==0xFF)
-              dyn_slave_num_bytes++;
+    case 0: if(dyn_slave_data[dyn_slave_num_rx_bytes]==0xFF)
+              dyn_slave_num_rx_bytes++;
             break;
-    case 1: if(dyn_slave_data[dyn_slave_num_bytes]==0xFF)
-              dyn_slave_num_bytes++;
+    case 1: if(dyn_slave_data[dyn_slave_num_rx_bytes]==0xFF)
+              dyn_slave_num_rx_bytes++;
             else
-              dyn_slave_num_bytes--;
+              dyn_slave_num_rx_bytes--;
             break;
-    case 2: dyn_slave_num_bytes++;
+    case 2: dyn_slave_num_rx_bytes++;
             break;
-    case 3: length=dyn_slave_data[dyn_slave_num_bytes]+3;
-            dyn_slave_num_bytes++;
+    case 3: length=dyn_slave_data[dyn_slave_num_rx_bytes]+3;
+            dyn_slave_num_rx_bytes++;
             break;
-    default: if(dyn_slave_num_bytes==length)
-             {
-               dyn_slave_num_bytes=0;
+    default: if(dyn_slave_num_rx_bytes==length)
                dyn_slave_packet_ready=1;
-               UCSRB&=~(1<<RXCIE);// disable the rx interrupt
-             }
-             else
-               dyn_slave_num_bytes++;
+             dyn_slave_num_rx_bytes++;
              break;
   }
   sei();// enable all interrutps
@@ -83,12 +78,14 @@ void dyn_slave_init(uint8_t baudrate,uint8_t id)
   // initialize the rs485 ports
   UCSRA = (1<<U2X);// double USART transmission speed
   dyn_slave_set_baudrate(baudrate);
-  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
+  UCSRA|=0x40;// clear any pending interrupt
+  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE);
   UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<< UCSZ0); // 8 bit data, no parity, 1 stop bit
 
   dyn_slave_set_id(id);
   // initialize private variables
-  dyn_slave_num_bytes=0;
+  dyn_slave_num_tx_bytes=0;
+  dyn_slave_num_rx_bytes=0;
   dyn_slave_packet_ready=0;
   dyn_slave_send_done=0;
 }
@@ -120,7 +117,10 @@ uint8_t dyn_slave_check_id(void)
   if(dyn_slave_id==dyn_slave_data[2])
     return 0x01;
   else
+  { 
+    dyn_slave_num_rx_bytes=0;
     return 0x00;
+  }
 }
 
 uint8_t dyn_slave_check_checksum(void)
@@ -169,7 +169,7 @@ void dyn_slave_send_status(uint8_t error,uint8_t length, uint8_t *data)
   dyn_slave_data[2]=dyn_slave_id;
   cs+=dyn_slave_id;
   dyn_slave_data[3]=length+2;
-  cs+=length;
+  cs+=length+2;
   dyn_slave_data[4]=error;
   cs+=error;
   for(i=0;i<length;i++)
@@ -181,9 +181,7 @@ void dyn_slave_send_status(uint8_t error,uint8_t length, uint8_t *data)
   // set in tex mode
   dyn_slave_set_tx();
   // start transmission
-  UCSRA|=0x40;// clear any pending interrupt
-  UCSRB|=(1<<TXCIE);
-  dyn_slave_num_bytes=1;
+  dyn_slave_num_tx_bytes=1;
   UDR=dyn_slave_data[0];
 }
 
diff --git a/servo_firmware/ax12/src/main.c b/servo_firmware/ax12/src/main.c
index ab3de0879e6dd041a2116e823a201cb61d4b5b17..88c25be1054a538ec14c428f025d5b5648547132 100755
--- a/servo_firmware/ax12/src/main.c
+++ b/servo_firmware/ax12/src/main.c
@@ -9,61 +9,28 @@
 #include "gpio.h"
 #include "dyn_slave.h"
 #include "mem.h"
-
-void do_write(uint8_t address,uint8_t length,uint8_t *data)
-{
-  uint8_t i,num=0;
-
-  // check is EEPROM space
-  for(i=address;i<address+length;i++)
-  {
-    if(i==ID)
-      dyn_slave_set_id(data[num]);
-    num++;
-  } 
-}
+#include "adc.h"
+#include "motor_control.h"
+#include "time_base.h"
+#include "sensors.h"
+#include "comm.h"
 
 int16_t main(void) 
 {
-  uint8_t *data;
-
   gpio_init();
-  dyn_slave_init(34,1);
   ram_init();
+  dyn_slave_init(ram_data[Baud_Rate],ram_data[ID]);
+  adc_init();
+  time_base_init();
+  sensors_init();
+  motor_init();
+  comm_init();
   sei();
 
   while (1) 
   {
-    if(dyn_slave_is_packet_ready())
-    {
-      if(dyn_slave_check_id())
-      {
-        if(dyn_slave_check_checksum())
-        {
-          switch(dyn_slave_get_instruction())
-          {
-            case INST_PING: dyn_slave_send_status(NO_ERROR,0x00,0x00000000);
-                            break;
-            case INST_READ: if(ram_read(dyn_slave_get_address(),dyn_slave_get_read_length(),&data))
-                              dyn_slave_send_status(NO_ERROR,dyn_slave_get_read_length(),data);
-                            else
-                              dyn_slave_send_status(INSTRUCTION_ERROR,0x00,0x00000000);
-                            break;
-            case INST_WRITE: if(ram_write(dyn_slave_get_address(),dyn_slave_get_write_length(),dyn_slave_get_write_data()))
-                             {
-                               do_write(dyn_slave_get_address(),dyn_slave_get_write_length(),dyn_slave_get_write_data());
-                               dyn_slave_send_status(NO_ERROR,0x00,0x00000000);
-                             }
-                             else 
-                               dyn_slave_send_status(INSTRUCTION_ERROR,0x00,0x00000000);
-                             break;
-            default: dyn_slave_send_status(INSTRUCTION_ERROR,0x00,0x00000000);
-                     break;
-          }
-        }
-        else
-          dyn_slave_send_status(CHECKSUM_ERROR,0x00,0x00000000);
-      }
-    }
+    comm_loop();
+    sensors_loop();
+    motor_control_loop();
   }
 }
diff --git a/servo_firmware/ax12/src/mem.c b/servo_firmware/ax12/src/mem.c
index 59b815e926851155486800481faa83a016461f32..530c3e3af051bc126c1554ea54e55c58d782a511 100644
--- a/servo_firmware/ax12/src/mem.c
+++ b/servo_firmware/ax12/src/mem.c
@@ -1,30 +1,30 @@
 #include "mem.h"
+#include "gpio.h"
 #include <avr/eeprom.h>
 
 // dynamixel RAM variables
 unsigned char ram_data[50];
 
 // Dynamixel EEPROM variables
-unsigned char EEMEM eeprom_data[19]={0x0C,0x00,0x00,0x01,0x22,0xFA,0x00,0x00,0xFF,0x03,0x00,0x50,0x3C,0xF0,0xFF,0x03,0x02,0x24,0x24};
+unsigned char EEMEM eeprom_data[19]={0x1C,0x00,0x00,0x01,0x22,0xFA,0x00,0x00,0xFF,0x03,0x00,0x50,0x3C,0xF0,0xFF,0x03,0x02,0x24,0x24};
 
 void ram_init(void)
 {
   uint8_t i;
- 
+
   for(i=0;i<Alarm_Shutdown;i++)
     ram_data[i]=eeprom_read_byte(&eeprom_data[i]);
-  for(;i<Punch_H;i++)
+  for(;i<=KD_H;i++)
     ram_data[i]=0x00;
-  ram_data[CW_Compliance_Slope]=0x20;
-  ram_data[CCW_Compliance_Slope]=0x20;
+  ram_data[KP_L]=0x20;
+  ram_data[KP_H]=0x00;
   ram_data[Torque_Limit_L]=ram_data[Max_Torque_L];
   ram_data[Torque_Limit_H]=ram_data[Max_Torque_H];
-  ram_data[Punch_L]=0x20;
 }
 
 uint8_t ram_read(uint8_t address, uint8_t length, uint8_t **data)
 {
-  if((address+length)>Punch_H)
+  if((address+length)>KD_H)
     return 0x00;
   else
   {
@@ -37,7 +37,7 @@ uint8_t ram_write(uint8_t address, uint8_t length, uint8_t *data)
 {
   uint8_t i,num=0;
 
-  if((address+length)>Punch_H)
+  if((address+length)>KD_H)
     return 0x00;
   else
   {
diff --git a/servo_firmware/ax12/src/motor_control.c b/servo_firmware/ax12/src/motor_control.c
new file mode 100644
index 0000000000000000000000000000000000000000..bde876e20675bc290c147b8290705a25c68ef27f
--- /dev/null
+++ b/servo_firmware/ax12/src/motor_control.c
@@ -0,0 +1,156 @@
+#include "motor_control.h"
+#include "time_base.h"
+#include "comm.h"
+#include "mem.h"
+#include "dyn_slave.h"
+#include "gpio.h"
+
+#define CW_PWM_MOTOR_PIN                PB1
+#define CCW_PWM_MOTOR_PIN               PB2
+
+#define CONTROL_COUNT                   10
+
+int16_t start_position;
+int16_t previous_position;
+int16_t previous_seek;
+int16_t seek_delta;
+int16_t count;
+
+void motor_init(void)
+{
+  /* configure the control signals */
+  DDRB|=(1 << CW_PWM_MOTOR_PIN)|(1 << CCW_PWM_MOTOR_PIN);
+  motor_set_pwm(0x0000,0x0000);
+
+  /* configure the PWM */
+  TCCR1A|=(1 << COM1A1)|(1 << COM1B1)|(1 << WGM11) | (1 << WGM10);     // set none-inverting mode PB1 and PB2, Mode fast PWM @ 10 bits
+  TCCR1B|=(1 << WGM12)|(1 << CS11) | (1 << CS10) ;     // set Mode Fast PWM, 10bit, prescaker 64
+
+  // initialize internal variables
+  previous_position=ram_data[Present_Position_L]+(ram_data[Present_Position_H]<<8);
+  start_position=previous_position;
+  previous_seek=previous_position;
+  seek_delta=-1;
+  count=0;
+}
+
+void motor_set_pwm(uint16_t cw,uint16_t ccw)
+{
+  OCR1A = ccw;   //PB1 => set PWM for X% duty cycle @ 10bit
+  OCR1B = cw;  //PB2 => set PWM for Y% duty cycle @ 10bit
+}
+
+void motor_control_loop(void)
+{
+  static int16_t current_position;
+  static int16_t current_velocity;
+  static int16_t seek_position;
+  static int16_t seek_velocity;
+  static int16_t minimum_position;
+  static int16_t maximum_position;
+  static int16_t p_component;
+  static int16_t d_component;
+  static int16_t i_component;
+  static int16_t torque_limit;
+  static int16_t deadband=10;
+  static int32_t pwm_output;
+  static uint16_t p_gain;
+  static uint16_t i_gain;
+  static uint16_t d_gain;
+
+  if(time_base_period())
+  {
+    // update control loop
+    // get all necessary variables
+    current_position=ram_data[Present_Position_L]+(ram_data[Present_Position_H]<<8);
+    current_velocity = current_position - previous_position;
+    ram_data[Present_Speed_L]=current_velocity&0xFF;
+    ram_data[Present_Speed_H]=((current_velocity>>8)&0xFF);
+    seek_position=ram_data[Goal_Position_L]+(ram_data[Goal_Position_H]<<8);
+    seek_velocity=ram_data[Moving_Speed_L]+(ram_data[Moving_Speed_H]<<8);
+    maximum_position=ram_data[CCW_Angle_Limit_L]+(ram_data[CCW_Angle_Limit_H]<<8);
+    minimum_position=ram_data[CW_Angle_Limit_L]+(ram_data[CW_Angle_Limit_H]<<8);
+    torque_limit=ram_data[Torque_Limit_L]+(ram_data[Torque_Limit_H]<<8);
+    p_gain=ram_data[KP_L]+(ram_data[KP_H]<<8);
+    i_gain=ram_data[KI_L]+(ram_data[KI_H]<<8);
+    d_gain=ram_data[KD_L]+(ram_data[KD_H]<<8);
+    /* saturate the target position */
+    if (seek_position < minimum_position)
+    {
+       seek_position = minimum_position;
+       comm_set_error(ANGLE_LIMIT_ERROR);
+    }
+    if (seek_position > maximum_position)
+    {
+       seek_position = maximum_position;
+       comm_set_error(ANGLE_LIMIT_ERROR);
+    }
+    /* update the new target */
+    if(previous_seek != seek_position)
+    {
+      previous_seek=seek_position;
+      seek_delta=current_position;
+      start_position=current_position;
+    }
+    /* generate the intermediate target point */
+    if(count==CONTROL_COUNT && seek_delta!=seek_position && seek_velocity>0) // Tick is our time constant
+    {
+      if(start_position<seek_position)
+      {
+        seek_delta+=seek_velocity;
+        if(seek_delta>=seek_position)
+          seek_delta=seek_position;
+      } 
+      else if(start_position>seek_position)
+      {
+        seek_delta-=seek_velocity;
+        if(seek_delta<=seek_position)
+          seek_delta=seek_position;
+      }
+    }
+    /* compute the error */
+    p_component = seek_delta - current_position;
+    if(count==CONTROL_COUNT)
+    {
+      i_component += p_component;
+      if(i_component<-128) // Somewhat arbitrary anti integral wind-up; we're experimenting
+        i_component=-128;
+      else if(i_component>128)
+        i_component=128;
+    }
+    d_component = previous_position - current_position;
+    previous_position = current_position;
+    /* compute the PWM */
+    pwm_output = 0;
+    if ((p_component > deadband) || (p_component < -deadband))
+    {
+      // Apply the proportional component of the PWM output.
+      pwm_output += (int32_t) p_component * (int32_t) p_gain;
+      // Apply the integral component of the PWM output.
+//      pwm_output += (int32_t) i_component * (int32_t) i_gain;
+      // Apply the derivative component of the PWM output.
+//      pwm_output += (int32_t) d_component * (int32_t) d_gain;
+    }
+    else
+      i_component = 0;
+    pwm_output>>=8;
+    if(pwm_output>torque_limit)
+      pwm_output=torque_limit;
+    else if(pwm_output<-torque_limit)
+      pwm_output=-torque_limit;
+    if(pwm_output<0)
+    {
+      pwm_output=-pwm_output;
+      motor_set_pwm((uint16_t)pwm_output,0x0000);
+    }
+    else
+      motor_set_pwm(0x0000,(uint16_t)pwm_output);
+    ram_data[Present_Load_L]=pwm_output&0xFF;
+    ram_data[Present_Load_H]=((pwm_output>>8)&0xFF);
+    /* update control loop variable */
+    if(count==CONTROL_COUNT)
+      count=0;
+    else
+      count++;
+  }
+}
diff --git a/servo_firmware/ax12/src/sensors.c b/servo_firmware/ax12/src/sensors.c
new file mode 100644
index 0000000000000000000000000000000000000000..39c452ac41c0d6e5eb056e073c82f4101d7d401b
--- /dev/null
+++ b/servo_firmware/ax12/src/sensors.c
@@ -0,0 +1,78 @@
+#include "sensors.h"
+#include "adc.h"
+#include "comm.h"
+#include "mem.h"
+#include "dyn_slave.h"
+
+typedef enum {adc_get_pos=0,adc_get_temp=1,adc_get_volt=2} adc_state;
+
+uint16_t current_position;
+adc_state state;
+
+void sensors_set_pos(uint16_t pos)
+{
+  ram_data[Present_Position_L]=pos&0xFF;
+  ram_data[Present_Position_H]=(pos>>8)&0xFF;
+  current_position=pos;
+}
+
+void sensors_set_temp(uint16_t temp)
+{
+  uint8_t temperature;
+
+  temperature=(((uint32_t)temp*50)>>10);
+  ram_data[Present_Temperature]=temperature;
+  // check the limits and generate the error  
+  if(temperature>ram_data[Int_Limit_Temperature])
+    comm_set_error(OVERHEATING_ERROR);
+  else
+    comm_set_error(NO_ERROR);
+}
+
+void sensors_set_voltage(uint16_t voltage)
+{
+  uint8_t volt;
+
+  volt=(((uint32_t)voltage*200)>>10);
+  ram_data[Present_Voltage]=volt;
+  // check the limits and generate the error  
+  if(volt>ram_data[High_Limit_Voltage] || volt<ram_data[Low_Limit_Voltage])
+    comm_set_error(VOLTAGE_ERROR);
+  else
+    comm_set_error(NO_ERROR);
+}
+
+void sensors_init(void)
+{
+  // start the voltage conversion
+  adc_start(ADC_pote_Port);
+  while(!adc_is_done());
+  sensors_set_pos(adc_get_value()); 
+  adc_start(ADC_temp_Port);
+  state=adc_get_temp;
+}
+
+void sensors_loop(void)
+{
+  if(adc_is_done())// the last AD conversion has finished
+  {
+    if(state==adc_get_pos)
+    {
+      sensors_set_pos(adc_get_value());
+      adc_start(ADC_temp_Port);
+      state=adc_get_temp;
+    }
+    else if(state==adc_get_temp)
+    {
+      sensors_set_temp(adc_get_value());
+      adc_start(ADC_voltage_Port);
+      state=adc_get_volt;
+    }
+    else
+    {
+      sensors_set_voltage(adc_get_value());
+      adc_start(ADC_pote_Port);
+      state=adc_get_pos;
+    }
+  }
+}
diff --git a/servo_firmware/ax12/src/time_base.c b/servo_firmware/ax12/src/time_base.c
new file mode 100644
index 0000000000000000000000000000000000000000..f8974c5d8e1f3acdd337fd64a0f140dae45229f6
--- /dev/null
+++ b/servo_firmware/ax12/src/time_base.c
@@ -0,0 +1,24 @@
+#include "time_base.h"
+
+void time_base_init(void)
+{
+  TCCR0|=(1<<CS01)|(1<<CS00); // clk src with  prescaler 64
+  TIMSK=0x00; // disable all interrupts
+  TCNT0 = 0x00;
+}
+
+uint8_t time_base_period(void)
+{
+  if(TIFR & (1<<TOV0))
+  {
+    TIFR|=(1<<TOV0);
+    return 0x01;
+  }
+  else
+    return 0x00;
+}
+
+uint8_t time_base_get_counter(void)
+{
+  return TCNT0;
+}