I am building a number numpad using 3 different capacitive touch sensor. So my function will be to label each the 3 touch sensors with a different number to create a password system.
However i realised that whenever i try to press the button to key in the number, for example the button tagged with number "3", multple values of 3 came out even though i only pressed once. Is there any function on arduino that i can use so that it only generate 1 results with 1 press instead of multiple results in a press.
Is there anyway to change my code such that i can create some sort of debounce for each button so that when i press the button once only 1 result will be shown.
Would appreciate an edit on my code, thanks!
#include <LiquidCrystal.h>
#include <CapacitiveSensor.h>
CapacitiveSensor cs_2_3= CapacitiveSensor(2,3);
CapacitiveSensor cs_2_4= CapacitiveSensor(2,4);
CapacitiveSensor cs_2_5= CapacitiveSensor(2,5);
int pos=0;
LiquidCrystal lcd(A0,A1,A2,A3,A4,A5);
char pass[]= "321";
int currentposition=0;
char code=0;
void setup() {
cs_2_3.set_CS_AutocaL_Millis(0xFFFFFFFF);
lcd.setCursor(0,0);
lcd.println("Enter Password: ");
Serial.begin(9600);
lcd.begin(16,2);
}
void loop() {
long total1= cs_2_3.capacitiveSensor(100);
long total2=cs_2_4.capacitiveSensor(100);
long total3= cs_2_5. capacitiveSensor(100);
if(total1>=1000)
{
code= '1';
}
if(total2>=1000)
{
code= '2';
}
if(total3>=1000)
{
code='3';
}
delay(100);
if(currentposition==0)
{
lcd.setCursor(0,0);
lcd.println("Enter Password: ");
}
int lu ;
if(code!=0)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("PASSWORD:");
lcd.setCursor(7,1);
lcd.print(" ");
lcd.setCursor(7,1);
for(lu=0;lu<=currentposition;++lu)
{
lcd.print(code);
delay(25);
}
if (code==pass[currentposition])
{
++currentposition;
if(currentposition==3)
{
delay(900);
lcd.setCursor(0,0);
lcd.println(" ");
lcd.setCursor(1,0);
lcd.print("Correct Password");
lcd.setCursor(4,1);
lcd.println("HELLO!!");
lcd.setCursor(15,1);
lcd.println(" ");
lcd.setCursor(16,1);
lcd.println(" ");
lcd.setCursor(14,1);
lcd.println(" ");
lcd.setCursor(13,1);
lcd.println(" ");
delay (5000);
lcd.clear();
lcd.setCursor(0,0);
lcd.println("Enter Password: ");
}
}
else
{
delay(500);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("PASSWORD");
lcd.setCursor(6,0);
lcd.print("INCORRECT");
lcd.setCursor(15,1);
lcd.println(" ");
lcd.setCursor(4,1);
lcd.println("GET AWAY!!!");
code=0;
lcd.setCursor(13,1);
lcd.println(" ");
delay(3000);
currentposition=0;
lcd.clear();
lcd.setCursor(0,0);
lcd.println("Enter Password: ");
}
}
}
Just debounce it like any other button. Only accept signal changes longer then a certain time.
From https://www.arduino.cc/en/tutorial/debounce
/*
Debounce
Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's a
minimum delay between toggles to debounce the circuit (i.e. to ignore noise).
The circuit:
- LED attached from pin 13 to ground
- pushbutton attached from pin 2 to +5V
- 10 kilohm resistor attached from pin 2 to ground
- Note: On most Arduino boards, there is already an LED on the board connected
to pin 13, so you don't need any extra components for this example.
created 21 Nov 2006
by David A. Mellis
modified 30 Aug 2011
by Limor Fried
modified 28 Dec 2012
by Mike Walters
modified 30 Aug 2016
by Arturo Guadalupi
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Debounce
*/
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// Variables will change:
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
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
// set initial LED state
digitalWrite(ledPin, ledState);
}
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}
You could use INPUT_PULLUP like this:
void setup() {
pinMode(pin, INPUT_PULLUP)
}
But since your using i library this may be an issue.
You could simply use the delay() function, as stated here: https://www.brainy-bits.com/arduino-switch-debounce/
This might be the fastest and simplest way to do it.
Debouncing the button will help - Adafruit got something especially on this topic: https://learn.adafruit.com/make-it-switch/debouncing
But for a quick and dirty solution delay() will do.
Related
I am currently troubleshooting a code in Arduino for a temperature and humidity project. There is a line in the void setup(), Serial.println("Feather LoRa TX Test!");, which keeps popping up. My ideal code is to run that particular line once in the output and that will be it. However, the current code keeps repeating that line again, and again. May I know how do I rectify this issue (The whole code is below)? Thanks in advance!!
#include <RH_RF95.h>
#include <DHT.h>
#define DHTPIN 7 // what digital pin we're connected to
#define DHTTYPE DHT22 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
#define RFM95_CS 10
#define RFM95_RST 9
#define RFM95_INT 3
// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 915.0
// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);
int node = 3; // to change based on node deployment
void setup()
{
pinMode(RFM95_RST, OUTPUT);
digitalWrite(RFM95_RST, HIGH);
while (!Serial);
Serial.begin(9600);
delay(100);
Serial.println("Feather LoRa TX Test!");
digitalWrite(RFM95_RST, LOW);
delay(100);
digitalWrite(RFM95_RST, HIGH);
delay(100);
while (!rf95.init()) {
Serial.println("LoRa radio init failed");
while (1);
}
Serial.println("LoRa radio init OK!");
// Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
if (!rf95.setFrequency(RF95_FREQ)) {
Serial.println("setFrequency failed");
while (1);
}
Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
dht.begin();
rf95.setTxPower(23, false);
}
void loop()
{
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
delay(1000);
return;
}
String d = "{\"Node\":"+ String (node) +",";
d += "\"Temp\":"+ String (t)+",";
d += "\"Hum\":"+ String (h);
d += "} "; // Add a trailing space is necessary
Serial.println("Transmitting...");
char data[d.length()];
d.toCharArray(data,d.length());
Serial.println(d);
rf95.send((uint8_t*)data, sizeof(data));
Serial.println("Waiting for packet to complete...");
delay(1000);
rf95.waitPacketSent();
Serial.println(" complete...");
delay(57000); // delay 1 minute
}
You have an infinite loop before you do any initialization. This will be detected because Arduino have a watchdog timer, and the system will reset.
And on reset setup is called again, and you again enter the infinite loop.
The loop it's about:
while (!Serial);
You must call Serial.begin(...) before that loop:
Serial.begin(9600);
while (!Serial);
Something is resetting your MCU before the code reaches the loop function. Therefore the setup function gets executed again and again. You can add more print messages in between lines so you'll know where it breaks.
I cannot explain to myself why this code works properly in some cases and in some not. Here is the situation:
I am trying to switch a relay with the Arduino Nano. Therefore I took the "Blink" example as a guide. It should switch on for like 5 minutes and switch off for like 25 minutes. Here is the code:
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
pinMode(2, OUTPUT); // sets PIN 2 as switcher for the relay
}
// the loop function runs over and over again forever
void loop() {
int count = 0;
int run_pump = 300; // 5 Min run
int stop_pump = 1500; // 25 Min stop
digitalWrite(LED_BUILTIN, LOW); // turn the LED off (HIGH is the voltage level)
digitalWrite(2, HIGH); // turn the pump on
while(count < run_pump) {
count++;
delay(1000); // wait for a second
}
count = 0;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on by making the voltage LOW
digitalWrite(2, LOW); // turn the pump off
while(count < stop_pump) {
count++;
delay(1000); // wait for a second
}
}
if I run this code on the Arduino it will just switch on the relay forever. BUT: If I set run_pump and stop_pump for like 10 sec. it will work properly! Is there an explanation why this does not work with the bigger counters? It's so confusing....
so this code here works absolutely fine, but why does the code above not?
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
pinMode(2, OUTPUT); // sets PIN 2 as switcher for the relay
}
// the loop function runs over and over again forever
void loop() {
int count = 0;
int run_pump = 5; // 5 sec run
int stop_pump = 10; // 10 sec stop
digitalWrite(LED_BUILTIN, LOW); // turn the LED off (HIGH is the voltage level)
digitalWrite(2, HIGH); // turn the pump on
while(count < run_pump) {
count++;
delay(1000); // wait for a second
}
count = 0;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on by making the voltage LOW
digitalWrite(2, LOW); // turn the pump off
while(count < stop_pump) {
count++;
delay(1000); // wait for a second
}
}
Hope someone has a clue.... Thanks!
Tom
OK guys, I solved it. The problem was a cheap relay that was trying to communicate with the Arduino... Replacing it with a better one solved the whole problem. Thanks for the idea with the LED, this brought some stones to roll... :)
I'm just learning Arduino and i've got a DC Motor & IR Receiver connected. It's working fine if i press the button once but i can't figure out how to keep the motor spinning if i hold the button down as the REPEAT command is the same numbers.
I figured i would store the last code sent and check if the repeat command and last code match but it doesn't seem to be working and can't figure out why.
#include <IRremote.h>
int IRpin = 11; // pin for the IR sensor
IRrecv irrecv(IRpin);
decode_results results;
int lastCode;
void setup() {
// put your setup code here, to run once:
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(13, OUTPUT);
Serial.begin(9600);
irrecv.enableIRIn(); // Enable IR Receiver.
}
void loop() {
// put your main code here, to run repeatedly:
if
(irrecv.decode(&results)) {
Serial.println(results.value);
irrecv.resume();
Serial.println("Last Code is set to: ");
Serial.write(lastCode);
if(results.value== 16748655 || (results.value== 4294967295 && lastCode== 16748655)) // Your ON button value
{
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
analogWrite(9, 255);
delay(1000);
analogWrite(9, 0);
lastCode= 16748655;
}
else if(results.value == 16769055 || (results.value== 4294967295 && lastCode== 16769055)) // Your OFF button value
{
digitalWrite(8, LOW);
digitalWrite(7, HIGH);
analogWrite(9, 255);
delay(1000);
analogWrite(9, 0);
lastCode= 16769055;
}
}
}
A more reliable approach to running the motor until the button is released is to use a "no-code" timeout. That is, if the "no code" state persists for a period longer than the auto-repeat period, then it has been released.
It is not clear in your code what the 1 second analogue pulse is for, but placing long delays in your loop() function makes your system far less responsive. Better to poll the system tick and "do stuff" when it is time to do so. Also magic numbers should be avoided if you want anyone to understand your code and avoid errors in maintenance.
The following uses system tick polling to implement the "no-code" timeout. I have omitted the motor on/off code because it is not clear what you are doing there with the 1 second delays.
#define NO_CODE 0xFFFFFFFFul
#define MOTOR_ON_CODE 0xFF906Ful
#define MOTOR_OFF_CODE 0xFFE01Ful
#define STOP_TIME_MS 250ul // stop after button release for 250ms
void loop( )
{
static unsigned long last_on_time = 0 ;
if( irrecv.decode( &results ) )
{
irrecv.resume() ;
unsigned long code = results.value ;
// If motor off code or no code timeout...
if( code == MOTOR_OFF_CODE ||
(code == NO_CODE && millis() - last_on_time > STOP_TIME_MS) )
{
// Motor off
...
}
else if( code == MOTOR_ON_CODE )
{
// Continuously update last on time while button is held
last_on_time = millis() ;
// Motor on
...
}
}
}
I have included response to the motor-off code, but that may not be necessary, since the motor will be switched off 250ms (or whatever time you choose) after the ON button is released in any case. You might instead have a forward/reverse button and release either to stop:
#define NO_CODE 0xFFFFFFFFul
#define MOTOR_FWD_CODE 0xFF906Ful
#define MOTOR_REV_CODE 0xFFE01Ful
#define STOP_TIME_MS 250ul // stop after button release for 250ms
void loop( )
{
static unsigned long last_on_time = 0 ;
if( irrecv.decode( &results ) )
{
irrecv.resume() ;
unsigned long code = results.value ;
switch( code )
{
case NO_CODE :
{
if( millis() - last_on_time > STOP_TIME_MS )
{
// Motor off
...
}
}
break ;
case MOTOR_FWD_CODE :
{
// Continuously update last on time while button is held
last_on_time = millis() ;
// Motor forward
...
}
break ;
case MOTOR_FWD_CODE :
{
// Continuously update last on time while button is held
last_on_time = millis() ;
// Motor reverse
...
}
break ;
}
}
}
Note: The code is designed to run on a Particle Photon. Please keep this in mind while reading my question.
I want to make a led blink based on a variable called blink_type this variable will be changed dynamically in a later stage when I implement the API call to fetch the status of something else. I'm currently simulating this behaviour in the loop() function (also tried a thread but that also didn't work).
The blinking works fine until the variable changes from 0 to 1, after that it never blinks again until I do a reset.
Below you will find my code:
// This #include statement was automatically added by the Particle IDE.
#include <httpsclient-particle.h>
// Base variables.
int led = D0;
int buzzer = D1;
// Defining blink types. 0 is normal, 1 is breathe.
int blink_type = 0;
// Set the threads
Thread *normalBlinkThread;
Thread *ledBreatherThread;
void setup() {
// Setup the outputs.
pinMode(led, OUTPUT);
pinMode(buzzer, OUTPUT);
// Create the required threads.
normalBlinkThread = new Thread("rest_status_light", normalBlink);
ledBreatherThread = new Thread("rest_status_light", hearthBeatBlink);
}
os_thread_return_t normalBlink(void*) {
// Start never ending loop
for(;;) {
if(blink_type == 0) {
// Blink led
digitalWrite(led, HIGH);
delay(3000);
digitalWrite(led, LOW);
delay(3000);
}
}
}
os_thread_return_t hearthBeatBlink(void*) {
// Start never ending loop
for(;;) {
if(blink_type == 1) {
// Blink led
digitalWrite(buzzer, HIGH);
delay(500);
digitalWrite(buzzer, LOW);
delay(500);
digitalWrite(buzzer, HIGH);
delay(500);
digitalWrite(buzzer, LOW);
delay(3000);
}
}
}
void loop() {
delay(10000);
switch (blink_type) {
case 0:
blink_type = 1;
break;
case 1:
blink_type = 0;
break;
}
}
To not get confused, the "buzzer" output (D1) is currently also wired to an LED.
If there would be a better approach to blink a led in two different ways based on a dynamic variable I'm happy to adopt to this sollution!
normalBlink() and hearthBeatBlink() have delays only when (blink_type == 1). When blink_type becomes 0 there are no delays in the for loops and one of them, the first which evaluates the variable change, happily spins for eternity. Try to add a small delay in the case blink_type is 0. Hope this helps!
Here is my code. It compiles and runs on my Arduino MEGA 2560.
#include "Arduino.h"//Standard Arduino Library
#include "Print.h" //Print to serial library, Serial.Println would not work by default for some reason.
#define led_pin 13 //Set var led_pin to equal 13, meaning pin 13
#define pinstate digitalRead(read_pin)
#define read_pin 50 // " 50, "50
int loopstore; //Def as global var so it won't be reset on next loop iteration
void setup() //Setup function, used to set pins and vars before running main Arduino Program
{
Serial.begin(9600); //Start serial comms, set baud rate
Serial.println("\nHello User.\n\nArduio has set baud rate and started serial communication.\n\nThank You, Sketch will run momentarily.\n\n");
pinMode(led_pin,OUTPUT); //Set led_pin to digital output mode;
pinMode(read_pin,INPUT); //", " read mode
}
void loop() //Actual program
{
loopstart = 1;
do
{
++loopstore;
} while (loopstart == 0);
Serial.println("This program has ran this many times:\n");
Serial.println(loopstore);
digitalWrite(led_pin,HIGH); //Set pin high
delay(1000); //Wait
if (pinstate == 1) //If else statement for outputting pin state to console
{
Serial.println("\nPin is in a HIGH state\n\n"); // Output to console
}
else
{
Serial.println("Pin is in a LOW state\n\n"); // Output to console
}
delay(1500); //Wait
digitalWrite(led_pin,LOW); //Set pin to Low State
delay(1000); //Wait
if (pinstate == 1) //If else funct for outputting pin state to console
{
Serial.println("Pin is in a HIGH state\n\n"); // Output to console
}
else
{
Serial.println("Pin is in a LOW state\n\n"); // Output to console
}
delay(1000); //Wait
digitalWrite(led_pin,HIGH); //Set pin high
delay(1500); //Wait
if (pinstate == 1) //If else funct for outputting pin state to console
{
Serial.println("Pin is in a HIGH state\n\n"); // Output to console
}
else
{
Serial.println("Pin is in a LOW state\n\n"); // Output to console
}
delay(1000); //Wait
digitalWrite(led_pin,LOW); //Set pin to Low State
delay(1500); //Wait
if (pinstate == 1) //If else funct for outputting pin state to console
{
Serial.println("Pin is in a HIGH state\n\n"); // Output to console
}
else
{
Serial.println("Pin is in a LOW state\n\n"); // Output to console
}
delay(1000); //Wait
digitalWrite(led_pin,HIGH); //Set pin high
delay(500); //Wait
if (pinstate == 1) //If else funct for outputting pin state to console
{
Serial.println("Pin is in a HIGH state\n\n"); // Output to console
}
else
{
Serial.println("Pin is in a LOW state\n\n"); // Output to console
}
delay(1000); //Wait
digitalWrite(led_pin,LOW); //Set pin to Low State
delay(500); //Wait
if (pinstate == 1) //If else funct for outputting pin state to console
{
Serial.println("Pin is in a HIGH state\n\n"); // Output to console
}
else
{
Serial.println("Pin is in a LOW state\n\n"); // Output to console
}
}
I'm just learning to work with Arduino and I made a quick and dirty program that simply sets the pin state of the LED pin on the Arduino (13) and then reads it with pin 50. It's a pointless program but I'm trying to learn/practice.
For extra practice I also made a counter for the amount of times the loop() function runs.
The "Do While" statement I made increments the counter. Then I print the result to serial afterwards. See that if loopstart == 0, the "Do While" statement runs again. This is impossible because it never gets set to 0. I wanted a sort of "passthrough" counter, but is this the best way?
I am almost positive there has to be a way to do what I did above more efficiently, but being new to Arduino (and programming in general), I have no idea how I would be able to simplify this.
Anybody have any suggestions or perhaps a place where they could point me to?
I've tried looking online for examples of a counter in C++, but I couldn't find anything that was outside of a "For" loop.
Thank you for your time and helping a kid learn!
Edit: Did not know about CodeReview. Thanks!
Maybe something like that can best suit you.
If I understand correctly your program basically toggle 3 times the led and then check for the pin state with a delay before and after (which is variable).
If you want me to detail some more parts, ask me I will edit my post ;)
#include "Arduino.h"//Standard Arduino Library
#include "Print.h" //Print to serial library, Serial.Println would not work by default for some reason.
// Some debugging macros
#define DEBUG 1
#define slog(a) { if (DEBUG) Serial.println(a); }; // No debug directive will be in compiled file if DEBUG is set to 0
// Let's define our port mapping
#define LED_PIN _BV(7) //bit 7 on PORTB on 2560 correspond to digital pin 13 (check http://arduino.cc/en/Hacking/PinMapping2560)
#define READ_PIN _BV(3)
// Some quick access for led pin / read pin manipulation
// Let's use bitwise operation on PORTB, digitalRead => 28 cycle, direct read with PORTB => 1 cycle (28x faster!)
// I prefer defining setters as functions, easier to read, but you are not force to (it is exactly the same once compiled)
//#define LED_ON() { PORTB |= LED_PIN; } // Put LED_PIN bit to 1 on PORTB
//#define LED_OFF() { PORTB &= ~LED_PIN; } // Put LED_PIN bit to 0 on PORTB
#define LED_TOGGLE() { PORTB ^= LED_PIN; } // Put LED_PIN bit to 0 if it was 1 or to 1 if it was 0
#define READ_STATE PORTB & READ_PIN // Read LED_PIN bit on PORTB
int loopcount = 0; //Def as global var so it won't be reset on next loop iteration
// Let's create an array which will define all the delays before and after serial calls
// ex: {1000, 1500} => 1000ms before serial output, 1500ms after serial output
int wrapDelays[][2] = { {1000, 1500}, {1000, 1000}, {1500, 1000}, {1500, 1000}, {500, 1000}, {500, 0} };
void setup() //Setup function, used to set pins and vars before running main Arduino Program
{
if (DEBUG) Serial.begin(9600); //Start serial comms, set baud rate
slog("\nHello User.\n\nArduio has set baud rate and started serial communication.\n\nThank You, Sketch will run momentarily.\n\n");
// Output/Input for PORTB (in DDRB register)
DDRB |= LED_PIN; // Set LED_PIN to digital output mode (put LED_PIN bit to 1)
DDRB &= ~READ_PIN; // Ensure READ_PIN is in input mode (put READ_PIN bit to 0)
}
// ToggleLed, write read pin state on serial, and wait `delayBefore`ms before and `delayAfter`ms after
void toggleLedBetweenDelays(int delayBefore, int delayAfter){
LED_TOGGLE();
if (delayBefore > 0) delay(delayBefore);
if (READ_STATE) {//If else funct for outputting pin state to console
slog("Pin is in a HIGH state\n\n"); // Output to console
}
else
slog("Pin is in a LOW state\n\n"); // Output to console
if (delayAfter > 0) delay(delayAfter);
}
void loopCounter(){
loopcount++; // increase count of loops
slog("This program has ran this many times:\n");
slog(loopcount);
}
void loop() //Actual program
{
for (int i = 0, l = sizeof(wrapDelays) / sizeof(wrapDelays[0]); i < l; ++i)
{
toggleLedBetweenDelays(wrapDelays[i][0], wrapDelays[i][1]);
}
loopCounter();
}
Note: Don't forget that it's not because the code you write is smaller that the final compiled binary will also be smaller/optimized.