denko 0.13.3 → 0.13.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,308 @@
1
+ module Denko
2
+ module Sensor
3
+ class QMP6988
4
+ include I2C::Peripheral
5
+ include Behaviors::Poller
6
+
7
+ UPDATE_TIME = 0.020
8
+ RESET_REGISTER = 0xE0
9
+ RESET_COMMAND = 0xE6
10
+ CTRL_MEAS_REGISTER = 0xF4
11
+ STANDBY_TIME_REGISTER = 0xF5
12
+ IIR_REGISTER = 0xF1
13
+ CONFIG_LENGTH = 5
14
+ DATA_REGISTER = 0xF7
15
+ DATA_LENGTH = 6
16
+ CALIBRATION_REGISTER = 0xA0
17
+ CALIBRATION_LENGTH = 25
18
+ CHIP_ID_REGISTER = 0xD1
19
+ CHIP_ID_LENGTH = 1
20
+ FORCED_MODE = 0b01
21
+ NORMAL_MODE = 0b11
22
+
23
+ # Standby Times for Normal (Continuous) Mode in milliseconds
24
+ STANDBY_TIMES = {
25
+ 1 => 0b000,
26
+ 5 => 0b001,
27
+ 50 => 0b010,
28
+ 250 => 0b011,
29
+ 500 => 0b100,
30
+ 1000 => 0b101,
31
+ 2000 => 0b110,
32
+ 4000 => 0b111,
33
+ }
34
+
35
+ #
36
+ # Oversample Setting Values
37
+ # Note: Each sensor has a separate oversample setting.
38
+ #
39
+ # General formula:
40
+ # 2 ** (n-1), where n is the decimal value of the bits, up to 16x max oversampling.
41
+ #
42
+ OVERSAMPLE_FACTORS = {
43
+ # 0 => 0b000, # Sensor skipped. Value will be 0x800000.
44
+ 1 => 0b001,
45
+ 2 => 0b010,
46
+ 4 => 0b011,
47
+ 8 => 0b100,
48
+ 16 => 0b101,
49
+ 32 => 0b110,
50
+ 64 => 0b111,
51
+ }
52
+ #
53
+ # Single sample times (in milliseconds) for each sensor, derived from datasheet examples.
54
+ TEMPERATURE_SAMPLE_TIME = 0.9
55
+ PRESSURE_SAMPLE_TIME = 0.85
56
+
57
+ # IIR Filter Coefficients
58
+ IIR_COEFFICIENTS = {
59
+ 0 => 0b000,
60
+ 2 => 0b001,
61
+ 4 => 0b010,
62
+ 8 => 0b011,
63
+ 16 => 0b100,
64
+ 32 => 0b101, # 0b110 and 0b111 are also valid for 16.
65
+ }
66
+
67
+ def before_initialize(options={})
68
+ @i2c_address = 0x70
69
+ super(options)
70
+ end
71
+
72
+ def after_initialize(options={})
73
+ super(options)
74
+
75
+ # Avoid repeated memory allocation for callback data and state.
76
+ @reading = { temperature: nil, pressure: nil }
77
+ self.state = { temperature: nil, pressure: nil }
78
+
79
+ reset
80
+
81
+ # Get 5 config registers. Copy 0xF4 to modify it for control.
82
+ get_config_registers
83
+ @ctrl_meas_register = @registers[:f4].dup
84
+
85
+ # Default settings
86
+ self.iir_coefficient = 0
87
+ self.temperature_samples = 1
88
+ self.pressure_samples = 1
89
+ self.forced_mode
90
+
91
+ # self.forced mode triggered an initial measurement so IIR works properly if enabled.
92
+ # Wait for those values to enter the data registers, but don't read them back.
93
+ sleep @measurement_time
94
+
95
+ get_calibration_data
96
+ end
97
+
98
+ #
99
+ # Configuration Methods
100
+ #
101
+ def reset
102
+ i2c_write [RESET_REGISTER, RESET_COMMAND]
103
+ sleep UPDATE_TIME
104
+ end
105
+
106
+ def iir_coefficient=(coeff)
107
+ raise ArgumentError, "invalid IIR coefficient: #{coeff}" unless IIR_COEFFICIENTS.keys.include? coeff
108
+ i2c_write [IIR_REGISTER, IIR_COEFFICIENTS[coeff]]
109
+ @iir_coefficient = coeff
110
+ end
111
+ attr_reader :iir_coefficient
112
+
113
+ def standby_time=(ms)
114
+ raise ArgumentError, "invalid standby time: #{ms}" unless self.class::STANDBY_TIMES.keys.include? ms
115
+ byte = STANDBY_TIMES[ms] << 5
116
+ @standby_time = ms
117
+ i2c_write [STANDBY_TIME_REGISTER, byte]
118
+ sleep UPDATE_TIME
119
+ end
120
+ attr_reader :standby_time
121
+
122
+ def temperature_samples=(factor)
123
+ raise ArgumentError, "invalid oversampling factor: #{factor}" unless OVERSAMPLE_FACTORS.keys.include? factor
124
+ @ctrl_meas_register = (@ctrl_meas_register & 0b00011111) | (OVERSAMPLE_FACTORS[factor] << 5)
125
+ @temperature_samples = factor
126
+ calculate_measurement_time
127
+ i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register]
128
+ sleep UPDATE_TIME
129
+ end
130
+ attr_reader :temperature_samples
131
+
132
+ def pressure_samples=(factor)
133
+ raise ArgumentError, "invalid oversampling factor: #{factor}" unless OVERSAMPLE_FACTORS.keys.include? factor
134
+ @ctrl_meas_register = (@ctrl_meas_register & 0b11100011) | (OVERSAMPLE_FACTORS[factor] << 2)
135
+ @pressure_samples = factor
136
+ calculate_measurement_time
137
+ i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register]
138
+ sleep UPDATE_TIME
139
+ end
140
+ attr_reader :pressure_samples
141
+
142
+ def calculate_measurement_time
143
+ @measurement_time = (@temperature_samples.to_i * TEMPERATURE_SAMPLE_TIME) +
144
+ (@pressure_samples.to_i * PRESSURE_SAMPLE_TIME)
145
+ # Add 5ms for safety and convert to seconds.
146
+ @measurement_time = (@measurement_time + 5) * 0.001
147
+ end
148
+
149
+ def forced_mode
150
+ @ctrl_meas_register = (@ctrl_meas_register & 0b11111100) | FORCED_MODE
151
+ i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register]
152
+ @forced_mode = true
153
+ sleep UPDATE_TIME
154
+ end
155
+
156
+ def continuous_mode
157
+ @ctrl_meas_register = (@ctrl_meas_register & 0b11111100) | NORMAL_MODE
158
+ i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register]
159
+ @forced_mode = false
160
+ sleep UPDATE_TIME
161
+ end
162
+
163
+ def chip_id
164
+ return @chip_id if @chip_id
165
+ i2c_read(CHIP_ID_REGISTER, 1)
166
+ sleep 0.001 while !@chip_id
167
+ @chip_id
168
+ end
169
+
170
+ #
171
+ # Reading & Processing
172
+ #
173
+ def _read
174
+ if @forced_mode
175
+ # Write CTRL_MEAS register to trigger reading, then wait for measurement.
176
+ i2c_write [CTRL_MEAS_REGISTER, @ctrl_meas_register]
177
+ sleep @measurement_time
178
+ end
179
+
180
+ # Read the data bytes.
181
+ i2c_read(DATA_REGISTER, DATA_LENGTH)
182
+ end
183
+
184
+ def pre_callback_filter(bytes)
185
+ if bytes.length == DATA_LENGTH
186
+ return process_reading(bytes)
187
+ elsif bytes.length == CONFIG_LENGTH
188
+ process_config(bytes)
189
+ elsif bytes.length == CALIBRATION_LENGTH
190
+ process_calibration(bytes)
191
+ elsif bytes.length == CHIP_ID_LENGTH
192
+ @chip_id = bytes[0]
193
+ end
194
+ return nil
195
+ end
196
+
197
+ def process_reading(bytes)
198
+ # Temperature and pressure are 24-bits long each, and need 2^23 subtracted.
199
+ dt = ((bytes[3] << 16) + (bytes[4] << 8) + bytes[5]) - (0b1 << 23)
200
+ dp = ((bytes[0] << 16) + (bytes[1] << 8) + bytes[2]) - (0b1 << 23)
201
+
202
+ # Compensated temperature calculated in 1/256 of a degree Celsius.
203
+ tr = @calibration[:a0] +
204
+ @calibration[:a1] * dt +
205
+ @calibration[:a2] * (dt ** 2)
206
+ @reading[:temperature] = tr / 256.0
207
+
208
+ # Compensated pressure calculated in Pascals.
209
+ @reading[:pressure] = @calibration[:b00] +
210
+ @calibration[:bt1] * tr +
211
+ @calibration[:bp1] * dp +
212
+ @calibration[:b11] * (tr * dp) +
213
+ @calibration[:bt2] * (tr ** 2) +
214
+ @calibration[:bp2] * (dp ** 2) +
215
+ @calibration[:b12] * (dp * (tr ** 2)) +
216
+ @calibration[:b21] * ((dp ** 2) * tr) +
217
+ @calibration[:bp3] * (dp ** 3)
218
+
219
+ # Return reading for callbacks.
220
+ @reading
221
+ end
222
+
223
+ def update_state(reading)
224
+ @state_mutex.synchronize do
225
+ @state[:temperature] = reading[:temperature]
226
+ @state[:pressure] = reading[:pressure]
227
+ end
228
+ end
229
+
230
+ def get_config_registers
231
+ @registers = {}
232
+ i2c_read(IIR_REGISTER, CONFIG_LENGTH)
233
+ sleep 0.001 while @registers.empty?
234
+ @registers
235
+ end
236
+
237
+ def process_config(bytes)
238
+ @registers = { f1: bytes[0], f2: bytes[1], f3: bytes[2], f4: bytes[3], f5: bytes[4] }
239
+ end
240
+ attr_reader :registers
241
+
242
+ #
243
+ # Calibration
244
+ #
245
+ attr_reader :calibration_data_loaded
246
+
247
+ CONVERSION_FACTORS = {
248
+ a1: { A: -6.3e-03, S: 4.3e-04 },
249
+ a2: { A: -1.9e-11, S: 1.2e-10 },
250
+ bt1: { A: 1.0e-01, S: 9.1e-02 },
251
+ bt2: { A: 1.2e-08, S: 1.2e-06 },
252
+ bp1: { A: 3.3e-02, S: 1.9e-02 },
253
+ b11: { A: 2.1e-07, S: 1.4e-07 },
254
+ bp2: { A: -6.3e-10, S: 3.5e-10 },
255
+ b12: { A: 2.9e-13, S: 7.6e-13 },
256
+ b21: { A: 2.1e-15, S: 1.2e-14 },
257
+ bp3: { A: 1.3e-16, S: 7.9e-17 },
258
+ a0: 16.0,
259
+ b00: 16.0,
260
+ }
261
+
262
+ def get_calibration_data
263
+ i2c_read(CALIBRATION_REGISTER, CALIBRATION_LENGTH)
264
+ end
265
+
266
+ def process_calibration(bytes)
267
+ if bytes
268
+ # These 2 values are 20-bit instead of 16-bit, so can't combine them with #pack.
269
+ a0_unsigned = (bytes[18] << 12) + (bytes[19] << 4) + (bytes[24] & 0b00001111)
270
+ b00_unsigned = (bytes[0] << 12) + (bytes[1] << 4) + ((bytes[24] & 0b11110000) >> 4)
271
+
272
+ # Cast the raw bytes as big-endian signed.
273
+ @calibration_raw = {
274
+ # Shift these to 32-bit before converting to signed, then reverse the shift after.
275
+ a0: [(a0_unsigned << 12)].pack('L>').unpack('l>')[0] >> 12,
276
+ b00: [(b00_unsigned << 12)].pack('L>').unpack('l>')[0] >> 12,
277
+
278
+ a1: bytes[20..21].pack('C*').unpack('s>')[0],
279
+ a2: bytes[22..23].pack('C*').unpack('s>')[0],
280
+
281
+ b11: bytes[8..9].pack('C*').unpack('s>')[0],
282
+ b12: bytes[12..13].pack('C*').unpack('s>')[0],
283
+ b21: bytes[14..15].pack('C*').unpack('s>')[0],
284
+
285
+ bp1: bytes[6..7].pack('C*').unpack('s>')[0],
286
+ bp2: bytes[10..11].pack('C*').unpack('s>')[0],
287
+ bp3: bytes[16..17].pack('C*').unpack('s>')[0],
288
+
289
+ bt1: bytes[2..3].pack('C*').unpack('s>')[0],
290
+ bt2: bytes[4..5].pack('C*').unpack('s>')[0],
291
+ }
292
+
293
+ # Use conversion formulae to calculate compensation coefficients, all as floats.
294
+ @calibration = {}
295
+ @calibration_raw.keys.each do |key|
296
+ if CONVERSION_FACTORS[key].class == Float
297
+ @calibration[key] = @calibration_raw[key] / CONVERSION_FACTORS[key]
298
+ else
299
+ @calibration[key] = CONVERSION_FACTORS[key][:A] + (CONVERSION_FACTORS[key][:S] * @calibration_raw[key] / 32767.0)
300
+ end
301
+ end
302
+
303
+ @calibration_data_loaded = true
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,34 @@
1
+ module Denko
2
+ module Sensor
3
+ class RCWL9620
4
+ include I2C::Peripheral
5
+ include Behaviors::Poller
6
+
7
+ def before_initialize(options={})
8
+ @i2c_address = 0x57
9
+ super(options)
10
+ end
11
+
12
+ def _read
13
+ i2c_write(0x01)
14
+ sleep(0.120)
15
+ i2c_read(nil, 3)
16
+ end
17
+
18
+ def pre_callback_filter(bytes)
19
+ # Data is in micrometers, 3 bytes, big-endian.
20
+ um = (bytes[0] << 16) + (bytes[1] << 8) + bytes[2]
21
+ mm = um / 1000.0
22
+
23
+ # Limit output between 20 and 4500mm.
24
+ if mm > 4500.0
25
+ return 4500.0
26
+ elsif mm < 20.0
27
+ return 20.0
28
+ else
29
+ return mm
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,128 @@
1
+ module Denko
2
+ module Sensor
3
+ class SHT3X
4
+ include I2C::Peripheral
5
+ include Behaviors::Poller
6
+
7
+ RESET = 0x30A2
8
+ RESET_TIME = 0.002
9
+ HEATER_OFF = 0x3066
10
+ HEATER_ON = 0x306D
11
+ FETCH_DATA = 0xE000
12
+ REPEATABILITY = {
13
+ high: { lsb: 0x00, measurement_time: 0.016 },
14
+ medium: { lsb: 0x0B, measurement_time: 0.007 },
15
+ low: { lsb: 0x16, measurement_time: 0.005 },
16
+ }
17
+
18
+ # Unused
19
+ READ_STATUS_REGISTER = 0xF32D
20
+ CLEAR_STATUS_REGISTER = 0x3041
21
+ BREAK = 0x3093
22
+ ART = 0x2B32
23
+
24
+ def before_initialize(options={})
25
+ @i2c_address = 0x44
26
+ super(options)
27
+ end
28
+
29
+ def after_initialize(options={})
30
+ super(options)
31
+
32
+ # Avoid repeated memory allocation for callback data and state.
33
+ @reading = { temperature: nil, humidity: nil }
34
+ self.state = { temperature: nil, humidity: nil }
35
+
36
+ reset
37
+ self.repeatability = :high
38
+ end
39
+
40
+ def repeatability=(key)
41
+ raise ArgumentError, "invalid repeatability setting: #{key}" unless REPEATABILITY.keys.include? key
42
+ @measurement_lsb = REPEATABILITY[key][:lsb]
43
+ @measurement_time = REPEATABILITY[key][:measurement_time]
44
+ end
45
+
46
+ def _read
47
+ i2c_write [0x24, @measurement_lsb]
48
+ sleep(@measurement_time)
49
+ i2c_read(FETCH_DATA, 6)
50
+ end
51
+
52
+ def pre_callback_filter(bytes)
53
+ # Temperature is bytes 0 to 2: MSB, LSB, CRC
54
+ if calculate_crc(bytes[0..2]) == bytes[2]
55
+ t_raw = (bytes[0] << 8) | bytes[1]
56
+ @reading[:temperature] = (175 * t_raw / 65535.0) - 45
57
+ else
58
+ @reading[:temperature] = nil
59
+ end
60
+
61
+ # Humidity is bytes 3 to 5: MSB, LSB, CRC
62
+ if calculate_crc(bytes[3..5]) == bytes[5]
63
+ h_raw = (bytes[3] << 8) | bytes[4]
64
+ @reading[:humidity] = 100 * h_raw / 65535.0
65
+ else
66
+ @reading[:humidity] = nil
67
+ end
68
+
69
+ @reading
70
+ end
71
+
72
+ def update_state(reading)
73
+ @state_mutex.synchronize do
74
+ @state[:temperature] = reading[:temperature]
75
+ @state[:humidity] = reading[:humidity]
76
+ end
77
+ end
78
+
79
+ def reset
80
+ i2c_write [RESET]
81
+ sleep RESET_TIME
82
+ @heater_on = false
83
+ end
84
+
85
+ def heater_on?
86
+ @heater_on
87
+ end
88
+
89
+ def heater_off?
90
+ !@heater_on
91
+ end
92
+
93
+ def heater_on
94
+ i2c_write [HEATER_ON]
95
+ @heater_on = true
96
+ end
97
+
98
+ def heater_off
99
+ i2c_write [HEATER_OFF]
100
+ @heater_on = false
101
+ end
102
+
103
+ # CRC is same as AHT20 sensor. Copied from that file.
104
+ CRC_INITIAL_VALUE = 0xFF
105
+ CRC_POLYNOMIAL = 0x31
106
+ MSBIT_MASK = 0x80
107
+
108
+ def calculate_crc(bytes)
109
+ crc = CRC_INITIAL_VALUE
110
+
111
+ # Ignore last byte. That's the CRC value to compare with.
112
+ bytes.take(bytes.length - 1).each do |byte|
113
+ crc = crc ^ byte
114
+ 8.times do
115
+ if (crc & MSBIT_MASK) > 0
116
+ crc = (crc << 1) ^ CRC_POLYNOMIAL
117
+ else
118
+ crc = crc << 1
119
+ end
120
+ end
121
+ end
122
+
123
+ # Limit CRC size to 8 bits.
124
+ crc = crc & 0xFF
125
+ end
126
+ end
127
+ end
128
+ end
data/lib/denko/sensor.rb CHANGED
@@ -4,10 +4,17 @@ module Denko
4
4
  autoload :Humidity, "#{__dir__}/sensor/virtual"
