3 次代码提交

作者 SHA1 备注 提交日期
  Thomas Buck 944f87e56b basic ble notification support 1年前
  Thomas Buck 7680476df9 prefetch volcano ble characteristics 1年前
  Thomas Buck 11483f370b only auto connect when device is visible within 10s of boot 1年前
共有 15 个文件被更改,包括 320 次插入45 次删除
  1. 9
    0
      README.md
  2. 8
    1
      include/ble.h
  3. 1
    0
      include/config.h
  4. 3
    0
      include/lcd.h
  5. 3
    0
      include/volcano.h
  6. 221
    15
      src/ble.c
  7. 2
    1
      src/buttons.c
  8. 8
    0
      src/console.c
  9. 2
    2
      src/lcd.c
  10. 0
    7
      src/mem.c
  11. 2
    2
      src/state_crafty.c
  12. 9
    2
      src/state_scan.c
  13. 9
    10
      src/text.c
  14. 37
    0
      src/volcano.c
  15. 6
    5
      src/workflow.c

+ 9
- 0
README.md 查看文件

@@ -1,9 +1,18 @@
1 1
 # Pi Pico Volcano Remote Control Gadget
2 2
 
3
+Supports:
4
+
5
+ * workflows for the Volcano Hybrid
6
+ * basic status and settings for Crafty+
7
+
3 8
 For use with Raspberry Pi Pico W boards with the [Waveshare Pico LCD 1.3](https://www.waveshare.com/wiki/Pico-LCD-1.3) and the [Pimoroni Pico Lipo Shim](https://shop.pimoroni.com/products/pico-lipo-shim).
4 9
 
5 10
 Adapted from the [tinyusb-cdc-example](https://github.com/hathach/tinyusb/blob/master/examples/device/cdc_msc/src/main.c), [adc example](https://github.com/raspberrypi/pico-examples/tree/master/adc/read_vsys), [standalone client example](https://github.com/raspberrypi/pico-examples/blob/master/pico_w/bt/standalone/client.c) and my [Trackball firmware](https://git.xythobuz.de/thomas/Trackball).
6 11
 
12
+`python-test` contains a similar app to the C version in the top level of the repo, but instead written for MicroPython on the Pico W.
13
+Unfortunately I had many performance and space problems with this, so I decided to rewrite it.
14
+`web-app` contains a script to conveniently fetch the original web app JS sources, for "reverse engineering".
15
+
7 16
 ## Quick Start
8 17
 
9 18
 When compiling for the first time, check out the required git submodules.

+ 8
- 1
include/ble.h 查看文件

@@ -54,8 +54,15 @@ void ble_connect(bd_addr_t addr, bd_addr_type_t type);
54 54
 bool ble_is_connected(void);
55 55
 void ble_disconnect(void);
56 56
 
57
+int8_t ble_discover(const uint8_t *service, const uint8_t *characteristic);
58
+
57 59
 int32_t ble_read(const uint8_t *characteristic, uint8_t *buff, uint16_t buff_len);
58 60
 int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
59
-                 uint8_t *buff, uint16_t buff_len);
61
+                 const uint8_t *buff, uint16_t buff_len);
62
+
63
+int8_t ble_notification_disable(const uint8_t *service, const uint8_t *characteristic);
64
+int8_t ble_notification_enable(const uint8_t *service, const uint8_t *characteristic);
65
+bool ble_notification_ready(void);
66
+uint16_t ble_notification_get(uint8_t *buff, uint16_t buff_len);
60 67
 
61 68
 #endif // __BLE_H__

+ 1
- 0
include/config.h 查看文件

@@ -31,6 +31,7 @@
31 31
 
32 32
 #ifdef MENU_PREFER_VOLCANO
33 33
 #define VOLCANO_AUTO_CONNECT_TIMEOUT_MS 2000
34
+#define VOLCANO_AUTO_CONNECT_WITHIN_MS 10000
34 35
 #endif // MENU_PREFER_VOLCANO
35 36
 
36 37
 #endif // NDEBUG

+ 3
- 0
include/lcd.h 查看文件

@@ -21,6 +21,9 @@
21 21
 
22 22
 #include <stdint.h>
23 23
 
