Holding a push button for 3 second in a for loop - algorithm

I have a button that basically has two functions. The aim is:
First push will blink a LED 15 times.
If someone holds the button longer than 3 seconds while the LED is blinking, it should stop and go back to the initial.
So I checked the Arduino's hold a button page and came up with this code. The problem is that I can not properly stop the blinking. The line Serial.println("DONE!!"); never works.
Where should I check if the button is held or not and should I use interrupt to end the for loop?
Here is my code:
int inPin = 2; // the pin number for input (for me a push button)
int ledPin = 9;
int current; // Current state of the button
// (LOW is pressed b/c I'm using the pullup resistors)
long millis_held; // How long the button was held (milliseconds)
long secs_held; // How long the button was held (seconds)
long prev_secs_held; // How long the button was held in the previous check
byte previous = LOW;
unsigned long firstTime; // how long since the button was first pressed
long millis_held2; // How long the button was held (milliseconds)
long secs_held2; // How long the button was held (seconds)
long prev_secs_held2; // How long the button was held in the previous check
byte previous2 = LOW;
unsigned long firstTime2; // how long since the button was first pressed
void setup() {
Serial.begin(9600); // Use serial for debugging
pinMode(ledPin, OUTPUT);
digitalWrite(inPin, INPUT); // Turn on 20k pullup resistors to simplify switch input
}
void loop() {
current = digitalRead(inPin);
// if the button state changes to pressed, remember the start time
if (current == HIGH && previous == LOW && (millis() - firstTime) > 200) {
firstTime = millis();
}
millis_held = (millis() - firstTime);
secs_held = millis_held / 1000;
// This if statement is a basic debouncing tool, the button must be pushed for at least
// 100 milliseconds in a row for it to be considered as a push.
if (millis_held > 50) {
// check if the button was released since we last checked
if (current == LOW && previous == HIGH) {
// HERE YOU WOULD ADD VARIOUS ACTIONS AND TIMES FOR YOUR OWN CODE
// ===============================================================================
//////////////////////////////////////////////////////// Button pressed Blink 15 times.
if (secs_held <= 0) {
for (int i = 0; i < 15; i++) {
ledblink(1, 750, ledPin);
current = digitalRead(inPin);
if (current == HIGH && previous == LOW && (millis() - firstTime2) > 200) {
firstTime2 = millis();
}
millis_held2 = (millis() - firstTime2);
secs_held2 = millis_held2 / 1000;
if (millis_held2 > 50) {
Serial.print("previousA ");
Serial.print(previous);
Serial.print(" currentA ");
Serial.println(current);
current = digitalRead(inPin);
if (current == HIGH && previous2 == HIGH) {
Serial.println("ALMOST! ");
Serial.println(secs_held2);
if (secs_held2 >= 2 && secs_held2 < 6) {
Serial.println("DONE!!");
}
}
}
previous2 = current;
prev_secs_held2 = secs_held2;
}
}
}
}
previous = current;
prev_secs_held = secs_held;
}
void ledblink(int times, int lengthms, int pinnum) {
for (int x = 0; x < times; x++) {
digitalWrite(pinnum, HIGH);
delay (lengthms);
digitalWrite(pinnum, LOW);
delay(lengthms);
}
}

This is how it would be done without using delay():
int inPin = 2;
int ledPin = 9;
long pressTimer;
long blinkTimer;
long blinkHalfDelay = 500; //milliseconds
int blinkCount = 0;
int blinkLimit = 15;
bool blinkFlag = false;
bool blinkLatch = true;
bool currentBtnState = false;
bool lastBtnState = false;
void setup() {
}
void loop() {
lastBtnState = currentBtnState;
currentBtnState = digitalRead(inPin);
//on rising edge, start timers
if(currentBtnState==true && lastBtnState==false)
{
pressTimer = millis();
}
//debounce activation
if(currentBtnState==true && !blinkFlag && millis()-pressTimer > 50)
{
blinkTimer = millis();
blinkCount = 0;
blinkLatch = true;
blinkFlag = true;
//functional execution would go here
}
if(currentBtnState = false || (millis()-pressTimer>3000 && currentBtnState == true))
{
blinkCount=blinkLimit;
blinkLatch = false;
}
if(blinkFlag == true)
{
if(millis()-blinkTimer > blinkHalfDelay)
{
blinkTimer = millis();
if(blinkLatch)
{
digitalWrite(pinnum, HIGH);
}
else
{
digitalWrite(pinnum, LOW);
blinkCount+=1;
}
}
if(blinkCount>blinkLimit)
{
blinkFlag = false;
digitalWrite(pinnum, LOW);
}
}
}
ps: sorry for not correcting your code directly, but it was kinda hard to read...

