Pre Compiler error. missing ;

BEFORE any code the precompiler finds an ‘error’. There are ~ 250 lines of comments and pre-compiler directives and defines, but even removing all but the offending line the ‘error’ remains …

<filepath & name>216:25: error: expected ';' before numeric constant
#define led_off 0B10000000 // this is Breaker tripped or selected Off pin on I2C expander


// Inputs

#define juicer 0B00000001

#define buzz_off 0B00000010 // Silence this buzzer

#define button_breaker 0B00000100 // an inline switch can allow local manual Distric Off too

// Outputs

#define reverse 0B00001000 // Output to switch relays

#define buzzer 0B00010000

#define led_juicer 0B00100000 // very fast acting mode (not implemented ... yet)

#define led_reverser 0B01000000 // show that this District will change polarity in faster time than a full trip

#define led_off 0B10000000 // this is Breaker tripped or selected Off pin on I2C expander


Please post a complete sketch that illustrates the problem and remember to use code tags when you post it

Which Arduino board are you compiling for ?

Your topic does not indicate a problem with IDE 2.x and therefore has been moved to a more suitable location on the forum.

The issue is likely elsewhere- I would guess in a #include before the code you shared and that we can’t see….

Target is Arduino Nano. IDE is 2.3.6. Reload of IDE has no effect.

Error goes away when there are only the 10 lines quoted plus an empty setup() and an empty loop() in a sketch. So its probably from the preprocessor’s second stage. I’ve stepped through all the code checking bracket & brace pairs, ; on every command, etc, but can’t find anything syntactical.

It must be a (hidden) char, but I have no idea of how it got in nor what it is. I loaded the sketch into Libre Write and turned on formating marks and there are no chars in the offending line different to those in any of the other 7 defines quoted.

I’ve been coding C for more than 30 years and use the preprocessor directives extensively for ‘self documentation’ and simple code updating. Never seen this before. Maybe I’ve hit a max defalut size; are there preprocesor buffer limits that can be set higher?

Any ideas ?

That's exactly why you have been asked to post the complete sketch

1 Like

Did you know that when you click your cursor on an opening brace, then the matching closing brace is highlighted by being outlined?

Reads like a compiler error, not a preprocessor error. Your sketch in an .ino file (or files plural) is converted into a single .ino.cpp file. Certain "magic" is applied to that file -- for example, #include <Arduino.h> is added at the top -- and the final result gets handed off to the compiler. The magic also includes adding forward declarations for functions, and directives so that errors in the .ino.cpp can be mapped back to the line numbers in the original .ino file(s). There have been cases where the magic is broken.

You should find the command that does the compile. This indicates the temp directory that contains the .ino.cpp. Maybe the mistake is kinda obvious. As an experienced programmer, you can also modify the command to keep the result of preprocessing; that might help.

To find the command, in the Settings, turn on "Show verbose output during compile". Just before the errors in red, you should see a line "Compiling sketch..." and then the command, which is roughly

/long/path/g++ -bunch -of -switches
  -lots -and -lots -of -switches
  -ending -with
  /temp/path/mysketch.ino.cpp -o /same/path/mysketch.ino.cpp.o

(i.e. compile the .ino.cpp into an object file with the .o extension)

Ok, I’ve removed all distracting code fragments and unnecessary comments and the error is still there -

D:\arduino sketches\DCC_Multi_Breaker\DCC_Multi_Breaker.ino: In function 'void untrip_handler()':
D:\arduino sketches\DCC_Multi_Breaker\DCC_Multi_Breaker.ino:158:25: error: expected ';' before numeric constant
 #define led_off         0B10000000    // this is Breaker tripped or selected Off. 'power is On' LED is connected direct from +5V
                         ^
D:\arduino sketches\DCC_Multi_Breaker\DCC_Multi_Breaker.ino:282:35: note: in expansion of macro 'led_off'
     system_states[i][user_shadow] led_off ) = ( system_states[i][user_shadow] ^= 1 << button_breaker )  ?   1  :   0;
                                   ^~~~~~~
In file included from D:\arduino sketches\DCC_Multi_Breaker\DCC_Multi_Breaker.ino:48:0:
C:\Users\bruce\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\Wire\src/Wire.h: In function 'void I2C_read(uint8_t, uint8_t)':
C:\Users\bruce\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\Wire\src/Wire.h:69:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int, int)
     uint8_t requestFrom(int, int, int);
             ^~~~~~~~~~~
