I'm having some trouble with my arduino code and I need help making it work, it is going to be used to control some LED lights. Brighten, darken, blink, and make them run.
I have added comments all over the script so you can read the problems and so on.
/*This script is supposed to make a arduino board control the lights on a lego creation for a school project.
Button1 should make lights brighter
Button2 should make ligts shine less
Button3 should make the light blink
Button4 is supposed to make the light run after each other.
*/
//Setting up all the lights and buttons
const int lights[] = {9, 8, 7};
int light = 0;
const int button1 = 24;
int buttonstate1 = 0;
const int button2 = 25;
int buttonstate2 = 0;
const int button3 = 26;
int buttonstate3 = 0;
const int button4 = 27;
int buttonstate4 = 0;
int lightStrength = 50;
int blinkToggle = 0;
//Setting up the input's and output's
void setup() {
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
pinMode(lights[0], OUTPUT);
pinMode(lights[1], OUTPUT);
pinMode(lights[2], OUTPUT);
//Here i have a problem with make the list take all in one line of code.
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
void loop() {
//checking if the buttons are being pressed
buttonstate1 = digitalRead(button1);
buttonstate2 = digitalRead(button2);
buttonstate3 = digitalRead(button3);
buttonstate1 = digitalRead(button4);
//Make the lights brighter
while (lightStrength <= 235){
if (buttonstate1 == HIGH){
delay(10);
lightStrength = lightStrength + 1;
delay(10);
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
}
//make the lights darker
while (lightStrength >= 45){
if (buttonstate2 == HIGH){
delay(5);
lightStrength = lightStrength - 1;
delay(5);
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
}
//Blink the lights
while(blinkToggle == 1){
if (buttonstate3 == HIGH){
delay(100);
blinkToggle = 0;
}
}
while(blinkToggle == 0){
if (buttonstate3 == HIGH){
delay(100);
blinkToggle = 1;
}
}
while(blinkToggle == 1){
delay(150);
analogWrite(lights[0], 0);
analogWrite(lights[1], 0);
analogWrite(lights[2], 0);
delay(150);
analogWrite(lights[0], lightStrength);
analogWrite(lights[1], lightStrength);
analogWrite(lights[2], lightStrength);
}
//make the lights run (Not completed because the other code didn't work)
if (buttonstate4 == HIGH){
delay(100);
}
}
First of all, asking "need help" is kind of general.. You should definitely ask a better question. For instance I could not understand fully what you meant, what the problems are and what is the expected behavior in some cases (for instance, what happens if I press more buttons?).
Anyway this is not a comment but an answer, because there are a few general mistakes in your code, and maybe these are enough to make your code worl.
for instance, you wrote all your tests as
while (lightStrength <= 235){
if (buttonstate1 == HIGH){
Well, if your button is low then lightStrength will not be incremented, the loop will never reach its ending and so the program will be stuck in there. I suggest you to change your code into
if (buttonstate1 == HIGH){
while (lightStrength <= 235){
This will not halt your code.
Then the tests for blinkToggle are wrong. You should not test them in a while, but with an if (e.g. if(blinkToggle == 1){).
The button 4 is not implemented, and I don't understand what is its behavior, so I cannot tell you how to implement it.
I did not understand the //Here i have a problem with make the list take all in one line of code. comment. If you want to write the same value without repeating it use a for loop:
byte i;
for (i = 0; i < 3; i++)
analogWrite(lights[i], lightStrength);
And now, some advices for your program.
First of all, debouncing. If you don't know what bouncing is, look on wikipedia or search on google. Anyway I found that the Bounce2 library is very useful whenever you have to deal with buttons. Search for its examples or simply ask to see some more examples.
And.. I suggest you to change your approach in this program. A FSM (Finite State Machine) approach is more suitable for this. Even without using complicated libraries, just plain C, you can make a very solid program
Related
I need a motor to cycle forward, then backward when the user pushes a once. the problem is, the arduino will run in loops after it is presses and wont stop.
How can i make it only cycle through once each time the button is pushed?
Ive tried exit(0), stop_it, etc, but those just exit the loop instead of starting back up when the button is pressed another time.
const int pwm_pin = 9;
const int dir_1a_pin = 8;
const int dir_2a_pin = 7;
int buttonPin = 2;
boolean on=false;
int buttonState = 0;
void setup() {
pinMode(buttonPin, INPUT);
pinMode(pwm_pin, OUTPUT);
pinMode(dir_1a_pin, OUTPUT);
pinMode(dir_2a_pin, OUTPUT);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH){
if (on==true){
on=false;
} else{
on=true;
}
}
if(on == true){
digitalWrite(dir_1a_pin, HIGH);
digitalWrite(dir_2a_pin, LOW);
analogWrite(pwm_pin, 255);
delay (8000);
digitalWrite(dir_1a_pin, LOW);
digitalWrite(dir_2a_pin, HIGH);
analogWrite(pwm_pin, 255);
delay (12000);
}
}
You are making the logic too much complicated. Just read the button state in your loop and if it was HIGH do your motorcycle job. The next time loop runs as you haven't pressed the button it would become LOW and won't go into if statement.
const int pwm_pin = 9;
const int dir_1a_pin = 8;
const int dir_2a_pin = 7;
int buttonPin = 2;
void MotorCycle()
{
digitalWrite(dir_1a_pin, HIGH);
digitalWrite(dir_2a_pin, LOW);
analogWrite(pwm_pin, 255);
delay(8000);
digitalWrite(dir_1a_pin, LOW);
digitalWrite(dir_2a_pin, HIGH);
analogWrite(pwm_pin, 255);
delay(12000);
}
void setup()
{
pinMode(buttonPin, INPUT);
pinMode(pwm_pin, OUTPUT);
pinMode(dir_1a_pin, OUTPUT);
pinMode(dir_2a_pin, OUTPUT);
}
void loop()
{
// if button pressed
if (digitalRead(buttonPin) == HIGH)
{
MotorCycle();
}
}
I assume that the part you want to run once is in the section at the end in the if(on == true) section. If you don't want that to repeat, then how about setting on to false in that section. Then next time loop repeats it won't go into that section.
I got a short time ago an Arduino Kit, and i am trying a little project. Using a Sound sensor i want to sequentially turn on 3 leds. Meaning one clap turns LED1, then a second one the second one and so on. Problem is that this happens only for LED 1 and LED2, and without waiting for the third clap the third LED turns on and without a 4th clap the lights go off, even though i am counting them and resetting the value from the sensor.
I cannot understand why this code works for the first and second Leds but the 3rd and 4th stages are going automatically .
Thanks!
I tried the following code, but it works only for the first and second LED, when the counter is 0 and 1, when it reaches 2, or 3 it activates even though i am not activating the sensor.
int soundSensor=2;
int LED1=4;
int LED2=5;
int LED3=6;
int counter =0;
int SensorData=0;
void setup() {
Serial.begin(9600);
pinMode(soundSensor,INPUT);
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
counter = 0;
}
void loop() {
SensorData=digitalRead(soundSensor);
if(SensorData==1 && counter == 0){
digitalWrite(LED1,HIGH);
counter++;
SensorData=2;
delay(1000);
}
if(SensorData==1 && counter == 1){
digitalWrite(LED2,HIGH);
counter++;
SensorData=2;
delay(1000);
}
if(SensorData==1 && counter == 2){
digitalWrite(LED3,HIGH);
counter++;
SensorData=2;
delay(1000);
}
if(SensorData==1 && counter == 3){
digitalWrite(LED1,LOW);
digitalWrite(LED2,LOW);
digitalWrite(LED3,LOW);
counter++;
SensorData=2;
delay(1000);
counter =0;
}
}
I have been trying to write a code to basically add points to a score whenever I pressed a button while a certain amount of time is running down. The problem I am finding is that it doesn't detect when the button is pressed while the time is decreasing, in fact it can only detect when the time starts to decrease and then it doesn't matter at which state the button is it will continue to add to the score. Anyway here is the main code:
void loop() {
buttonState01 = digitalRead(button01);
buttonState02 = digitalRead(button02);
buttonState03 = digitalRead(button03);
if (buttonState01){
time = 3000;
while(time > 0){
if (buttonState02){
score += 10;
Serial.println(score);
}
time--;
Serial.println(time);
}
}
}
And here is the full code if needed:
int button01 = 4;
int button02 = 3;
int button03 = 2;
int buttonState01 = 0;
int buttonState02 = 0;
int buttonState03 = 0;
float time;
int score;
void setup() {
score = 0;
time = 0;
pinMode(button01, INPUT);
pinMode(button02, INPUT);
pinMode(button03, INPUT);
Serial.begin(9600);
}
void loop() {
buttonState01 = digitalRead(button01);
buttonState02 = digitalRead(button02);
buttonState03 = digitalRead(button03);
if (buttonState01){
time = 3000;
while(time > 0){
if (buttonState02){
Serial.println("Points");
}
time--;
Serial.println(time);
}
}
}
You should read the status of a button inside the while loop. Like this:
while(time > 0)
{
buttonState02 = digitalRead(button02);
if (buttonState02){
Serial.println("Points");
}
time--;
Serial.println(time);
}
And in your code, there is no logic to add points to the score.
A hardware interrupt would do exactly what you need.
Attach an interrupt routine to the pin your button is linked to, and get it to set the 'score' variable. Make sure you introduce some sort of timeout to avoid button-bounce (I.e. set LastTimeIncremented when you increase the score, and only increment score if LastTimeIncremented is more than 1 second ago)
This way the score will always be set regardless of what else the program may be doing.
Information on this can be found in the Arduino https://www.arduino.cc/en/Reference/attachInterrupt
The example on that page would do exactly what you want, just replace 'blink' with 'incrementScore' and you're pretty much done
const byte ledPin = 13;
const byte interruptPin = 2;
int score = 0;
int increment = 1;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), incScore, RISING);
}
void loop() {
digitalWrite(ledPin, state);
}
void incScore() {
score = score+increment;
// add anti-bounce functionality here
}
I just got my arduino the other day. I am currently making a program in java to control my arduino using serial communication. So far, I only have the program turn it on or off. But I ran into an issue. I have my arduino fade two rgb leds, looping through every color. I run into my issue here. When I press the button to turn it off(java program), it doesn't turn off until its ran through every color(complete the for loops). I want it to instantly shut off. Is there any way I can read serial data in the for loops, or is there any possible way I can turn it off instantly, not having to wait for the for loops to complete? Here is the code:
const int redPins[] = {11,6};
const int greenPins[] = {10,5};
const int bluePins[] = {9, 3};
const int pinCountPerColor = 2;
const int sensorPin = 0;
int lightLevel;
int val = 0;
boolean isOn;
void setup() {
Serial.begin(9600);
setColourRgb(0,0,0);
isOn = true;
}
void loop() {
if(isOn) {
unsigned int rgbColour[3];
lightLevel = analogRead(sensorPin);
if(lightLevel >= 400) {
rgbColour[0] = 255;
rgbColour[1] = 0;
rgbColour[2] = 0;
for (int decColour = 0; decColour < 3; decColour += 1) {
int incColour = decColour == 2 ? 0 : decColour + 1;
for(int i = 0; i < 255; i += 1) {
lightLevel = analogRead(sensorPin);
if(lightLevel <= 400) {
setColourRgb(255, 255, 255);
} else {
rgbColour[decColour] -= 1;
rgbColour[incColour] += 1;
setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
delay(5);
}
}
}
} else {
setColourRgb(255, 255, 255);
}
}
}
void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
for(int r = 0; r < pinCountPerColor; r++) {
analogWrite(redPins[r], red);
}
for(int g = 0; g < pinCountPerColor; g++) {
analogWrite(greenPins[g], green);
}
for(int b = 0; b < pinCountPerColor; b++) {
analogWrite(bluePins[b], blue);
}
}
void serialEvent()
{
while (Serial.available())
{
val = Serial.parseInt();
if(val == 1)
{
isOn = true;
//do nothing
}
else if(val == 0)
{
setColourRgb(255, 255, 255);
isOn = false;
}
}
Serial.println("Succesfully received.");
}
It is best to create a state machine for the colors, that does not have any blocking for loops, to dwell in. Especially loops with delays. So that each cycle through the loop changes the color and polls the Serial.
This is the art to writing real time code, or simply non-blocking code.
Note it is possible to create a timer interrupt to better schedule RGB updates. See Answer about Timer Interrupts to write precision updates.
#mpflaga answered your question correctly.
I would add that if you projects get bigger than just two leds fading, you might want to use something more reliable than a hand-made state machine.
That is called a Real Time Operating System (RTOS) and it allows you to have different threads running at different frequencies.
I personally use ChibiOS/RT for my robot project. There is a port for Arduino you can download here, it's very well documented and I'd say pretty easy to use once you get the basics. The nice thing to do is to add a higher level layer to manage the threads.
Here is a page with describing it and other solutions : Arduino rtoslibs
And here are some tutorials on real time and ChibiOS for Arduino:
It’s time for real-time
Blinking in real-time
ChibiOS for the Arduino IDE
Hope it helps! :)
This program is intended to count the number of button1 presses and then break out of the loop with the button2 press. The button2 is like an enter key.
If I run what is inside the do while statement by itself without the do while it will count up each button push. I used this to verify that I have constructed my circuit correctly. but for some unknown reason if I put the same code into a do while or just a while then it does not read the pins. It will loop inside the do while but never exit to that done statement at the end. If I start the arduino as I press down either of the two buttons then it will register that a button is being pressed, but as soon as I let go then it will do nothing again. Please tell me what I am doing wrong.
My code
int ledpin = 11;
int button1pin = 7;
int button2pin = 2;
int button1counter = 0;
int button1state = 0;
int lastButton1state = 0;
int button2state = 0;
int lastButton2state = 0;
int button2counter = 0;
void setup() {
// initialize the digital pin as an output.
pinMode(button1pin, INPUT);
pinMode(button2pin, INPUT);
Serial.begin(9600);
}
void loop() {
button1state = digitalRead(button1pin);
button2state = digitalRead(button2pin);
do {
if (button1state != lastButton1state) {
if (button1state == HIGH) {
button1counter++;
Serial.print("number of button 1 pushes: ");
Serial.println(button1counter);
}
lastButton1state = button1state;
}
} while(button2state == LOW);
Serial.println("done");
}
Thanks I changed it and of course your right. However, I can't quite understand why your right. Let me comment the code with my understanding and please correct me if I'm wrong.
void setup() {
pinMode(button1pin, INPUT);//tells comp to make button 1 input
pinMode(button2pin, INPUT);//tells comp to make button 2 input
Serial.begin(9600);
}
void loop() {
button1state = digitalRead(button1pin);//tells comp to begin reading pin? but for how long?
button2state = digitalRead(button2pin);
do {
You read your button state outside of your while loop, so your button1state and button2state are never updated, that is why you enter in an infinite loop just do that little change:
void loop() {
do {
button1state = digitalRead(button1pin);
button2state = digitalRead(button2pin);
if (button1state != lastButton1state) {
if (button1state == HIGH) {
button1counter++;
Serial.print("number of button 1 pushes: ");
Serial.println(button1counter);
}
lastButton1state = button1state;
}
} while(button2state == LOW);
Serial.println("done");
}