Skip to content

Commit f98500f

Browse files
committed
Fix for analog expansion apparently not taking I2C address
The problem was due to the fact that I2C change address in the expansion is done in the main loop So the expansion gets the request from the controller to change the address, but the the actual change is performed after a while in the main loop There is no way to understand how much this can take because depends on the channel setting (for example RTD is slow and when is active the main loop is slower) To solve this problem 3 actions were taken: 1. in the expansion the main loop only execute the Module::update() if the address is not set up (this ensure the main loop is as fast as possible) 2. in the controller the timeout for I2C set up address has been increased up to five seconds (but kept at 50 ms for any other message) 3. the controller has now a flag that continue to ask for the confirmation of a changed I2C address until the confirmation is received (send_new_address) This flag allow the controller to set up a new address for an expansion without a valid address is received only if the previous one has confirmed it has the new address The problem in fact was related to the fact that the expansion actually gets the address (in the main loop) but it was not able to respond in time So the controller was setting the new address of the next expansion without understanding that the old one was there
1 parent fd8c016 commit f98500f

9 files changed

+114
-32
lines changed

src/OptaAnalog.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,16 @@ void OptaAnalog::debug_with_leds() {
288288

289289
void OptaAnalog::update() {
290290
Module::update();
291+
292+
/* Opta analog has a slow main that depends on the operation it is performing
293+
at the very beginning (when the espansion has not an address yet) it is
294+
necessary to go faster so the main is skipped untill the expansion gets
295+
a valid address */
296+
297+
if(wire_i2c_address <= OPTA_DEFAULT_SLAVE_I2C_ADDRESS || wire_i2c_address >= OPTA_CONTROLLER_FIRST_TEMPORARY_ADDRESS) {
298+
return;
299+
}
300+
291301
#ifdef DEBUG_UPDATE_FW
292302
debug_with_leds();
293303
updateLedStatus();

src/OptaBlueModule.cpp

+10-11
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,8 @@ void Module::reset() {
155155

156156
setStatusLedWaitingForAddress();
157157
/* put address to invalid */
158+
wire_i2c_address = OPTA_DEFAULT_SLAVE_I2C_ADDRESS;
158159

159-
address = OPTA_DEFAULT_SLAVE_I2C_ADDRESS;
160-
161160
/* detect_in (toward Controller) as Output */
162161
pinMode(detect_in, OUTPUT);
163162
/* put detect in pin to LOW -> signal the MODULE wants an address */
@@ -176,7 +175,7 @@ void Module::reset() {
176175

177176
/* put I2C address to the default one */
178177
if (Module::expWire != nullptr) {
179-
Module::expWire->begin(address);
178+
Module::expWire->begin(wire_i2c_address);
180179
}
181180

182181
}
@@ -187,15 +186,15 @@ void Module::reset() {
187186
/* --------------------------------------------------------------------------
188187
*/
189188
Module::Module()
190-
: address(OPTA_DEFAULT_SLAVE_I2C_ADDRESS), rx_num(0), reboot_required(false),
189+
: rx_num(0), reboot_required(false),
191190
reset_required(false), ans_buffer(nullptr),
192191
expansion_type(OPTA_CONTROLLER_CUSTOM_MIN_TYPE), reboot_sent(0),
193192
detect_in(DETECT_IN), detect_out(DETECT_OUT) {
194193
Module::expWire = &Wire;
195194
}
196195

197196
Module::Module(TwoWire *tw, int _detect_in, int _detect_out)
198-
: address(OPTA_DEFAULT_SLAVE_I2C_ADDRESS), rx_num(0),
197+
: rx_num(0),
199198
reboot_required(false), reset_required(false), ans_buffer(nullptr),
200199
expansion_type(OPTA_CONTROLLER_CUSTOM_MIN_TYPE), reboot_sent(0),
201200
detect_in(_detect_in), detect_out(_detect_out) {
@@ -207,7 +206,7 @@ Module::Module(TwoWire *tw, int _detect_in, int _detect_out)
207206
/* --------------------------------------------------------------------------
208207
*/
209208
bool Module::addressAcquired() {
210-
return ((address > OPTA_DEFAULT_SLAVE_I2C_ADDRESS));
209+
return ((wire_i2c_address > OPTA_DEFAULT_SLAVE_I2C_ADDRESS));
211210
}
212211

213212
/* --------------------------------------------------------------------------
@@ -241,14 +240,14 @@ void Module::begin() {
241240
/* --------------------------------------------------------------------------
242241
*/
243242
void Module::update() {
244-
245243
if(reset_I2C_bus) {
246244
/* 20240515_moved_I2C_reset moved reset I2C to main */
247245
pinMode(detect_out, INPUT_PULLUP);
248246
delay(1);
249247
/* accept the address only if detect out is HIGH */
250248
if (digitalRead(detect_out) == HIGH) {
251-
setAddress(address);
249+
wire_i2c_address = rx_i2c_address;
250+
setAddress(wire_i2c_address);
252251
}
253252
reset_I2C_bus = false;
254253
}
@@ -301,7 +300,7 @@ bool Module::parse_set_address() {
301300
/* ------------------------------------------------------------------------ */
302301
if (checkSetMsgReceived(rx_buffer, ARG_ADDRESS, LEN_ADDRESS,
303302
MSG_SET_ADDRESS_LEN)) {
304-
address = rx_buffer[BP_PAYLOAD_START_POS];
303+
rx_i2c_address = rx_buffer[BP_PAYLOAD_START_POS];
305304
set_address_msg_received = true;
306305
return true;
307306
}
@@ -399,7 +398,7 @@ bool Module::parse_reboot() {
399398
int Module::prepare_ans_get_address_and_type() {
400399
/* ----------------------------------------------------------------------
401400
*/
402-
tx_buffer[BP_PAYLOAD_START_POS] = address;
401+
tx_buffer[BP_PAYLOAD_START_POS] = wire_i2c_address;
403402
tx_buffer[BP_PAYLOAD_START_POS + 1] = expansion_type;
404403
return prepareGetAns(tx_buffer, ANS_ARG_ADDRESS_AND_TYPE,
405404
ANS_LEN_ADDRESS_AND_TYPE, ANS_MSG_ADDRESS_AND_TYPE_LEN);
@@ -561,7 +560,7 @@ void Module::updatePinStatus() {
561560
} else {
562561
#if defined DEBUG_SERIAL && defined DEBUG_UPDATE_PIN_ENABLE
563562
Serial.print("ADDRESS ACQUIRED ");
564-
Serial.println(address, HEX);
563+
Serial.println(wire_i2c_address, HEX);
565564
#endif
566565
setStatusLedHasAddress();
567566
#ifdef USE_CONFIRM_RX_MESSAGE

src/OptaBlueModule.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,11 @@ class Module {
102102
int prepare_ans_reboot();
103103
int prepare_ans_get_flash();
104104

105-
uint8_t getI2CAddress() { return address; }
105+
uint8_t getI2CAddress() { return wire_i2c_address; }
106106

107107
protected:
108-
uint8_t address;
108+
volatile uint8_t rx_i2c_address = OPTA_DEFAULT_SLAVE_I2C_ADDRESS;
109+
uint8_t wire_i2c_address = OPTA_DEFAULT_SLAVE_I2C_ADDRESS;
109110
uint8_t rx_num;
110111
volatile bool reboot_required;
111112
volatile bool reset_required;

src/OptaController.cpp

+55-12
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ uint8_t Controller::send(int add, int device, unsigned int type, int n, int r) {
188188
_send(add, n, r);
189189

190190
if (r > 0) {
191-
if (wait_for_device_answer(device, r)) {
191+
if (wait_for_device_answer(device, r, OPTA_CONTROLLER_WAIT_REQUEST_TIMEOUT)) {
192192
return SEND_RESULT_OK;
193193
}
194194
return SEND_RESULT_COMM_TIMEOUT;
@@ -377,7 +377,7 @@ bool Controller::rebootExpansion(uint8_t device) {
377377

378378
_send(exp_add[device], msg_opta_reboot(), req);
379379

380-
if (wait_for_device_answer(OPTA_BLUE_UNDEFINED_DEVICE_NUMBER, req)) {
380+
if (wait_for_device_answer(OPTA_BLUE_UNDEFINED_DEVICE_NUMBER, req, OPTA_CONTROLLER_WAIT_REQUEST_TIMEOUT)) {
381381
if (parse_opta_reboot()) {
382382
delay(OPTA_CONTROLLER_DELAY_AFTER_REBOOT);
383383
return true;
@@ -562,18 +562,29 @@ void Controller::checkForExpansions() {
562562
tmp_exp_add[i] = 0;
563563
}
564564
num_of_exp = 0;
565+
566+
for(int i = OPTA_CONTROLLER_FIRST_AVAILABLE_ADDRESS + 1; i < OPTA_CONTROLLER_FIRST_AVAILABLE_ADDRESS + 2*OPTA_CONTROLLER_MAX_EXPANSION_NUM; i++) {
567+
_send(i, msg_opta_reset(), 0);
568+
}
569+
delay(OPTA_CONTROLLER_SETUP_INIT_DELAY);
565570
}
566571

567572
tmp_address = OPTA_CONTROLLER_FIRST_TEMPORARY_ADDRESS;
573+
bool send_new_address = true;
568574

569575
while (enter_while) {
576+
577+
if(send_new_address) {
578+
570579
#if defined DEBUG_SERIAL && defined DEBUG_ASSIGN_ADDRESS_CONTROLLER
571580
Serial.println("[LOG]: - DETECT pin is LOW (expansions without address)");
572-
Serial.println(" - Sending SET address message");
581+
Serial.println(" - Sending SET temp address message 0x" + String(tmp_address,HEX));
573582
#endif
574-
_send(OPTA_DEFAULT_SLAVE_I2C_ADDRESS, msg_set_address(tmp_address), 0);
583+
_send(OPTA_DEFAULT_SLAVE_I2C_ADDRESS, msg_set_address(tmp_address), 0);
584+
delay(OPTA_CONTROLLER_DELAY_AFTER_SET_ADDRESS);
585+
}
575586

576-
delay(OPTA_CONTROLLER_DELAY_AFTER_SET_ADDRESS);
587+
send_new_address = false;
577588

578589
#if defined DEBUG_SERIAL && defined DEBUG_ASSIGN_ADDRESS_CONTROLLER
579590
Serial.println(" - Sending GET address message");
@@ -598,10 +609,26 @@ void Controller::checkForExpansions() {
598609
tmp_num_of_exp so that tmp_exp_add array is filled in a circular way
599610
*/
600611

601-
if (wait_for_device_answer(OPTA_BLUE_UNDEFINED_DEVICE_NUMBER, req)) {
602-
parse_address_and_type(tmp_address);
612+
if (wait_for_device_answer(OPTA_BLUE_UNDEFINED_DEVICE_NUMBER, req, OPTA_CONTROLLER_TIMEOUT_FOR_SETUP_MESSAGE)) {
613+
if(parse_address_and_type(tmp_address)) {
614+
#ifdef USE_CONFIRM_RX_MESSAGE
615+
delay(5);
616+
_send(tmp_address, msg_confirm_rx_address(),0);
617+
#endif
618+
send_new_address = true;
619+
#if defined DEBUG_SERIAL && defined DEBUG_ASSIGN_ADDRESS_CONTROLLER
620+
Serial.println(" GOT IT! ");
621+
#endif
622+
}
623+
else {
624+
#if defined DEBUG_SERIAL && defined DEBUG_ASSIGN_ADDRESS_CONTROLLER
625+
Serial.println(" TIMEOUT ");
626+
#endif
627+
}
603628
}
604629

630+
631+
605632
#if defined DEBUG_SERIAL && defined DEBUG_ASSIGN_ADDRESS_CONTROLLER
606633
Serial.print("TEMPORARY Number of expansions found ");
607634
Serial.println(tmp_num_of_exp);
@@ -696,7 +723,7 @@ void Controller::checkForExpansions() {
696723
after 3 failed attemps the address is skipped and then the
697724
tmp_num_of_exp is decreased in the else branch */
698725

699-
if (wait_for_device_answer(OPTA_BLUE_UNDEFINED_DEVICE_NUMBER, req)) {
726+
if (wait_for_device_answer(OPTA_BLUE_UNDEFINED_DEVICE_NUMBER, req, OPTA_CONTROLLER_TIMEOUT_FOR_SETUP_MESSAGE)) {
700727
if (parse_address_and_type(address)) {
701728
remain_in_while_loop = (tmp_num_of_exp != initial_value);
702729
}
@@ -724,7 +751,7 @@ void Controller::checkForExpansions() {
724751
if (exp_type[i] >= OPTA_CONTROLLER_CUSTOM_MIN_TYPE) {
725752
_send(exp_add[i], msg_get_product_type(), CTRL_ANS_MSG_GET_PRODUCT_LEN);
726753
if (wait_for_device_answer(OPTA_BLUE_UNDEFINED_DEVICE_NUMBER,
727-
CTRL_ANS_MSG_GET_PRODUCT_LEN)) {
754+
CTRL_ANS_MSG_GET_PRODUCT_LEN, OPTA_CONTROLLER_WAIT_REQUEST_TIMEOUT)) {
728755
if (parse_get_product()) {
729756
exp_type[i] = next_available_custom_type;
730757
next_available_custom_type++;
@@ -820,6 +847,20 @@ uint8_t Controller::msg_set_address(uint8_t add) {
820847
MSG_SET_ADDRESS_LEN);
821848
}
822849

850+
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
851+
#ifdef USE_CONFIRM_RX_MESSAGE
852+
uint8_t Controller::msg_confirm_rx_address() {
853+
tx_buffer[CONFIRM_ADDRESS_FIRST_POS] = CONFIRM_ADDRESS_FIRST_VALUE;
854+
tx_buffer[CONFIRM_ADDRESS_SECOND_POS] = CONFIRM_ADDRESS_SECOND_VALUE;
855+
856+
857+
return prepareSetMsg(tx_buffer, ARG_CONFIRM_ADDRESS_RX, LEN_CONFIRM_ADDRESS_RX,
858+
CONFIRM_ADDRESS_RX_LEN);
859+
860+
}
861+
#endif
862+
863+
823864
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
824865

825866
uint8_t Controller::msg_get_product_type() {
@@ -933,7 +974,9 @@ bool Controller::parse_address_and_type(int slave_address) {
933974
Serial.println("EXPANSION_OPTA_DIGITAL_MEC");
934975
} else if (tmp_exp_type[tmp_num_of_exp] == EXPANSION_OPTA_DIGITAL_STS) {
935976
Serial.println("EXPANSION_OPTA_DIGITAL_STS");
936-
} else {
977+
} else if (tmp_exp_type[tmp_num_of_exp] == EXPANSION_OPTA_ANALOG) {
978+
Serial.println("EXPANSION_OPTA_ANALOG");
979+
}else {
937980
Serial.println("expansion code unknown!!!!!!");
938981
}
939982
#endif
@@ -1015,10 +1058,10 @@ void Controller::_send(int add, int n, int r) {
10151058
/* when an answer is requested from expansion this function wait for an
10161059
answer and put it into the rx buffer
10171060
return true if an answer is available */
1018-
bool Controller::wait_for_device_answer(uint8_t device, uint8_t wait_for) {
1061+
bool Controller::wait_for_device_answer(uint8_t device, uint8_t wait_for, uint16_t timeout) {
10191062
uint8_t rx = 0;
10201063
unsigned long int start = millis();
1021-
while (millis() - start < OPTA_CONTROLLER_WAIT_REQUEST_TIMEOUT &&
1064+
while (millis() - start < timeout &&
10221065
rx < wait_for) {
10231066
while (Wire.available()) {
10241067
uint8_t rec = Wire.read();

src/OptaController.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class Controller {
204204

205205
/* --------------- generic message handling functions ----------------- */
206206

207-
bool wait_for_device_answer(uint8_t device, uint8_t wait_for);
207+
bool wait_for_device_answer(uint8_t device, uint8_t wait_for, uint16_t timeout);
208208

209209
/* ---------------- message preparation functions ---------------------- */
210210

@@ -213,12 +213,16 @@ class Controller {
213213
uint8_t msg_opta_reset();
214214
uint8_t msg_opta_reboot();
215215
uint8_t msg_get_product_type();
216+
#ifdef USE_CONFIRM_RX_MESSAGE
217+
uint8_t msg_confirm_rx_address();
218+
#endif
216219
/* -------------------- parse message functions ------------------------ */
217220

218221
bool parse_get_product();
219222
bool parse_address_and_type(int slave_address);
220223
bool parse_opta_reboot();
221224

225+
222226
void _send(int add, int n, int r);
223227

224228
bool is_detect_high();

src/OptaControllerCfg.h

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
It exits as soon as the message is received */
3737
#define OPTA_CONTROLLER_WAIT_REQUEST_TIMEOUT 50
3838

39+
#define OPTA_CONTROLLER_TIMEOUT_FOR_SETUP_MESSAGE 100
40+
3941
#define OPTA_CONTROLLER_DELAY_AFTER_REBOOT 600
4042

4143
/* this is the time the controller leaves to expansion to "set up" themselves

src/OptaDigital.cpp

+14-2
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ void OptaDigital::update() {
464464
Module */
465465
Module::update();
466466

467-
// if (Module::addressAcquired()) {
467+
468468
/* always "refresh" the header of the answers */
469469
ans_get_din_buffer[BP_CMD_POS] = BP_ANS_GET;
470470
ans_get_din_buffer[BP_ARG_POS] = ANS_ARG_OPDIG_DIGITAL;
@@ -474,6 +474,18 @@ void OptaDigital::update() {
474474
ans_get_all_ain_buffer[BP_ARG_POS] = ANS_ARG_OPTDIG_ALL_ANALOG_IN;
475475
ans_get_all_ain_buffer[BP_LEN_POS] = ANS_LEN_OPTDIG_ALL_ANALOG_IN;
476476

477+
/* Added to have the same behaviour of Opta Analog
478+
[Opta analog has a slow main that depends on the operation it is performing
479+
at the very beginning (when the espansion has not an address yet) it is
480+
necessary to go faster so the main is skipped untill the expansion gets
481+
a valid address]
482+
This would not be necessary in case of Digital because the main loop is fast
483+
*/
484+
if(wire_i2c_address <= OPTA_DEFAULT_SLAVE_I2C_ADDRESS || wire_i2c_address >= OPTA_CONTROLLER_FIRST_TEMPORARY_ADDRESS) {
485+
return;
486+
}
487+
488+
477489
/* update output */
478490
_updateDigitalOut();
479491
/* update input*/
@@ -530,7 +542,7 @@ void OptaDigital::update() {
530542

531543
R_ADC_ScanStart(&(opta_adc.ctrl));
532544
}
533-
//}
545+
534546
}
535547

536548
#ifdef EN_DIGITAL_STANDALONE

src/OptaModuleProtocol.h

+11
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@
5353
#define CTRL_ANS_MSG_GET_PRODUCT_LEN LEN_ANS_GET_PRODUCT_TYPE
5454
#endif
5555

56+
57+
#ifdef USE_CONFIRM_RX_MESSAGE
58+
#define ARG_CONFIRM_ADDRESS_RX 0x26
59+
#define LEN_CONFIRM_ADDRESS_RX 2
60+
#define CONFIRM_ADDRESS_FIRST_POS (BP_HEADER_DIM + 0)
61+
#define CONFIRM_ADDRESS_SECOND_POS (BP_HEADER_DIM + 1)
62+
#define CONFIRM_ADDRESS_FIRST_VALUE 0xC9
63+
#define CONFIRM_ADDRESS_SECOND_VALUE 0xB1
64+
#define CONFIRM_ADDRESS_RX_LEN (BP_HEADER_DIM + LEN_CONFIRM_ADDRESS_RX)
65+
#endif
66+
5667
/* ######################## */
5768
/* VERSION related messages */
5869
/* ######################## */

tests/testStressAnalog/testStressAnalog.ino

+4-4
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ void initReverse_2() {
190190
void setup() {
191191
/* -------------------------------------------------------------------------- */
192192
Serial.begin(115200);
193-
delay(2000);
193+
delay(5000);
194194

195195
OptaController.begin();
196196
initReverse_1();
@@ -313,14 +313,14 @@ void loop() {
313313
if(rtd_in) {
314314
for(int i = 0; i < 8; i++) {
315315
if(rtd_in.isChRtd(i)) {
316-
Serial.println("RTD expansion - channel " + String(i) + " reading value " + String(rtd_in.getRtd(i)) + " ohm");
316+
Serial.println("RTD expansion " + String(rtd_in.getIndex()) + " - channel " + String(i) + " reading value " + String(rtd_in.getRtd(i)) + " ohm");
317317
}
318318
else if(rtd_in.isChDigitalInput(i)) {
319319
rtd_in.updateDigitalInputs();
320320
if(rtd_in.digitalRead(i)==HIGH){
321-
Serial.println("RTD expansion - channel " + String(i) + " reading value HIGH (DIGITAL)");
321+
Serial.println("RTD expansion " + String(rtd_in.getIndex()) + " - channel " + String(i) + " reading value HIGH (DIGITAL)");
322322
} else if(rtd_in.digitalRead(i)==LOW){
323-
Serial.println("RTD expansion - channel " + String(i) + " reading value LOW (DIGITAL)");
323+
Serial.println("RTD expansion " + String(rtd_in.getIndex()) + " - channel " + String(i) + " reading value LOW (DIGITAL)");
324324
}
325325
}
326326
}

0 commit comments

Comments
 (0)