C:\Users\bruce\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\libraries\Wire\src/Wire.h:66:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t, uint8_t)
     uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
             ^~~~~~~~~~~
exit status 1

Compilation error: expected ';' before numeric constant

Ignore the TwoWire warning about ambiguous data type.

And here is the current code -

/*
Title - DCC Multi Breaker
bruceg  Aug 2025
*/

/* 
Model Train Digital Command/Control Solid State Circuit Breaker
Original design & program by Terry Chamberlain 2025.
The Breaker sub circuit used is a slightly modified version of the 2002 MERG BCO1 using 4 N-channel Mosfets to fully isolate
both tracks.
Terry Chamberlain designed an all-in-one PCB holding a Nano, power, 2 sense circuits & 2 Breakers with user config via DCC
variables inputed to a DCC Command Station and displayed via the Arduino Serial Monitor.

I prefer a more modular approach with the microcontroller and power at one location, then the DCC config via DIP switches
next to individual Sensor/Breakers at the middle of each Power District with user display/interfaces for each Power District
nearby where they can be easily reached.

Hardware (my variant) -
1 Arduino Nano microcontroller.   30k prog, 2k data, 1k EEPROM, 14 (20) I/Os + on-board ADC mux, comparitor, timers, comms

1 Power.  +9, -9V, +5 and Gnd is derived from the Rail DCC, or a +12V DC source with 1 A voltage regulators and a charge pump.
An on-board optocoupler also outputs a +5V single sided copy of the bi-polar DCC signal.

2 to 6 DCC Sense & Switch modules.  Direct operating connections between microcontroller & modules.
Sense - a current transformer into a voltage via a resistor to an opamp precision rectifier, then to the ADC on the Nano
Range 1 is 0.25 to 7.75A/300 turns via 180R = 0.6V per A = 124ADC counts
or Range 2, double Range 1 is 15.5A/1000 turns via 165R = 0.3V per A = 62ADC counts.
Switch - opto isolated mosfet isolators for both DCC rail currents.  Switch in opto LED trace for manual Off over ride
Polarity Reverser - Dual SPDT relays.  (or 4 cheap solid state SPST relays)

2 to 6 user interface/display modules using PCF8574 8 I/O Expanders.  Indicator LEDs, slide switch & push buttons.
P82B715 I2C Extenders allows ~30m twisted pair cables.

2 to 6 sets of PCF8575 I2C 16 I/O Expanders with DIP switches for Breaker configuration settings.
will need a TCA9548A I2C mux to be able to re-use the same 6 I2C addresses as the PCF8574 8 I/O Expanders

I/O Extender & I2C mux modules are ~$1 each these days.


I2C addresses assigned are fixed.  To simplify the code a module count is performed in setup() then that value
is used in loops to process each Breaker in turn.  Ensure that there are no gaps in the module numbers used;
if you only have 3 Breakers they must be connected to the pin numbers assigned to Breakers 1, 2 & 3 with their
I2C expanders set to the correct addresses defined below.

*/

//#include <NmraDcc.h>
#include <Wire.h>

#define version  "0.0.6"

/*
#define processor_volts  5                                                // volts used by the microprocessor
#define ADC_volts_per_amp  0.6                                            // measured input
#define ADC_max_counts 1024                                               // Arduino Nano internal ADC is 10 bits
#define current_quarter_counts ( ADC_max_counts * ( ADC_volts_per_amp / 4 / processor_volts ) )   // ADC counts for 0.25 Amps
*/

// These values are implememtation dependant -

#define quarter_amp       31  // ADC counts **** check that your current transformers output this value ****
#define amps_default      2
#define trip_default      12  // ms
#define reset_default     16  // ms between reset checks

#define time_between_checks   1     // ms = 1,000us = 16,000 clocks
#define count_trip_times      4     // for 'settled' evaluation
#define count_rev_times       3     // must be more than half of trip for counting logic to prevent re-reversing
#define relay_time            5     // ms for mechanical changeover to start/end
#define attention             256   // ms buzzer duration

#define modules_max           7     // Nano + 6 Breakers