24
+#define LCD_WIDTH 240
25
+#define LCD_HEIGHT 240
26
+
24 27
 #define RGB_565(r, g, b) ( \
25 28
       (((r) >> 3) << 11)   \
26 29
     | (((g) >> 2) << 5)    \

+ 3
- 0
include/volcano.h 查看文件

@@ -22,6 +22,9 @@
22 22
 #include <stdint.h>
23 23
 #include <stdbool.h>
24 24
 
25
+// returns < 0 on error
26
+int8_t volcano_discover_characteristics(void);
27
+
25 28
 // in 1/10th degrees C, or < 0 on error
26 29
 int16_t volcano_get_current_temp(void);
27 30
 int16_t volcano_get_target_temp(void);

+ 221
- 15
src/ble.c 查看文件

@@ -28,10 +28,11 @@
28 28
 #include "util.h"
29 29
 #include "ble.h"
30 30
 
31
-#define BLE_READ_TIMEOUT_MS (2 * 500)
32
-#define BLE_SRVC_TIMEOUT_MS (2 * 500)
33
-#define BLE_CHAR_TIMEOUT_MS (2 * 2000)
34
-#define BLE_WRTE_TIMEOUT_MS (2 * 500)
31
+#define BLE_READ_TIMEOUT_MS (3 * 500)
32
+#define BLE_SRVC_TIMEOUT_MS (3 * 500)
33
+#define BLE_CHAR_TIMEOUT_MS (3 * 2000)
34
+#define BLE_WRTE_TIMEOUT_MS (3 * 500)
35
+#define BLE_NOTY_TIMEOUT_MS (3 * 500)
35 36
 #define BLE_MAX_SCAN_AGE_MS (10 * 1000)
36 37
 #define BLE_MAX_SERVICES 8
37 38
 #define BLE_MAX_CHARACTERISTICS 8
@@ -48,11 +49,14 @@ enum ble_state {
48 49
     TC_W4_CHARACTERISTIC,
49 50
     TC_W4_WRITE,
50 51
     TC_WRITE_COMPLETE,
52
+    TC_W4_NOTIFY_ENABLE,
53
+    TC_NOTIFY_ENABLED,
51 54
 };
52 55
 
53 56
 struct ble_characteristic {
54 57
     bool set;
55 58
     gatt_client_characteristic_t c;
59
+    gatt_client_notification_t n;
56 60
 };
57 61
 
58 62
 struct ble_service {
@@ -319,6 +323,11 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
319 323
             state = TC_WRITE_COMPLETE;
320 324
             break;
321 325
 
326
+        case TC_W4_NOTIFY_ENABLE:
327
+            //debug("notify enable complete");
328
+            state = TC_NOTIFY_ENABLED;
329
+            break;
330
+
322 331
         default:
323 332
             debug("gatt query complete in invalid state %d", state);
324 333
             break;
@@ -326,6 +335,22 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
326 335
         break;
327 336
     }
328 337
 
338
+    case GATT_EVENT_NOTIFICATION: {
339
+        if ((state != TC_READY) && (state != TC_WRITE_COMPLETE)) {
340
+            debug("gatt notification in invalid state %d", state);
341
+            return;
342
+        }
343
+
344
+        uint16_t value_length = gatt_event_notification_get_value_length(packet);
345
+        const uint8_t *value = gatt_event_notification_get_value(packet);
346
+        if ((read_len + value_length) <= BLE_MAX_VALUE_LEN) {
347
+            memcpy(data_buff + read_len, value, value_length);
348
+            read_len += value_length;
349
+        }
350
+
351
+        break;
352
+    }
353
+
329 354
     default:
330 355
         //debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
331 356
         break;
@@ -572,20 +597,14 @@ int32_t ble_read(const uint8_t *characteristic, uint8_t *buff, uint16_t buff_len
572 597
 
573 598
     memcpy(buff, data_buff, read_len);
574 599
 
600
+    uint16_t tmp = read_len;
601
+    read_len = 0;
602
+
575 603
     cyw43_thread_exit();
576
-    return read_len;
604
+    return tmp;
577 605
 }
578 606
 
