dtostrf erwartet einen Zeiger auf einen Block aus mehreren Zeichen, wo der ASCII-String gespeichert werden soll. In Deinem Fall ist da aber kein Platz für den String, weil dieser genau 0 Zeichen aufnehmen kann (""). Deshalb wird Speicher von anderen Variablen beim Aufruf von dtostrf überschrieben und es kommt zu dem. o.g. Verhalten.

Wenn die beiden Variablen x_start und y_start außerhalb der main deklariert sind, ergibt das Ganze ein anderes Speicherlayout als wenn sie in der main deklariert sind, weshalb es bei der einen Variante zufälligerweise richtig funktioniert.

-> Lege ein Array mit genügend Elementen an, damit der mit dtostrf erzeugte String auch Platz darin hat.

Code:
#include "RP6RobotBaseLib.h"
#include <math.h>

int16_t x_start = 0;
int16_t y_start = 0;
 
int main (void)
  {
  initRobotBase();
     
  int16_t x_ziel = 500;
  int16_t y_ziel = 500;
 
  int16_t alpha2 = atan((y_ziel - y_start)/(x_ziel - x_start)) * 180/M_PI;
  int16_t c = (y_ziel - y_start) / sin(alpha2);
 
  char c2 = [12]; // <---- Platz für max. 11 Zeichen
  dtostrf(alpha2, 10, 0, c2);

  writeString(c2);
  writeString_P("\n");
 
  while (true)
    {
   }
  return 0;
  }