If I don't Serial.print(), nothing happens..?!

I feel like I'm breaking a rule by asking this because it seems so simple, but I've read through the "before you post" stuff and can't find an answer. Also, I'm new to Arduino coding, though I used to be a professional developer (C, C# and more).

OK - I have the following code - it's basically taking a double tap to the device using a BMI160 IMU, and turning on the LED. It uses an interrupt to do this.

That's fine - plugged into the computer, it works. BUT, if I remove all of the Serial stuff (so I can run it off a battery), it doesn't get past setup. If I just remove the Serial.printing from the loop, it doesn't seem to execute the loop() (no LEDs changing). Weirdly, and this could be key to my failure to understand what's happening, the LED only turns on for 250-500ms, then turns itself off.

Can someone point me in the direction of something that tells me what's going on here? Thanks!

#include <BMI160Gen.h>
// Requires https://github.com/hanyazou/BMI160-Arduino

const int bmi160_i2c_addr = 0x69;
const int bmi160_interrupt_pin = 7;
volatile bool running = false;

void bmi160_intr(void)
{
  running = !running;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);    // sets the digital pin as output

  Serial.begin(9600); // initialize Serial communication
  while (!Serial);    // wait for the serial port to open

  // initialize device
  Serial.println("Initializing IMU device...");
  BMI160.begin(BMI160GenClass::I2C_MODE, bmi160_i2c_addr, bmi160_interrupt_pin);
  BMI160.attachInterrupt(bmi160_intr);
  BMI160.setIntDoubleTapEnabled(true);
  Serial.println("Initializing IMU device...done.");
}

void loop() {
    if(running) {
      Serial.print(".");
      digitalWrite(LED_BUILTIN, HIGH);      
      delay(1000); //Note, this causes the LED to flash, remove it and the LED stays on)
    } else {
      digitalWrite(LED_BUILTIN, LOW);
    }
}
  • Show us the sketch with stuff removed.
1 Like

OK, this works (light blinking), outputting 0 to start then 1... (re-pasting because I tried a few things!)

#include <BMI160Gen.h>
// Requires https://github.com/hanyazou/BMI160-Arduino

const int bmi160_i2c_addr = 0x69;
const int bmi160_interrupt_pin = 7;
bool running;

void bmi160_intr(void)
{
  running = !running;
}

void setup() {
  running = false;
  pinMode(LED_BUILTIN, OUTPUT);    // sets the digital pin as output

  Serial.begin(9600); // initialize Serial communication
  while (!Serial);    // wait for the serial port to open

  // initialize device
  Serial.println("Initializing IMU device...");
  BMI160.begin(BMI160GenClass::I2C_MODE, bmi160_i2c_addr, bmi160_interrupt_pin);
  BMI160.attachInterrupt(bmi160_intr);
  BMI160.setIntDoubleTapEnabled(true);
  Serial.println("Initializing IMU device...done.");
}

void loop() {
    if(running) {
      Serial.print(running);
      digitalWrite(LED_BUILTIN, HIGH);      
      delay(1000);
    } else {
      Serial.print(running);
      digitalWrite(LED_BUILTIN, LOW);
      delay(1000);
    }
}

But, this does nothing (light doesn't go off, so it's not hitting loop()):

#include <BMI160Gen.h>
// Requires https://github.com/hanyazou/BMI160-Arduino

const int bmi160_i2c_addr = 0x69;
const int bmi160_interrupt_pin = 7;
bool running;

void bmi160_intr(void)
{
  running = !running;
}

void setup() {
  running = false;
  pinMode(LED_BUILTIN, OUTPUT);    // sets the digital pin as output

  // initialize device
  BMI160.begin(BMI160GenClass::I2C_MODE, bmi160_i2c_addr, bmi160_interrupt_pin);
  BMI160.attachInterrupt(bmi160_intr);
  BMI160.setIntDoubleTapEnabled(true);
}

void loop() {
    if(running) {
      digitalWrite(LED_BUILTIN, HIGH);      
      delay(1000);
    } else {
      digitalWrite(LED_BUILTIN, LOW);
      delay(1000);
    }
}

More inexplicably (to me), if I change loop() to remove the serial.prints (but keep serial.begin in setup(), it no longer flashes the light. I don't know if that means it's not running loop(), or the lack of a print is causing the light to turn off before it even turns on..?

void loop() {
    if(running) {
      digitalWrite(LED_BUILTIN, HIGH);      
      delay(1000);
    } else {
      digitalWrite(LED_BUILTIN, LOW);
      delay(1000);
    }
}

Did you also remove these lines?

Yes, if I remove serial.begin and while (!Serial), loop() doesn't seem to get called at all (the light stays on)

Then consider the program is doing exactly what you programmed it to do. Can you follow your logic, one step at a time through the program?

Sorry, "volatile" was something I missed in my cutting and pasting. I agree that's a mistake, but it seems to be one that the compiler is tolerant of! Fixing that doesn't fix the problems.
Let me be clear here then for the last two answers..

The function of the code is that the light should start off. When I double tap, the light should turn on. When I double tap again, the light should turn off. The problems are:

  1. A delay in the true, "running" condition in loop() causes the light to blink rather than switch on permanently.
  2. If I remove Serial from the code entirely, the "!running" condition in loop() never runs so the light stays on.
  3. If I Serial.begin in setup, but don't Serial.print in the loop, the light stays off

It does seem likely that what's actually happening is that the light is only staying on or off?!) as long as it takes to run the serial communication. But that everything else is OK. Is my code to permanently switch the light on or off not correct?

  • Did you put this back ?

volatile bool running = false;

Sure.

  1. setup some constants and a flag to say if the "code" should be running. In this case, that's simply code to switch a light on. If it's not running, it's code to switch it off.
  2. set the flag to not running, set my "output" pin, initialise my IMU and set an double tap interrupt
  3. That interrupt flips running/!running
  4. in the loop, if it's running, turn on the light, and wait a little while (just because it's interesting that the light turns itself off, if )
  5. If it's not running, turn off the light and delay a little while

