diff --git a/adaptors/java/src/se/lth/control/realtime/moberg/Moberg.java b/adaptors/java/src/se/lth/control/realtime/moberg/Moberg.java
index 2a79c03ccf8cade5e6be27dcec2c9008621195c4..ec3643d53dbb3ba57090d7472990bf606708cb91 100644
--- a/adaptors/java/src/se/lth/control/realtime/moberg/Moberg.java
+++ b/adaptors/java/src/se/lth/control/realtime/moberg/Moberg.java
@@ -28,7 +28,7 @@ public class Moberg {
 
   public static native void analogOutOpen(int index) throws MobergException;
   public static native void analogOutClose(int index) throws MobergException;
-  public static native void analogOut(int index, double value) throws MobergException;
+  public static native double analogOut(int index, double value) throws MobergException;
 
   public static native void digitalInOpen(int index) throws MobergException;
   public static native void digitalInClose(int index) throws MobergException;
@@ -36,7 +36,7 @@ public class Moberg {
 
   public static native void digitalOutOpen(int index) throws MobergException;
   public static native void digitalOutClose(int index) throws MobergException;
-  public static native void digitalOut(int index, boolean value) throws MobergException;
+  public static native boolean digitalOut(int index, boolean value) throws MobergException;
 
   public static native void encoderInOpen(int index) throws MobergException;
   public static native void encoderInClose(int index) throws MobergException;
diff --git a/adaptors/java/src/se_lth_control_realtime_moberg_Moberg.c b/adaptors/java/src/se_lth_control_realtime_moberg_Moberg.c
index 8cd8e4aaff9e42706773b2305e918ad497fa2a2d..769f4235e2341d42b43a56ef35b71ba40b287e57 100644
--- a/adaptors/java/src/se_lth_control_realtime_moberg_Moberg.c
+++ b/adaptors/java/src/se_lth_control_realtime_moberg_Moberg.c
@@ -261,16 +261,19 @@ Java_se_lth_control_realtime_moberg_Moberg_analogOutClose(
 }
 
 
-JNIEXPORT void JNICALL 
+JNIEXPORT double JNICALL 
 Java_se_lth_control_realtime_moberg_Moberg_analogOut(
-  JNIEnv *env, jobject obj, jint index, jdouble value
+  JNIEnv *env, jobject obj, jint index, jdouble desired
 ) 
 {
   struct channel *channel = channel_get(&analog_out, index);
   if (! channel) {
     throwMobergNotOpenException(env, index);
+    return 0.0;
   } else {
-    channel->analog_out.write(channel->analog_out.context, value);
+    double actual;
+    channel->analog_out.write(channel->analog_out.context, desired, &actual);
+    return actual;
   }
 }
 
@@ -354,16 +357,19 @@ Java_se_lth_control_realtime_moberg_Moberg_digitalOutClose(
   }
 }
 
-JNIEXPORT void JNICALL 
+JNIEXPORT jboolean JNICALL 
 Java_se_lth_control_realtime_moberg_Moberg_digitalOut(
-  JNIEnv *env, jobject obj, jint index, jboolean value
+  JNIEnv *env, jobject obj, jint index, jboolean desired
 ) 
 {
   struct channel *channel = channel_get(&digital_out, index);
   if (! channel) {
     throwMobergNotOpenException(env, index);
+    return 0;
   } else {
-    channel->digital_out.write(channel->digital_out.context, value);
+    int actual;
+    channel->digital_out.write(channel->digital_out.context, desired, &actual);
+    return actual;
   }
 }
 
diff --git a/adaptors/julia/AnalogOut.jl b/adaptors/julia/AnalogOut.jl
index a911d103c57c7521c8476953e64e08414052cc39..47ae229ae6661d2386c72d1e86ee110af2b1a1c7 100644
--- a/adaptors/julia/AnalogOut.jl
+++ b/adaptors/julia/AnalogOut.jl
@@ -29,8 +29,10 @@ function close(aout::AnalogOut)
 end
 
 function write(aout::AnalogOut, value::Cdouble)
+    result = Ref{Cdouble}(0.0)
     checkOK(ccall(aout.channel.write,
                   Status,
-                  (Ptr{Nothing}, Cdouble),
-                  aout.channel.context, value))
+                  (Ptr{Nothing}, Cdouble, Ptr{Cdouble}),
+                  aout.channel.context, value, result))
+    return result[];
 end