#define I2C_release  true             // Wire.endTransmission() & Wire.requestFrom() hold on to control of the I2C bus when I2C_release = 0
#define I2C_expander_bytes  1         // Each Breaker's setting switches will be read in setup(), the User Display/Control will be read/written as required 

                                      // PCF8574 are 1 byte = 8 I/O + interrupt.  PCF8575 are 2 bytes = 16 I/O + interrupt.
                                      // PCF857x 0x20 to 0x27

#define I2C_mux       0x70            // The I2C Gateway control is at 0x70 to 0x77. Write a single 8 bit byte for selecting any combination of the 8 buses 

#define I2C_user         1            // I2C_user buttons & LEDs
#define I2C_config       2            // I2C_config is 16 DIP switches
#define I2C_display   0x20            // reserved for possible future LCD
#define I2C_expander1 0x21            // PCF8574 7 bit I2C addresses (address bit 0 sets data direction - 0B01010AAAD ->D extracted)  PCF8575s are set to 4 higher here
#define I2C_expander2 0x22            // 1mA source by default, set lo can sink 25mA.  All I/Os max total 100mA.  Use reverse logic to sink devices ON
#define I2C_expander3 0x23            // interrupt method requires microcontroller pin to be pulled up
#define I2C_expander4 0x24            // I2C spec limits the Data & Clock lines to 3mA, BUT PCF857xs are built compatible to microcontroller port output specs, so can take more
#define I2C_expander5 0x25
#define I2C_expander6 0x26            // max using Nano ADC.  Could add more using ADS7128 8 channel, 12 bit ADC modules at 0x10 to 0x17 (address set with resistor values to single pin)
//#define spare 0x27

// Nano pins assigned -
#define ADC_pin   0   // array position where each module's pin numbers are stored
#define analog1   A0          // pin number for module 1.  Modules are numbered from USB end of Nano
#define analog2   A1
#define analog3   A2
#define analog4   A3          // I2C uses A4, A5 pins.  A6, A7 are analog in only, no digital I/O
#define analog5   A6
#define analog6   A7

#define BREAK_pin 1      // array position where each module's pin numbers are stored
#define power1  9             // pin number for module 1
#define power2  8
#define power3  7
#define power4  6
#define power5  5
#define power6  4

#define district_reverse  3   // bit/array position where each module's pin positions are stored

// District settings are made with 16 DIP switches on I2C expanders, read in setup()
// byte 1 Bits 0 to 4 are Amp bits x 0.25 Amps; so 0=0.25, 1=0.5, 2=1 ...  , bit 5 is high range, bit 6 reverser mode on/off, bit 7 auto reset on/off
// byte 2 is 2 packed nibbles, nibble 1 is trip time, nibble 2 is reset time;

#define amps_bits       0B00011111    // 5 bits x 0.25A = 0.25 to 7.75A OR x 0.5A to 15.5A
#define amps_hi         5             // 1:1000 current transformer doubles range & reduces hi_quarter_amp value /2
#define reverser_ok     6             // bit to test for reverse is allowed
#define reset_ok        7             // bit to test for reset manual/auto
#define trip_bits       0B00001111    // 4 bits x 4ms = 4 to 60ms
#define reset_bits      0B11110000    // reset times are 16x bigger than trip times; 64 to 960ms

// data layout for arrays -
// system-state bytes
#define breaker_state   0     // see further defines below
#define user_shadow     1     // state of user Display/Inputs
#define rev_count       2
#define trip_count      3
#define trip_value      4     // ADC value stored on Expander as 4x desired 0.25A    default when left at 0 = 2A
#define trip_time       5     // low nibble 0-8. max 15, x4 = 4-60ms       default when left at 0 = 16ms
#define recheck_time    6     // hi nibble 16-128, max 240, x4 = 64-960ms  default when left at 0 = 512ms ~0.5s

#define states_size     7     // bytes for second array dimension (to store above values)

#define module_off      0     // module breaker_state bit values/flags
#define reverse_en      1
#define module_on       2     // only need to test this for on & on_rev
#define module_on_rev   3
#define reset_en        4
//#define range_hi        8     // not used.  may be needed if status is shown on an LCD

#define module_ck       2     // <2 = Off

// User I/O shadow registers bit assignments, make bit changes in system_states[n][x] then write whole byte to expanders
// Expanders default to all Hi (max 1mA). Hi = Off

