Three state humidifier problem

I am writing a sketch where I'm trying to control a humidifier. The humidifier has three states (FULL POWER ON/50% POWER ON/OFF) and I only want it to be on/off. It is powered by an external PSU at 12V and it has a cable with a very low voltage (24 mV) that changes the state of the humidifier when it's connected to ground.

In my sketch, I am using that cable to switch between states every time I send a HIGH through the 12th pin. That HIGH is send whenever the pushbutton is pressed. My goal is to switch states between FULL POWER ON/OFF going very quickly through the 50% POWER ON state, but I've not succeeded for now.

I think it should be rather simple, but I can’t figure out how to do it. Does ayone know how to program this?

Here is the current sketch I'm running.

#define pushbutton 11
#define transducer 12

// These are the variables
bool buttonstate        = LOW;
bool lastbuttonstate   = LOW;

// Debouncing constants
unsigned long debouncetime  = 0;
unsigned long debouncedelay = 20;

void setup() {
  pinMode(pushbutton, INPUT);
  pinMode(transducer, OUTPUT);
  digitalWrite(transducer, LOW);
}

void loop() {
  buttonstate = digitalRead(pushbutton);
  if((millis()- debouncetime) > debouncedelay){
    if (buttonstate != lastbuttonstate){
      debouncetime = millis();
      if (buttonstate == HIGH){
        digitalWrite(transducer, HIGH);
        delay(100);
        digitalWrite(transducer, LOW);
      }
      else {
        digitalWrite(transducer, HIGH);
        delay(100);
        digitalWrite(transducer, LOW);
        delay(100);
        digitalWrite(transducer, HIGH);
        delay(100);
        digitalWrite(transducer, LOW);
      }
    }
    else{
      debouncetime = debouncetime;
    }
  }
  lastbuttonstate = buttonstate;
}

I have also attached an schematic of what I have.

What happens when you run the sketch ?

Try adding Serial.print()s of pertinent variables a strategic points in the code such as before testing their values. Does the code execute the sections that you expect and are the values of the variables what you expect ?

When running the sketch, it turns FULL POWER ON while pressed the pushbutton. Then, once released the button, it switch to 50% POWER ON and quickly jumps to OFF. That's similar to what I'm trying to achieve.

But, my main goal is to make some kind of "toggle switch" whith that humidifier.

Thank you for your help.

every time I send a HIGH through the 12th pin

What sequence of states does the humidifier enter when the button is pressed ?

For instance does it go OFF, MEDIUM, HIGH, OFF, MEDIUM, HIGH etc, or some other sequence such as OFF, MEDIUM, HIGH, MEDIUM, OFF etc ?

The secuence of the humidifier is HIGH-MEDIUM-OFF, HIGH-MEDIUM-OFF...

While pressed the pushbutton, it stays on HIGH. When released, it goes MEDIUM-OFF and stays OFF.

Your program needs to keep track of the current state of the humidifier with a variable

In loop(), detect when the button becomes pressed then if the state variable is in the OFF state send two on/off transitions to the humidifier and set the state variable to ON, else if the state variable is in the ON state send one on/off transition to the humidifier and set the state variable to OFF

I'm not sure if I've understand it proprely. Do you mean something like this?

void loop() {
  buttonstate = digitalRead(pushbutton);
  if ((millis() - debouncetime) > debouncedelay) {
    if (buttonstate != lastbuttonstate) {
      debouncetime = millis();
      if (buttonstate == HIGH) {
        if (transducer_state == LOW) {
          digitalWrite(transducer, HIGH);
          delay(100);
          digitalWrite(transducer, LOW);
          transducer_state = !transducer_state;
        }
        else {
          transducer_state = transducer_state;
        }
      }
      else {
        if (transducer_state == LOW) {
          transducer_state = transducer_state;
        }
        else {
          digitalWrite(transducer, HIGH);
          delay(100);
          digitalWrite(transducer, LOW);
          delay(100);
          digitalWrite(transducer, HIGH);
          delay(100);
          digitalWrite(transducer, LOW);
          transducer_state = !transducer_state;
        }
      }
    }
    else {
      debouncetime = debouncetime;
    }
  }
  lastbuttonstate = buttonstate;
}

I'm not able to try any sketch until tomorrow, so I can't tell you if its working or not.

Thanks for your help

I think one of your problems is your debounce code is incorrect. Comparing your code to the debounce tutorial it looks like it should be:

