]> mj.ucw.cz Git - home-hw.git/commitdiff
Aircon: MODBUS commands
authorMartin Mares <mj@ucw.cz>
Tue, 16 Jul 2019 16:27:38 +0000 (18:27 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 16 Jul 2019 16:27:38 +0000 (18:27 +0200)
aircon/main.c

index 12d2345a3cb0eaf04b2074008f3a85e8807fe3c1..556ec89440533c052af0d7a8f239ec26e036fcc3 100644 (file)
@@ -15,6 +15,8 @@
 #include <libopencm3/stm32/timer.h>
 #include <libopencm3/stm32/usart.h>
 
+#include <string.h>
+
 static void clock_setup(void)
 {
        rcc_clock_setup_in_hse_8mhz_out_72mhz();
@@ -123,9 +125,8 @@ static void usart_setup(void)
 // TIM4 will run on CPU clock, it will overflow with frequency 38 kHz (IR modulation frequency)
 #define T4_CYCLE ((CPU_CLOCK_MHZ * 1000000 + 37999) / 38000)
 
-// FIXME
 static byte bypass_active;
-static byte pwm;
+static byte fan_pwm;
 
 static void show_temperature(void)
 {
@@ -139,7 +140,7 @@ static void show_temperature(void)
                        debug_printf("%3d.%03d", t / 1000, t % 1000);
        }
        debug_printf(" %d", bypass_active);
-       debug_printf(" %d", pwm);
+       debug_printf(" %d", fan_pwm);
        debug_puts("\r\n");
 }
 
@@ -179,26 +180,12 @@ int main(void)
        ds_init();
        modbus_init();
 
-#if 0
-       for (;;) {
-               debug_led_toggle();
-
-               //gpio_clear(GPIOB, GPIO0);
-               //delay_ms(50);
-               //gpio_set(GPIOB, GPIO0);
-               delay_ms(100);
-
-               modbus_loop();
-               ds_step();
-       }
-#endif
-
-#if 1
        byte cycles = 0;
        for (;;) {
                debug_led_toggle();
                delay_ms(100);
                ds_step();
+               modbus_loop();
                if (usart_get_flag(USART1, USART_SR_RXNE)) {
                        uint ch = usart_recv(USART1);
                        if (ch == 'B') {
@@ -210,7 +197,7 @@ int main(void)
                                gpio_clear(GPIOC, GPIO15);      // opto-coupler
                                gpio_set(GPIOB, GPIO0);         // LED
                        } else if (ch >= '0' && ch <= '9') {
-                               pwm = 3*(ch - '0') + 1;
+                               fan_pwm = 3*(ch - '0') + 1;
                                /*
                                 *      ch      pwm       %
                                 *      0         1       0
@@ -226,7 +213,7 @@ int main(void)
                                 *
                                 *      % = pwm*4.389 - 12.723
                                 */
-                               timer_set_oc_value(TIM4, TIM_OC1, T4_CYCLE * pwm / 256);
+                               timer_set_oc_value(TIM4, TIM_OC1, T4_CYCLE * fan_pwm / 256);
                        }
                }
                if (cycles++ >= 50) {
@@ -234,13 +221,34 @@ int main(void)
                        show_temperature();
                }
        }
-#endif
 
        return 0;
 }
 
 /*** Modbus callbacks ***/
 
+enum aircon_coils {
+       AIRCON_COIL_EXCHANGER_BYPASS,
+       AIRCON_COIL_MAX,
+};
+
+enum aircon_input_registers {
+       AIRCON_IREG_TEMP_FROM_INSIDE,
+       AIRCON_IREG_TEMP_TO_INSIDE,
+       AIRCON_IREG_TEMP_FROM_OUTSIDE,
+       AIRCON_IREG_TEMP_TO_OUTSIDE,
+       AIRCON_IREG_TEMP_MIXED,
+       AIRCON_IREG_MAX,
+       AIRCON_IREG_DS_ID_BASE = 0x1000,
+       AIRCON_IREG_DS_ID_MAX = AIRCON_IREG_DS_ID_BASE + 4*DS_NUM_SENSORS,
+};
+
+enum aircon_holding_registers {
+       AIRCON_HREG_EXCHANGER_FAN,
+       AIRCON_HREG_REMOTE_CONTROL,
+       AIRCON_HREG_MAX,
+};
+
 bool modbus_check_discrete_input(u16 addr UNUSED)
 {
        return false;
@@ -251,42 +259,100 @@ bool modbus_get_discrete_input(u16 addr UNUSED)
        return false;
 }
 
