Constant Reset at end of Setup

Look at the 8 lines of code at the end of setup. If the serial print statements or the delay is included, the program progresses into the loop. If not, the program gets to the end of setup and then resets and never gets to the loop. What the heck?

The gpio is a PCA9555 and not accessed after it is checked.

void setup() {
  Wire.begin();
  pinMode(led, OUTPUT) ;    // for test only
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW
 
  delay(500) ;              // Wait 0.5 seconds at start

  Serial.begin(9600) ; 
  Serial.println(ver) ;       // send software version
  Serial.println(chan1) ;
  Serial.println(chan2) ; 
  
  // Input GPIO for switches; the lower byte reads 8 channels of switches
  // the upper byte, lower 6 bits, reads occupancy sensors
  // the upper byte, bits 6 & 7, outputs circuit status
  gpio_dir(gpio, 0xffff) ;    // all input
  _16bits = gpio_read(gpio) ; // this is a dummy read for test
  blinker (500) ;                 // two longs followed by two shorts
  blinker (500) ;                 // shows that GPIO-0 is OK
  blinker (150) ;
  blinker (150) ;
  Serial.println("input checks OK") ;
  delay (500) ;
 
// this code leaves the other pins unchanged 
  DDRB = DDRB | 0x0F ; // set B0-B3 (digital pins 8-11) as outputs
//  Serial.println("8-11 set to output") ;
  DDRD = DDRD | 0xF0 ; // set D4-D7 (digital pins 4-7) as outputs
//  Serial.println("4-7 seet to output") ;  
  loop_count = 0 ;
//  Serial.println("Setup OK") ;
  delay(100) ; // needed to get outof setup?
  }
// -------------End of Setup---------------
  