5
5
  autoload :DHT, "#{__dir__}/sensor/dht"
6
6
  autoload :DS18B20, "#{__dir__}/sensor/ds18b20"
7
+ autoload :BMP180, "#{__dir__}/sensor/bmp180"
7
8
  autoload :BME280, "#{__dir__}/sensor/bme280"
9
+ autoload :BMP280, "#{__dir__}/sensor/bme280"
8
10
  autoload :HTU21D, "#{__dir__}/sensor/htu21d"
9
11
  autoload :HTU31D, "#{__dir__}/sensor/htu31d"
10
12
  autoload :AHT10, "#{__dir__}/sensor/aht"
11
13
  autoload :AHT20, "#{__dir__}/sensor/aht"
14
+ autoload :SHT3X, "#{__dir__}/sensor/sht3x"
15
+ autoload :QMP6988, "#{__dir__}/sensor/qmp6988"
16
+ autoload :RCWL9620, "#{__dir__}/sensor/rcwl9620"
17
+ autoload :HCSR04, "#{__dir__}/sensor/hcsr04"
18
+ autoload :GenericPIR, "#{__dir__}/sensor/generic_pir"
12
19
  end
13
20
  end
data/lib/denko/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Denko
2
- VERSION = "0.13.3"
2
+ VERSION = "0.13.5"
3
3
  end
