Square wave output with button always starting on the HIGH

Hi,
Simple enough thing but i can't seem to figure this out and can't find exactly what i'm after searching the web.
I have this code running on an attiny85. It's putting out a square wave whilst a button is pressed. I'm using millis and a potentiometer to set the rate but because of this i'm struggling to get it to always start with a HIGH.
I'm using an LED so i can see whats going on and basically when the button is pressed it should always start with the LED on. As it is it's waiting for the millis counter to pass enough time so the output is just wherever the millis counter happens to be. I hope that makes sense.
I feel like this should be simple enough but i can't wrap my tiny mind around it. Any help would be greatly appreciated!

All the tone stuff can be ignored as that's for something else.

// set pin numbers:
const int buttonPin = 2;      //  (attiny pin 7)
const int triggerPin = 0;     //  (attiny pin 5)
const int outputPin =  1;     //  (attiny pin 6)
const int toneOut =  3;       //  (attiny pin 2)

// variables
int triggerState = 0;         // variable for reading the pushbutton status
int buttonState;
int outState = HIGH;          // ledState used to set the LED on or off
long previousMillis = 0;     // last time LED was updated
long rate;         // half of 1 on/off cycle time
int potVal;
int dt = 200;
int buttonCount = 0;

void setup() {
  pinMode(outputPin, OUTPUT);   // initialize the LED pin as an output
  pinMode(triggerPin, INPUT_PULLUP); // initialize the pushbutton pin as an input

  pinMode (buttonPin, INPUT_PULLUP);
  pinMode (toneOut, OUTPUT);

}

void loop() {


  buttonState = digitalRead (buttonPin);

  if (buttonState == LOW) {
    buttonCount ++;
  }

  if (buttonCount == 1 && buttonState == LOW) {

    tone(toneOut, 250);
    delay (dt);
    tone (toneOut, 950);
    delay (dt);
    tone (toneOut, 4670);
    delay (dt);
    tone (toneOut, 8490);
    delay (dt);
    tone (toneOut, 17490);
    delay (dt);

    tone (toneOut, 0);


  }


  potVal = analogRead (2); // read pot on attiny pin 3
  rate = map (potVal, 0, 1023, 10, 2000); // map pot value to 0.5 - 12 hz
  triggerState = digitalRead(triggerPin);              // read the state of the pushbutton value
  delay (15); // debouce
  if (triggerState == LOW) {  // check if the pushbutton is pressed, if it is, the buttonState is LOW


    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > rate) { // check if it's time to change LED state
      previousMillis = currentMillis;                // save the time you blinked the LED
      outState = !outState;                          // if the LED is off turn it on and vice-versa:
      digitalWrite(outputPin, outState);                // set the LED with the ledState of the variable:
    }
  }
  else {                         // if no button is pressed
    digitalWrite(outputPin, LOW);   // turn LED off
  }
}

Hello
to start with LED == on you may change the sketch to

 else {                         // if no button is pressed
    digitalWrite(outputPin, HIGH);   // turn LED ON 
  }

when the button is pressed it should always start with the LED on.

consider

// set pin numbers:
#undef MyHW
#ifdef MyHW
const int buttonPin  = 2;
const int triggerPin = A1; 
const int outputPin  = 10;
const int toneOut    = 3;
#else
const int buttonPin = 2;      // (attiny pin 7)
const int triggerPin = 0;     // (attiny pin 5)
const int outputPin =  1;     // (attiny pin 6)
const int toneOut =  3;       // (attiny pin 2)
#endif

// variables
int triggerState = 0;         // variable for reading the pushbutton status
int buttonState;

unsigned long previousMillis;   // last time LED was updated
unsigned long rate;             // half of 1 on/off cycle time
int potVal;
int dt = 200;
int buttonCount = 0;

enum { Off = HIGH, On = LOW };

void setup () {

    digitalWrite (outputPin, Off);
    pinMode (outputPin, OUTPUT);

    pinMode (triggerPin, INPUT_PULLUP); // initialize the pushbutton pin as an input
    triggerState = digitalRead (triggerPin);

    pinMode (buttonPin, INPUT_PULLUP);
    pinMode (toneOut, OUTPUT);
}