// I2C bit positions in user_shadow for quick bitwise manipulation by names, Uses inverted logic Hi = Off
// Arduino C code is 'little endian', so hi bit is at the beginning (left) and Lo bit is at the 'end' (right)
// Inputs
#define juicer          0B00000001    // not implemented yet ...
#define buzz_off        0B00000010    // Silence this buzzer
#define button_breaker  0B00000100    // request On/Off.  an inline switch can allow local manual Distric Off too
// Outputs
#define reverse         0B00001000    // Output to switch relays
#define buzzer          0B00010000
#define led_juicer      0B00100000    // very fast acting mode (not implemented ... yet)
#define led_reverser    0B01000000    // show that this District will change polarity in faster time than a full trip
#define led_off         0B10000000    // this is Breaker tripped or selected Off. 'power is On' LED is connected direct from +5V


// global variables

//volatile bool buttonPressed = false;      // flag for activity on an I2C PCF857x I/O expander.  Set in an Interrupt Service Routine, read in loop()
                                          // volatile tells compiler to NOT optimize this storage location so it can be found by an ISR when interrupts are Off

uint8_t temp, i, j, modules;    // counters that will be used repeatedly
uint32_t time_last_check = millis(); 
// 5 arrays.  Position 0 is used for flags, then 1:1 (human style) numbering for data positions
uint8_t I2C_data[3];                // max 2 bytes to/from Expanders

uint8_t I2C_addresses[modules_max] = { 0, I2C_expander1, I2C_expander2, I2C_expander3, I2C_expander4, I2C_expander5, I2C_expander6 };

uint8_t module_control_pins[modules_max][3] =
      {
      { 0, 0, 0 },
      { analog1, power1, 0 },       // Input pin / Output pins for identical external modules
      { analog2, power2, 0 },       // analog & power are directly to/from Nano I/Os, button is on expanders
      { analog3, power3, 0 },
      { analog4, power4, 0 },
      { analog5, power5, 0 },
      { analog6, power6, 0 },
      };

uint8_t system_states[modules_max][states_size];   // Off/On/RevOk/RevOn/Juice, userState, rev_count, trip_count, trip_value, trip_time, recheck_time

uint16_t module_ADC_counts[modules_max];   // current ADC counts (10 bit)

////////////////////////////////////////////////////////////////////////////////////

void  setup()
{
  Serial.begin( 115200 );                 // default speed for Arduino IDE 2 Serial monitor
  while ( !Serial );                      // wait for slow hardware setup on fast devices

  Wire.begin();                           // use default pins - for Nano Clock = A4, Data = A5.  buffers default to 32 bytes each
//  Wire.setClock( 400000 );              // 400kHz, go faster than default 100000.  probably too fast for long cables
  Wire.setWireTimeout( 2500, true );      // defaults to 2500us = 0.0025s = 250 bit times at 100kHz.  Ignores missing devices, but sets a flag & error codes

  for( i = 1; i < modules_max; i++ )                                                  // module expanders are at 0x21 - 0x27, only 7 addresses are available,
  {                                                                                   // but need 12+ for 6 Breakers, so will use an I2C mux to re-use addresses on multiple buses
    I2C_write1( I2C_mux, I2C_user );                                                  // TCA9548A mux boots to no output buses selected, switch mux to read/write user control modules,
                                                                                      // this actually makes a 9th 'master' bus available
    I2C_read( I2C_addresses[i], 1 );                                                  // who's here ?  A proper response has error = 0; error 5 = timeout, no module found at address !    
    if( Wire.getWireTimeoutFlag() )   break;                                          // flag is bool.  exit for( loop ) at first reply failure
    modules++;                                                                        // count of modules that reply

    system_states[i][user_shadow] = I2C_data[1];                                      // 1 byte returned is from the user control module, make a master copy (module & master reconciled in loop)

    I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] & 1 << buzzer ) );  // set lo with bitwise AND (don't update shadow)
    delay( attention );                                                               // short buzz from each board at startup
    I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] | 1 << buzzer ) );  // back to hi with bitwise OR (don't update shadow)  Bitwise XOR (^) toggles a current value

    // TO DO: button_breaker pressed at startup = debug mode

    I2C_write1( I2C_mux, I2C_config );                                                // select correct I2C bus for reading config switches 
                                                                                      // I2C Expanders startup with all bits set Hi.  They use inverted logic to 'turn on' devices
    I2C_read( I2C_addresses[i], 2 );                                                  // Config Switches PCF8575 16 bit Expanders return 2 bytes
                                                                                      // store values read in, if zero then apply defaults.  Byte 1 is Reverser, Reset & Amps, byte 2 is trip & reset time (2 nibbles)
    if( I2C_data[1] & reverser_ok )   system_states[i][user_shadow] |= 1 <<  led_reverser;   // test bit for reversing allowed, set flag bit in shadow
    if( I2C_data[1] & reset_ok )      system_states[i][breaker_state] |= 1 <<  reset_en;     // test bit for auto/manual reset and store result   

    system_states[i][trip_value] =    ( I2C_data[1] & amps_bits ) * ( ( I2C_data[1] & amps_hi ) ? ( quarter_amp + 1 ) / 2 : quarter_amp );  // convert Amps value to ADC counts
    system_states[i][trip_time] =     ( I2C_data[2] & trip_bits )  ?  ( I2C_data[2] & trip_bits )   :  trip_default;          // low nibble ms gets multiplied by 4 trip tests
    system_states[i][recheck_time] =  ( I2C_data[2] & reset_bits ) ?  ( I2C_data[2] & reset_bits )  :  reset_default;         // high nibble ms is 16x bigger than low, then also requires 4 continuous under tests, so 64x

    pinMode( module_control_pins[i][BREAK_pin], OUTPUT);                         // enable output pin to this Breaker
    if( system_states[i][user_shadow] & button_breaker )      digitalWrite( module_control_pins[i][BREAK_pin], HIGH );   // if not user isolated, switch the Breaker On
  }
  I2C_write1( I2C_mux, I2C_user );                                                    // finished reading configs, only need bus 1 from now on