// ------------Main Program Loop------------
void loop() {
  loop_count = loop_count + 0x01 ; 
//  PORTB = ~ loop_count ;
//  PORTD = ~ loop_count ;
    PORTB = ~ (loop_count >> 4) & 0x0F ;
    PORTD = ~ (loop_count << 4) & 0XF0 ;
 // blinker(50) ;
  delay(100) ;

Without all the code I can't verify it. Heck, from this snippet I can't even tell how you know the loop isn't reached...

And any reason to do all of the direct port manipulation?

  1. Code: except for the last closed "}" and the declaration of variables prior setup, that IS all the code.

  2. Port Manipulation: why would I want to address 8 digital lines with 8 lines of code when I can do it in two lines with direct port operations? IMHO, the Arduino community resists port manipulation (look at the port mapping versus the external digital I/O pins), but I think it is the right way to go when you build controllers with multiple inputs and outputs.

  3. Reaching the loop: there are LEDs attached to external hardware drivers that are attached to digital pins 4-11. When the loop is functioning, they light up and count up (in binary, of course).

  4. Reset: when the loop isn't reached, I can see that Setup continues to repeat because I see the "two long, two short" blinks on the LED attached to pin 13 over and over and over and....

Dr.Q

Post code.
All of it.
Post a schematic.
All of it.

  1. No it’s not. At least my version of the IDE does not come with a function called blinker() or gpio_read(). And besides, errors CAN happen in variable declaration. So we’re not Snippers R Us

  2. Because of the non-portable nature. But mainly I ask because in 99% of the cases people here use it because they saw it somewhere and they “need” it to solve there magic problem. But if you want it to save some lines, fine by me.

  3. Yes of course :slight_smile: But always checking what observations let to a conclusion :slight_smile:

I made a version of the program:

#include <Wire.h>

byte led = 13;
byte loop_count;

void setup() {
  Wire.begin();
  Serial.begin(115200);
  pinMode(led, OUTPUT) ;    // for test only
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW

  delay(500) ;              // Wait 0.5 seconds at start


  // this code leaves the other pins unchanged
  DDRB = DDRB | 0x0F ; // set B0-B3 (digital pins 8-11) as outputs
  //  Serial.println("8-11 set to output") ;
  DDRD = DDRD | 0xF0 ; // set D4-D7 (digital pins 4-7) as outputs
  //  Serial.println("4-7 seet to output") ;
  loop_count = 0 ;
  //  Serial.println("Setup OK") ;
  //delay(100) ; // needed to get outof setup?
}
// -------------End of Setup---------------

// ------------Main Program Loop------------
void loop() {
  loop_count = loop_count + 0x01 ;
  Serial.println(loop_count);
  //  PORTB = ~ loop_count ;
  //  PORTD = ~ loop_count ;
  PORTB = ~ (loop_count >> 4) & 0x0F ;
  PORTD = ~ (loop_count << 4) & 0XF0 ;
  // blinker(50) ;
  delay(100) ;
}

Which works fine.

BUT, only thing I do notice, you do mask part of the port when you set DDR but you don’t when you call PORT. Aka, you probably unintended set other pins. And because of the resets I’m starting to think you’re electrical connections are causing that… So indeed, all the code and a schematic would really help :slight_smile:

A common error is defining a pointer and using it as an array. That will cause your program to write to address 0 or some other address it doesn't own and will reset it. Show ALL the code.

PORTD = ~ (loop_count << 4) & 0XF0 ;

Doesn’t that clear pins D3, D2, TX & RX?

  1. You guys have great insight, which is appreciated. Thanks

JCA34F: Yes, and it might be important for me to remember that for future sketches, but I am not using TX/RX and no interrupts are set in this sketch

FormerlyAWOL: I'll get on it.

Septillion: Entire code coming, but I will go out on a limb and bet that the "blinker()" doesn't mess things up. I only say that because it's commented out but has run fine in previous tests.

Your remark about portability opens an issue I hadn't considered, since I thought that all the C instructions were portable (not across versions of Arduino, but at least across the language--one has to worry about their own specific hardware issues).

All this having been said by you guys/gals (and me), the point is that if I comment out the lasts line in Setup, eg, delay(100), the processor goes into endless resets that runs the whole Setup -- oops, CRAP, I see something missing -- duh. I'll post the whole code in the morning.

Dr.Q

Here’s ALL the code. I suddenly realized last night that I had deleted some code when I got ride of several lines of comments:

//             "01234567890123456789"
char ver[] =   "cable_10" ;
char chan1[] = "10/18/19" ;
char chan2[] = "10 wire cable test" ;
 
#include <Wire.h>
#define gpio 0x20 //  I2C input device address is 00100000 (x020)

int _16bits ;
int led = 13 ;
int loop_count ;


// ---------------SETUP---------------------  
void setup() {
  Wire.begin();
  pinMode(led, OUTPUT) ;    // for test only
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW
 
  // 9555 gpio port direction register
  //   input = 1
  //   output = 0
  // invert register for inputs = 1 for inversion, 0 for no inversion
  // register addresses, low byte is port0, high byte is port1
  // (gpio code takes care of the register addresses)
  //   input data = 0
  //   output data = 2
  //   inversion register = 4
  //   data direction = 6

  delay(500) ;              // Wait 0.5 seconds at start

  Serial.begin(9600) ; 
  Serial.println(ver) ;       // send software version
  Serial.println(chan1) ;
  Serial.println(chan2) ; 
  
  // Input GPIO for switches; the lower byte reads 8 channels of switches
  // the upper byte, lower 6 bits, reads occupancy sensors
  // the upper byte, bits 6 & 7, outputs circuit status
  gpio_dir(gpio, 0xffff) ;    // all input
  _16bits = gpio_read(gpio) ; // this is a dummy read for test
  blinker (500) ;                 // two longs followed by two shorts
  blinker (500) ;                 // shows that GPIO-0 is OK
  blinker (150) ;
  blinker (150) ;
  Serial.println("input checks OK") ;
  delay (500) ;
 
// this code leaves the other pins unchanged 
  DDRB = DDRB | 0x0F ; // set B0-B3 (digital pins 8-11) as outputs
//  Serial.println("8-11 set to output") ;
  DDRD = DDRD | 0xF0 ; // set D4-D7 (digital pins 4-7) as outputs
//  Serial.println("4-7 seet to output") ;  
  loop_count = 0 ;
//  Serial.println("Setup OK") ;
//  delay(100) ; // needed to get out of setup?
  }
// -------------End of Setup---------------
  
// ------------Main Program Loop------------
void loop() {
  loop_count = loop_count + 0x01 ; 
//  PORTB = ~ loop_count ;
//  PORTD = ~ loop_count ;
    PORTB = ~ (loop_count >> 4) & 0x0F ;
    PORTD = ~ (loop_count << 4) & 0XF0 ;
 // blinker(50) ;
  delay(100) ;
  
  }
// -----------End Main Program Loop---------------


// ---------------- blinker ------------------------
void blinker(int a) {       // blink for "a" msec
  delay(a / 2) ;            // ensure there is a blink
  digitalWrite(led, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(a);                 // wait for a second
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW
  delay(a / 2) ; }          // ensure there is a blink, end of blinker
// ---------------- end of blinker ------------------------


/******************************************************************************
 *  i2c_gpio
 *  Keith Neufeld
 *  May 26, 2008
 *
 *  Prototype I2C interface to TI 9535 and 9555 GPIO expanders.
 *
 *  Arduino analog input 5 - I2C SCL
 *  Arduino analog input 4 - I2C SDA
 *
 ******************************************************************************/

#define REGISTER_INPUT (0)
#define REGISTER_OUTPUT (2)
#define REGISTER_CONFIG (6)

// the gpio_check routine reads the configuration registers to see if outputs
// have been changed to inputs, indicating a power-on reset has occurred

int gpio_check(int address) {
  int data = 0;
  Wire.beginTransmission(address);  //  Send input register address
  Wire.write(REGISTER_CONFIG);
  Wire.endTransmission();
  Wire.beginTransmission(address); //  Connect to device and request two bytes
  Wire.requestFrom(address, 2);
  if (Wire.available()) {
    data = Wire.read(); }
  if (Wire.available()) {
    data |= Wire.read() << 8; }
  Wire.endTransmission();
  return data; } // end of gpio_check

int gpio_read(int address) {
  int data = 0;
  Wire.beginTransmission(address);  //  Send input register address
  Wire.write(REGISTER_INPUT);
  Wire.endTransmission();
  Wire.beginTransmission(address); //  Connect to device and request two bytes
  Wire.requestFrom(address, 2);
  if (Wire.available()) {
    data = Wire.read(); }
  if (Wire.available()) {
    data |= Wire.read() << 8; }
  Wire.endTransmission();
  return data; } // end of gpio_read

void gpio_dir(int address, int dir) {
  Wire.beginTransmission(address);   //  Send config register address
  Wire.write(REGISTER_CONFIG);
  //  Connect to device and send two bytes
  Wire.write(0xff & dir);   // low byte
  Wire.write(dir >> 8);     // high byte
  Wire.endTransmission(); } // end of gpio_dir

void gpio_write(int address, int data) {
  Wire.beginTransmission(address);  //  Send output register address
  Wire.write(REGISTER_OUTPUT);
  //  Connect to device and send two bytes
  Wire.write(0xff & data);  // low byte
  Wire.write(data >> 8);    // high byte
  Wire.endTransmission(); } // end of gpio_write

// end of light_control

And here’s the essential schematic. There are also pullups on RX/TX, but they are not addressed in this sketch. Also missing some power supply line caps and headers/screw terminals. But you get the idea. Pin 13 and its associated LED is used in the sketch at address “int led = 13 ;”



JCA34F:

PORTD = ~ (loop_count << 4) & 0XF0 ;

Doesn’t that clear pins D3, D2, TX & RX?

Yessss. May want to

PORTD |= ~ (loop_count << 4) & 0XF0 ;
PORTD &= ~ (loop_count << 4) | ~0XF0 ;

or a more optimized version if you don’t want to mess with the lower outputs. Same of course for the other register.

Or switched to a portable version :stuck_out_tongue:

const byte CounterPins[] = {4, 5, 6, 7, 8, 9, 10, 11};
const byte NrCounterPins = sizeof(CounterPins);

byte loop_count;

void setup(){
  Serial.begin(115200);
  for(byte i = 0; i < NrCounterPins; i++){
    pinMode(CounterPins[i], OUTPUT);
  }
}

void loop(){
  setCounterPins(++loop_count);
}

void setCounterPins(byte val){
  for(byte i = 0; i < NrCounterPins; i++){
    digitalWrite(CounterPins[i], val & 0x1);
    val >>= 1;
  }
}

Could argue it’s more code, but I say it barely is because this code is self explaining aka you can leave the extensive comments :smiley:

Up to your code. First thing I notice, do youself a favor and line up your } with the line that caused it. Like I did above. Makes it soooooo much easier to see what in in a block and what’s not.

And probably not related, no need to call Wire.beginTransmission() before a Wire.requestFrom(). And no need for Wire.endTransmission() either.

Makes it for example:

uint16_t gpio_check(int address) {
  uint16_t data = 0;
  Wire.beginTransmission(address);  //  Send input register address
  Wire.write(REGISTER_CONFIG);
  Wire.endTransmission(false);
  Wire.requestFrom(address, 2);
  if (Wire.available() >= 2) {
    data = Wire.read(); 
    data |= Wire.read() << 8; 
  }
  return data;
} // end of gpio_check

Alright, because I don’t have leds connected I just simply added a print:

//             "01234567890123456789"
char ver[] =   "cable_10" ;
char chan1[] = "10/18/19" ;
char chan2[] = "10 wire cable test" ;
 
#include <Wire.h>
#define gpio 0x20 //  I2C input device address is 00100000 (x020)

int _16bits ;
int led = 13 ;
int loop_count ;


// ---------------SETUP--------------------- 
void setup() {
  Wire.begin();
  pinMode(led, OUTPUT) ;    // for test only
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW
 
  // 9555 gpio port direction register
  //   input = 1
  //   output = 0
  // invert register for inputs = 1 for inversion, 0 for no inversion
  // register addresses, low byte is port0, high byte is port1
  // (gpio code takes care of the register addresses)
  //   input data = 0
  //   output data = 2
  //   inversion register = 4
  //   data direction = 6

  delay(500) ;              // Wait 0.5 seconds at start

  Serial.begin(9600) ;
  Serial.println(ver) ;       // send software version
  Serial.println(chan1) ;
  Serial.println(chan2) ;
 
  // Input GPIO for switches; the lower byte reads 8 channels of switches
  // the upper byte, lower 6 bits, reads occupancy sensors
  // the upper byte, bits 6 & 7, outputs circuit status
  gpio_dir(gpio, 0xffff) ;    // all input
  _16bits = gpio_read(gpio) ; // this is a dummy read for test
  blinker (500) ;                 // two longs followed by two shorts
  blinker (500) ;                 // shows that GPIO-0 is OK
  blinker (150) ;
  blinker (150) ;
  Serial.println("input checks OK") ;
  delay (500) ;
 
// this code leaves the other pins unchanged
  DDRB = DDRB | 0x0F ; // set B0-B3 (digital pins 8-11) as outputs
//  Serial.println("8-11 set to output") ;
  DDRD = DDRD | 0xF0 ; // set D4-D7 (digital pins 4-7) as outputs
//  Serial.println("4-7 seet to output") ; 
  loop_count = 0 ;
//  Serial.println("Setup OK") ;
//  delay(100) ; // needed to get out of setup?
  }
// -------------End of Setup---------------
 
// ------------Main Program Loop------------
void loop() {
  loop_count = loop_count + 0x01 ;
//  PORTB = ~ loop_count ;
//  PORTD = ~ loop_count ;
    PORTB = ~ (loop_count >> 4) & 0x0F ;
    PORTD = ~ (loop_count << 4) & 0XF0 ;
 // blinker(50) ;
  Serial.println(loop_count);
  delay(100) ;
 
  }
// -----------End Main Program Loop---------------


// ---------------- blinker ------------------------
void blinker(int a) {       // blink for "a" msec
  delay(a / 2) ;            // ensure there is a blink
  digitalWrite(led, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(a);                 // wait for a second
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW
  delay(a / 2) ; }          // ensure there is a blink, end of blinker
// ---------------- end of blinker ------------------------


/******************************************************************************
 *  i2c_gpio
 *  Keith Neufeld
 *  May 26, 2008
 *
 *  Prototype I2C interface to TI 9535 and 9555 GPIO expanders.
 *
 *  Arduino analog input 5 - I2C SCL
 *  Arduino analog input 4 - I2C SDA
 *
 ******************************************************************************/

#define REGISTER_INPUT (0)
#define REGISTER_OUTPUT (2)
#define REGISTER_CONFIG (6)

// the gpio_check routine reads the configuration registers to see if outputs
// have been changed to inputs, indicating a power-on reset has occurred

int gpio_check(int address) {
  int data = 0;
  Wire.beginTransmission(address);  //  Send input register address
  Wire.write(REGISTER_CONFIG);
  Wire.endTransmission();
  Wire.beginTransmission(address); //  Connect to device and request two bytes
  Wire.requestFrom(address, 2);
  if (Wire.available()) {
    data = Wire.read(); }
  if (Wire.available()) {
    data |= Wire.read() << 8; }
  Wire.endTransmission();
  return data; } // end of gpio_check

int gpio_read(int address) {
  int data = 0;
  Wire.beginTransmission(address);  //  Send input register address
  Wire.write(REGISTER_INPUT);
  Wire.endTransmission();
  Wire.beginTransmission(address); //  Connect to device and request two bytes
  Wire.requestFrom(address, 2);
  if (Wire.available()) {
    data = Wire.read(); }
  if (Wire.available()) {
    data |= Wire.read() << 8; }
  Wire.endTransmission();
  return data; } // end of gpio_read

void gpio_dir(int address, int dir) {
  Wire.beginTransmission(address);   //  Send config register address
  Wire.write(REGISTER_CONFIG);
  //  Connect to device and send two bytes
  Wire.write(0xff & dir);   // low byte
  Wire.write(dir >> 8);     // high byte
  Wire.endTransmission(); } // end of gpio_dir

void gpio_write(int address, int data) {
  Wire.beginTransmission(address);  //  Send output register address
  Wire.write(REGISTER_OUTPUT);
  //  Connect to device and send two bytes
  Wire.write(0xff & data);  // low byte
  Wire.write(data >> 8);    // high byte
  Wire.endTransmission(); } // end of gpio_write

// end of light_control

Compiled with 1.8.5 for Uno (board dev 1.8.1)

This prints fine :slight_smile: But, I have nothing connected to I2C. So only thing I can think of is the PCA9555 holding the I2C? Maybe cause by the wrong use of requestFrom()?

PS We live in 2019:

const byte GpioAddress = 0x20;
const byte GpioRegisterInput = 0;
const byte GpioRegisterOutput = 2;
const byte GpioRegisterConfig = 6;

PPS Damn, would not have expected the twi library to throw around warnings :s

Ow, and the image:
10-wire.JPG

You really have the I2C pullups? No long (<20cm) wires on the I2C?

septillion:

You really have the I2C pullups? No long (<20cm) wires on the I2C?

Yes, I do have the pullups. And both chips are on a 3x3" PCB, so the connections are a little less than 20 cm.

However, I have some light controllers (6 ea.) working that have off-board 9555s with leads that are 50-60 cm and they have no issues (for 3 years). And the leads go into the 120V box that also has a raft of relays. Maybe I’m just lucky.

Your issue with the I2C causing problems doesn’t wash, since there are no I2C calls in the loop, anyway.

Dr.Q

Dr_Quark:
Your issue with the I2C causing problems doesn't wash, since there are no I2C calls in the loop, anyway.

Why? You're saying it's not getting to loop() so it may hang before...

Try:

  • Fixing the .requestFrom()-issue
  • Disconnecting I2C (as a test)

About I2C, yeah, that is stretching the limits...

Up to your code. First thing I notice, do youself a favor and line up your } with the line that caused it. Like I did above. Makes it soooooo much easier to see what in in a block and what's not.

I've struggled with the formatting for as long as I've used the IDE. For some reason your recommendation looks like run-on sentences to me. However, I'll give it a try. The last coding class I took was five languages ago back in 1966, so I may have missed a few "advances" since then. :slight_smile:

And probably not related, no need to call Wire.beginTransmission() before a Wire.requestFrom(). And no need for Wire.endTransmission() either.

Back in 2005 I struggled to get I2C to work and never could, so when I found Neufeld's code I never looked back. I guess it's time to be a bit more precise (although his code seems to have worked great in all my applications--disregarding the current unexplained glitch). But I am going to comb through his code and see if I can find some other, more recent, examples for I2C.

Re your "optimized code" recommendation: I'm not sure it's more readable, but it avoids the problem of overwriting the other nibbles in Ports D and B. In this simple little tester for my headers, IDC connectors, etc., speed is not an issue. However, I do have some routines running in a Mega where I am counting the width of the loop window in mircroseconds, so I need to use byte-wide operations there. When the instruction is really a full width byte, it becomes a lot more readable to me.

Thanks for all your insights.
Dr.Q

I can not confirm the resets. I think there must be some issue with your PCA9555 expander.

I ran your code connected to a DS3231 rtc and the only change I made was to change I2C address to 0x68 to match the RTC. I can see the registers being written and read.

I added Serial.println(loop_count); as the first line of loop().

My output was

cable_10
10/18/19
10 wire cable test
input checks OK
0
1
2
3
4
5
6
7
8
9
10
......

You're getting what I'm getting, except for the glitch. I will work on the 9555, but I'm also suspecting some transient in the Nano.

Thanks for all the side info on programming.

Dr.Q