Browse Source

add support for PCF8574 gpio expansion

Thomas Buck 3 months ago
parent
commit
6de07b6cc9
5 changed files with 130 additions and 28 deletions
  1. 2
    0
      include/GPIOBank.h
  2. 34
    2
      include/config_pins.h
  3. 1
    0
      platformio.ini
  4. 16
    16
      src/Functionality.cpp
  5. 77
    10
      src/GPIOBank.cpp

+ 2
- 0
include/GPIOBank.h View File

@@ -20,6 +20,8 @@
20 20
 #ifndef _GPIO_BANK_H_
21 21
 #define _GPIO_BANK_H_
22 22
 
23
+void gpio_i2c_init(void);
24
+
23 25
 class GPIOBank {
24 26
 public:
25 27
     GPIOBank(int _size);

+ 34
- 2
include/config_pins.h View File

@@ -31,6 +31,10 @@
31 31
 
32 32
 #ifdef FUNCTION_UI
33 33
 
34
+/*
35
+ * AVR UI
36
+ */
37
+
34 38
 #define SERIAL_LCD_TX_PIN 10
35 39
 
36 40
 #define KEYMATRIX_ROWS 4
@@ -44,6 +48,10 @@
44 48
 
45 49
 #ifdef FUNCTION_CONTROL
46 50
 
51
+/*
52
+ * AVR Controller
53
+ */
54
+
47 55
 // out 1, out 2, out 3, out 4, in
48 56
 #define VALVE_COUNT 5
49 57
 #define VALVE_PINS 10, 11, 12, 14, 15
@@ -75,6 +83,10 @@
75 83
 
76 84
 #ifdef FUNCTION_UI
77 85
 
86
+/*
87
+ * ESP UI
88
+ */
89
+
78 90
 #error configuration not supported
79 91
 
80 92
 #endif // FUNCTION_UI
@@ -83,8 +95,28 @@
83 95
 
84 96
 #ifdef FUNCTION_CONTROL
85 97
 
86
-#define PLANT_COUNT 4
87
-#define PLANT_PINS 27, 14, 5, 18
98
+/*
99
+ * ESP Controller
100
+ */
101
+
102
+/*
103
+ * I2C Port Expander PCF8574(A)
104
+ *
105
+ * Address ranges:
106
+ * PCF8574: 0x20 - 0x27
107
+ * PCF8574A: 0x38 - 0x3F
108
+ */
109
+#define I2C_GPIO_EXPANDER_COUNT 1
110
+#define I2C_GPIO_EXPANDER_ADDR 0x20
111
+
112
+/*
113
+ * GPIO Numbering Scheme
114
+ * 000 - 099: normal ESP32 GPIOs
115
+ * 100 - 228: consecutive I2C Expander GPIOs
116
+ */
117
+
118
+#define PLANT_COUNT 8
119
+#define PLANT_PINS 27, 14, 5, 18, 100, 101, 102, 103
88 120
 
89 121
 #define INLET_PIN 15
90 122
 

+ 1
- 0
platformio.ini View File

@@ -34,6 +34,7 @@ lib_deps =
34 34
     https://github.com/Links2004/arduinoWebSockets
35 35
     https://github.com/rlogiacco/CircularBuffer
36 36
     https://github.com/tobiasschuerg/InfluxDB-Client-for-Arduino.git
37
+    https://github.com/RobTillaart/PCF8574
37 38
 
38 39
 [env:arduino_ui]
39 40
 platform = atmelavr

+ 16
- 16
src/Functionality.cpp View File

@@ -56,9 +56,7 @@ bool doing_multi_input = false;
56 56
 
57 57
 #ifdef FUNCTION_CONTROL
58 58
 
59
-#ifndef FUNCTION_UI
60 59
 #include <Wire.h>
61
-#endif // ! FUNCTION_UI
62 60
 
63 61
 #include "Plants.h"
64 62
 #include "Statemachine.h"
@@ -457,13 +455,6 @@ Plants *get_plants(void) {
457 455
 }
458 456
 
459 457
 void control_setup(void) {
460
-    plants.setValvePins(valve_pins);
461
-    plants.setPumpPins(pump_pins);
462
-    plants.setSwitchPins(switch_pins, true);
463
-    plants.setAuxPins(aux_pins);
464
-    
465
-#ifndef FUNCTION_UI
466
-    
467 458
     debug.println("Initializing I2C Master");
468 459
     Wire.setClock(I2C_BUS_SPEED);
469 460
     
@@ -473,12 +464,18 @@ void control_setup(void) {
473 464
     Wire.begin();
474 465
 #endif // defined(I2C_SDA_PIN) && defined(I2C_SCL_PIN)
475 466
     
467
+    gpio_i2c_init();
468
+
476 469
 #ifdef DEBUG_WAIT_FOR_SERIAL_CONN
477 470
     debug.println("Wait for Serial");
478 471
     while (!Serial);
479 472
 #endif // DEBUG_WAIT_FOR_SERIAL_CONN
480
-    
481
-#endif // ! FUNCTION_UI
473
+
474
+    debug.println("Initializing GPIOs");
475
+    plants.setValvePins(valve_pins);
476
+    plants.setPumpPins(pump_pins);
477
+    plants.setSwitchPins(switch_pins, true);
478
+    plants.setAuxPins(aux_pins);
482 479
 }
483 480
 
484 481
 void control_begin(void) {
@@ -540,24 +537,27 @@ void write_to_all(const char *a, const char *b,
540 537
     
541 538
     //debug.println("write_to_all i2c");
542 539
     
540
+    // rarely some lines don't update
541
+    delay(100);
542
+
543 543
     for (int i = 0; i < 4; i++) {
544 544
         Wire.beginTransmission(OWN_I2C_ADDRESS);
545 545
         Wire.write(0x03); // display command
546
-    
546
+
547 547
         Wire.write(i);
548
-        
548
+
549 549
         int l = strlen(lines[i]);
550 550
         Wire.write(l);
551
-        
551
+
552 552
         for (int n = 0; n < l; n++) {
553 553
             Wire.write(lines[i][n]);
554 554
         }
555
-    
555
+
556 556
         Wire.endTransmission();
557 557
     }
558 558
     
559 559
     Wire.beginTransmission(OWN_I2C_ADDRESS);
560
-    Wire.write(0x04); // display command
560
+    Wire.write(0x04); // button command
561 561
     Wire.write((int8_t)num_input);
562 562
     Wire.endTransmission();
563 563
     

+ 77
- 10
src/GPIOBank.cpp View File

@@ -20,13 +20,80 @@
20 20
 #include <Arduino.h>
21 21
 
22 22
 #include "GPIOBank.h"
23
+#include "config.h"
24
+#include "config_pins.h"
23 25
 
24 26
 #ifdef PLATFORM_ESP
27
+#include <PCF8574.h>
28
+#include <Wire.h>
25 29
 #include "WifiStuff.h"
26 30
 #endif // PLATFORM_ESP
27 31
 
28 32
 //#define GPIO_HIGH_AS_INPUT
29 33
 
34
+// ----------------------------------------------------------------------------
35
+
36
+#if (I2C_GPIO_EXPANDER_COUNT > 0)
37
+static PCF8574 expand[I2C_GPIO_EXPANDER_COUNT];
38
+#endif
39
+
40
+void gpio_i2c_init(void) {
41
+#if (I2C_GPIO_EXPANDER_COUNT > 0)
42
+    for (int i = 0; i < I2C_GPIO_EXPANDER_COUNT; i++) {
43
+        expand[i].begin(0xFF);
44
+    }
45
+#endif
46
+}
47
+
48
+static void gpio_pinMode(int pin, int value) {
49
+    if (pin < 100) {
50
+        pinMode(pin, value);
51
+    } else {
52
+        pin -= 100;
53
+        int ex = pin / 8;
54
+        pin = pin % 8;
55
+        if (ex < I2C_GPIO_EXPANDER_COUNT) {
56
+            uint8_t mask = expand[ex].getButtonMask();
57
+            if (value == OUTPUT) {
58
+                mask &= ~(1 << pin);
59
+            } else {
60
+                mask |= (1 << pin);
61
+            }
62
+            expand[ex].setButtonMask(mask);
63
+        }
64
+    }
65
+}
66
+
67
+static void gpio_digitalWrite(int pin, int value) {
68
+    if (pin < 100) {
69
+        digitalWrite(pin, value);
70
+    } else {
71
+        pin -= 100;
72
+        int ex = pin / 8;
73
+        pin = pin % 8;
74
+        if (ex < I2C_GPIO_EXPANDER_COUNT) {
75
+            expand[ex].write(pin, value);
76
+        }
77
+    }
78
+}
79
+
80
+static int gpio_digitalRead(int pin) {
81
+    if (pin < 100) {
82
+        return digitalRead(pin);
83
+    } else {
84
+        pin -= 100;
85
+        int ex = pin / 8;
86
+        pin = pin % 8;
87
+        if (ex < I2C_GPIO_EXPANDER_COUNT) {
88
+            return expand[ex].readButton(pin);
89
+        } else {
90
+            return 0;
91
+        }
92
+    }
93
+}
94
+
95
+// ----------------------------------------------------------------------------
96
+
30 97
 GPIOBank::GPIOBank(int _size) {
31 98
     size = _size;
32 99
     pins = new int[size];
@@ -48,10 +115,10 @@ void GPIOBank::setPinNumbers(int _pins[]) {
48 115
 void GPIOBank::setOutput(void) {
49 116
     for (int i = 0; i < size; i++) {
50 117
 #ifdef GPIO_HIGH_AS_INPUT
51
-        pinMode(pins[i], INPUT);
118
+        gpio_pinMode(pins[i], INPUT);
52 119
 #else
53
-        pinMode(pins[i], OUTPUT);
54
-        digitalWrite(pins[i], HIGH);
120
+        gpio_pinMode(pins[i], OUTPUT);
121
+        gpio_digitalWrite(pins[i], HIGH);
55 122
 #endif
56 123
         out_state[i] = true;
57 124
     }
@@ -61,9 +128,9 @@ void GPIOBank::setOutput(void) {
61 128
 void GPIOBank::setInput(bool pullup) {
62 129
     for (int i = 0; i < size; i++) {
63 130
         if (pullup) {
64
-            pinMode(pins[i], INPUT_PULLUP);
131
+            gpio_pinMode(pins[i], INPUT_PULLUP);
65 132
         } else {
66
-            pinMode(pins[i], INPUT);
133
+            gpio_pinMode(pins[i], INPUT);
67 134
         }
68 135
     }
69 136
     is_output = false;
@@ -81,13 +148,13 @@ void GPIOBank::setPin(int n, bool state) {
81 148
     if ((n >= 0) && (n < size)) {
82 149
 #ifdef GPIO_HIGH_AS_INPUT
83 150
         if (state) {
84
-            pinMode(pins[n], OUTPUT);
85
-            digitalWrite(pins[n], LOW);
151
+            gpio_pinMode(pins[n], OUTPUT);
152
+            gpio_digitalWrite(pins[n], LOW);
86 153
         } else {
87
-            pinMode(pins[n], INPUT);
154
+            gpio_pinMode(pins[n], INPUT);
88 155
         }
89 156
 #else
90
-        digitalWrite(pins[n], (!state) ? HIGH : LOW);
157
+        gpio_digitalWrite(pins[n], (!state) ? HIGH : LOW);
91 158
 #endif
92 159
 
93 160
         out_state[n] = !state;
@@ -109,7 +176,7 @@ bool GPIOBank::getPin(int n) {
109 176
         if (is_output) {
110 177
             return !out_state[n];
111 178
         } else {
112
-            return (!digitalRead(pins[n]));
179
+            return (!gpio_digitalRead(pins[n]));
113 180
         }
114 181
     } else {
115 182
         return false;

Loading…
Cancel
Save