void loop () {
    buttonState = digitalRead (buttonPin);
    if (buttonState == LOW) {
        buttonCount ++;
    }
    if (buttonCount == 1 && buttonState == LOW) {
        tone (toneOut, 250);
        delay (dt);
        tone (toneOut, 950);
        delay (dt);
        tone (toneOut, 4670);
        delay (dt);
        tone (toneOut, 8490);
        delay (dt);
        tone (toneOut, 17490);
        delay (dt);
        tone (toneOut, 0);
    }

    // -------------------------------------
    // LED
    potVal = analogRead (2); // read pot on attiny pin 3
    rate = map (potVal, 0, 1023, 10, 2000); // map pot value to 0.5 - 12 hz

    unsigned long msec = millis ();

    // recognize button press
    byte but = digitalRead (triggerPin);
    if (triggerState != but)  {
        triggerState = but;
        delay (15); // debouce

        if (LOW == but)  {
            digitalWrite (outputPin, On);
            previousMillis = msec;
        }
    }

    if (triggerState == LOW) {          // button being pressed
        if ( (msec - previousMillis) > rate) {
            previousMillis = msec;
            digitalWrite (outputPin, ! digitalRead (outputPin));
        }
    }
    else {                              // if no button is pressed
        digitalWrite (outputPin, Off);
    }
}

