   const float motor = 250;          // rating, W
   const float dt = 1E-3;            // s (time step)
   const float gauge = 1.5;          // x-axis separation of wheels
-
-  const float coefficient = motor / max_speed;
-
-  float max_T1 = coefficient * eff_div_v(abs(v1));
-  float max_T2 = coefficient * eff_div_v(abs(v2));
-
-  float vx = ((float) target_vx) / 127;
-  float vy = ((float) target_vy) / 127;
+  const float friction = 0.2;
+
+  const float slip_T = friction * 9.81 * mass / 4;
+
+  float max_T1 = eff_div_v(abs(v1)) * motor / max_speed;
+  float max_T2 = eff_div_v(abs(v2)) * motor / max_speed;
 
   float target_v1;
   float target_v2;
 
-  if (target_vx >= 0) {
-    target_v1 = vy + vy * vx - vx;
-    target_v2 = vy - vy * vx + vx;
+  if (target_vy >= 0) {
+    target_v1 = target_vy + target_vy * target_vx - target_vx;
+    target_v2 = target_vy - target_vy * target_vx + target_vx;
   } else {
-    target_v1 = vy + vy * vx + vx;
-    target_v2 = vy - vy * vx - vx;
+    target_v1 = target_vy + target_vy * target_vx + target_vx;
+    target_v2 = target_vy - target_vy * target_vx - target_vx;
   }
 
   // v. clumsy control system:
-  float T1 = max_T1 * ((target_v1 > v1) ? 1 : -1) / 20; // applied tractions
-  float T2 = max_T2 * ((target_v2 > v2) ? 1 : -1) / 20;
+  float T1 = max_T1 * ((target_v1 > v1) ? 1 : -1); // applied tractions
+  float T2 = max_T2 * ((target_v2 > v2) ? 1 : -1);
+
+  slip_right = T1 / slip_T;
+  slip_left  = T2 / slip_T;
+
+  T1 = (T1 > slip_T) ? slip_T : ((T1 < -slip_T) ? (-slip_T) : T1); // traction limit because of friction / slip
+  T2 = (T2 > slip_T) ? slip_T : ((T2 < -slip_T) ? (-slip_T) : T2);
 
   float a = (T1 + T2) / mass;
   float alpha = (T1 - T2) * (gauge / 2) / inertia;

  static char buffer[16];

  if (++count == 1000) { // silence or junk on the input line! (emergency stop support feature)
    code = 'Q';
    value = 0;
    count = 0;
    return true;
  }
  while (Serial.available()) {
    char next = (char) Serial.read();


  previous_time = millis();
}

float byte_to_norm(unsigned long value) { // convert integer in range 0..254 to floating point number in range -1..1
  float f = 0;

  if (value < 255) {
    f = (-127.0 +(float) value) / 127.0;
  }
  return f;
}

unsigned long norm_to_byte(float value) { // convert floating point number in range -1..1 to integer in range 0..254
  int ival = 127 + (int) round(127 * value);

  return (unsigned long) ((ival < 0) ? 0 : ((ival > 254) ? 254 : ival));
}

float eff_div_v(float v) { // motor efficiency divided by velocity fraction, i.e., v in [0..1]
  float edv = 0;

  if (v <= 0.5) {
