Getting tripped up by a simple Button sketch - really frustrating !

This involves the buttons on a Wii Chuck.

At first i thought it was a Debounce issue, but as i made the sketch ever more simple, it boiled down to a strange difference between the sketch working and not.

THIS does NOT work;

#include <Wire.h>
#include "nunchuck_funcs.h"
int zbut,cbut;

const int ledPin = 13;      // the number of the LED pin
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

void setup() {
  nunchuck_setpowerpins();
  nunchuck_init(); // send the initilization handshake    

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, ledState);

  Serial.begin(9600);
}

void loop(){
  nunchuck_get_data();
  zbut = nunchuck_zbutton();

  // read the state of the pushbutton value:
  buttonState = zbut;
  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
  
//  Serial.println(buttonState);
}

but then THIS does (?!);

#include <Wire.h>
#include "nunchuck_funcs.h"
int zbut,cbut;

const int ledPin = 13;      // the number of the LED pin
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

void setup() {
  nunchuck_setpowerpins();
  nunchuck_init(); // send the initilization handshake    

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, ledState);

  Serial.begin(9600);
}

void loop(){
  nunchuck_get_data();
  zbut = nunchuck_zbutton();

  // read the state of the pushbutton value:
  buttonState = zbut;
  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
  
  Serial.println(buttonState);
}

the only difference is the very last line being commented out or not.

it is basically the standard Arduino example of "Button" except adding the library for the WiiChuck.

the relevant code from the include of "nunchuck_funcs.h" is;

// returns zbutton state: 1=pressed, 0=notpressed
static int nunchuck_zbutton()
{
    return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1;  // voodoo
}

why is it the Serial.println() makes the sketch work, i am guessing it's to do with typecasting - but i can't understand what is going on.

Please help explain.

Thanks.

"THIS does NOT work" What does that mean? It won't compile? It gives some error? The program freezes? The LED doesn't blink?

If you're concerned about typecasting, why are you using lines like:

int ledState = HIGH; // Why an int for what is apparently a bool?

JaBa:
int ledState = HIGH; // Why an int for what is apparently a bool?

In my opinion, uint8_t would be more appropriate than a bool in this case. bools should only be true or false.

Have you anything else connected e.g something that is using pins 0 or 1 ?

Edit
And try commenting this out in the non-working version

Serial.begin(9600);

aarg:
In my opinion, uint8_t would be more appropriate than a bool in this case. bools should only be true or false.

implicit casting is your friend

I guess this is the library: wiichuck_adapter/nunchuck_funcs.h at master · todbot/wiichuck_adapter · GitHub

It looks like a timing issue and maybe your print statement just delayed things long enough for it to appear to work. It uses I2C to get the data from your module:

You should test the return code from:
static int nunchuck_get_data() { . . . }    // 0 is buffer not filled yet, 1 is good

Just for testing, you can change:
nunchuck_get_data();
to:
if ( nunchuck_get_data() == 0 ) return ;
and improve the code later.

JaBa:
"THIS does NOT work" What does that mean? It won't compile? It gives some error? The program freezes? The LED doesn't blink?

no error message, the LED just doesn't blink.
(i wasn't explicit because i assumed the next code which "worked" would hint at that.)

JaBa:
If you're concerned about typecasting, why are you using lines like:

int ledState = HIGH; // Why an int for what is apparently a bool?

yes, that also puzzled me - i have started to use byte wherever i see int when declaring variables (especially for pins) and whenever i know the value is less than 256.

but, as i said, it's exactly the Arduino code example, and since i didn't want to change things to stuff "not guaranteed" to work, i stuck as close as possible to the Example Code.

i had even tried to change all the 'HIGH/LOW' to '1/0' but that didn't help.

6v6gt:
It looks like a timing issue and maybe your print statement just delayed things long enough for it to appear to work. It uses I2C to get the data from your module:

You should test the return code from:
static int nunchuck_get_data() { . . . }    // 0 is buffer not filled yet, 1 is good

Just for testing, you can change:
nunchuck_get_data();
to:
if ( nunchuck_get_data() == 0 ) return ;
and improve the code later.

Thanks - that looks like the issue to investigate further.

Will try your code and post my solution.

okay - all typecasting issues aside, the sketch problem is not failing because of that.

it is indeed a timing issue and how the information is coming in from the i2c bus.

i did get to solve the issue by putting in a delay and it fixed the problem;

    nunchuck_get_data() 
    delay(1);  // THIS solved it ! (the same way the Serial.println "solved" it.)
    zbut = nunchuck_zbutton();

this is of course 'blocking code', and one wonders whether it is actually the solution or just a crude fix.

i wasn't sure how to proceed with your suggested code, i didn't know what to do after 'return' - and so i tried to understand the nunchuck_get_data() itself;

// Receive data back from the nunchuck, 
// returns 1 on successful read. returns 0 on failure
static int nunchuck_get_data()
{
    int cnt=0;
    Wire.requestFrom (0x52, 6);// request data from nunchuck
    while (Wire.available ()) {
        // receive byte as an integer
        nunchuck_buf[cnt] = nunchuk_decode_byte( Wire.read() );
        cnt++;
    }
    nunchuck_send_request();  // send request for next data payload
    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5) {
        return 1;   // success
    }
    return 0; //failure
}

and this which it calls;

// Send a request for data to the nunchuck
static void nunchuck_send_request()
{
    Wire.beginTransmission(0x52);// transmit to device 0x52
    Wire.write((uint8_t)0x00);// sends one byte
    Wire.endTransmission();// stop transmitting
}

so then, instead of putting in a delay, i thought i'd change the "get data" code to this;

      if(nunchuck_get_data()) {
        zbut = nunchuck_zbutton();
      }

thinking that it will only continue program execution IF the "get data" was successful.

but it still didn't work (LED blink) unless there is that delay after it.

is there a time lag between the Arduino executing the instruction and the data actually arriving into the variable - which means the delay(1) is infact the proper solution to this timing issue.

OK. And if you try this ?

      if(nunchuck_get_data()) {
        zbut = nunchuck_zbutton();
        // and the rest of the stuff in your loop here 
      }

it still fails without the delay(1) statement;

void loop(){
    if ( nunchuck_get_data() ) {
 //     delay(1);
      zbut = nunchuck_zbutton();
      buttonState = zbut;

    if (buttonState == 1) {     
      digitalWrite(ledPin, 1);  
    } 
    else {
      digitalWrite(ledPin, 0); 
    }
  }
}

EDIT: to address the typecasting comments above; have changed all the int (HIGH/LOW) to byte (1/0)

it really seems like there is a time-lag - but i don't know enough about electronics (or the i2c bus) to make that a reasonable guess.