void loop() {
  buttonstate = digitalRead(pushbutton);
  if (buttonstate != lastbuttonstate) {
      debouncetime = millis();
  }
  if ((millis() - debouncetime) > debouncedelay) {
      if (buttonstate == HIGH) {

Thanks Blue Eyes! I thought mine was a different approach, but after studying it al little bit more, I've realised didn't work as I expected. I've changed it, however I haven't noticed any difference in the way the sketch works.

Please post the complete sketch as it is now and describe the current problem

Yes, of course. Here it is:

#define pushbutton 11
#define transducer 12

// These are the variables
bool buttonstate       = LOW;
bool lastbuttonstate   = LOW;
bool transducer_state  = LOW;

// Debouncing constants
unsigned long debouncetime  = 0;
unsigned long debouncedelay = 20;

void setup() {
  pinMode(pushbutton, INPUT);
  pinMode(transducer, OUTPUT);
  digitalWrite(transducer, transducer_state);
}

void loop() {
  buttonstate = digitalRead(pushbutton);
  if (buttonstate != lastbuttonstate) {
    debouncetime = millis();
  }
  else {
    debouncetime = debouncetime;
  }
  if ((millis() - debouncetime) > debouncedelay) {
    if (buttonstate == HIGH) {
      if (transducer_state == LOW) {
        transducer_state = HIGH;
      }
      else {
        transducer_state = transducer_state;
      }
    }
    else {
      if (transducer_state == LOW) {
        transducer_state = transducer_state;
      }
      else {
        transducer_state = HIGH;
      }
    }
  }
  else {
    debouncetime = debouncetime;
  }
  lastbuttonstate = buttonstate;
  if (transducer_state == HIGH) {
    digitalWrite(transducer, HIGH);
    delay(100);
    digitalWrite(transducer, LOW);
  }
  else {
    digitalWrite(transducer, HIGH);
    delay(100);
    digitalWrite(transducer, LOW);
    delay(100);
    digitalWrite(transducer, HIGH);
    delay(100);
    digitalWrite(transducer, LOW);
  }
}

The first thing that I notice is that you have several lines like this

  debouncetime = debouncetime;

They do nothing but make the code longer and harder to read. Eliminate them all and the associated else clauses where relevant, post the new code and describe the current problems

All right, I thouht it was a good habit to write an 'else' clause when doing an 'if' statement.

Here is the current code:

#define pushbutton 11
#define transducer 12

// These are the variables
bool buttonstate       = LOW;
bool lastbuttonstate   = LOW;
bool transducer_state  = LOW;
bool humidifier        = LOW;

// Debouncing constants
unsigned long debouncetime  = 0;
unsigned long debouncedelay = 20;

void setup() {
  pinMode(pushbutton, INPUT);
  pinMode(transducer, OUTPUT);
  digitalWrite(transducer, transducer_state);
}

void loop() {
  buttonstate = digitalRead(pushbutton);
  if (buttonstate != lastbuttonstate) {
    if (buttonstate == HIGH) {
      humidifier = !humidifier;
    }
    lastbuttonstate = buttonstate;
  }
  if (humidifier == HIGH) {
    if (transducer_state == LOW) {
      digitalWrite(transducer, HIGH);
      delay(100);
      digitalWrite(transducer, LOW);
      transducer_state = HIGH;
    }
  }
  else {
    if (transducer_state == HIGH) {
      digitalWrite(transducer, HIGH);
      delay(100);
      digitalWrite(transducer, LOW);
      delay(100);
      digitalWrite(transducer, HIGH);
      delay(100);
      digitalWrite(transducer, LOW);
      transducer_state = LOW;
    }
  }
}

It's working nearly as I want, but it still have some problems:

  • I had to remove the debouncing part. My approach actually didn't debounce and the code in the tutorial doesn't work for me. I may be still missing something, but I've tried it many times.
  • I would love to make it work without usign delays. The board used by the humidifier changes it state every time it gets a HIGH and I haven't found another way to do so.

The current code makes the system work as follows:

When turning on the system, it keeps everythig off. After pressing the pushbutton, the humidifier turns on (FULL POWER ON) and stays in that state. Then, if the pushbutton is pressed again, the humidifier switchs to 50% POWER ON and to OFF very fast. It keeps in the OFF state until the pushbutton is pressed again.

If someone has any suggestion to solve the issues I still have, I would be very gratefull.