data/src/denko_wifi.ino CHANGED
@@ -30,8 +30,8 @@
30
30
  #elif defined(ESP32)
31
31
  #include <WiFi.h>
32
32
  #include <ESPmDNS.h>
33
- // #include <WiFiUdp.h>
34
- // #include <ArduinoOTA.h>
33
+ #include <WiFiUdp.h>
34
+ #include <ArduinoOTA.h>
35
35
  #define WIFI_STATUS_LED 2
36
36
  #else
37
37
  #define WIFI_STATUS_LED 13
@@ -48,13 +48,13 @@
48
48
  #endif
49
49
 
50
50
  // Configure your WiFi options here. IP address is not configurable. Uses DHCP.
51
- int port = 3466;
52
- char* ssid = "yourNetwork";
53
- char* pass = "yourPassword";
51
+ #define DENKO_TCP_PORT 3466
52
+ #define WIFI_SSID "yourNetwork"
53
+ #define WIFI_PASSWORD "yourPassword"
54
54
  boolean connected = false;
55
55
 
56
56
  Denko denko;
57
- WiFiServer server(port);
57
+ WiFiServer server(DENKO_TCP_PORT);
58
58
  WiFiClient client;
59
59
 
60
60
  // Use the built in LED to indicate WiFi status.
@@ -82,7 +82,7 @@ void printWifiStatus() {
82
82
  DENKO_SERIAL_IF.println(WiFi.localIP());
83
83
  #endif
84
84
  DENKO_SERIAL_IF.print("Denko TCP Port: ");
85
- DENKO_SERIAL_IF.println(port);
85
+ DENKO_SERIAL_IF.println(DENKO_TCP_PORT);
86
86
  indicateWiFi(true);
87
87
  }