579
-int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
580
-                  uint8_t *buff, uint16_t buff_len) {
581
-    cyw43_thread_enter();
582
-
583
-    if (state != TC_READY) {
584
-        cyw43_thread_exit();
585
-        debug("invalid state for write (%d)", state);
586
-        return -1;
587
-    }
588
-
607
+static int discover_service(const uint8_t *service) {
589 608
     // check if service has already been discovered
590 609
     int srvc = -1, free_srvc = -1;
591 610
     for (int i = 0; i < BLE_MAX_SERVICES; i++) {
@@ -652,6 +671,10 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
652 671
         cyw43_thread_enter();
653 672
     }
654 673
 
674
+    return srvc;
675
+}
676
+
677
+static int discover_characteristic(int srvc, const uint8_t *characteristic) {
655 678
     // check if characteristic has already been discovered
656 679
     int ch = -1, free_ch = -1;
657 680
     for (int i = 0; i < BLE_MAX_CHARACTERISTICS; i++) {
@@ -719,6 +742,31 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
719 742
         cyw43_thread_enter();
720 743
     }
721 744
 
745
+    return ch;
746
+}
747
+
748
+int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
749
+                 const uint8_t *buff, uint16_t buff_len) {
750
+    cyw43_thread_enter();
751
+
752
+    if (state != TC_READY) {
753
+        cyw43_thread_exit();
754
+        debug("invalid state for write (%d)", state);
755
+        return -1;
756
+    }
757
+
758
+    int srvc = discover_service(service);
759
+    if (srvc < 0) {
760
+        debug("error discovering service (%d)", srvc);
761
+        return srvc;
762
+    }
763
+
764
+    int ch = discover_characteristic(srvc, characteristic);
765
+    if (ch < 0) {
766
+        debug("error discovering characteristic (%d)", ch);
767
+        return ch;
768
+    }
769
+
722 770
     if (buff_len > BLE_MAX_VALUE_LEN) {
723 771
         buff_len = BLE_MAX_VALUE_LEN;
724 772
     }
@@ -768,3 +816,161 @@ int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
768 816
     cyw43_thread_exit();
769 817
     return ret;
770 818
 }