//  Wire.clearTimeout();
}
////////////////////////////////////////////////////////////////////////////////////

void loop()
{
  if( ( millis() - time_last_check ) > time_between_checks )     // default 1ms = 1,000us = 16,000 Nano clocks
  {
  time_last_check = millis();

  for( i = 1; i == modules; i++ )
  {                                                           // calls trip or untrip handlers to update trip counts to turn Breakers Off/On
    analogRead( module_control_pins[i][ADC_pin] );         // switch the input pin, ignore first reading after switching to allow proper settling time
    ( ( module_ADC_counts[i] = analogRead( module_control_pins[i][ADC_pin] ) ) >= system_states[i][trip_value] )   ?   trip_handler()   :   untrip_handler();
  }
  user_reconcile();

    // TO DO: update possible display or serial monitor
  }


}
////////////////////////////////////////////////////////////////////////////////////
 
void trip_handler()
{    // i was set in calling function ADC_read()
  if( ( system_states[i][breaker_state] & reverser_ok ) && ( module_control_pins[i][rev_count] <= count_rev_times ) )     system_states[i][rev_count]++;   // do NOT increment more than 1 above count_rev_times
  if( ( system_states[i][rev_count] == count_rev_times ) )     reverse_phase();   // only counts up when reverse_ok

  if( system_states[i][trip_count] <= count_trip_times )    system_states[i][trip_count]++;   // do NOT increment more than 1 above count_trip_times
  if( ( system_states[i][trip_count] == count_trip_times ) && ( module_control_pins[i][BREAK_pin] & module_on ) )    // only switch Off if currently On
  {
    digitalWrite( module_control_pins[i][BREAK_pin], LOW );   // switch OFF module_pin
    system_states[i][user_shadow] & led_off;
  }
}

////////////////////////////////////////////////////////////////////////////////////
 