diff --git a/adaptors/julia/DigitalOut.jl b/adaptors/julia/DigitalOut.jl
index 3c978fbbcb4d9650daf35e503370618ff7cce76a..b65cc1af963bdb243741012178294cf4b00f4801 100644
--- a/adaptors/julia/DigitalOut.jl
+++ b/adaptors/julia/DigitalOut.jl
@@ -29,8 +29,10 @@ function close(dout::DigitalOut)
 end
 
 function write(dout::DigitalOut, value::Bool)
+    result = Ref{Cint}(0)
     checkOK(ccall(dout.channel.write,
                   Status,
-                  (Ptr{Nothing}, Cint),
-                  dout.channel.context, value ? 1 : 0))
+                  (Ptr{Nothing}, Cint, Ptr{Cint}),
+                  dout.channel.context, value ? 1 : 0, result))
+    return result[] != 0
 end
diff --git a/adaptors/matlab/analogout.c b/adaptors/matlab/analogout.c
index a1d5909669a7af86b7cf6d25fdfdb400ea448672..e545ab93cd860c48a222857451a2f43e588c972f 100644
--- a/adaptors/matlab/analogout.c
+++ b/adaptors/matlab/analogout.c
@@ -136,7 +136,7 @@ static void mdlOutputs(SimStruct *S, int_T tid)
 
     for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
       struct moberg_analog_out *aout = (struct moberg_analog_out*)pwork[i];