819
+
820
+int8_t ble_discover(const uint8_t *service, const uint8_t *characteristic) {
821
+    cyw43_thread_enter();
822
+
823
+    if (state != TC_READY) {
824
+        cyw43_thread_exit();
825
+        debug("invalid state for discovery (%d)", state);
826
+        return -1;
827
+    }
828
+
829
+    int srvc = discover_service(service);
830
+    if (srvc < 0) {
831
+        debug("error discovering service (%d)", srvc);
832
+        return srvc;
833
+    }
834
+
835
+    int ch = discover_characteristic(srvc, characteristic);
836
+    if (ch < 0) {
837
+        debug("error discovering characteristic (%d)", ch);
838
+        return ch;
839
+    }
840
+
841
+    cyw43_thread_exit();
842
+    return 0;
843
+}
844
+
845
+int8_t ble_notification_disable(const uint8_t *service, const uint8_t *characteristic) {
846
+    cyw43_thread_enter();
847
+
848
+    if (state != TC_READY) {
849
+        cyw43_thread_exit();
850
+        debug("invalid state for notify (%d)", state);
851
+        return -1;
852
+    }
853
+
854
+    int srvc = discover_service(service);
855
+    if (srvc < 0) {
856
+        debug("error discovering service (%d)", srvc);
857
+        return srvc;
858
+    }
859
+
860
+    int ch = discover_characteristic(srvc, characteristic);
861
+    if (ch < 0) {
862
+        debug("error discovering characteristic (%d)", ch);
863
+        return ch;
864
+    }
865
+
866
+    gatt_client_stop_listening_for_characteristic_value_updates(&services[srvc].chars[ch].n);
867
+
868
+    cyw43_thread_exit();
869
+    return 0;
870
+}
871
+
872
+int8_t ble_notification_enable(const uint8_t *service, const uint8_t *characteristic) {
873
+    cyw43_thread_enter();
874
+
875
+    if (state != TC_READY) {
876
+        cyw43_thread_exit();
877
+        debug("invalid state for notify (%d)", state);
878
+        return -1;
879
+    }
880
+
881
+    int srvc = discover_service(service);
882
+    if (srvc < 0) {
883
+        debug("error discovering service (%d)", srvc);
884
+        return srvc;
885
+    }
886
+
887
+    int ch = discover_characteristic(srvc, characteristic);
888
+    if (ch < 0) {
889
+        debug("error discovering characteristic (%d)", ch);
890
+        return ch;
891
+    }
892
+
893
+    gatt_client_listen_for_characteristic_value_updates(&services[srvc].chars[ch].n,
894
+                                                        hci_event_handler,
895
+                                                        connection_handle,
896
+                                                        &services[srvc].chars[ch].c);
897
+
898
+    gatt_client_write_client_characteristic_configuration(hci_event_handler,
899
+                                                          connection_handle,
900
+                                                          &services[srvc].chars[ch].c,
901
+                                                          GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
902
+
903
+    state = TC_W4_NOTIFY_ENABLE;
904
+    cyw43_thread_exit();
905
+
906
+    uint32_t start_time = to_ms_since_boot(get_absolute_time());
907
+    while (1) {
908
+        sleep_ms(1);
909
+        main_loop_hw();
910
+
911
+        uint32_t now = to_ms_since_boot(get_absolute_time());
912
+        if ((now - start_time) >= BLE_NOTY_TIMEOUT_MS) {
913
+            debug("timeout waiting for notify enable");
914
+            cyw43_thread_enter();
915
+            state = TC_READY;
916
+            cyw43_thread_exit();
917
+            return -6;
918
+        }
919
+
920
+        cyw43_thread_enter();
921
+        enum ble_state state_cached = state;
922
+        cyw43_thread_exit();
923
+
924
+        if ((state_cached == TC_NOTIFY_ENABLED) || (state_cached == TC_READY)) {
925
+            break;
926
+        }
927
+    }
928
+
929
+    cyw43_thread_enter();
930
+
931
+    int8_t ret = (state == TC_NOTIFY_ENABLED) ? 0 : -7;
932
+    state = TC_READY;
933
+
934
+    cyw43_thread_exit();
935
+    return ret;
936
+}
937
+
938
+bool ble_notification_ready(void) {
939
+    cyw43_thread_enter();
940
+
941
+    if (state != TC_READY) {
942
+        cyw43_thread_exit();
943
+        debug("invalid state for notify (%d)", state);
944
+        return -1;
945
+    }
946
+
947
+    uint16_t tmp = read_len;
948
+
949
+    cyw43_thread_exit();
950
+    return (tmp > 0);
951
+
952
+}
953
+
954
+uint16_t ble_notification_get(uint8_t *buff, uint16_t buff_len) {
955
+    cyw43_thread_enter();
956
+
957
+    if (state != TC_READY) {
958
+        cyw43_thread_exit();
959
+        debug("invalid state for notify (%d)", state);
960
+        return -1;
961
+    }
962
+
963
+    if (read_len > buff_len) {
964
+        debug("buffer too short (%d < %d)", buff_len, read_len);
965
+        cyw43_thread_exit();
966
+        return -2;
967
+    }
968
+
969
+    memcpy(buff, data_buff, read_len);
970
+
971
+    uint16_t tmp = read_len;
972
+    read_len = 0;
973
+
974
+    cyw43_thread_exit();
975
+    return tmp;
976
+}

+ 2
- 1
src/buttons.c 查看文件

@@ -69,8 +69,9 @@ void buttons_run(void) {
69 69
 
70 70
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
71 71
             if (state != buttons[i].current_state) {
72
+                //debug("btn %d now %s", i, state ? "pressed" : "released");
73
+
72 74
                 buttons[i].current_state = state;
73
-                debug("btn %d now %s", i, state ? "pressed" : "released");
74 75
                 if (callback) {
75 76
                     callback(i, state);
76 77
                 }

+ 8
- 0
src/console.c 查看文件

@@ -171,6 +171,14 @@ static void cnsl_interpret(const char *line) {
171 171
                         bd_addr_to_str(results[i].addr),
172 172
                         results[i].type, results[i].rssi,
173 173
                         age / 1000.0, results[i].name, info);
174
+
175
+                if (results[i].data_len > 0) {
176
+                    hexdump(results[i].data, results[i].data_len);
177
+                }
178
+
179
+                if (i < (n - 1)) {
180
+                    println();
181
+                }
174 182
             }
175 183
         }
176 184
     } else if (str_startswith(line, "con ")) {

+ 2
- 2
src/lcd.c 查看文件

@@ -34,8 +34,8 @@
34 34
 #define LCD_PIN_RST 12
35 35
 #define LCD_PIN_BL 13
36 36
 
37
-#define ST7789_PICO_COLUMN                             240
38
-#define ST7789_PICO_ROW                                ST7789_PICO_COLUMN
37
+#define ST7789_PICO_COLUMN                             LCD_HEIGHT
38
+#define ST7789_PICO_ROW                                LCD_WIDTH
39 39
 
40 40
 #define ST7789_PICO_ACCESS                            (ST7789_ORDER_PAGE_TOP_TO_BOTTOM | \
41 41
                                                        ST7789_ORDER_COLUMN_LEFT_TO_RIGHT | \

+ 0
- 7
src/mem.c 查看文件

@@ -79,10 +79,8 @@ static uint32_t calc_checksum(const struct mem_contents *data) {
79 79
 
80 80
 void mem_load_defaults(void) {
81 81
     data_ram.data.wf_count = wf_default_count;
82
-    debug("preparing %d default workflows", data_ram.data.wf_count);
83 82
     for (uint16_t i = 0; i < wf_default_count; i++) {
84 83
         data_ram.data.wf[i] = wf_default_data[i];
85
-        debug("\"%s\" by \"%s\"", data_ram.data.wf[i].name, data_ram.data.wf[i].author);
86 84
     }
87 85
 }
88 86
 
@@ -108,11 +106,6 @@ void mem_init(void) {
108 106
     } else {
109 107
         debug("invalid config (0x%02X != 0x%02X)", flash_ptr->version, MEM_VERSION);
110 108
     }
111
-
112
-    debug("found %d workflows", data_ram.data.wf_count);
113
-    for (uint16_t i = 0; i < data_ram.data.wf_count; i++) {
114
-        debug("\"%s\" by \"%s\"", data_ram.data.wf[i].name, data_ram.data.wf[i].author);
115
-    }
116 109
 }
117 110
 
118 111
 static void mem_write_flash(void *param) {

+ 2
- 2
src/state_crafty.c 查看文件

@@ -28,7 +28,7 @@
28 28
 
29 29
 #include "menu.h"
30 30
 
31
-#define CRAFTY_UPDATE_TIME_MS 1000
31
+#define CRAFTY_UPDATE_TIME_MS 3000
32 32
 
33 33
 static bd_addr_t ble_addr = {0};
34 34
 static bd_addr_type_t ble_type = 0;
@@ -115,8 +115,8 @@ void state_crafty_run(void) {
115 115
     static uint32_t last = 0;
116 116
     uint32_t now = to_ms_since_boot(get_absolute_time());
117 117
     if (((now - last) >= CRAFTY_UPDATE_TIME_MS) || (last == 0)) {
118
-        last = now;
119 118
         menu_run(draw, true);
119
+        last = to_ms_since_boot(get_absolute_time());
120 120
     }
121 121
 
122 122
     if (wait_for_disconnect && !ble_is_connected()) {

+ 9
- 2
src/state_scan.c 查看文件

@@ -100,9 +100,16 @@ static void draw(struct menu_state *menu) {
100 100
 #ifdef MENU_PREFER_VOLCANO
101 101
             if (dev == DEV_VOLCANO) {
102 102
                 menu->selection = devs - 1;
103
+
103 104
 #ifdef VOLCANO_AUTO_CONNECT_TIMEOUT_MS
104
-                auto_connect_time = to_ms_since_boot(get_absolute_time());
105
-                auto_connect_idx = i;
105
+#ifdef VOLCANO_AUTO_CONNECT_WITHIN_MS
106
+                if (to_ms_since_boot(get_absolute_time()) <= VOLCANO_AUTO_CONNECT_WITHIN_MS) {
107
+#endif // VOLCANO_AUTO_CONNECT_WITHIN_MS
108
+                    auto_connect_time = to_ms_since_boot(get_absolute_time());
109
+                    auto_connect_idx = i;
110
+#ifdef VOLCANO_AUTO_CONNECT_WITHIN_MS
111
+                }
112
+#endif // VOLCANO_AUTO_CONNECT_WITHIN_MS
106 113
 #endif // VOLCANO_AUTO_CONNECT_TIMEOUT_MS
107 114
             }
108 115
 #endif // MENU_PREFER_VOLCANO

+ 9
- 10
src/text.c 查看文件

@@ -166,16 +166,16 @@ void text_box(const char *s, bool centered) {
166 166
         text_prepare_font(&font);
167 167
     }
168 168
 
169
-    int x = 0;
170
-    int width = 240;
169
+    int x_off = 0;
170
+    int width = LCD_WIDTH;
171 171
 
172
-    int y = 50;
173
-    int height = MENU_MAX_LINES * (20 + 2);
172
+    int y_off = 50;
173
+    int height = (MENU_MAX_LINES * 20) + ((MENU_MAX_LINES - 1) * 2);
174 174
 
175 175
     struct text_conf text = {
176 176
         .text = "",
177
-        .x = x,
178
-        .y = y,
177
+        .x = x_off,
178
+        .y = y_off,
179 179
         .justify = false,
180 180
         .alignment = centered ? MF_ALIGN_CENTER : MF_ALIGN_LEFT,
181 181
         .width = width,
@@ -186,10 +186,9 @@ void text_box(const char *s, bool centered) {
186 186
         .font = &font,
187 187
     };
188 188
 
189
-    lcd_write_rect(x,
190
-                   y,
191
-                   x + width - 1,
192
-                   y + height - 1,
189
+    lcd_write_rect(x_off, y_off,
190
+                   x_off + width - 1,
191
+                   y_off + height - 1,
193 192
                    RGB_565(0x00, 0x00, 0x00));
194 193
 
195 194
     text.text = s;

+ 37
- 0
src/volcano.c 查看文件

@@ -40,6 +40,43 @@ static uint8_t uuid_base2[16] = {
40 40
     0x5a, 0x26, 0x42, 0x49, 0x43, 0x4b, 0x45, 0x4c,
41 41
 };
42 42
 
43
+int8_t volcano_discover_characteristics(void) {
44
+    uuid_base[3] = UUID_WRITE_SRVC;
45
+    int8_t r;
46
+
47
+    uuid_base2[3] = UUID_TARGET_TEMP;
48
+    r = ble_discover(uuid_base, uuid_base2);
49
+    if (r < 0) {
50
+        return r;
51
+    }
52
+
53
+    uuid_base2[3] = UUID_HEATER_ON;
54
+    r = ble_discover(uuid_base, uuid_base2);
55
+    if (r < 0) {
56
+        return r;
57
+    }
58
+
59
+    uuid_base2[3] = UUID_HEATER_OFF;
60
+    r = ble_discover(uuid_base, uuid_base2);
61
+    if (r < 0) {
62
+        return r;
63
+    }
64
+
65
+    uuid_base2[3] = UUID_PUMP_ON;
66
+    r = ble_discover(uuid_base, uuid_base2);
67
+    if (r < 0) {
68
+        return r;
69
+    }
70
+
71
+    uuid_base2[3] = UUID_PUMP_OFF;
72
+    r = ble_discover(uuid_base, uuid_base2);
73
+    if (r < 0) {
74
+        return r;
75
+    }
76
+
77
+    return 0;
78
+}
79
+
43 80
 int16_t volcano_get_current_temp(void) {
44 81
     uuid_base[3] = UUID_CURRENT_TEMP;
45 82
 

+ 6
- 5
src/workflow.c 查看文件

@@ -199,12 +199,13 @@ void wf_start(uint16_t index) {
199 199
     wf_i = index;
200 200
     step = 0;
201 201
 
202
-    // discover characteristics
203
-    volcano_set_pump_state(false);
204
-    volcano_set_heater_state(false);
205
-    volcano_set_target_temp(1850);
206
-
202
+    /*
203
+     * first turn on heater, then do discovery, to save some time.
204
+     * this means we heat for some seconds before changing the setpoint.
205
+     * should not be a problem in practice.
206
+     */
207 207
     volcano_set_heater_state(true);
208
+    volcano_discover_characteristics();
208 209
 
209 210
     do_step();
210 211
 }

正在加载...
取消
保存