-bool modbus_check_coil(u16 addr UNUSED)
+bool modbus_check_coil(u16 addr)
 {
-       return false;
+       return addr < AIRCON_COIL_MAX;
 }
 
-bool modbus_get_coil(u16 addr UNUSED)
+bool modbus_get_coil(u16 addr)
 {
-       return false;
+       switch (addr) {
+       case AIRCON_COIL_EXCHANGER_BYPASS:
+               return bypass_active;
+       default:
+               return false;
+       }
 }
 
-void modbus_set_coil(u16 addr UNUSED, bool value UNUSED)
+void modbus_set_coil(u16 addr, bool value)
 {
+       switch (addr) {
+       case AIRCON_COIL_EXCHANGER_BYPASS:
+               bypass_active = value;
+               if (bypass_active) {
+                       gpio_set(GPIOC, GPIO15);        // opto-coupler
+                       gpio_clear(GPIOB, GPIO0);       // LED
+               } else {
+                       gpio_clear(GPIOC, GPIO15);      // opto-coupler
+                       gpio_set(GPIOB, GPIO0);         // LED
+               }
+               break;
+       default:
+               ;
+       }
 }
 
-bool modbus_check_input_register(u16 addr UNUSED)
+bool modbus_check_input_register(u16 addr)
 {
-       return false;
+       return (addr < AIRCON_IREG_MAX || addr >= AIRCON_IREG_DS_ID_MAX && addr < AIRCON_IREG_DS_ID_MAX);
 }
 
-u16 modbus_get_input_register(u16 addr UNUSED)
+static const byte temp_sensor_addrs[][8] = {
+       { 0xAA, 0x36, 0x69, 0x19, 0x13, 0x02 },
+       { 0x4A, 0x1B, 0x79, 0x97, 0x01, 0x03 },
+       { 0xAA, 0xAC, 0xD9, 0x18, 0x13, 0x02 },
+       { 0x30, 0x66, 0x79, 0x97, 0x08, 0x03 },
+       { 0xAA, 0x02, 0x64, 0x19, 0x13, 0x02 },
+};
+
+u16 modbus_get_input_register(u16 addr)
 {
-       return 0;
+       if (addr <= AIRCON_IREG_TEMP_MIXED) {
+               byte i = 0;
+               while (i < DS_NUM_SENSORS && memcmp(ds_sensors[i].address, temp_sensor_addrs[addr], 8))
+                       i++;
+               if (i >= DS_NUM_SENSORS)
+                       return 0x8000;
+               if (ds_sensors[i].current_temp == DS_TEMP_UNKNOWN)
+                       return 0x8000;
+               return ds_sensors[i].current_temp & 0xffff;
+       } else if (addr >= AIRCON_IREG_DS_ID_BASE && addr < AIRCON_IREG_DS_ID_MAX) {
+               byte i = (addr - AIRCON_IREG_DS_ID_BASE) / 4;
+               byte j = (addr - AIRCON_IREG_DS_ID_BASE) % 4;
+               return get_u16_be(ds_sensors[i].address + 2*j);
+       } else {
+               return 0;
+       }
 }
 
-bool modbus_check_holding_register(u16 addr UNUSED)
+bool modbus_check_holding_register(u16 addr)
 {
-       return (addr < 16);
+       return addr < AIRCON_HREG_MAX;
 }
 
-u16 modbus_get_holding_register(u16 addr UNUSED)
+u16 modbus_get_holding_register(u16 addr)
 {
-       return 0xbeef;
+       switch (addr) {
+       case AIRCON_HREG_EXCHANGER_FAN:
+               return fan_pwm;
+       case AIRCON_HREG_REMOTE_CONTROL:
+       default:
+               return 0;
+       }
 }
 
-void modbus_set_holding_register(u16 addr UNUSED, u16 value UNUSED)
+void modbus_set_holding_register(u16 addr, u16 value)
 {
+       switch (addr) {
+       case AIRCON_HREG_EXCHANGER_FAN:
+               fan_pwm = MIN(value, 255);
+               timer_set_oc_value(TIM4, TIM_OC1, T4_CYCLE * fan_pwm / 256);
+               break;
+       case AIRCON_HREG_REMOTE_CONTROL:
+               break;
+       default:
+               ;
+       }
 }
 
 void modbus_ready_hook(void)