void untrip_handler()
{    // i was set in calling function ADC_read()
  if( ( system_states[i][breaker_state] & reverser_ok ) && ( module_control_pins[i][trip_count] > 0 ) )     system_states[i][rev_count]--;   // check reverser first, do NOT decrement below 0
  if( system_states[i][trip_count] > 0 )    system_states[i][trip_count]--;   // do NOT decrement below 0

  if( module_control_pins[i][button_breaker] )
  {
    I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] &= 1 << buzzer ) );     // set lo with bitwise AND, 
    delay( attention );                                                                   // buzz
    I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] |= 1 << buzzer ) );     // back hi with bitwise OR.  Bitwise XOR (^) toggles a current value
    delay( 500 );

    system_states[i][user_shadow] led_off ) = ( system_states[i][user_shadow] ^= 1 << button_breaker )  ?   1  :   0;
  }


  if( ( system_states[i][breaker_state] & reset_ok ) || ( system_states[i][user_shadow] &= 1 << button_breaker ) )
  {
    if( ( system_states[i][trip_count] == 0 ) && ( module_control_pins[i][BREAK_pin] |= 1 << module_on ) )    // only switch On if allowed & currently Off
    {
      digitalWrite( module_control_pins[i][BREAK_pin], HIGH );   // switch On module_pin
      system_states[i][user_shadow] & led_off;
    }
  }
}

////////////////////////////////////////////////////////////////////////////////////

void reverse_phase()
{
  digitalWrite( module_control_pins[i][BREAK_pin], 0 );                               // blind, quick switch Off
  delay( relay_time );                                                                         // debounce & power off time
  I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] ^= 1 << reverse ) );  // toggle reverse; update shadow & user module
  delay( relay_time );                                                                         // time for relays to change over too
  if( system_states[i][BREAK_pin] & module_on )    digitalWrite( module_control_pins[i][BREAK_pin], 1 );
  system_states[i][rev_count] = 0;
}

////////////////////////////////////////////////////////////////////////////////////
 
void user_reconcile()
{
  for( i = 1; i == modules; i++ )
  {
    I2C_read( I2C_addresses[i], I2C_expander_bytes );                         // fetch & copy to begin status alignment/reconciliation
                                                                              // update system_states with any switch changes made on Breaker
    if( I2C_data[1] & juicer )                system_states[i][user_shadow] |= 1 << juicer;    // over write with same does nothing,
    else                                      system_states[i][user_shadow] &= 1 << juicer;    // so just do it quickly anyway

    if( I2C_data[1] & buzz_off )              system_states[i][user_shadow] |= 1 << buzzer;
    else                                      system_states[i][user_shadow] &= 1 << buzzer;

    if( !( I2C_data[1] & button_breaker ) )   button_press_handle();

    I2C_write1( I2C_addresses[i], system_states[i][user_shadow] );            // write any changes made back to the Breaker to take effect
  }
}

////////////////////////////////////////////////////////////////////////////////////

void button_press_handle()
{
  I2C_write1( i, user_shadow & buzzer );                 // acknowledge button press

  while(  !( I2C_data[1] && button_breaker ) )   I2C_read( I2C_addresses[i], 1 );  // wait for release

  I2C_write1( i, user_shadow | buzzer );
  digitalWrite( module_control_pins[i][module_off],  !digitalRead( module_control_pins[i][module_off] ) );  // toggle states
  system_states[i][user_shadow] ^= 1 << led_off;
  delay( 1 );
}

////////////////////////////////////////////////////////////////////////////////////

void I2C_write1( uint8_t address, uint8_t data )        // all Expanders used here accept 1 byte at a time, PCF8574 just over writes its 8 bits 
{                                                       // PCF8575 over writes its 2 bytes sequentially, 1, 2, 1, 2, ...
  Wire.beginTransmission( address );                    // set target address
  Wire.write( data );                                   // load Tx buffer (single bytes in this prog, can use pointers for strings or arrays)
  Wire.endTransmission( I2C_release );                  // send the data queued up (default max 32 bytes), release control of the bus after sending,
}                                                       // return value is error report, may be ignored, but useful for auto-discovery via timeout

////////////////////////////////////////////////////////////////////////////////////

void I2C_read( uint8_t address, uint8_t size )          // all Expanders used here output all their contents when requested,
{                                                       // the size value is ignored, but should be sent as a place holder
  Wire.requestFrom( address, size, I2C_release );       // buffer size bytes from target and release control of the bus after receipt
  if( Wire.getWireTimeoutFlag() )   return;
  
  j = 0;
  while( Wire.available() ) I2C_data[j++] = Wire.read();       // copy bytes from I2C buffer (not strictly necessary, but makes for more modular code)
}

////////////////////////////////////////////////////////////////////////////////////

Any clues as to the error’s cause ?