With no serial at all, #5 doesn't happen, which I don't understand... I don't really know why - is that because loop() isn't running? Or is it because the code for turning off the light is wrong?). I'm using a sparkfun pro micro, so no debug other than serial logging seems to be possible other than using this light?!

Yes, this is code that doesn't do anything (the LED stays on):

#include <BMI160Gen.h>
// Requires https://github.com/hanyazou/BMI160-Arduino

const int bmi160_i2c_addr = 0x69;
const int bmi160_interrupt_pin = 7;
volatile bool running;

void bmi160_intr(void)
{
  running = !running;
}

void setup() {
  running = false;
  pinMode(LED_BUILTIN, OUTPUT);    // sets the digital pin as output

  // initialize device
  BMI160.begin(BMI160GenClass::I2C_MODE, bmi160_i2c_addr, bmi160_interrupt_pin);
  BMI160.attachInterrupt(bmi160_intr);
  BMI160.setIntDoubleTapEnabled(true);
}

void loop() {
  if(running) {
    digitalWrite(LED_BUILTIN, HIGH);      
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

Which LED? TX, RX or L? Post a photograph.

const int bmi160_i2c_addr = 0x69; // confirm this is correct, might be 68

const int bmi160_interrupt_pin = 7; // try pin 2

  • Always show us a good schematic of your proposed circuit.
    Show us good images of your ‘actual’ wiring.
    Give links to components.

how can you tell that it's not going off without any delays ??
add a delay (400)

Make a line of code in setup() to be a comment, compile and test. The the next line, compile and test, Repeat until there is nothing left in setup().

As @gcjr mentioned, slow things down.

void loop() {
if(running) {
digitalWrite(LED_BUILTIN, HIGH);
add delay
} else {
digitalWrite(LED_BUILTIN, LOW);
add delay
}

OK, I'm getting a bit tangled here. I've simplified the code a little hopefully to make it clear where the problem should lie. Here is the circuit and the code in Cirkit: Cirkit Designer IDE. However, in case that doesn't work, here's the circuit (you can ignore the EEPROMS at the bottom, I'm trying to get this working on battery first!):

Now, with this code, when I double-tap the device, the Sparkfun Pro Micro LED (pin 13) flashes and EITHER 0 or 1 is output through USB to serial. Now, that doesn't make sense to me either - surely it should either turn on or off, but every time (whether running or !running) it flashes..?!

#include <BMI160Gen.h>
// Requires https://github.com/hanyazou/BMI160-Arduino

const int bmi160_i2c_addr = 0x69;
const int bmi160_interrupt_pin = 7;
volatile bool running = true;

void bmi160_intr(void)
{
  running = !running;
  Serial.print(running);
  if(running) {
    digitalWrite(LED_BUILTIN, HIGH);      
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);    // sets the digital pin as output

  Serial.begin(9600);
  while (!Serial);

  // initialize device
  BMI160.begin(BMI160GenClass::I2C_MODE, bmi160_i2c_addr, bmi160_interrupt_pin);
  BMI160.attachInterrupt(bmi160_intr);
  BMI160.setIntDoubleTapEnabled(true);
  bmi160_intr();
}

void loop() {
}

If I remove all serial, as per below. The light never switches off and tapping the device does nothing:

#include <BMI160Gen.h>
// Requires https://github.com/hanyazou/BMI160-Arduino

const int bmi160_i2c_addr = 0x69;
const int bmi160_interrupt_pin = 7;
volatile bool running = true;

void bmi160_intr(void)
{
  running = !running;
  if(running) {
    digitalWrite(LED_BUILTIN, HIGH);      
  } else {
    digitalWrite(LED_BUILTIN, LOW);
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);    // sets the digital pin as output

  // initialize device
  BMI160.begin(BMI160GenClass::I2C_MODE, bmi160_i2c_addr, bmi160_interrupt_pin);
  BMI160.attachInterrupt(bmi160_intr);
  BMI160.setIntDoubleTapEnabled(true);
  bmi160_intr();
}

void loop() {
}

Tried this, no difference.

With the Serial.print debug code, it only outputs one digit per doubletap (and none for a single tap)...

I think we fall into "Arduino clone" with this answer? Sparkfun pro micro (selected for it's USB + smallness as my first "Arduino" project.

Oh crap. First of all, thanks for being a sounding board...

I have used some beginners "blink LED" code before while learning this stuff and it worked. But I just had a look at Sparkfun Pro Micro specific code, and it seems it could be that the only reason the light is blinking is because it thinks data is transmitting (the interrupt counts as data?) and you have to use pin 17 for the RX LED and a macro for the TX LED...

Changed it to the following which is working...

#include <BMI160Gen.h>
// Requires https://github.com/hanyazou/BMI160-Arduino

const int bmi160_i2c_addr = 0x69;
const int bmi160_interrupt_pin = 7;
volatile bool running = true;
int RXLED = 17;

void bmi160_intr(void)
{
  running = !running;
  if(running) {
    digitalWrite(RXLED, HIGH);
  } else {
    digitalWrite(RXLED, LOW);
  }
}

void setup() {
  pinMode(RXLED, OUTPUT);    // sets the digital pin as output

  // initialize device
  BMI160.begin(BMI160GenClass::I2C_MODE, bmi160_i2c_addr, bmi160_interrupt_pin);
  BMI160.attachInterrupt(bmi160_intr);
  BMI160.setIntDoubleTapEnabled(true);
  bmi160_intr();
}

void loop() {
}