Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Bloody
Mar 3, 2013

as currently written it will turn on and immediately off as digitalRead(button) is probably not edge triggered but instead level-triggered. both if-statements execute every time, probably.

Adbot
ADBOT LOVES YOU

Bloody
Mar 3, 2013

Nelson MandEULA posted:

yospos please help. why is my code not working?

i want to turn on a pin (led for now, eventually dc motor via a TA7291P) when i push a button, and have it turn off after 15 seconds, or immediately if i push the button again. but it isn't working. idk why.

code:
unsigned long onTime;
const int BUTTON = 2;  // pushbutton 1 pin
const int LED =  13;    // LED pin
char on = 0;

void setup()
{
  onTime = millis();
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
  
}

void loop()
{
   
  if (digitalRead(BUTTON) == LOW && on == 0)   // ON- STARTS TIMER
       {
         digitalWrite(LED, HIGH);  // LED comes On  
         onTime = millis();
	on = 1;
       }
  else if ((millis() - onTime > 15000 || digitalRead(BUTTON) == LOW) && on == 1)
       {
         digitalWrite(LED, LOW);
	on = 0;
       }
}
hth

Bloody
Mar 3, 2013

actually that still probably won't work

Bloody
Mar 3, 2013

code:
unsigned long onTime;
const int BUTTON = 2;  // pushbutton 1 pin
const int LED =  13;    // LED pin
char on = 0;

void setup()
{
  onTime = millis();
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
  
}

void loop()
{
   
  if (digitalRead(BUTTON) == LOW && on == 0)   // ON- STARTS TIMER
       {
         digitalWrite(LED, HIGH);  // LED comes On  
         onTime = millis();
       }
  else if (millis() - onTime > 15000 || (digitalRead(BUTTON) == LOW && on == 1))
       {
         digitalWrite(LED, LOW);
	on = 0;
       }
  else if(digitalRead(BUTTON) == HIGH)
	{
		on = 1;
	}
}

Bloody
Mar 3, 2013

also this may still suffer from poor debouncing

Sagebrush
Feb 26, 2012

try this

code:
unsigned long onTime;
const int BUTTON = 2;  // pushbutton 1 pin
const int LED =  13;    // LED pin
boolean active = false;


void setup()
{
  onTime = millis();
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
  
}

void loop()
{

  if (digitalRead(BUTTON) == LOW) {   //if button is pressed
    if (active) {                     //and the light is already on,
      active = false;                 //set status to off
    }    
    else {                            //if the light is not already on
     active = true;                   //set status to on
     onTime = millis();               //and initialize the timer
    }
    delay(200);                       //this is here to debounce the button
  }

  if (millis() > onTime + 15000) {    //if 15 seconds have elapsed since the last time the led went on
    active = false;		      //set status to off
  } 

  if (active) {                       //if status is on
    digitalWrite(LED, HIGH);          //turn led on
  }
  else {                              //otherwise
    digitalWrite(LED, LOW);           //turn led off
  }

}
	
i like breaking things up into logical blocks executed in order instead of one big conditional

Sagebrush fucked around with this message at 00:46 on Dec 1, 2014

Sagebrush
Feb 26, 2012

bloody likes using char instead of boolean and 0|1 instead of true|false because he's a big lameoid sperg who doesn't wanna follow the arduino guidelines

Nelson MandEULA
Feb 27, 2011

"...the biggest shitbag
I have ever met."
thanks guys - i really appreciate the help! must sleep now but i will try these tomorrow.

as you can tell, i am not very good at this whole programming thing. :saddowns:

Nelson MandEULA
Feb 27, 2011

"...the biggest shitbag
I have ever met."

Sagebrush posted:

big lameoid sperg who doesn't wanna follow the arduino guidelines

mods

Sagebrush
Feb 26, 2012

also rather than using const int just use #defines, there are technical reasons you'd go one way or another but on arduino if you are just wanting to give a convenient name to a number that won't change the #define saves you memory

so instead of

const int BUTTON = 2;

it's

#define BUTTON 2