88
88
 
@@ -94,7 +94,7 @@ void connect(){
94
94
 
95
95
  // Try to connect.
96
96
  DENKO_SERIAL_IF.print("Connecting to WiFi ");
97
- WiFi.begin(ssid, pass);
97
+ WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
98
98
 
99
99
  // Delay until connected.
100
100
  while (WiFi.status() != WL_CONNECTED) {
@@ -117,14 +117,39 @@ void setup() {
117
117
  DENKO_SERIAL_IF.begin(115200);
118
118
  while(!DENKO_SERIAL_IF);
119
119
 
120
- // Enable over the air updates on the ESP8266.
121
- #if defined(ESP8266)
120
+ // Attempt initial WiFi connection.
121
+ connect();
122
+
123
+ // Enable over the air updates on the ESP8266 and ESP32.
124
+ // Taken from standard ESP8266/ESP32 OTA examples.
125
+ #if defined(ESP8266) || (ESP32)
126
+ ArduinoOTA.onStart([]() {
127
+ String type;
128
+ if (ArduinoOTA.getCommand() == U_FLASH) {
129
+ type = "sketch";
130
+ } else { // U_FS (ESP8266) or U_SPIFFS (ESP32)
131
+ type = "filesystem";
132
+ }
133
+ // NOTE: if updating FS or SPIFFS, this would be the place to unmount using FS.end() or SPIFFS.end()
134
+ Serial.println("Arduino OTA: Start updating " + type);
135
+ });
136
+ ArduinoOTA.onEnd([]() {
137
+ Serial.println("\nArduino OTA: End\n");
138
+ });
139
+ ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
140
+ Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
141
+ });
142
+ ArduinoOTA.onError([](ota_error_t error) {
143
+ Serial.printf("Error[%u]: ", error);
144
+ if (error == OTA_AUTH_ERROR) Serial.println("Arduino OTA: Auth Failed");
145
+ else if (error == OTA_BEGIN_ERROR) Serial.println("Arduino OTA: Begin Failed");
146
+ else if (error == OTA_CONNECT_ERROR) Serial.println("Arduino OTA: Connect Failed");
147
+ else if (error == OTA_RECEIVE_ERROR) Serial.println("Arduino OTA: Receive Failed");
148
+ else if (error == OTA_END_ERROR) Serial.println("Arduino OTA: End Failed");
149
+ });
122
150
  ArduinoOTA.begin();
123
151
  #endif
124
152
 
125
- // Attempt initial WiFi connection.
126
- connect();
127
-
128
153
  // Start the denko TCP server.
129
154
  server.begin();
130
155
 
@@ -141,7 +166,7 @@ void loop() {
141
166
  maintainWiFi();
142
167
 
143
168
  // Handle OTA updates.
144
- #if defined(ESP8266)
169
+ #if defined(ESP8266) || (ESP32)
145
170
  ArduinoOTA.handle();
146
171
  #endif
147
172
 
data/src/lib/Denko.cpp CHANGED
@@ -3,6 +3,9 @@
3
3
  */
4
4
  #include "Denko.h"
5
5
  #include "BoardMap.h"
6
+ #ifdef DENKO_EEPROM
7
+ #include "EEPROM.h"
8
+ #endif
6
9
 
7
10
  Denko::Denko(){
8
11
  messageFragments[0] = cmdStr;
@@ -119,7 +122,8 @@ void Denko::process() {
119
122
  #endif
120
123
 
121
124
  // Implemented in DenkoPulseInput.cpp
122
- case 9: pulseRead (); break;
125
+ case 9: pulseRead (); break;
126
+ case 20: hcsr04Read (); break;
123
127
 
124
128
  // Implemented in DenkoServo.cpp
125
129
  #ifdef DENKO_SERVO
@@ -275,7 +279,7 @@ void Denko::handshake() {
275
279
  stream->print(',');
276
280
  #if defined(EEPROM_EMULATED)
277
281
  stream->print(EMULATED_EEPROM_LENGTH);
278
- #elif defined(EEPROM_PRESENT)
282
+ #elif defined(DENKO_EEPROM)
279
283
  stream->print(EEPROM.length());
280
284
  #endif
281
285
 
data/src/lib/Denko.h CHANGED
@@ -95,11 +95,13 @@ class Denko {
95
95
  void eepromRead (); //cmd = 7
96
96
  void eepromWrite (); //cmd = 8
97
97
 
98
- // Included Libraries
98
+ // Pulse inputs (DHT and HC-SR04)
99
99
  void pulseRead (); //cmd = 9
100
+ void hcsr04Read (); //cmd = 20
101
+
102
+ // Servos
100
103
  void servoToggle (); //cmd = 10
101
104
  void servoWrite (); //cmd = 11
102
- void handleSerial (); //cmd = 12
103
105
 
104
106
  // Single Bit Bang UART
105
107
  #ifdef DENKO_UART_BB
@@ -134,9 +134,24 @@
134
134
  // Best performance acknowledging at 64 bytes, or 32 if buffer is only 64.
135
135
  //
136
136
  // These are 256/64 regardless of whether native USB CDC or UART bridge.
137
- #if defined(ARDUINO_ARCH_RP2040) || defined(ESP32) || defined(ESP8266) || defined(__SAM3X8E__)
137
+ #if defined(ARDUINO_ARCH_RP2040) || defined(ESP8266) || defined(__SAM3X8E__)
138
138
  #define DENKO_SERIAL_BUFFER_SIZE 256
139
139
  #define DENKO_RX_ACK_INTERVAL 64
140
+ // ESP32 defaults to 256 buffer. Stay one under.
141
+ #elif defined(ESP32)
142
+ #define DENKO_SERIAL_BUFFER_SIZE 255
143
+ #ifdef ARDUINO_USB_CDC_ON_BOOT
144
+ // S2 unreliable with acknowledgement before buffer is full.
145
+ #ifdef CONFIG_IDF_TARGET_ESP32S2
146
+ #define DENKO_RX_ACK_INTERVAL 255
147
+ // S3 and C3 are fine acknowledging at half buffer filled.
148
+ #else
149
+ #define DENKO_RX_ACK_INTERVAL 128
150
+ #endif
151
+ // Default to 64 if using a UART bridge.
152
+ #else
153
+ #define DENKO_RX_ACK_INTERVAL 64
154
+ #endif
140
155
  // RA4M1 has a 512 Serial buffer.
141
156
  #elif defined(_RENESAS_RA_)
142
157
  #define DENKO_SERIAL_BUFFER_SIZE 512
@@ -31,7 +31,7 @@ void Denko::showLEDArray() {
31
31
 
32
32
  // ATmega4809 still needs this delay to avoid corrupt data. Not sure why.
33
33
  #if defined(__AVR_ATmega4809__)
34
- delayMicroseconds(64);
34
+ microDelay(64);
35
35
  #endif
36
36
 
37
37
  // Write the pixel buffer to the array.