I don't get the error you do when I try to compile your sketch. I get a whole raft of errors relating to bitshifts that are out of range.

arduino-cli compile -b arduino:avr:nano:cpu=atmega328 --warnings all --output-dir ~/tmp --no-color (in directory: /home/me/Documents/sketchbook/Nano/test)
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void setup()':
/home/me/Documents/sketchbook/Nano/test/test.ino:155:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define buzzer          0B00010000
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:209:74: note: in expansion of macro 'buzzer'
     I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] & 1 << buzzer ) );  // set lo with bitwise AND (don't update shadow)
                                                                          ^~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino:155:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define buzzer          0B00010000
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:211:74: note: in expansion of macro 'buzzer'
     I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] | 1 << buzzer ) );  // back to hi with bitwise OR (don't update shadow)  Bitwise XOR (^) toggles a current value
                                                                          ^~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino:157:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define led_reverser    0B01000000    // show that this District will change polarity in faster time than a full trip
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:219:78: note: in expansion of macro 'led_reverser'
     if( I2C_data[1] & reverser_ok )   system_states[i][user_shadow] |= 1 <<  led_reverser;   // test bit for reversing allowed, set flag bit in shadow
                                                                              ^~~~~~~~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void trip_handler()':
/home/me/Documents/sketchbook/Nano/test/test.ino:264:35: warning: statement has no effect [-Wunused-value]
     system_states[i][user_shadow] & led_off;
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void untrip_handler()':
/home/me/Documents/sketchbook/Nano/test/test.ino:155:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define buzzer          0B00010000
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:277:75: note: in expansion of macro 'buzzer'
     I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] &= 1 << buzzer ) );     // set lo with bitwise AND,
                                                                           ^~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino:155:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define buzzer          0B00010000
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:279:75: note: in expansion of macro 'buzzer'
     I2C_write1( I2C_addresses[i], ( system_states[i][user_shadow] |= 1 << buzzer ) );     // back hi with bitwise OR.  Bitwise XOR (^) toggles a current value
                                                                           ^~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino:158:25: error: expected ';' before numeric constant
 #define led_off         0B10000000    // this is Breaker tripped or selected Off. 'power is On' LED is connected direct from +5V
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:282:35: note: in expansion of macro 'led_off'
     system_states[i][user_shadow] led_off ) = ( system_states[i][user_shadow] ^= 1 << button_breaker )  ?   1  :   0;
                                   ^~~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino:282:33: warning: statement has no effect [-Wunused-value]
     system_states[i][user_shadow] led_off ) = ( system_states[i][user_shadow] ^= 1 << button_breaker )  ?   1  :   0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
/home/me/Documents/sketchbook/Nano/test/test.ino:291:37: warning: statement has no effect [-Wunused-value]
       system_states[i][user_shadow] & led_off;
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void user_reconcile()':
/home/me/Documents/sketchbook/Nano/test/test.ino:155:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define buzzer          0B00010000
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:319:85: note: in expansion of macro 'buzzer'
     if( I2C_data[1] & buzz_off )              system_states[i][user_shadow] |= 1 << buzzer;
                                                                                     ^~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino:155:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define buzzer          0B00010000
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:320:85: note: in expansion of macro 'buzzer'
     else                                      system_states[i][user_shadow] &= 1 << buzzer;
                                                                                     ^~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void button_press_handle()':
/home/me/Documents/sketchbook/Nano/test/test.ino:158:25: warning: left shift count >= width of type [-Wshift-count-overflow]
 #define led_off         0B10000000    // this is Breaker tripped or selected Off. 'power is On' LED is connected direct from +5V
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:338:41: note: in expansion of macro 'led_off'
   system_states[i][user_shadow] ^= 1 << led_off;
                                         ^~~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void I2C_read(uint8_t, uint8_t)':
/home/me/Documents/sketchbook/Nano/test/test.ino:355:48: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
   Wire.requestFrom( address, size, I2C_release );       // buffer size bytes from target and release control of the bus after receipt
                                                ^
In file included from /home/me/Documents/sketchbook/Nano/test/test.ino:48:0:
/home/me/.arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire/src/Wire.h:69:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int, int)
     uint8_t requestFrom(int, int, int);
             ^~~~~~~~~~~