Related

How do I turn off my void loop function after a certain IF condition is met? (arduino)

I am trying to make a simple burglar alarm using magnet value as my door. After pressing button1 it goes into countdown and then the user should be able to press button1 again to insert a 3 digit code with the help of pmeter. Except that after button1 is clicked it calls toggleOnOff() again. How do I block my void toggleOnOff() function after the conditions of the first IF statement are met? Thank you in advance.
int startMagnetValue;
int Code[3] = {1, 2, 3};
int userCode[3] = {0, 0, 0};
int secondsLimit = 20;
int countDown;
int pMeter = 0;
int pMin = 14;
int pMax = 948;
unsigned long time_now = 0;
unsigned long time_then = 0;
unsigned long seconds = 0;
unsigned long secondsbefore = 1;
unsigned long interval = 1000;
void setup() {
initializeBreadboard();
startMagnetValue = analogRead(MAGNETSENSOR);
}
//turns off leds
void turnOffLEDS() {
digitalWrite(LED_RED, LOW);
digitalWrite(LED_BLUE, LOW);
digitalWrite(LED_YELLOW, LOW);
digitalWrite(LED_GREEN, LOW);
}
// returns true when the difference is bigger than 50, returns false when it's less than 50. True meaning door is open and False meaning it is closed
bool isOpen(int magnetValue) {
int magnetValueDifference = abs(startMagnetValue - magnetValue);
if (magnetValueDifference <= 50) {
return true;
} else {
return false;
}
}
//Toggles the alarm On or Off
void toggleOnOff() {
isAlarmOn = !isAlarmOn;
delay(200);
}
//registers if the alarm is on or off, also prints current magnet value to the oled
void loop() {
pMeter = analogRead(POTENTIOMETER);
int currentMagnetValue = analogRead(MAGNETSENSOR);
pMeter = map(pMeter, pMin, pMax, 0, 9); //translates pmeter to simple digits
OLED.printBottom(pMeter);
Serial.println(userCode[1]);
//On Off
if (digitalRead(BUTTON1)) {
toggleOnOff();
}
// Door Open, Alarm On
if(isOpen(currentMagnetValue) && isAlarmOn) {
turnOffLEDS();
digitalWrite(LED_RED, HIGH);
OLED.printTop(secondsLimit);
time_now = millis();
while((time_now - time_then) >= 1000)
{ secondsLimit--;
time_then = time_now;
Serial.println(secondsLimit);
}
if (userCode[1] = 0) {
if (digitalRead(BUTTON1)) {
userCode[1] = pMeter;
}
}
if (userCode[2] = 0) {
if (digitalRead(BUTTON1)) {
userCode[2] = pMeter;
}
}
if (userCode[3] = 0) {
if (digitalRead(BUTTON1)) {
userCode[3] = pMeter;
}
}
if (Code == userCode) {
isAlarmOn = false;
}
if (secondsLimit <= 0) {
digitalWrite(BUZZER, HIGH);
turnOffLEDS();
while (secondsLimit <= 0) {
OLED.print("INTRUDER");
turnOffLEDS();
digitalWrite(LED_RED, HIGH);
delay(100);
turnOffLEDS();
digitalWrite(LED_BLUE, HIGH);
delay(100);
turnOffLEDS();
digitalWrite(LED_YELLOW, HIGH);
delay(100);
turnOffLEDS();
digitalWrite(LED_GREEN, HIGH);
}
}
} else if (isOpen(currentMagnetValue) && !isAlarmOn) {
turnOffLEDS();
digitalWrite(LED_BLUE, HIGH);
//Door closed, Alarm On
} else if (!isOpen(currentMagnetValue) && isAlarmOn) {
turnOffLEDS();
digitalWrite(LED_GREEN, HIGH);
//Door closed, Alarm Off
} else if (!isOpen(currentMagnetValue) && !isAlarmOn) {
turnOffLEDS();
digitalWrite(LED_YELLOW, HIGH);
}
}```

How to exit or break from 'for loop' on Arduino C Program

I'm not new to the programming world, but for last 2 weeks I'm working with Arduino C++. I have a strange problem. In general, I have a 7-segment display that will act as an up counter when the condition is 01, down counter when the condition is 10, 00 for reset to zero, and 11 for stop (pause in that number).
The problem is, when the up or down counter is still counting and I've change the state, the 7-segment is still counting! Besides that, I've printed the status of state when state is changed, but nothing happens. I think maybe there's mistakes in my code, I need some advice from you guys. Here is my code:
*FYI, I've try to use break, return, also call loop(), but nothing happens
*saklar1 = switch1
*saklar2 = switch2
#include <SevSeg.h>
SevSeg sevseg;
const int saklar1 = 2;
const int saklar2 = 3;
void setup() {
byte sevenSegments = 1;
byte commonPins[] = {};
byte sevenPins[] = {11, 10, 9, 8, 7, 6, 5, 4};
bool resistor = true;
sevseg.begin(COMMON_CATHODE, sevenSegments, commonPins, sevenPins, resistor);
sevseg.setBrightness(90);
pinMode(saklar1, INPUT);
pinMode(saklar2, INPUT);
Serial.begin(9600);
}
void loop() {
checking(digitalRead(saklar1), digitalRead(saklar2));
}
void checking(bool saklar1, bool saklar2){
if (saklar1 == LOW && saklar2 == LOW) {
setSevSeg(0);
} else if (saklar1 == LOW && saklar2 == HIGH) {
for (int i=0; i<=9; i++) {
setSevSeg(i);
if (saklar1 != LOW || saklar2 != HIGH) {
Serial.println("STATE CHANGED"); //THIS LINE IS NOT EXECUTED OR PRINTED
checking(digitalRead(saklar1), digitalRead(saklar2));
}
}
} else if (saklar1 == HIGH && saklar2 == LOW) {
for (int i=9; i>=0; i--) {
setSevSeg(i);
if (saklar1 != HIGH || saklar2 != LOW) {
checking(digitalRead(saklar1), digitalRead(saklar2));
}
}
} else if (saklar1 == HIGH && saklar2 == HIGH) {
delay(100); //Stop
}
}
void setSevSeg(int num) {
sevseg.setNumber(num);
sevseg.refreshDisplay();
delay(500); //1 detik
}
In the following code, the control exits the for loop when the sensor value exceeds the threshold.
Reference: [https://www.arduino.cc/reference/en/language/structure/control-structure/break]
int threshold = 40;
for (int x = 0; x < 255; x++) {
analogWrite(PWMpin, x);
sens = analogRead(sensorPin);
if (sens > threshold) { // bail out on sensor detect
x = 0;
break;
}
delay(50);
}

Arduino-uno project [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm currently working with an Raspberry Pi for a exercise.
I'm working with the following on the breadboard:
5 LED's
2 Switches
My following code is supposed to work as follows:
With the first button you can select the next LED and with the second button you can put the selected LED on/off. When you're at the last LED it gives a true or a false (on or off) with the following output:
Circuits
I don't see what's wrong with my code:
//const variables
const int leds[] = {3, 5, 6, 9, 11};
const int buttons[] = {12, 13};
//variables that will change
int buttonState[] = {false, false};
int lastButtonState[] = {false, false};
int values[] = {false, false, false, false};
void setup() {
//init LEDs
for(int i = 0; i < sizeof(leds); i++){
pinMode(leds[i], OUTPUT);
}
//init buttons
for(int i = 0; i < sizeof(buttons); i++){
pinMode(buttons[i], INPUT);
}
}
void loop() {
//fade when game starts
fade();
//start game
start();
//output of game
output();
}
void output(){
bool t1 = !values[0];
bool t2 = t1 && values[1];
bool t3 = values[2] || values[3];
bool Q = !(t2 || t3);
if(!Q){
digitalWrite(leds[4], true);
}else{
digitalWrite(leds[4], false);
}
}
void start(){
//total of leds
int j = 0;
//check if user is not at 5th led
while(j < 4){
//loop through buttons
for(int i = 0; i < 2; i++){
// Read button
buttonState[i] = digitalRead(buttons[i]);
// check button state
if (buttonState[i] != lastButtonState[i]) {
// if the state has changed
if (buttonState[i] == HIGH) {
//check if button 1
if(i == 0){
//select next LED
j++;
}
//else button 2
else{
// if the current state of the 2nd button is HIGH
while(i == 1){
//if current value of led is false, put it true
if(values[j] == false){
//put led on
digitalWrite(leds[j], true);
values[j] = true;
delay(50);
}else{
//put led off
digitalWrite(leds[j], false);
delay(50);
values[j] = false;
}
//go back to button 1?
i = 0;
}
}
//go back to button 1?
i = 0;
}
}
// save the current state as the last state,
// for next time through the loop
lastButtonState[i] = buttonState[i];
// wait a little
delay(50);
}
}
}
void fade(){
//put every led on half-on
for(int i = 0; i < sizeof(leds); i++){
analogWrite(leds[i], 100);
}
}
In C and C++, if you want to compare two values to check if they are equal, you have to use == (the comparison operator) instead of = (the assignment operator). You accidentily use the wrong operator here:
while(i = 1){
And here:
if(values[j] = false){
Change those to ==.

How to pause frame rate to display a frame rate dependent variable

Im trying to display my score in a 2d sidescrolling videogame im making in processing. The problem is that my Score is dependent on the Framecount and after the character dies I want to display the score enlarged across the screen. The way my program works is that after the collision occurs a counter is set to a specific Number (100), each loop that counter will decrease and once it hits a certain number the program will restart. My Idea was to display the score in the time between collision and the program restarting. My Problem is that the Score will keep increasing, since the program is still running. Any Ideas on how I could solve this? I tried pausing the draw loop but that doesn't work since the game wont resume again. Thanks a lot for your help.
Here is my Score class:
public class Score {
private PFont font;
private int x, y;
private PImage img;
//constructor
public Score ( int x, int y, PFont font) {
this.x = x;
this.y = y;
this.font = font;
}
public void draw () {
Scorevar = frameCount/20;
textFont(font);
fill (0);
//textAlign(CENTER);
textMode(MODEL);
text("Score = "+ Scorevar, x, y);
}
}
Here is the part of my main loop which involves the score
void draw() {
background (255);
chari.draw();
//collision and collison image
if ( collide_count == 0 ) {
chari.draw();
}
else {
image( collide, chari.x+130, chari.y+100 );
collide_count--;
}
if ( collide_count > 5 && collide_count < 80) {
score2.draw();
}
if ( collide_count == 5) {
frameCount = 0;
setup();
}
blockfield.draw();
score1.draw();
}
Code for collision :
public void update(float cY, float cW) {
for ( int i =frameCount/200; i >0; i--) {
//for (int i =frameCount/400; i >0; i--) {
//moves blocks right to left
block[i].x -=(frameCount/200);
//spawns block when they leave the screen
if (block[i].x < -Blockpic.width) {
block[i].setX( random(width, width*2));
block[i].setY( random (height));
//println(block[i].x + " " + block[i].y);
}
if (block[i].x < 130) {
if(block[i].y > cY && block[i].y < (cY+cW)){
//println(collide_count + " with");
collide_count = 100;
}
}
}
}
Just save the score value into a separate variable. Then use that variable to set the score for the death screen.
I introduced a new Boolean called finished, which was set to false by default and to true during collision.
if (block[i].x < 130) {
if(block[i].y > cY && block[i].y < (cY+cW) && !finished){
//println(collide_count + " with");
collide_count = 80;
finished = true;
currentCount = frameCount/20;
}
In the collison i set currentCount= Framecount and let the score be printed when finished == true.
public void draw () {
Scorevar = frameCount/20;
textFont(font);
fill (0);
//textAlign(CENTER);
textMode(MODEL);
if ( finished == true) {
text("Score = "+ currentCount, x, y);
}
else {
text("Score = "+ Scorevar, x, y);
}
}
Thanks alot again!

Read byte from Serial

I´ve made this program that reads info from serial and writes the value binary to 6 LEDs. I don´t feel that it´s the easiest or the fastest way though and that is what I´m really looking for. My code looks like this:
boolean enable = false;
void setup()
{
for (int i = 2; i < 8; i++)
{
pinMode(i, OUTPUT);
}
}
void loop()
{
if (Serial.available() > 0)
{
enable = true;
}
if (enable)
{
while (Serial.available() > 0)
{
byte b = Serial.parseInt();
b = constrain(b, 0, 63);
byte val = b;
for (int i = 7; i >= 2; i--)
{
if (pow(2, (i-2)) <= val)
{
digitalWrite(i, HIGH);
val -= pow(2, (i-2));
}
else
{
digitalWrite(i, LOW);
}
}
}
enable = false;
}
delay(100);
}
A valid code example would be nice. I´ve tried using PORTD but it does not work.
Use binary operations
for(int i = 0 ; i < 8 ; i++ ) {
val = ( b >> i ) & 0x1;
digitalWrite(i, val == 1 ? HIGH : LOW );
}
If you plan some serious serial communication have a look into library I created https://github.com/lukaszkujawa/arduino-serial-helper

Resources