diff --git a/firmware/rust1/src/bin/heizung.rs b/firmware/rust1/src/bin/heizung.rs
index 91797c81159b8edb56771cb3afef99d11a3709fd..49a4b333d1f9604aed15584b0786a7ad8065dad1 100644
--- a/firmware/rust1/src/bin/heizung.rs
+++ b/firmware/rust1/src/bin/heizung.rs
@@ -2,7 +2,7 @@
 #![no_main]
 #![feature(type_alias_impl_trait)]
 
-use core::sync::atomic::{AtomicU16, AtomicU32, Ordering};
+use core::sync::atomic::*;
 
 use defmt::*;
 use embassy_executor::Spawner;
@@ -10,7 +10,9 @@ use embassy_executor::Spawner;
 use embassy_futures::select::*;
 use embassy_rp::adc::{self, Adc};
 use embassy_rp::peripherals::*;
-use embassy_time::{Duration, Timer};
+use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
+use embassy_sync::mutex::Mutex;
+use embassy_time::{Duration, Timer, Instant};
 use embassy_rp::gpio::{Input, Level, Output, Pull, Flex};
 use embassy_rp::i2c;
 use embassy_rp::interrupt;
@@ -79,46 +81,230 @@ async fn uart_task(this: RS485<ModbusServer<ModBusRegs<'static>>>) {
     this.run_task().await;
 }
 
+// Zero offset for current measurement will be exponential smoothing with alpha=1/ZERO_OFFSET_FACTOR.
+// The value in zero_offset_raw will be the smoothed offset times ZERO_OFFSET_FACTOR. This factor
+// should be a power of two because we will divide by it.
+const ZERO_OFFSET_FACTOR : u32 = 32;
+
+struct AdcCurrentData {
+    // Value measured while both MOSFETs are off
+    // (multiplied by ZERO_OFFSET_FACTOR)
+    zero_offset_raw: AtomicU32,
+    // Current measured with 2k resistor (raw value and 1/10 mA)
+    current_2k_raw: AtomicU16,
+    current_2k_dezi_milliamps: AtomicU16,
+    // Current measured while main MOSFET is/was on (raw value and 1/10 mA and when this was measured)
+    current_on_raw: AtomicU16,
+    current_on_dezi_milliamps: AtomicU16,
+    current_on_time: Mutex<CriticalSectionRawMutex, Instant>,
+}
+
+impl AdcCurrentData {
+    const fn const_default() -> AdcCurrentData {
+        AdcCurrentData {
+            zero_offset_raw: AtomicU32::new(0),
+            current_2k_raw: AtomicU16::new(0),
+            current_2k_dezi_milliamps: AtomicU16::new(0),
+            current_on_raw: AtomicU16::new(0),
+            current_on_dezi_milliamps: AtomicU16::new(0),
+            current_on_time: Mutex::new(Instant::from_ticks(0)),
+        }
+    }
+}
+
 struct AdcData {
-    current1: AtomicU16,
-    current2: AtomicU16,
     analog_in1_raw: AtomicU16,
     analog_in1_millivolt: AtomicU16,
+    vcc_raw: AtomicU16,
     vcc: AtomicU16,
+    temp_raw: AtomicU16,
+    temp_centicelsius: AtomicU16,
+
+    currents: [AdcCurrentData; 2],
 }
 