(note the lack of a semicolon, preprocessor directives like this are just a find/replace so if you put the semicolon in then a line down below like

digitalRead(BUTTON);

becomes

digitalRead(2;);

and failes for obvious reasons

bobbilljim
May 29, 2013

this christmas feels like the very first christmas to me
:shittydog::shittydog::shittydog:

Sagebrush posted:

bloody likes using char instead of boolean and 0|1 instead of true|false because he's a real life dev

Luigi Thirty
Apr 30, 2006

Emergency confection port.

reminds me I need to rewrite my C program to not be a spaghetti mess of interrupts and if statements

Bloody
Mar 3, 2013

Sagebrush posted:

bloody likes using char instead of boolean and 0|1 instead of true|false because he's a big lameoid sperg who doesn't wanna follow the arduino guidelines

ive never used an ardweener so i dont wanna assume

Bloody
Mar 3, 2013


:smugmrgw:

Bloody
Mar 3, 2013

Luigi Thirty posted:

reminds me I need to rewrite my C program to not be a spaghetti mess of interrupts and if statements

lol if your C program is anything but this

Sagebrush
Feb 26, 2012

Bloody posted:

ive never used an ardweener so i dont wanna assume

tbh i don't even remember what boolean maps to, i think it's just a uint8 so char is functionally equivalent

Luigi Thirty
Apr 30, 2006

Emergency confection port.

Bloody posted:

lol if your C program is anything but this

I'm writing a programmable display not a cancer laser gun

suffix
Jul 27, 2013

Wheeee!

Sagebrush posted:

try this

code:
unsigned long onTime;
const int BUTTON = 2;  // pushbutton 1 pin
const int LED =  13;    // LED pin
boolean active = false;


void setup()
{
  onTime = millis();
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
  
}

void loop()
{

  if (digitalRead(BUTTON) == LOW) {   //if button is pressed
    if (active) {                     //and the light is already on,
      active = false;                 //set status to off
    }    
    else {                            //if the light is not already on
     active = true;                   //set status to on
     onTime = millis();               //and initialize the timer
    }
    delay(200);                       //this is here to debounce the button
  }

  if (millis() > onTime + 15000) {    //if 15 seconds have elapsed since the last time the led went on
    active = false;		      //set status to off
  } 

  if (active) {                       //if status is on
    digitalWrite(LED, HIGH);          //turn led on
  }
  else {                              //otherwise
    digitalWrite(LED, LOW);           //turn led off
  }

}
	
i like breaking things up into logical blocks executed in order instead of one big conditional

that will flip off again if the user holds down the button for more than 200 ms

something like this would probably be good enough:

code:
void wait_for_user_to_release_button() {
  delay(50);  // debounce the button press
  while (digitalRead(BUTTON) == LOW) {
    ;// wait until we get an unpressed reading
  }
  delay(50); // debounce the button release
}

Sagebrush
Feb 26, 2012

yea, a delay is the cheapest and dumbest debouncing you can do, but you know, the guy is still new so one step at a time

echinopsis
Apr 13, 2004

by Fluffdaddy
I'm surpsied you didn't use a delay, sagebrush, because if I recall correctly, you consider delay to be an efficient and space saving method

Bloody
Mar 3, 2013

the cheapest and dumbest debouncing you can do is a capacitor.

Sagebrush
Feb 26, 2012

an extra component costs less than a line of code?

Doc Block
Apr 15, 2003
Fun Shoe
the arduino language is C++, not C, so bools are a real thing. as is const, which in C++ is a typesafe equivalent of #define

getting to the source of your problem, and ignoring the debouncing issues that others have already solved, you say that your button is wired up using a pull-down resistor, yet in your code you are checking to see if the pin is LOW. problem is, the pull-down resistor means the pin will be LOW when the button isn't being pressed, and will be HIGH when it is pressed.

another problem is that with arduinos (and any ATmega microcontrollers) that external pull-down resistor is unneeded. the ATmega328 has internal pull-up resistors on all pins capable of being used as input, so just use those unless you really really need that pin to be pulled low when unpressed instead of being pulled high.

to enable the internal pull-up resistor for a pin, using the arduino library you just do
C++ code:
pinMode(your_pin, INPUT_PULLUP);
then the pin will be LOW when the button is pressed and HIGH when it isn't.

Doc Block fucked around with this message at 01:36 on Dec 1, 2014

EIDE Van Hagar
Dec 8, 2000

Beep Boop
adding a delay seems expensive because you are stalling the loop and you gotta keep getting poo poo done the cheapest debounce would be keeping track of it with a counter in the loop so you can update the actual value a few loops later if the input is stable, no?

Bloody
Mar 3, 2013

Sagebrush posted:

an extra component costs less than a line of code?

an extra component is simpler than a line of code

Doc Block
Apr 15, 2003
Fun Shoe
actually, what you should do is forego the busy loop and just set the pin up to fire an interrupt when its pulled to the desired level, and the interrupt handler sets up a timer interrupt that goes off after 15 seconds, and the rest of the time keep the microcontroller in the lowest power mode possible that still keeps the timers and pin change sensing enabled.

edit: and an extra component is way more complicated and expensive than even many extra lines of code.

Nelson MandEULA
Feb 27, 2011

"...the biggest shitbag
I have ever met."

Doc Block posted:

the arduino language is C++, not C, so bools are a real thing. as is const, which in C++ is a typesafe equivalent of #define

getting to the source of your problem, and ignoring the debouncing issues that others have already solved, you say that your button is wired up using a pull-down resistor, yet in your code you are checking to see if the pin is LOW. problem is, the pull-down resistor means the pin will be LOW when the button isn't being pressed, and will be HIGH when it is pressed.

another problem is that with arduinos (and any ATmega microcontrollers) that external pull-down resistor is unneeded. the ATmega328 has internal pull-up resistors on all pins capable of being used as input, so just use those unless you really really need that pin to be pulled low when unpressed instead of being pulled high.

to enable the internal pull-up resistor for a pin, using the arduino library you just do
C++ code:
pinMode(your_pin, INPUT_HIGH);
then the pin will be LOW when the button is pressed and HIGH when it isn't.

meant to say pull-up, not pull-down. but yeah, you're right - i forgot about the internal pull-ups and the pinMode. makes things a bit simpler. :)

Doc Block
Apr 15, 2003
Fun Shoe
Whoops, should've been INPUT_PULLUP instead of INPUT_HIGH, fixed.

Doc Block
Apr 15, 2003
Fun Shoe
Also, if you're new at this and can't seem to get it to work, start even simpler. Make the button turn the LED on, and that's it. Then make it so pressing the button turns the LED on, but pressing it again turns the LED off. Then add the timer functionality.

That way, you start off knowing that each piece works, and if the next thing you add makes it not work, it'll be easier to figure out why.

Bloody
Mar 3, 2013

Doc Block posted:

actually, what you should do is forego the busy loop and just set the pin up to fire an interrupt when its pulled to the desired level, and the interrupt handler sets up a timer interrupt that goes off after 15 seconds, and the rest of the time keep the microcontroller in the lowest power mode possible that still keeps the timers and pin change sensing enabled.

edit: and an extra component is way more complicated and expensive than even many extra lines of code.

idk, having a lab tech spend a minute soldering a cap on is a lot cheaper than spending 30 seconds even considering pin debouncing!

but yeah the best solution is edge-triggered interrupts for the pins and a timer to debounce

Doc Block
Apr 15, 2003
Fun Shoe
except that the extra component takes up space on the PCB, affects your design, adds complexity to manufacturing, and the capacitor itself adds to the unit's cost.

edit: and if I remember my low-level ATmega poo poo correctly, when going from low power mode to full power mode after a pin change interrupt, the microcontroller can't respond to another pin change interrupt for X number of milliseconds, taking care of your debouncing for you. IIRC.

edit2: and if I'm wrong, you can still just immediately disable interrupts (if they aren't automatically disabled by the MCU, I don't remember) until your interrupt handler is ready to exit, which should also take care of debouncing.

Doc Block fucked around with this message at 02:00 on Dec 1, 2014

Sagebrush
Feb 26, 2012

also the capacitor is still less flexible and reliable than suffix's code or an interrupt solution

graph
Nov 22, 2006

aaag peanuts
shut up nerds

Bloody
Mar 3, 2013

Doc Block posted:

except that the extra component takes up space on the PCB, affects your design, adds complexity to manufacturing, and the capacitor itself adds to the unit's cost.

edit: and if I remember my low-level ATmega poo poo correctly, when going from low power mode to full power mode after a pin change interrupt, the microcontroller can't respond to another pin change interrupt for X number of milliseconds, taking care of your debouncing for you. IIRC.

doc block: mad about caps

Doc Block
Apr 15, 2003
Fun Shoe

Bloody posted:

doc block: mad about caps

:science:

also mad about subpixel antialiasing :eng101:

Doc Block fucked around with this message at 02:01 on Dec 1, 2014

bobbilljim
May 29, 2013

this christmas feels like the very first christmas to me
:shittydog::shittydog::shittydog:

graph posted:

shut up nerds

chill out james

Doc Block
Apr 15, 2003
Fun Shoe
Apple Macintosh users: hold down Ctrl on the keyboard and then scroll up with your mouse or tragic mackpad. wheeee!

Now you can study the subpixel antialiasing of fonts! Yay!

Fanged Lawn Wormy
Jan 4, 2008

SQUEAK! SQUEAK! SQUEAK!
who was it that said the thing about wearing your big boy pants and pissing in them too that has made me chuckle all week

Balls-kun
Jun 29, 2010

Adbot
ADBOT LOVES YOU

Jonny 290
May 5, 2005



[ASK] me about OS/2 Warp

there's either a good dad or husband behind all this. or possibly not one at all

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply