MycilaJSY 13.0.0
Arduino / ESP32 library for the JSY1031, JSY-MK-163, JSY-MK-193, JSY-MK-194, JSY-MK-227, JSY-MK-229, JSY-MK-333 families single-phase and three-phase AC bidirectional meters from Shenzhen Jiansiyan Technologies Co, Ltd.
Loading...
Searching...
No Matches
MycilaDimmerDFRobot.cpp
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright (C) 2023-2025 Mathieu Carbou
4 */
5#include <MycilaDimmerDFRobot.h>
6
7// logging
8#include <esp32-hal-log.h>
9
10#ifdef MYCILA_LOGGER_SUPPORT
11 #include <MycilaLogger.h>
12extern Mycila::Logger logger;
13 #define LOGD(tag, format, ...) logger.debug(tag, format, ##__VA_ARGS__)
14 #define LOGI(tag, format, ...) logger.info(tag, format, ##__VA_ARGS__)
15 #define LOGW(tag, format, ...) logger.warn(tag, format, ##__VA_ARGS__)
16 #define LOGE(tag, format, ...) logger.error(tag, format, ##__VA_ARGS__)
17#else
18 #define LOGD(tag, format, ...) ESP_LOGD(tag, format, ##__VA_ARGS__)
19 #define LOGI(tag, format, ...) ESP_LOGI(tag, format, ##__VA_ARGS__)
20 #define LOGW(tag, format, ...) ESP_LOGW(tag, format, ##__VA_ARGS__)
21 #define LOGE(tag, format, ...) ESP_LOGE(tag, format, ##__VA_ARGS__)
22#endif
23
24#define TAG "DFR_DIMMER"
25
27 if (_enabled)
28 return;
29
30 uint8_t resolution = getResolution();
31 if (!resolution) {
32 LOGE(TAG, "Disable DFRobot Dimmer: SKU not set!");
33 return;
34 }
35
36 // sanity checks
37 if (_sku == SKU::DFR1071_GP8211S) {
38 if (_channel > 0) {
39 LOGW(TAG, "DFRobot DFR1071 (GP8211S) has only one channel: switching to channel 0");
40 _channel = 0;
41 }
42 }
43
44 if (_channel > 2) {
45 LOGE(TAG, "Disable DFRobot Dimmer: invalid channel %d", _channel);
46 return;
47 }
48
49 // discovery
50 bool found = false;
51 if (_deviceAddress) {
52 LOGI(TAG, "Searching for DFRobot Dimmer @ 0x%02x...", _deviceAddress);
53 for (int i = 0; i < 3; i++) {
54 uint8_t err = _test(_deviceAddress);
55 if (err) {
56 LOGD(TAG, "DFRobot Dimmer @ 0x%02x: TwoWire communication error: %d", _deviceAddress, err);
57 delay(10);
58 } else {
59 found = true;
60 break;
61 }
62 }
63
64 } else {
65 LOGI(TAG, "Searching for DFRobot Dimmer @ 0x58 up to 0x5F...");
66 for (uint8_t addr = 0x58; !found && addr <= 0x5F; addr++) {
67 if (_test(addr) == ESP_OK) {
68 _deviceAddress = addr;
69 found = true;
70 break;
71 }
72 }
73 }
74
75 if (found) {
76 LOGI(TAG, "Found DFRobot Dimmer @ 0x%02x and channel %d", _deviceAddress, _channel);
77 } else if (_deviceAddress) {
78 LOGW(TAG, "DFRobot Dimmer @ 0x%02x: Unable to communicate with device", _deviceAddress);
79 } else {
80 _deviceAddress = 0x58;
81 LOGW(TAG, "DFRobot Dimmer no found! Using default address 0x58");
82 }
83
84 // set output
85 uint8_t err = _sendOutput(_deviceAddress, _output);
86 if (err) {
87 LOGE(TAG, "Disable DFRobot Dimmer @ 0x%02x: Unable to set output voltage: TwoWire communication error: %d", _deviceAddress, err);
88 return;
89 }
90
91 _enabled = true;
92
93 // restart with last saved value
94 setDutyCycle(_dutyCycle);
95}
96
98 if (!_enabled)
99 return;
100 _enabled = false;
101 _online = false;
102 LOGI(TAG, "Disable DFRobot Dimmer @ 0x%02x", _deviceAddress);
103 _apply();
104}
105
106uint8_t Mycila::DFRobotDimmer::_sendDutyCycle(uint8_t address, uint16_t duty) {
107 duty = duty << (16 - getResolution());
108 switch (_channel) {
109 case 0: {
110 uint8_t buffer[2] = {uint8_t(duty & 0xff), uint8_t(duty >> 8)};
111 return _send(address, 0x02, buffer, 2) == 0;
112 }
113 case 1: {
114 uint8_t buffer[2] = {uint8_t(duty & 0xff), uint8_t(duty >> 8)};
115 return _send(address, 0x04, buffer, 2) == 0;
116 }
117 case 2: {
118 uint8_t buffer[4] = {uint8_t(duty & 0xff), uint8_t(duty >> 8), uint8_t(duty & 0xff), uint8_t(duty >> 8)};
119 return _send(address, 0x02, buffer, 4) == 0;
120 }
121 default:
122 assert(false); // fail
123 return ESP_FAIL;
124 }
125}
126
127uint8_t Mycila::DFRobotDimmer::_sendOutput(uint8_t address, Output output) {
128 switch (output) {
129 case Output::RANGE_0_5V: {
130 LOGI(TAG, "Set output range to 0-5V");
131 uint8_t data = 0x00;
132 return _send(address, 0x01, &data, 1);
133 }
134 case Output::RANGE_0_10V: {
135 LOGI(TAG, "Set output range to 0-10V");
136 uint8_t data = 0x11;
137 return _send(address, 0x01, &data, 1);
138 }
139 default:
140 assert(false); // fail
141 return ESP_FAIL;
142 }
143}
144
145uint8_t Mycila::DFRobotDimmer::_send(uint8_t address, uint8_t reg, uint8_t* buffer, size_t size) {
146 _wire->beginTransmission(address);
147 _wire->write(reg);
148 for (uint16_t i = 0; i < size; i++) {
149 _wire->write(buffer[i]);
150 }
151 return _wire->endTransmission();
152}
153
154uint8_t Mycila::DFRobotDimmer::_test(uint8_t address) {
155 // return _sendDutyCycle(address, 0);
156 _wire->beginTransmission(address);
157 delayMicroseconds(100);
158 return _wire->endTransmission();
159}
virtual void end()
Disable the dimmer.
uint8_t getResolution() const
Get the PWM resolution in bits.
virtual void begin()
Enable a dimmer on a specific GPIO pin.
bool setDutyCycle(float dutyCycle)
Set the power duty.