-fn convert_to_celsius(raw_temp: u16) -> f32 {
-    // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet
-    27.0 - (raw_temp as f32 * 3.0522 / 4096.0 - 0.706) / 0.001721 as f32
+impl AdcData {
+    const fn const_default() -> AdcData {
+        AdcData {
+            analog_in1_raw: AtomicU16::new(0),
+            analog_in1_millivolt: AtomicU16::new(0),
+            vcc_raw: AtomicU16::new(0),
+            vcc: AtomicU16::new(0),
+            temp_raw: AtomicU16::new(0),
+            temp_centicelsius: AtomicU16::new(0),
+            currents: [AdcCurrentData::const_default(), AdcCurrentData::const_default()],
+        }
+    }
 }
 
 #[embassy_executor::task]
-async fn adc_task(shared_data: &'static AdcData, adc: ADC, en_measure_current: Output<'static, PIN_3>,
-    mut analog_in1: PIN_26, mut current2: PIN_27, mut current1: PIN_28, mut measure_vcc: PIN_29) {
+async fn adc_task(shared_data: &'static AdcData, adc: ADC, mut en_measure_current: Output<'static, PIN_3>,
+    mut analog_in1: PIN_26, mut current2: PIN_27, mut current1: PIN_28, mut measure_vcc: PIN_29, outputs_active: &'static AtomicU8) {
     let irq = interrupt::take!(ADC_IRQ_FIFO);
     let mut adc = Adc::new(adc, irq, adc::Config::default());
 
+    let debug = true;
+    let mut en_measure_current_toggle = 0;
+
     loop {
-        let level = adc.read(&mut analog_in1).await;
-        shared_data.analog_in1_raw.store(level, Ordering::Release);
-        let value = 3.05*level as f32/4096. * (10.+2.*5.1)/5.1;
-        shared_data.analog_in1_millivolt.store((value * 1000.) as u16, Ordering::Release);
-        info!("ADC analog_in1: {} -> {}", level, value);
-
-        let level = adc.read(&mut current2).await;
-        info!("ADC current2: {}", level);
-        let level = adc.read(&mut current1).await;
-        info!("ADC current1: {}", level);
-
-        let level = adc.read(&mut measure_vcc).await;
-        let vcc = 3.05 * level as f32 / 4096. * (100. + 10.)/10.;
-        info!("ADC measure_vcc: {} -> {}", level, vcc);
-
-        let temp = adc.read_temperature().await;
-        info!("Temp: {} -> {} degrees", temp, convert_to_celsius(temp));
-        Timer::after(Duration::from_secs(1)).await;
+        if true {
+            let level = adc.read(&mut analog_in1).await;
+            // 3.05 V for 4096 counts, voltage divider with (10k + 5.1k) over 5.1k, result in mV:
+            // level * 3.05/4096. * (10+5.1+5.1)/5.1 * 1000
+            // -> level * 305 * (100+51+51) * 1000 / 100 / 4096 / 51
+            // -> level * 305 * ((100+51+51)/2) * (1000/100) / 2048 / 51  --> fits in 32 bits for level=4096 (but barely)
+            let value = level as u32 * 305 * ((100+51+51)/2) * (1000/100);
+            let value = (value + 2048*51/2) / 2048 / 51;
+            let value = if value > u16::MAX as u32 { u16::MAX } else { value as u16 };
+            shared_data.analog_in1_raw.store(level, Ordering::Relaxed);
+            shared_data.analog_in1_millivolt.store(value, Ordering::Relaxed);
+            if debug {
+                let value2 = 3.05*level as f32/4096. * (10.+2.*5.1)/5.1;
+                info!("ADC analog_in1: {} cnt -> {} V ({} mV)", level, value2, value);
+            }
+        }
+
+        if true {
+            let level = adc.read(&mut measure_vcc).await;
+            // 3.05V for 4096 counts, voltage divider with 100k over 10, result in mV:
+            // level * 3.05/4096. * (100 + 10)/10 * 1000
+            // -> level * 305 * 11 * 1000 / 100 / 4096
+            let value = (level as u32 * 305 * 11 * 1000 / 100 + 2048) / 4096;
+            let value = if value > u16::MAX as u32 { u16::MAX } else { value as u16 };
+            shared_data.vcc_raw.store(level, Ordering::Relaxed);
+            shared_data.vcc.store(value, Ordering::Relaxed);
+            if debug {
+                let vcc = 3.05 * level as f32 / 4096. * (100. + 10.)/10.;
+                info!("ADC measure_vcc: {} cnt -> {} V ({} mV)", level, vcc, value);
+            }
+        }
+
+        let outputs_were_active = outputs_active.load(Ordering::SeqCst);
+        let mut measure_currents = true;
+        if outputs_were_active != 0 && false {
+            // output is active but also en_measure_current -> turn it off
+            // -> Actually, don't do that because there is no harm and it can be useful for the other channel.
+            if en_measure_current.is_set_high() {
+                en_measure_current.set_low();
+                measure_currents = false;
+            }
+            en_measure_current_toggle = 0;
+        } else {
+            match en_measure_current_toggle {
+                0 | 8 => {
+                    en_measure_current.set_level(if en_measure_current_toggle >= 8 { Level::High } else { Level::Low });
+                    // skip in this loop to give it time to settle
+                    measure_currents = false;
+                }
+                _ => {}
+            }
+            en_measure_current_toggle = (en_measure_current_toggle + 1) % 16;
+        }
+
+        // read another value between looking at output_active and measuring the currents
+        if true {
+            let level = adc.read_temperature().await;
+            // According to chapter 4.9.5. Temperature Sensor in RP2040 datasheet
+            let adc_vcc = 3.0522;  // from CJ431
+            let celsius = 27.0 - (level as f32 * adc_vcc / 4096.0 - 0.706) / 0.001721;
+            let value = celsius * 100.;
+            let value = if value > u16::MAX as f32 { u16::MAX } else { value as u16 };
+            shared_data.temp_raw.store(level, Ordering::Relaxed);
+            shared_data.temp_centicelsius.store(value, Ordering::Relaxed);
+            if debug {
+                info!("Temp: {} -> {} deg C", level, celsius);
+            }
+        }
+
+        if measure_currents {
+            let levels = [
+                adc.read(&mut current1).await,
+                adc.read(&mut current2).await,
+            ];
+            let outputs_are_active = outputs_active.load(Ordering::SeqCst);
+            //let en_measure_current_is_active = en_measure_current.is_set_high();  //FIXME I think is_set_high() has a bug.
+            let en_measure_current_is_active = en_measure_current_toggle >= 8;
+            for i in 0..2 {
+                // 3.05 V for 4096 counts, shunt resistor is 0.1 ohms (i.e. 0.1 V/A), amplifier gain is 56, result should be mA/10
+                // (level - offset) * 3.05/4096 / 0.1 * 1/56 * 1e4
+                // -> (level - offset) * 305 * 10 * 1e4 / 56 / 4096 / 100
+                // -> (level - offset) * 305 * 1000 / 56 / 4096
+                // -> (level - offset) * 305 * (1000/8) / 4096 / 7
+                let level = levels[i];
+                let offset = (shared_data.currents[i].zero_offset_raw.load(Ordering::Relaxed)/ZERO_OFFSET_FACTOR) as u16;
+                let level2 = if level > offset { level - offset } else { 0 };
+                //info!("CUR{}: raw: {}, {}, zero={}", i, level, level2, shared_data.currents[i].zero_offset_raw.load(Ordering::Relaxed));
+                let value = (level2 as u32 * 305 * (1000/8) + 7*4096/2) / 4096 / 7;
+                let value = if value > u16::MAX as u32 { u16::MAX } else { value as u16 };
+
+                let output_was_active = (outputs_were_active>>i) & 1 != 0;
+                let output_is_active = (outputs_are_active>>i) & 1 != 0;
+                #[allow(unused_variables, unused_assignments)]
+                let mode : char;
+                match (output_was_active, output_is_active, en_measure_current_is_active) {
+                    (true, true, false) => {
+                        // output was consistently (hopefully) turned on during our measurement
+                        // and en_measure_current is off -> good measurement for current in "on" state
+                        shared_data.currents[i].current_on_raw.store(levels[i], Ordering::Relaxed);
+                        shared_data.currents[i].current_on_dezi_milliamps.store(value, Ordering::Relaxed);
+                        *shared_data.currents[i].current_on_time.lock().await = Instant::now();
+                        mode = 'O';
+                    }
+                    (false, false, false) => {
+                        // output and en_measure_current are off -> good measurement for zero level
+
+                        // fetch_update is exactly what we want but it doesn't seem to be available...
+                        //shared_data.currents[i].zero_offset_raw.fetch_update(Ordering::Relaxed, Ordering::Relaxed,
+                        //    |x| { x*(ZERO_OFFSET_FACTOR-1)/ZERO_OFFSET_FACTOR + levels[i] });
+                        //SAFETY: We are the only writers for zero_offset_raw.
+                        let x = shared_data.currents[i].zero_offset_raw.load(Ordering::Relaxed);
+                        let x2 = x*(ZERO_OFFSET_FACTOR-1)/ZERO_OFFSET_FACTOR + level as u32;
+                        shared_data.currents[i].zero_offset_raw.store(x2, Ordering::Relaxed);
+
+                        mode = 'z';
+                    }
+                    (false, false, true) => {
+                        // output is off and en_measure_current is on -> good measurement through 2k resistor
+                        shared_data.currents[i].current_2k_raw.store(levels[i], Ordering::Relaxed);
+                        shared_data.currents[i].current_2k_dezi_milliamps.store(value, Ordering::Relaxed);
+                        mode = 'k';
+                    }
+                    _ => {
+                        // inconsistent state of MOSFETs -> ignore this measurement
+                        mode = '!';
+                    }
+                }
+                
+                if debug {
+                    info!("ADC current{}: {}: {} -> {} [10*mA]", i, mode, level, value);
+                }
+            }
+
+            //FIXME remove
+            info!("CUR: 2k={}, {}, {}, zero={}, {} -> {}, {}",
+                en_measure_current_is_active, levels[0], levels[1],
+                shared_data.currents[0].zero_offset_raw.load(Ordering::Relaxed),
+                shared_data.currents[1].zero_offset_raw.load(Ordering::Relaxed),
+                shared_data.currents[1].current_2k_raw.load(Ordering::Relaxed),
+                shared_data.currents[1].current_2k_raw.load(Ordering::Relaxed),
+            );
+        }
+
+        if debug {
+            Timer::after(Duration::from_secs(1)).await;
+        } else {
+            Timer::after(Duration::from_millis(1)).await;
+        }
     }
 }
+
+
+#[derive(Clone, Copy, PartialEq, Eq)]
+enum ReadType {
+    HoldingRegister,
+    InputRegister,
+}
+
 struct ModBusRegs<'a> {
     led_g: Output<'a, PIN_5>,
     button_boot2: Input<'a, PIN_11>,
@@ -127,6 +313,30 @@ struct ModBusRegs<'a> {
     reed2: Input<'a, PIN_21>,
     reed1: Input<'a, PIN_22>,
     adc_data: &'a AdcData,
+
+    consistent_read_type: ReadType,
+    consistent_read_addr: u16,
+    consistent_read_length: u16,
+    consistent_read_data: [u16; 4],
+}
+
+impl<'a> ModBusRegs<'a> {
+    fn read_reg_u64(self: &mut Self, read_type: ReadType, base_addr: u16, addr: u16, value: u64) -> Result<u16, ModbusErrorCode> {
+        defmt::assert!(addr >= base_addr);
+        defmt::assert!(addr < base_addr + 64/16);
+
+        self.consistent_read_type = read_type;
+        self.consistent_read_addr = base_addr;
+        self.consistent_read_length = 64/16;
+        self.consistent_read_data = [
+            ((value >> 0) & 0xffff) as u16,
+            ((value >> 16) & 0xffff) as u16,
+            ((value >> 32) & 0xffff) as u16,
+            ((value >> 48) & 0xffff) as u16,
+        ];
+
+        Ok(self.consistent_read_data[(addr - base_addr) as usize])
+    }
 }
 
 impl<'a> ModbusRegisters for ModBusRegs<'a> {
@@ -142,6 +352,11 @@ impl<'a> ModbusRegisters for ModBusRegs<'a> {
     }
 
     fn read_holding_register(self: &mut Self, addr: u16) -> Result<u16, ModbusErrorCode> {
+        if self.consistent_read_type == ReadType::HoldingRegister
+                && addr >= self.consistent_read_addr && addr < self.consistent_read_addr + self.consistent_read_length {
+            return Ok(self.consistent_read_data[(addr - self.consistent_read_addr) as usize]);
+        }
+
         if addr == 1 {
             return Ok(42)
         }
@@ -149,10 +364,39 @@ impl<'a> ModbusRegisters for ModBusRegs<'a> {
     }
 
     fn read_input_register(self: &mut Self, addr: u16) -> Result<u16, ModbusErrorCode> {
+        if self.consistent_read_type == ReadType::InputRegister
+                && addr >= self.consistent_read_addr && addr < self.consistent_read_addr + self.consistent_read_length {
+            return Ok(self.consistent_read_data[(addr - self.consistent_read_addr) as usize]);
+        }
+
         match addr {
             0 => Ok(42),
+
             1 => Ok(self.adc_data.analog_in1_raw.load(Ordering::Relaxed)),
             2 => Ok(self.adc_data.analog_in1_millivolt.load(Ordering::Relaxed)),
+            3 => Ok(self.adc_data.vcc_raw.load(Ordering::Relaxed)),
+            4 => Ok(self.adc_data.vcc.load(Ordering::Relaxed)),
+            5 => Ok(self.adc_data.temp_raw.load(Ordering::Relaxed)),
+            6 => Ok(self.adc_data.temp_centicelsius.load(Ordering::Relaxed)),
+
+            7 => Ok((self.adc_data.currents[0].zero_offset_raw.load(Ordering::Relaxed) / ZERO_OFFSET_FACTOR) as u16),
+            8 => Ok(self.adc_data.currents[0].current_2k_raw.load(Ordering::Relaxed)),
+            9 => Ok(self.adc_data.currents[0].current_2k_dezi_milliamps.load(Ordering::Relaxed)),
+            10 => Ok(self.adc_data.currents[0].current_on_raw.load(Ordering::Relaxed)),
+            11 => Ok(self.adc_data.currents[0].current_on_dezi_milliamps.load(Ordering::Relaxed)),
+            12 | 13 | 14 | 15 => self.read_reg_u64(ReadType::InputRegister, 12, addr,
+                self.adc_data.currents[0].current_on_time.try_lock().map(
+                    |x| x.as_micros()).unwrap_or(0)),
+
+            16 => Ok((self.adc_data.currents[1].zero_offset_raw.load(Ordering::Relaxed) / ZERO_OFFSET_FACTOR) as u16),
+            17 => Ok(self.adc_data.currents[1].current_2k_raw.load(Ordering::Relaxed)),
+            18 => Ok(self.adc_data.currents[1].current_2k_dezi_milliamps.load(Ordering::Relaxed)),
+            19 => Ok(self.adc_data.currents[1].current_on_raw.load(Ordering::Relaxed)),
+            20 => Ok(self.adc_data.currents[1].current_on_dezi_milliamps.load(Ordering::Relaxed)),
+            21 | 22 | 23 | 24 => self.read_reg_u64(ReadType::InputRegister, 21, addr,
+                self.adc_data.currents[1].current_on_time.try_lock().map(
+                    |x| x.as_micros()).unwrap_or(0)),
+
             _ => Err(ModbusErrorCode::IllegalDataAddress)
         }
     }
@@ -213,11 +457,9 @@ async fn main(spawner: Spawner) {
     i2c_config.frequency = 400_000;
     unwrap!(spawner.spawn(i2c_task(p.I2C0, scl, sda, i2c_irq, i2c_config)));
 
-    static ADC_DATA: AdcData = AdcData {
-        current1: AtomicU16::new(0), current2: AtomicU16::new(0), analog_in1_raw: AtomicU16::new(0),
-        analog_in1_millivolt: AtomicU16::new(0), vcc: AtomicU16::new(0)
-    };
-    unwrap!(spawner.spawn(adc_task(&ADC_DATA, p.ADC, en_measure_current, analog_in1, current2, current1, measure_vcc)));
+    static ADC_DATA: AdcData = AdcData::const_default();
+    static OUTPUTS_ACTIVE: AtomicU8 = AtomicU8::new(0);
+    unwrap!(spawner.spawn(adc_task(&ADC_DATA, p.ADC, en_measure_current, analog_in1, current2, current1, measure_vcc, &OUTPUTS_ACTIVE)));
 
     // use 19200 baud in 8E1 mode - not great but it's the Modbus default
     let mut uart_config = uart::Config::default();
@@ -231,6 +473,10 @@ async fn main(spawner: Spawner) {
             button_boot2,
             reed1, reed2, reed3, reed4,
             adc_data: &ADC_DATA,
+            consistent_read_type: ReadType::InputRegister,
+            consistent_read_addr: u16::default(),
+            consistent_read_length: u16::default(),
+            consistent_read_data: [0; 4],
         }),
     );
     unwrap!(spawner.spawn(uart_task(rs485)));