-      if (! moberg_OK(aout->write(aout->context, *up[i]))) {
+      if (! moberg_OK(aout->write(aout->context, *up[i], NULL))) {
         static char error[256];
         double *channel = mxGetPr(ssGetSFcnParam(S,1));
         sprintf(error, "Failed to write analogout #%d", (int)channel[i]);
diff --git a/adaptors/matlab/digitalout.c b/adaptors/matlab/digitalout.c
index 97d9a8bac7be2be3e1368449161ebdecf9d9df35..be8d48e9e85e3e9d786797d4b73f7a705519cd81 100644
--- a/adaptors/matlab/digitalout.c
+++ b/adaptors/matlab/digitalout.c
@@ -136,7 +136,7 @@ static void mdlOutputs(SimStruct *S, int_T tid)
 
     for (i = 0 ; i < ssGetNumPWork(S) ; i++) {
       struct moberg_digital_out *dout = (struct moberg_digital_out*)pwork[i];
-      if (! moberg_OK(dout->write(dout->context, *up[i]))) {
+      if (! moberg_OK(dout->write(dout->context, *up[i], NULL))) {
         static char error[256];
         double *channel = mxGetPr(ssGetSFcnParam(S,1));
         sprintf(error, "Failed to write digitalout #%d", (int)channel[i]);
diff --git a/adaptors/python/python-moberg.c b/adaptors/python/python-moberg.c
index 33dced2f621cbcb786529647b8faee4f2a92ce2e..c00392e16191776529bfeffa16dacf640c4e16f0 100644
--- a/adaptors/python/python-moberg.c
+++ b/adaptors/python/python-moberg.c
@@ -276,7 +276,7 @@ MobergAnalogIn_read(MobergAnalogInObject *self, PyObject *Py_UNUSED(ignored))
     PyErr_Format(PyExc_OSError, "moberg._AnalogIn(%d).read() failed with %d",
                  self->index, status.result);
   }
-  return Py_BuildValue("f", value);
+  return Py_BuildValue("d", value);
 }
 
 static PyMethodDef MobergAnalogIn_methods[] = {
@@ -373,19 +373,20 @@ MobergAnalogOut_init(MobergAnalogOutObject *self, PyObject *args, PyObject *kwds
 static PyObject *
 MobergAnalogOut_write(MobergAnalogOutObject *self, PyObject *args)
 {
-  double value = 1.23;
-  if (! PyArg_ParseTuple(args, "d", &value)) {
+  double desired_value, actual_value;
+  if (! PyArg_ParseTuple(args, "d", &desired_value)) {
     goto err;
   }
   struct moberg_status status = self->channel.write(self->channel.context,
-                                                    value);
+                                                    desired_value,
+                                                    &actual_value);
   if (!moberg_OK(status)) {
     PyErr_Format(PyExc_OSError, "moberg._AnalogOut(%d).write() failed with %d",
                  self->index, status.result);
     goto err;
   }
-  Py_INCREF(Py_None);
-  return Py_None;
+  
+  return Py_BuildValue("d", actual_value);
 err:
   return NULL;
 }
@@ -588,19 +589,20 @@ MobergDigitalOut_init(MobergDigitalOutObject *self, PyObject *args, PyObject *kw
 static PyObject *
 MobergDigitalOut_write(MobergDigitalOutObject *self, PyObject *args)
 {
-  double value = 1.23;
-  if (! PyArg_ParseTuple(args, "d", &value)) {
+  PyObject *desired;
+  int actual;
+  if (! PyArg_ParseTuple(args, "O", &desired)) {
     goto err;
   }
   struct moberg_status status = self->channel.write(self->channel.context,
-                                                    value);
+                                                    PyObject_IsTrue(desired),
+                                                    &actual);
   if (!moberg_OK(status)) {
     PyErr_Format(PyExc_OSError, "moberg._DigitalOut(%d).write() failed with %d",
                  self->index, status.result);
     goto err;
   }
-  Py_INCREF(Py_None);
-  return Py_None;
+  return Py_BuildValue("O", actual ? Py_True: Py_False);
 err:
   return NULL;
 }
diff --git a/moberg.h b/moberg.h
index 3023e06717a0a5b6bf9c27d64721c7b9cd7123fd..69c432248a6b51891e96a76d40653790668f9ea1 100644
--- a/moberg.h
+++ b/moberg.h
@@ -53,7 +53,8 @@ struct moberg_analog_in {
 struct moberg_analog_out {
   struct moberg_channel_analog_out *context;
   struct moberg_status (*write)(struct moberg_channel_analog_out *,
-                                double value);
+                                double desired_value,
+                                double *actual_value);
 };
 
 struct moberg_digital_in {
@@ -65,7 +66,8 @@ struct moberg_digital_in {
 struct moberg_digital_out {
   struct moberg_channel_digital_out *context;
   struct moberg_status (*write)(struct moberg_channel_digital_out *,
-                                int value);
+                                int desired_value,
+                                int *actual_value);
 };
 
 struct moberg_encoder_in {
diff --git a/plugins/comedi/comedi.c b/plugins/comedi/comedi.c
index 00a1912950c85d8711197c3f1fe91bb7406e33cc..8755b23f3daac399baed83e9b90bf46dd78533dd 100644
--- a/plugins/comedi/comedi.c
+++ b/plugins/comedi/comedi.c
@@ -112,16 +112,17 @@ err_errno:
 
 static struct moberg_status analog_out_write(
   struct moberg_channel_analog_out *analog_out,
-  double value)
+  double desired_value,
+  double *actual_value)
 {
   struct channel_descriptor descriptor = analog_out->channel_context.descriptor;
   lsampl_t data;
-  if (value < descriptor.min) {
+  if (desired_value < descriptor.min) {
     data = 0;
-  } else if (value > descriptor.max) {
+  } else if (desired_value > descriptor.max) {
     data = descriptor.maxdata;
   } else {
-    data = (value - descriptor.min) / descriptor.delta;
+    data = (desired_value - descriptor.min) / descriptor.delta;
   }
   if (data < 0) {
     data = 0;
@@ -134,6 +135,10 @@ static struct moberg_status analog_out_write(
                             0, 0, data)) {
     goto err_errno;
   }
+  if (actual_value) {
+    *actual_value = data * descriptor.delta + descriptor.min;
+  }
+    
   return MOBERG_OK;
 err_errno:
   return MOBERG_ERRNO(comedi_errno());
@@ -162,16 +167,20 @@ err_errno:
 
 static struct moberg_status digital_out_write(
   struct moberg_channel_digital_out *digital_out,
-  int value)
+  int desired_value,
+  int *actual_value)
 {
   struct channel_descriptor descriptor = digital_out->channel_context.descriptor;
-  lsampl_t data = value==0?0:1;
+  lsampl_t data = desired_value==0?0:1;
   if (0 > comedi_data_write(digital_out->channel_context.device->comedi.handle,
                             descriptor.subdevice,
                             descriptor.subchannel,
                             0, 0, data)) {
     goto err_errno;
   }
+  if (actual_value) {
+    *actual_value = data;
+  }
   return MOBERG_OK;
 err_errno:
   return MOBERG_ERRNO(comedi_errno());
diff --git a/plugins/libtest/libtest.c b/plugins/libtest/libtest.c
index c0b6f2c55159826e82ecd55f7e2cd1079c0e5523..8ea3a2167711e38c58927415fc473b229e81fb30 100644
--- a/plugins/libtest/libtest.c
+++ b/plugins/libtest/libtest.c
@@ -96,11 +96,15 @@ err_einval:
 
 static struct moberg_status analog_out_write(
   struct moberg_channel_analog_out *analog_out,
-  double value)
+  double desired_value,
+  double *actual_value)
 {
   struct moberg_channel_context *channel = &analog_out->channel_context;
   struct moberg_device_context *device = channel->device;
-  device->analog = value * (channel->index + 1);
+  device->analog = desired_value * (channel->index + 1);
+  if (actual_value) {
+    *actual_value = desired_value;
+  }
   return MOBERG_OK;
 }
 
@@ -120,16 +124,20 @@ err_einval:
 
 static struct moberg_status digital_out_write(
   struct moberg_channel_digital_out *digital_out,
-  int value)
+  int desired_value,
+  int *actual_value)
 {
   struct moberg_channel_context *channel = &digital_out->channel_context;
   struct moberg_device_context *device = channel->device;
   int mask =  (1<<channel->index);
-  if (value) {
+  if (desired_value) {
     device->digital |= mask;
   } else {
     device->digital &= ~mask;
   }
+  if (actual_value) {
+    *actual_value = desired_value;
+  }
   return MOBERG_OK;
 }
 
diff --git a/plugins/serial2002/serial2002.c b/plugins/serial2002/serial2002.c
index 4017406a4b6604f307a456c3f030286be5db2285..3b6f93268e28950f62aa798f61720e8de592f376 100644
--- a/plugins/serial2002/serial2002.c
+++ b/plugins/serial2002/serial2002.c
@@ -128,12 +128,13 @@ err_einval:
 
 static struct moberg_status analog_out_write(
   struct moberg_channel_analog_out *analog_out,
-  double value)
+  double desired_value,
+  double *actual_value)
 {
   struct moberg_channel_context *channel = &analog_out->channel_context;
   struct moberg_device_context *device = channel->device;
   struct analog_map map = device->analog_out.map[channel->index];
-  long as_long = (value - map.min) / map.delta;
+  long as_long = (desired_value - map.min) / map.delta;
   if (as_long < 0) {
     as_long = 0;
   } else if (as_long > map.maxdata) {
@@ -141,7 +142,11 @@ static struct moberg_status analog_out_write(
   }
 
   struct serial2002_data data = { is_channel, map.index, as_long };
-  return serial2002_write(device->port.fd,  data);
+  struct moberg_status result = serial2002_write(device->port.fd,  data);
+  if (OK(result) && actual_value) {
+    *actual_value = data.value * map.delta + map.min;    
+  }
+  return result;
 }
 
 static struct moberg_status digital_in_read(
@@ -173,13 +178,18 @@ err_einval:
 
 static struct moberg_status digital_out_write(
   struct moberg_channel_digital_out *digital_out,
-  int value)
+  int desired_value,
+  int *actual_value)
 {
   struct moberg_channel_context *channel = &digital_out->channel_context;
   struct moberg_device_context *device = channel->device;
   struct digital_map map = device->digital_out.map[channel->index];
-  struct serial2002_data data = { is_digital, map.index, value != 0 };
-  return serial2002_write(device->port.fd,  data);
+  struct serial2002_data data = { is_digital, map.index, desired_value != 0 };
+  struct moberg_status result = serial2002_write(device->port.fd,  data);
+  if (OK(result) && actual_value) {
+    *actual_value = data.value;
+  }
+  return result;
 }
 
 static struct moberg_status encoder_in_read(
diff --git a/test/Makefile b/test/Makefile
index ec3b973cbfb61e19eb8fd25b3384f41b8eab1f12..50ee3e2374622eb6f38c9760941a259f35d7d9fa 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -14,12 +14,13 @@ PYTHON3PATH=$(shell realpath ../adaptors/python/install/usr/lib*/python3*/site-p
 all:
 
 .PHONY: test
-test: $(PYTEST:%=run_py_%) $(JULIATEST:%=run_jl_%) $(CTEST:%=run_c_%) 
+test: $(CTEST:%=run_c_%) $(PYTEST:%=run_py_%) $(JULIATEST:%=run_jl_%) 
 	echo Tests run
 
 .PHONY: run_c_%
 run_c_%:build/%
 	$(ENV_TEST) valgrind --leak-check=full ./build/$*
+	env -i  LD_LIBRARY_PATH=../build valgrind --leak-check=full ./build/$*
 
 .PHONY: run_py_%
 run_py_%: %.py
diff --git a/test/test_io.c b/test/test_io.c
index 72a644b8897901aeeb4c2eef71e1b3adfd94a790..a730a2f48c6971b01864006f4ef3d5496658aaf4 100644
--- a/test/test_io.c
+++ b/test/test_io.c
@@ -10,7 +10,7 @@ int main(int argc, char *argv[])
   }
   struct moberg_analog_in ai0;
   struct moberg_analog_out ao0;
-  double ai0_value;
+  double ai0_value, ao0_actual;
   if (! moberg_OK(moberg_analog_in_open(moberg, 0, &ai0))) {
     fprintf(stderr, "OPEN failed\n");
     goto free;
@@ -24,11 +24,11 @@ int main(int argc, char *argv[])
     fprintf(stderr, "OPEN failed\n");
     goto free;
   } 
-  if (! moberg_OK(ao0.write(ao0.context, ai0_value * 2))) { 
+  if (! moberg_OK(ao0.write(ao0.context, ai0_value * 2, &ao0_actual))) { 
     fprintf(stderr, "READ failed\n");
     goto close_ao0;
   }
-  fprintf(stderr, "WROTE ao0: %f\n", ai0_value * 2);
+  fprintf(stderr, "WROTE ao0: %f %f\n", ai0_value * 2, ao0_actual);
 close_ao0:
   moberg_analog_out_close(moberg, 0, ao0);
 close_ai0:
diff --git a/test/test_jl.jl b/test/test_jl.jl
index 89a7f00e7c07004886d3c885a1f5849ebdae742d..270b88829d9a4ddbb72db85bf2f5ff311edf7f8c 100644
--- a/test/test_jl.jl
+++ b/test/test_jl.jl
@@ -7,33 +7,32 @@ import MobergIO: read, write
 
 function test()
     m = MobergIO.Moberg()
-    println(stderr,m)
+    println(m)
     
     for v in -10.0:2.0:10 
         for i in 0:1
             try
                 aout = MobergIO.AnalogOut(m, Unsigned(i))
                 value = v + i;
-                write(aout, value)
-                print("$value ")
+                actual = write(aout, value)
+                print("($value, $actual)")
             catch ex
                 println(stderr,"analog_out $i does not exist $(ex)")
             end
         end
-        println(stderr)
-        flush(stderr)
+        println()
         sleep(0.01)
         for j in 0:3
             try
                 ain = MobergIO.AnalogIn(m, Unsigned(j))
                 println(stderr,read(ain))
             catch ex
-                println(stderr,"analog_in $j does not exist $(ex)")
+                println("analog_in $j does not exist $(ex)")
             end
-            flush(stderr)
+            flush(stdout)
         end
-        println(stderr)
-        flush(stderr)
+        println()
+        flush(stdout)
     end
     for v in false:true
         for i in 0:6
@@ -43,34 +42,34 @@ function test()
                 write(dout, value)
                 print("$value ")
             catch ex
-                println(stderr,"digital_out $i does not exist $(ex)")
+                println("digital_out $i does not exist $(ex)")
             end
-            flush(stderr)
+            flush(stdout)
         end
-        println(stderr)
-        flush(stderr)
+        println()
+        flush(stdout)
         for i in 0:6
             try
                 din = MobergIO.DigitalIn(m, Unsigned(i))
                 print("$(read(din)) ")
             catch ex
-                println(stderr,"digital_in $i does not exist $(ex)")
+                println("digital_in $i does not exist $(ex)")
             end
-            flush(stderr)
+            flush(stdout)
         end
-        println(stderr)
-        println(stderr)
+        println()
+        println()
         sleep(0.01)
     end
 end
 
 test()
 
-println(stderr,"DONE")
-flush(stderr)
+println("DONE")
+flush(stdout)
 GC.gc()
-println(stderr,"....")
-flush(stderr)
+println("....")
+flush(stdout)
 GC.gc() # See https://github.com/JuliaCI/BenchmarkTools.jl/blob/af35d0513fe1e336ad0d8b9a35f924e8461aefa2/src/execution.jl#L1
-println(stderr,"Really DONE")
-flush(stderr)
+println("Really DONE")
+flush(stdout)
diff --git a/test/test_start_stop.c b/test/test_start_stop.c
index 393d9328350d50aef54094c852b7fddfbb4b9e49..ee0a49a51262b7af609519eb7be2527d0ab0427d 100644
--- a/test/test_start_stop.c
+++ b/test/test_start_stop.c
@@ -3,11 +3,13 @@
 
 int main(int argc, char *argv[])
 {
+  fprintf(stderr, "NEW\n");
   struct moberg *moberg = moberg_new(NULL);
-  printf("START:\n");
+  fprintf(stderr, "START:\n");
   moberg_start(moberg, stdout);
-  printf("STOP:\n");
+  fprintf(stderr, "STOP:\n");
   moberg_stop(moberg, stdout);
-  printf("DONE\n");
+  fprintf(stderr, "FREE\n");
   moberg_free(moberg);
+  fprintf(stderr, "DONE\n");
 }