Small description for you... Using arduino uno I am trying to make it so I press a button to switch on the entire program, not hold down press but press and let it release to make it on then do it again to make it off. While its on it needs to output data given from a LDR every 1 second.
Anyway, in the serial monitor (output of data) I want it to say "off" to start with then say "on" after the button is pressed. I have gotten this far.
My problem is when it is on, i cant figure out how to make it display the LDR light sense amount each second while also testing that if it goes over 500 for example, it should then stop and say alarm triggered. And be able to be switched off after also.
Here is my code:
// Devices attached
const int buttonPin = 2; // Pin that BUTTON uses
const int sensorPin = 0; // Pin that SENSOR uses
// List of dynamic variables
int pushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastbuttonState = 0; // previous state of the button
void setup()
{
// Set the BUTTON as an INPUT
pinMode(buttonPin, INPUT);
// Create serial prompt
Serial.begin(9600);
}
void loop()
{
// read the pushbutton current state
buttonState = digitalRead(buttonPin);
// compare the buttonState to its previous state
if (buttonState != lastbuttonState)
{
// if the state has changed, increment the counter
if (buttonState == HIGH)
{
// if the current state is HIGH then the button
// wend from off to on:
pushCounter++;
int sensorValue = 0;
// Divides counter by 2, if remainder (not0), then the following
if (pushCounter % 2 == 0){
analogWrite(sensorPin, HIGH);
Serial.println("Power ON");
sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);
delay(1000);
}
else
{
analogWrite(sensorPin, LOW);
Serial.println("OFF");
}
// Debouncing delay
delay(250);
}
// Save the current BUTTON state as the LAST state
lastbuttonState = buttonState;
}
}
Your requirement seems to be a question of task multithreading. It is not possible in bare arduinos. The arduino is single threaded.
analogRead() does not set the pin to be readable, but it returns the value in that pin.
Use analog A0 instead of digital pin 0
const int sensorPin = A0; // Pin that SENSOR uses
boolean isOn = false;
int sensorValue = 0, pinValue = 0;
void loop()
{
buttonState = digitalRead(buttonPin);
if(buttonState != lastbuttonState && buttonState == HIGH) {
pushCounter++;
lastbuttonState = buttonState;
}
if (pushCounter % 2 == 0){
Serial.println("Power ON");
isOn = true;
} else {
Serial.println("OFF");
isOn = false;
}
if(isOn) {
pinValue = analogRead(sensorPin);
Serial.println(pinValue);
if(pinValue > 500) { Serial.println("Alarm triggered"); }
delay(1000);
}
}
Related
The basic logic of my game is:
the player goes from random room to random
there is a set of rooms that randomly repeat
each room he passes the counter goes up
he has a button where he can signal, if he goes through a room that he already passed
if a room repeats and he presses the button, he goes to the next random room and the counter goes up
if a room repeats and he didnt notice, he is set back to the unnoticed room and the counter goes back to the repeating room
The result of the following code is, that the room doesnt change at all, when he reaches the trigger at the end of the room. But there are no compiler errors.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class RoomHandler : MonoBehaviour
{
public List<Vector2> PassedRoomsAndCounter;
Vector2 roomAndCounter;
int roomCounting = 1; //position in ascending order
int roomNumber = 1; //unique number of current room
bool RepetitionWasSignaled;
float CountOfRepeatedRoom;
void Update()
{
//Has Repetition button been pressed?
bool InputRepetition = Input.GetButtonDown("Submit");
if(InputRepetition == true){
RepetitionWasSignaled = true;
}
}
void OnTriggerEnter2D(Collider2D col){
print("Trigger "+col.gameObject.name);
//collided with Scene Trigger?
if(col.gameObject.tag == "SceneTrigger"){
roomCounting++;
roomNumber = Random.Range(1,6);
roomAndCounter = new Vector2(roomNumber,roomCounting);
print(roomAndCounter);
PassedRoomsAndCounter.Add(roomAndCounter);
for(int i = 1; i < PassedRoomsAndCounter.Count; i++) { //Go throught all entries
if(PassedRoomsAndCounter[i].x == roomNumber){ //RoomNumber already passed?
if(RepetitionWasSignaled == true){ //Repetition Button pressed?
SceneManager.LoadScene(roomNumber); //Yes - go to next normal room
}else{
CountOfRepeatedRoom = PassedRoomsAndCounter[i].y;
SceneManager.LoadScene(CountOfRepeatedRoom.ToString());
}
}else{
SceneManager.LoadScene(roomNumber);
}
}
}
}
}
I'm a first semester software student and for a course I am exploring the world of C++ and Arduino (UNO in my case).
My assignment is to make a timer counting down from 10 minutes (shown on a 4 digit display).
The thing I struggled with is how to program a pause functionality on the same button (btnOne) that also starts the timer. When I finally discovered how, I noticed something buggy: the delay() might be causing some trouble. See my code for implementation.
When clicking on the start/pause button the button doesn't immediately register it. Possibly because the delay might be blocking the communication of user input to the button.
The delay (of 1 second) is used to limit the execution of the if-statement in timer() to once per second; like a timer.
My question is: how can I improve my code so that the clicks on btnOne are immediately registered?
Thanks so much in advance.
const int btnOne = 8;
const int btnTwo = 9;
int btnOn = LOW;
int btnOff = HIGH;
const int clockPin = 10;
const int dataPin = 11;
const int buzzer = 3;
int btnOneState = 0;
int btnTwoState = 0;
long time = 600000;
long timeValueState = time;
int timerDisplay = 1000;
bool pause = true;
void setup()
{
Serial.begin(9600);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(btnOne, INPUT_PULLUP);
pinMode(btnTwo, INPUT_PULLUP);
pinMode(buzzer, OUTPUT);
}
void timer() {
// Count down from 600000 to 0
if (timeValueState >= 600 ) {
timeValueState = timeValueState - 600;
Display.show(--timerDisplay);
// When reached last count, display is set to 0 and buzzer turns on for 5 seconds
if (timeValueState == 600) {
Display.show(timerDisplay == 0);
tone(buzzer, 200);
delay(5000);
noTone(buzzer);
}
Serial.println("time:");
Serial.println(timeValueState);
delay(1000);
}
}
void loop()
{
btnOneState = digitalRead(btnOne);
btnTwoState = digitalRead(btnTwo);
// If button is on, change state of pause (true, false)
if (btnOneState == btnOn) {
Serial.println("btnOne pressed");
pause = !pause;
}
// When button is off and pause is not true, activate the timer
else if (btnOneState == btnOff && pause == false) {
Serial.println("btnOne NOT pressed");
timer();
}
// Reset time and timerDisplay back to 10 minutes.
if (btnTwoState == btnOn) {
Serial.println("btnTwo pressed");
timeValueState = time;
Display.show(timerDisplay = 1000);
}
}
I won't give you code so you learn more.
You can run a loop that checks the return value of millis vs a timestamp stored in a variable, when you started. Every 1000 milliseconds you update your display.
That way you don't block your code for 1 second.
This should serve as a good starting point for further research.
I made a code where, for every time I press the button, it plays the next note in the song. But the problem is, for some reason it keeps skipping the same notes in the array.
For example (my code):
int mariomelody[] = {
NOTE_E5, NOTE_E5, NOTE_E5, NOTE_E5, NOTE_C5, NOTE_E5, NOTE_G5, NOTE_G4,
//THERE ARE TWO 'NOTE_E5's BECAUSE THE THIRD NOTE DOESNT PLAY
NOTE_C5, NOTE_G4, NOTE_E4, NOTE_A4, NOTE_B5, NOTE_AS4, NOTE_A4,
NOTE_G4, NOTE_E5, NOTE_G5, NOTE_A5, NOTE_F5, NOTE_G5, NOTE_E5,
NOTE_C5, NOTE_D5, NOTE_B4,
//buttonPin sits at DIG. 12
int buttonPin = 12;
void setup()
{
// put your setup code here, to run once:
pinMode(buttonPin, INPUT);
}
void loop()
{
// put your main code here, to run repeatedly:
for (int i = 0; i < sizeof(mariomelody) / sizeof(mariomelody[0]); i++)
{
while (digitalRead(buttonPin) == HIGH)
{
tone(8, mariomelody[i], 20);
}
while (digitalRead(buttonPin) == LOW)
{
}
}
Everybody knows the mario melody right. The first three notes are the same at different speeds (4 is half the speed of 8); E(4) E(4) E(8). For some reason it just skips the third NOTE_E5 so I just put another NOTE_E5 there and now it works "just fine".
Does anybody know why it skips the notes? Is it my code?
I don't know the mario melody, but anyway I think your code is wrong:
Try this:
void loop()
{
for (int i = 0; i < sizeof(mariomelody) / sizeof(mariomelody[0]); i++)
{
while (digitalRead(buttonPin) == LOW)
{
// wait until button is pressed
}
tone(8, mariomelody[i], 20);
while (digitalRead(buttonPin) == HIGH)
{
// wait until button is released
}
}
}
What would be the best way of counting how many times a bool flag was changed from false to true inside a game update loop? For example if I have this simple example below, where if you hold button "A" pressed the Input class sets the enable bool of the Game class to true and if you release it sets it to false and a counter inside the Game class that counts how many times enable was changed from true to false. For example if you press "A" and release twice counter should update to 2. Having Game::Update() updating at 60fps the counter would be wrong with the current approach. To fix it I moved the check and the counter inside SetEnable instead of the Update loop.
// Input class
// Waits for input
void Input::HandleKeyDown()
{
// Checks if key A is pressed down
if (key == KEY_A)
game.SetEnable(true);
}
void Input::HandleKeyUp()
{
// Checks if key A is released
if (key == KEY_A)
game.SetEnable(false);
}
// Game class
void Game::SetEnable(bool enable)
{
if(enable == enable_)
return;
enable_ = enable;
//Will increment the counter as many times A was pressed
if(enable)
counter_ += 1;
}
void Game::Update()
{
// Updates with 60fps
// Will increment the counter as long as A is pressed
/*
if(enable_ == true)
counter_ += 1;
*/
}
void Game::Update()
{
if (key == KEY_A && ! enable_)
{
enable_ = true;
++counter_;
}
else if (key == KEY_B)
enable_ = false;
}
If I get you right, you want to count how many times enable_ changes. Your code has a small flaw, imagine this example:
enable_ = false
counter = 0
update gets called, key is A -> enable_ = true, counter = 1
update gets called, key is B -> enable_ = false, counter remains 1
Function that might fix this can look, for example, like this:
void Game::Update() {
if (key == KEY_A && !enable_) { // key is A and previous state is false
++counter;
enable_ = true;
}
if (key == KEY_B && enable_) { // key is B and previous state is true
++counter;
enable_ = false;
}
}
I am working on a home light project and have it working, in a simple fashion so one switch controls multiple lights.
I have introduced another array that checks previous state, if there is no change then it doesn't drop into the routine that turns the light on or off. I have two reasons for doing this, first at the moment the routine is constantly pulling the pin high. The second and more import reason, I have created another project that controls the lights via a webpage. I would like to combine the switches and web control into one project. If I have the switches saying off constantly and the web saying on it will cause me problems.
With the previous state array introduced switches control the wrong light or not at all and it seems to be in a random state.
const int zone2[] = {8,13,0};
const int zone3[] = {11,0};
const int zone4[] = {7,0};
const int zone5[] = {9,0};
const int zone6[] = {12,0};
const int * zones[]={zone2,zone3,zone4,zone5,zone6};
int buttonState[] = {0,0}; // variable for reading the pushbutton status
int previousState[]={0,0,0,0,0}; // array for holding the previous state
void setup()
{
//initialize the output pins that will control lights
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13,OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9,OUTPUT);
// initialize the pushbutton pin as an input:
//set all light switches to the same block ie pins 30 - 36
byte i;
//this loop sets all the pins as inputs
for (i=30;i< 36;i++) {
pinMode(i, INPUT);
digitalWrite(i,HIGH); // this makes it connect to the internal resistor
}
}
void loop()
{
// read the state of the pushbutton value:
byte myInput =2; //?? is this needed?? don't thinks so
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
int ArrayCount;
int arrayPosition;
for (int z = 0; z < 5; ++z)
{
buttonState[z] = digitalRead(z+30);
for (arrayPosition = 0;zones[z][arrayPosition] ; arrayPosition++)
{
if ((buttonState[z] == HIGH) && (previousState[z] == 0 ))
// turn LED on:
digitalWrite(zones[z][arrayPosition],HIGH);
previousState[z] = 1;//I have added this line to handle previous state
}
else if ((buttonState[z] == LOW) && (previousState[z] == 1)) {
// turn LED off;
digitalWrite(zones[z][arrayPosition],LOW);
previousState[z] = 0;//I have added this line to handle previous state
}
}
}
}