/home/me/.arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire/src/Wire.h:66:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t, uint8_t)
     uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
             ^~~~~~~~~~~
Used library Version Path
Wire         1.0     /home/me/.arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire
Used platform Version Path
arduino:avr   1.8.3   /home/me/.arduino15/packages/arduino/hardware/avr/1.8.3
Error during build: exit status 1
Compilation failed.

Your code's method of shifting a 1 by what looks like a bit mask rather than a bit number seems odd to me. Could you explain it please? Because if I remove all the 1 << bits associated with those macros I get a much smaller list of errors:

arduino-cli compile -b arduino:avr:nano:cpu=atmega328 --warnings all --output-dir ~/tmp --no-color (in directory: /home/me/Documents/sketchbook/Nano/test)
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void trip_handler()':
/home/me/Documents/sketchbook/Nano/test/test.ino:264:35: warning: statement has no effect [-Wunused-value]
     system_states[i][user_shadow] & led_off;
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void untrip_handler()':
/home/me/Documents/sketchbook/Nano/test/test.ino:158:25: error: expected ';' before numeric constant
 #define led_off         0B10000000    // this is Breaker tripped or selected Off. 'power is On' LED is connected direct from +5V
                         ^
/home/me/Documents/sketchbook/Nano/test/test.ino:282:35: note: in expansion of macro 'led_off'
     system_states[i][user_shadow] led_off ) = ( system_states[i][user_shadow] ^= button_breaker )  ?   1  :   0;
                                   ^~~~~~~
/home/me/Documents/sketchbook/Nano/test/test.ino:282:33: warning: statement has no effect [-Wunused-value]
     system_states[i][user_shadow] led_off ) = ( system_states[i][user_shadow] ^= button_breaker )  ?   1  :   0;
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
/home/me/Documents/sketchbook/Nano/test/test.ino:291:37: warning: statement has no effect [-Wunused-value]
       system_states[i][user_shadow] & led_off;
/home/me/Documents/sketchbook/Nano/test/test.ino: In function 'void I2C_read(uint8_t, uint8_t)':
/home/me/Documents/sketchbook/Nano/test/test.ino:355:48: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
   Wire.requestFrom( address, size, I2C_release );       // buffer size bytes from target and release control of the bus after receipt
                                                ^
In file included from /home/me/Documents/sketchbook/Nano/test/test.ino:48:0:
/home/me/.arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire/src/Wire.h:69:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int, int)
     uint8_t requestFrom(int, int, int);
             ^~~~~~~~~~~
/home/me/.arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire/src/Wire.h:66:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t, uint8_t)
     uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
             ^~~~~~~~~~~
Used library Version Path
Wire         1.0     /home/me/.arduino15/packages/arduino/hardware/avr/1.8.3/libraries/Wire
Used platform Version Path
arduino:avr   1.8.3   /home/me/.arduino15/packages/arduino/hardware/avr/1.8.3
Error during build: exit status 1
Compilation failed.

and there is your "expected ';' before numeric constant" error. Which is not referencing the #define, but the line below:

    system_states[i][user_shadow] led_off ) = ( system_states[i][user_shadow] ^= 1 << button_breaker )  ?   1  :   0;

Which is simply gibberish and the compiler is quite correct to be utterly confused. I would be most interested in your explanation as to what, exactly, that line is supposed to do. Because whatever it is, there's no way it's going to happen.

1 Like

In your untrip_handler() - check that line again and ask yourself about led_off

Side note

There are lots of very weird stuff like

for( i = 1; i == modules; i++ )

Or comparing PIN numbers instead of status of the pin

if( ( system_states[i][trip_count] == count_trip_times ) && ( module_control_pins[i][BREAK_pin] & module_on ) )

Or

I2C_write1( i, user_shadow & buzzer );

where i is not the I2C address and 5. user_shadow is a constant index, not the actual byte of shadow data...

And many more - so fixing the macro issue won’t get you running … more work and attention needed

Yeah, the untrip code was just a mix of copy & paste pieces from older code, as was the trip code that I was working on when the compiler error first showed up. As the error was pointing to a #define well away from both of these function I concentrated on fixing the trip code and just didn’t look at untrip at all.

So good catch guys, and thanks. All good now that I’ve just gone with bit masks and removed all the bit shifts.

bye.

Proof read the retry of the code