Thanks so much for the replies.
Unfortunately that doesn't do quite what i'm after. Maybe i didn't explain myself well enough, apologies if that's the case.
With this new code the LED is always on, then begins the square wave routine when the button is pressed. I need the LED to be always off but when the square wave routine begins it always starts with a HIGH (so always starts with the LED coming on, then going off, on, off, etc..

Hello
Post a timing diagram to see how your sketch shall work.

Not entirely sure what you mean by timing diagram but hopefully this will suffice.!

SQUARE WAVE OUTPUT|690x293

So LED starts off and stays off until button is pressed. When button is pressed square wave routine begins but it needs to always starts ON when the button is pressed.

Thanks again!

Hi,
@patrick398 image.

Tom.. :smiley: :+1: :coffee: :australia:

Pretty close!

This is a timing diagram from a hardware shift register.

Notice it shows the relationships between inputs and reactions of the outputs at given time intervals.

Your diagram shows a symmetrical square wave.  Is it required that the ending high be the same length as all previous highs?

change the enum for Off/On for your HW

Thank you so much again for all the help. Apologies for the late reply, i've been away from my computer for a while.

switching the enum order seemed to do the trick for the square wave, that's working really nicely now.

A new problem which has arisen however is that now the tone function executes about every 16 seconds if buttonPin is held at ground. It should happen once when buttonPin goes to ground and then not again until the chip is powered off/on.

My guess is that the code merely checks whether buttonPin is at ground rather than checking for a change of state. I tried detecting a state change but i have the same problem when the pin is held at ground, the tone still executes every 16 seconds or so and i can't work out why.


// set pin numbers:
#undef MyHW
#ifdef MyHW
const int buttonPin  = 2;
const int triggerPin = A1; 
const int outputPin  = 10;
const int toneOut    = 3;
#else
const int buttonPin = 2;      // (attiny pin 7)
const int triggerPin = 0;     // (attiny pin 5)
const int outputPin =  1;     // (attiny pin 6)
const int toneOut =  3;       // (attiny pin 2)
#endif

// variables
int triggerState = 0;         // variable for reading the pushbutton status
int buttonState;

unsigned long previousMillis;   // last time LED was updated
unsigned long rate;             // half of 1 on/off cycle time
int potVal;
int dt = 200;
int buttonCount = 0;
int lastButtonState = HIGH;

enum { Off = LOW, On = HIGH };

void setup () {

    digitalWrite (outputPin, Off);
    pinMode (outputPin, OUTPUT);

    pinMode (triggerPin, INPUT_PULLUP); // initialize the pushbutton pin as an input
    triggerState = digitalRead (triggerPin);

    pinMode (buttonPin, INPUT_PULLUP);
    pinMode (toneOut, OUTPUT);
}


void loop () {
    buttonState = digitalRead (buttonPin);
    if (buttonState != lastButtonState) {
        buttonCount ++;
    
    if (buttonCount == 1 && buttonState != lastButtonState) {
        tone (toneOut, 250);
        delay (dt);
        tone (toneOut, 950);
        delay (dt);
        tone (toneOut, 4670);
        delay (dt);
        tone (toneOut, 8490);
        delay (dt);
        tone (toneOut, 17490);
        delay (dt);
        tone (toneOut, 0);

    }

    // -------------------------------------
    // LED
    potVal = analogRead (2); // read pot on attiny pin 3
    rate = map (potVal, 0, 1023, 43, 2000); // map pot value to 0.5 - 12 hz

    unsigned long msec = millis ();

    // recognize button press
    byte but = digitalRead (triggerPin);
    if (triggerState != but)  {
        triggerState = but;
        delay (15); // debouce

        if (LOW == but)  {
            digitalWrite (outputPin, On);
            previousMillis = msec;
        }
    }

    if (triggerState == LOW) {          // button being pressed
        if ( (msec - previousMillis) > rate) {
            previousMillis = msec;
            digitalWrite (outputPin, ! digitalRead (outputPin));
        }
    }
    else {                              // if no button is pressed
        digitalWrite (outputPin, Off);
    }
    }
    }
  if (buttonState != lastButtonState)
  {
    buttonCount ++;
    if (buttonCount == 1 && buttonState != lastButtonState)

The second test in the second 'if' is redundant. It will do no harm but it is not needed

More importantly you never update the value of lastButtonState

Aha, good point. So I need to include something like:
LastButtonState = ButtonState;
At the end of that sequence?

Thank you

Ok updating the value of lastButtonState did solve that problem but now that i think about it i don't think state change is actually what i need.
The switch on buttonPin is latching, so it will stay at ground. I've tried writing it so that it checks the value of buttonPin and if it is LOW it increases the counter by one and then if the buttonPin is LOW and the counter is at 1 it plays the tone. I think i increased the counter again at the end of the tone part too so in theory it should be at 2 and therefore will not play the tone again until the chip is powered off/on.

It keeps playing the tone about every 15 seconds however and i'm completely stumped.

Any guidance would be greatly appreciated!


// set pin numbers:
#undef MyHW
#ifdef MyHW
const int buttonPin  = 2;
const int triggerPin = A1; 
const int outputPin  = 10;
const int toneOut    = 3;
#else
const int buttonPin = 2;      // (attiny pin 7)
const int triggerPin = 0;     // (attiny pin 5)
const int outputPin =  1;     // (attiny pin 6)
const int toneOut =  3;       // (attiny pin 2)
#endif

// variables
int triggerState = 0;         // variable for reading the pushbutton status
int buttonState;

unsigned long previousMillis;   // last time LED was updated
unsigned long rate;             // half of 1 on/off cycle time
int potVal;
int dt = 200;
int buttonCount = 0;
int lastButtonState =HIGH;

enum { Off = LOW, On = HIGH };

void setup () {

    digitalWrite (outputPin, LOW);
    pinMode (outputPin, OUTPUT);

    pinMode (triggerPin, INPUT_PULLUP); // initialize the pushbutton pin as an input
    triggerState = digitalRead (triggerPin);

    pinMode (buttonPin, INPUT_PULLUP);
    pinMode (toneOut, OUTPUT);
}


void loop () {
    buttonState = digitalRead (buttonPin);
    if (buttonState == LOW) {
        buttonCount ++;
    
    if (buttonCount == 1 && buttonState ==LOW) {
        tone (toneOut, 250);
        delay (dt);
        tone (toneOut, 950);
        delay (dt);
        tone (toneOut, 4670);
        delay (dt);
        tone (toneOut, 8490);
        delay (dt);
        tone (toneOut, 17490);
        delay (dt);
        tone (toneOut, 0);

buttonCount ++;

    }

    

    // -------------------------------------
    // LED
   
    
    potVal = analogRead (2); // read pot on attiny pin 3
    rate = map (potVal, 0, 1023, 43, 2000); // map pot value to 0.5 - 12 hz

    unsigned long msec = millis ();

    // recognize button press
    byte but = digitalRead (triggerPin);
    if (triggerState != but)  {
        triggerState = but;
        delay (15); // debouce

        if (LOW == but)  {
            digitalWrite (outputPin, On);
            previousMillis = msec;
        }
    }

    if (triggerState == LOW) {          // button being pressed
        if ( (msec - previousMillis) > rate) {
            previousMillis = msec;
            digitalWrite (outputPin, ! digitalRead (outputPin));
        }
    }
    else {                              // if no button is pressed
        digitalWrite (outputPin, Off);
    }
}
}

Every time through loop(), if buttonState is LOW, you increment the counter so eventually, it rolls over and you get back to 1... apparently about every 15 seconds. (0,1,2,3,...,32767, -32768, -32767, -32766,..., -1, 0, 1)
You only want to increment the counter when the button changes state. There is an example in the IDE (File->exampes-02.digital->StateChangeDetection) [much like your triggerState code]

That makes sense thank you. I'll give that a go