Suppose I have an array:
int rgbcolors = {{R1,G1,B1},{R2,G2,B2},{R3,G3,B3},{Rn,Gn,Bn}}
How do I cycle through the values of this array by pressing 1 button on the remote?
So pressing once, gives the first {R1,G1,B1}, pressing twice, gives {R2,G2,B2} etc...
My current void loop for predefined colors:
if (irrecv.decode(&results))
{
int i = 0;
int j = 0;
int k = 0;
unsigned int val = results.value;
irrecv.resume();
switch(val) {
case button1: //RED
analogWrite(RedPin,255);
analogWrite(GreenPin,0);
analogWrite(BluePin,0);
break;
case button2: //GREEN
analogWrite(RedPin,0);
analogWrite(GreenPin,255);
analogWrite(BluePin,0);
break;
case button3: //BLUE
analogWrite(RedPin,0);
analogWrite(GreenPin,0);
analogWrite(BluePin,255);
break;
case button4: //YEL0
analogWrite(RedPin,255);
analogWrite(GreenPin,255);
analogWrite(BluePin,0);
break;
case button5: //PURPLE
analogWrite(RedPin,255);
analogWrite(GreenPin,0);
analogWrite(BluePin,255);
break;
case button6: //TURQUOISE
analogWrite(RedPin,0);
analogWrite(GreenPin,255);
analogWrite(BluePin,255);
break;
case button7: //ORANGE
analogWrite(RedPin,255);
analogWrite(GreenPin,140);
analogWrite(BluePin,0);
break;
case button8: //LIME !!! DON'T USE // CRASHES
analogWrite(RedPin,133);
analogWrite(GreenPin,255);
analogWrite(BluePin,140);
break;
case button9: //PINK
analogWrite(RedPin,50);
analogWrite(GreenPin,50);
analogWrite(BluePin,50);
break;
case buttonOn:
analogWrite(RedPin,255);
analogWrite(GreenPin,255);
analogWrite(BluePin,255);
break;
case buttonOff:
analogWrite(RedPin,0);
analogWrite(GreenPin,0);
analogWrite(BluePin,0);
break;
}
}
I unfortunately cannot help you with your "IR receiver value suddenly changed" issue, but I think I can help with your "cycle through the values of this array by pressing 1 button on the remote" question. The following is a code sample that does what I think you want to do:
const int NumberOfModes = 4;
int CurrentMode = -1;
void loop() {
int rgbcolors[NumberOfModes][3] = {
{ 255,0,0 }, // RED
{ 0,255,0 }, // GREEN
{ 0,0,255 }, // BLUE
{ 255,255,0 } // YELLOW
};
if (irrecv.decode(&results))
{
unsigned int val = results.value;
irrecv.resume();
if (val == button1) {
// Switch to new mode
CurrentMode++;
if (CurrentMode >= NumberOfModes)
{
CurrentMode = 0;
}
// Set output values
analogWrite(RedPin, rgbcolors[CurrentMode][0]);
analogWrite(GreenPin, rgbcolors[CurrentMode][1]);
analogWrite(BluePin, rgbcolors[CurrentMode][2]);
}
}
}
Related
I have bought a WS2812B Led Strip. I'm trying to controll it with a IR remote. it is all controlled by a arduino uno.
I know the leds work and i know the remote works. I'm trying to pre-program a few animations on the remote.
The code below is as far as i got. I can show one animation, but i have to wait until it end to change it to onother one.
Is it possible to interupt this (becouse some animations are infinite) when i push a button to choose another animation?
#include <IRremote.h>
#include "FastLED.h"
#define NUM_LEDS 232
CRGB leds[NUM_LEDS];
#define PIN 7
const int RECV_PIN = 6;
IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long key_value = 0;
void setup(){
FastLED.addLeds<WS2812B, PIN, RGB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
Serial.begin(9600);
irrecv.enableIRIn();
irrecv.blink13(true);
}
//switch case for remote
void loop(){
if (irrecv.decode(&results)){
if (results.value == 0XFFFFFFFF)
results.value = key_value;
switch(results.value){
case 0xFF30CF:
Serial.println("1");
RGBLoop();
break ;
case 0xFF18E7:
Serial.println("2");
red();
break ;
case 0xFF7A85:
Serial.println("3");
break ;
}
key_value = results.value;
irrecv.resume();
}
}
void RGBLoop(){
while(key_value==key_value){
for(int j = 0; j < 6; j++ ) {
// Fade IN
for(int k = 0; k < 256; k++) {
switch(j) {
case 0: setAll(k,0,0); break;
case 2: setAll(k,k,0); break;
case 3: setAll(0,k,0); break;
case 4: setAll(0,k,k); break;
case 5: setAll(0,0,k); break;
}
showStrip();
delay(3);
}
// Fade OUT
for(int k = 255; k >= 0; k--) {
switch(j) {
case 0: setAll(k,0,0); break;
case 2: setAll(k,k,0); break;
case 3: setAll(0,k,0); break;
case 4: setAll(0,k,k); break;
case 5: setAll(0,0,k); break;
}
showStrip();
delay(3);
}
}
}
}
void red(){
irrecv.resume();
setAll(0,255,255);
showStrip();
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
#endif
}
void setAll(byte red, byte green, byte blue) {
for(int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
FastLED.show();
#endif
}
void fadeall() { for(int i = 0; i < NUM_LEDS; i++) { leds[i].nscale8(250); } }
being honnest most of this I got online. it is my first time programming an arduino. but so far Im liking it
Instead of using infinite loops, you can just check for if any other command is received.
E.g:
instead of
while ( key_value == key_value ) //This is a weird infinite loop condition but whatever
{
// do stuff
}
you can have
while ( decode() == condition_for_this_loop )
{
// do stuff
}
or
for(;;) //This also is just an infinite loop, but looks nicer.
{
// do stuff
if ( decode() != condition_for_this_loop ) { break; }
}
Note that this is a pseudo code. You need to properly implement it. And you may need to alter the logic of your program a bit.
Since you have defined irrecv object globally, it will be visible for other functions below, this won't be a problem. Your code may even work just by replacing the loop condition. But if you get errors, you need to deal with them, I am just pointing to the logic. In the end, you can have something like this:
irrecv.decode( &results );
switch ( results )
{
case CONDITION_1:
inf_loop1();
break;
case CONDITION_2:
int_loop2();
break;
}
...
void inf_loop1()
{
for(;;)
{
// do stuff
irrecv.decode( &results );
if ( results != CONDITION_1 ) { break; }
}
}
void inf_loop2()
{
for(;;)
{
// do stuff
irrecv.decode( &results );
if ( results != CONDITION_2 ) { break; }
}
}
By the way, it's not a good idea to start with relatively big projects. By your question, I am assuming this is not only your first program for Arduino, but your first ever program. You don't run before you walk. Start slowly, blink some LEDs, implement some fun algorithms with LEDs, i don't know, have multiple of them and light them in different sequences, have some buttons and combine them with LEDs. Just play with LEDs. As you get more experience, you won't be asking questions like this. And if you start with some big project, chances are, you won't be able to do it, and got disappointed, or you will be just followed some online tutorials and copy-paste code, hence it won't feel like you did it.
I am making an alarm system using an ultrasonic distance sensor. It can be armed and disarmed using a remote, and I want a green led to be on when it is disarmed, and a red led to be on when it is armed. The red led works fine, but the green one stays on.
I have tried commenting out the line that turns on the green led, but it seems to be on by default, so when I start the program, it is already on and won't turn off. The code in question is near the bottom, marked by a comment that says //HERE
#include "IRremote.h"
#include "SR04.h"
#define TRIG_PIN 12
#define ECHO_PIN 11
SR04 sr04 = SR04(ECHO_PIN,TRIG_PIN);
long distance;
int receiver = 10;
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results; // create instance of 'decode_results'
int buzzer = 3;
int red_led = 2;
int green_led = 0;
bool can_sense = false;
bool release_pressed = false;
bool alarm_off = false;
/*-----( Function )-----*/
void translateIR() // takes action based on IR code received
// describing Remote IR codes
{
switch(results.value)
{
case 0xFFA25D: Serial.println("POWER"); alarm_off = true; break;
case 0xFFE21D: Serial.println("FUNC/STOP"); break;
case 0xFF629D: Serial.println("VOL+"); break;
case 0xFF22DD: Serial.println("FAST BACK"); break;
case 0xFF02FD: Serial.println("PAUSE"); release_pressed = true; break;
case 0xFFC23D: Serial.println("FAST FORWARD"); break;
case 0xFFE01F: Serial.println("DOWN"); break;
case 0xFFA857: Serial.println("VOL-"); break;
case 0xFF906F: Serial.println("UP"); break;
case 0xFF9867: Serial.println("EQ");release_pressed = false; break;
case 0xFFB04F: Serial.println("ST/REPT"); break;
case 0xFF6897: Serial.println("0"); break;
case 0xFF30CF: Serial.println("1"); break;
case 0xFF18E7: Serial.println("2"); break;
case 0xFF7A85: Serial.println("3"); break;
case 0xFF10EF: Serial.println("4"); break;
case 0xFF38C7: Serial.println("5"); break;
case 0xFF5AA5: Serial.println("6"); break;
case 0xFF42BD: Serial.println("7"); break;
case 0xFF4AB5: Serial.println("8"); break;
case 0xFF52AD: Serial.println("9"); break;
case 0xFFFFFFFF: Serial.println(" REPEAT");break;
default:
Serial.println(" other button ");
}// End Case
delay(100);
}
void setup() {
Serial.begin(9600);
pinMode(buzzer,OUTPUT);
pinMode(red_led,OUTPUT);
pinMode(green_led,OUTPUT);
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
irrecv.resume(); // receive the next value
}
distance = sr04.Distance();
if (distance < 70)
{
can_sense = true;
}
if (can_sense==true and release_pressed==false)
{
while (alarm_off==false)
{
digitalWrite(buzzer,HIGH);
digitalWrite(red_led,HIGH);
delay(500);
digitalWrite(buzzer,LOW);
digitalWrite(red_led,LOW);
delay(250);
if (irrecv.decode(&results)) // have we received an IR signal?
{
translateIR();
irrecv.resume(); // receive the next value
}
}
}
if (release_pressed==false) //HERE
{
digitalWrite(red_led,HIGH);
digitalWrite(green_led,LOW); // This should turn off the green led, but it doesn't
}
if (release_pressed==true)
{
digitalWrite(red_led,LOW);
digitalWrite(green_led,HIGH);
}
alarm_off = false;
can_sense = false;
}
Thanks for any help :)
Pins 0 and 1 on an Uno are used for serial communication.
As soon as you did Serial.begin(9600);, you enabled those pins for serial comms, so you can't also use them as standard digital pins.
Simply use another pin for your green LED.
I'm trying to get the function flash() to repeat, but it stops when clickevent() occurs again and case 0 becomes active.
I think my error is that case 0 is not becoming active because it's stuck on case 1 maybe? I can get it to start using while() statements or do while() statements but then I can't exit the loop, any help would be very appreciated.
// ======== change the lighting mode setting between flash and solid with a single click of the button ===========
int ModeSetting = 0;
void clickEvent()
{
Serial.println("Click Occured");
ModeSetting++;
if (ModeSetting > 1)
ModeSetting = 0;
ChangeMode(ModeSetting);
}
void ChangeMode(int i)
{
switch (i)
{
case 0:
strip.setBrightness(255);
Serial.println("MODE = SOLID COLOUR"); // SOLID LIGHT;
break;
case 1:
flash(); // THE FUNCTION THAT NEEDS TO LOOP pls help
break;
}
}
int flashstate = LOW;
unsigned long PrevFlashMillis = 0;
const long flashinterval = 1000;
void flash()
{
unsigned long currentFlashMillis = millis();
if (currentFlashMillis - PrevFlashMillis >= flashinterval)
{
// save the last time you blinked the LED
PrevFlashMillis = currentFlashMillis;
// if the LED is off turn it on and vice-versa:
if (flashstate == LOW)
{
strip.setBrightness(255);
Serial.println("FLASH ON");
flashstate == HIGH;
}
else
{
strip.setBrightness(0);
Serial.println("FLASH OFF");
flashstate == LOW;
}
}
}
I have a problem with an activation/deactivation system for Arduino. I can get the code to activate or deactivate once I upload a fresh copy of the code, but once I activate it after upload and try to deactivate the security system, it only takes in 2 numbers and then prompts me to Wrong password.
#include "Keypad.h"
#include "LiquidCrystal.h"
#include "Password.h"
LiquidCrystal lcd(0,1,10,11,12,13);
char newPasswordString; //hold the new password
char newPassword[4]; //character string of newPasswordString
//initialize password to 1234
//you can use password.set(newPassword) to overwrite it
Password password = Password("1234");
byte maxPasswordLength = 6;
byte currentPasswordLength = 0;
// keypad type definition
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9,8,7,6}; //Rows 0 to 4
byte colPins[COLS]= {5,4,3,2}; //Columns 0 to 4
int count=0;
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup()
{
lcd.begin(16, 2);
mainScreen();
}
void loop(){
char key = keypad.getKey();
if (key != NO_KEY){
delay(60);
switch (key){
case 'A': activate(); break;
case 'B': break;
case 'C': break;
case 'D': deactivate(); break;
case '#': break;
case '*': break;
default: processNumberKey(key);
}
}
}
void processNumberKey(char key) {
lcd.print(key);
currentPasswordLength++;
password.append(key);
if (currentPasswordLength == maxPasswordLength) {
activate();
}
}
void activate() {
if (password.evaluate()){
lcd.clear();
lcd.print("Activated.");
delay(1000);
mainScreen();
} else {
lcd.clear();
lcd.print("Wrong Password!");
}
}
void deactivate(){
if (password.evaluate()){
lcd.clear();
lcd.print("Deactivated.");
delay(1000);
mainScreen();
} else {
lcd.clear();
lcd.print("Wrong Password!");
delay(1000);
mainScreen();
}
}
void mainScreen(){
lcd.clear();
lcd.print("Enter Pin:");
keypad.getKey();
}
So for the first time it works (activation) and next time (deactivation) it doesn't?
The only occurrences of currentPasswordLenght are these:
Global variable declaration and initialization: byte currentPasswordLength = 0;
Incrementation in processNumberKey: currentPasswordLength++;
Compare and call activate in processNumberKey: if (currentPasswordLength == maxPasswordLength) {
The third one also explains why the deactivation (second round) fails after the second key press as maxPasswordLength is 6 and after the activation the currentPasswordLength is 4.
Example of working code:
#include <Key.h>
#include <Keypad.h>
#include <Password.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
const char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
const byte rowPins[ROWS] = {9,8,7,6};
const byte colPins[COLS] = {5,4,3,2};
Keypad keypad { makeKeymap(keys), rowPins, colPins, ROWS, COLS };
Password passwd { "1234" };
bool activated = false;
byte count = 0;
uint32_t timeout = 0;
void setup() {
Serial.begin(115200);
}
void loop() {
char key = keypad.getKey();
switch (key) {
case '0' ... '9':
Serial.print(key);
passwd << key;
timeout = millis() + 5000;
if (++count == 4) {
Serial.println();
if (passwd.evaluate()) {
activated = !activated;
Serial.println(activated ? F("Activated") : F("Deactivated"));
} else {
Serial.println(F("Wrong password"));
}
passwd.reset();
count = 0;
}
break;
case 'A' ... 'D':
break;
default:
delay(60);
break;
}
if ((count != 0) && (millis() > timeout)) {
Serial.println(F("\nTimeout"));
passwd.reset();
count = 0;
}
}
I am creating an Arduino project that plays Rock Paper Scissors.
I have a part of the code reading the value of the button and whenever I click only one button, it outputs three times (View code and images of serial monitor to understand what I mean, I can't really explain it)
Here is my code:
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin1 = A0; // the number of the pushbutton pin
const int buttonPin2 = A1;
const int buttonPin3 = A2;
const int ledPin = 12; // the number of the LED pin
// variables will change:
int buttonState1 = 0; // variable for reading the pushbutton status
int buttonState2 = 0;
int buttonState3 = 0;
char * choices[3] = {"Rock", "Paper", "Scissors"};
char * finalResult[3] = {"You Lost", "You Won!", "It's a Tie"};
byte Human = 0, Computer = 0, FR = 0;
char result[25];
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
digitalWrite(ledPin,LOW);
Serial.begin(9600);
unsigned long R;
randomSeed(R);
}
void loop(){
int choice = random(1,4);
int pick;
// read the state of the pushbutton value:
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
Serial.println("Entering Reading Loop...");
while(true)
{
buttonState1 = digitalRead(buttonPin1);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);
if (buttonState1 == HIGH && buttonState2 == LOW && buttonState3 == LOW) {
// turn LED on:
Throw('1');
} else if (buttonState1 == LOW && buttonState2 == HIGH && buttonState3 == LOW) {
// turn LED on:
pick = 2; //Paper
Throw('2');
}else if (buttonState1 == LOW && buttonState2 == LOW && buttonState3 == HIGH) {
// turn LED on:
pick = 3; //Scissor
Throw('3');
}
}
}
void Throw(char H)
{
bool thrown = false;
H -= '0'; //convert ascii to decimal
H -= 1; // instead of 1,2,3, H is now 0,1,2
byte C = random(0, 3);
sprintf(result, "The Computer chose: %s, You chose: %s", choices[C], choices[H]);
Serial.println(result);
if ( C == H)
Serial.println(F("Its a TIE"));
else
{
switch (C)
{
case 0:
switch (H)
{
case 1:
Serial.println(F("Paper wraps Rock, You WIN!"));
Human++;
break;
case 2:
Serial.println(F("Rock crushes Scissors, You LOSE!"));
Computer++;
break;
}
break;
case 1:
switch (H)
{
case 0:
Serial.println(F("Paper wraps Rock, You LOSE!"));
Computer++;
break;
case 2:
Serial.println(F("Scissors cuts Paper, You WIN!"));
Human++;
break;
}
break;
case 2:
switch (H)
{
case 0:
Serial.println(F("Rock crushes Scissors, You WIN!"));
Human++;
break;
case 1:
Serial.println(F("Scissors cuts Paper, You LOSE!"));
Computer++;
break;
}
break;
}
}
}
This is what I'm getting on the serial monitor when I click only ONE button(the rock button)
http://gyazo.com/ceb5c8329993339368cf5d52181ed4d7
As you can see, it chooses the right option for the button but it calls the throw function 3 times.
http://playground.arduino.cc/Main/RockPaperScissors)
From the Arduino docs they recommend using a Debounce strategy for handling inputs.
Without debouncing, pressing the button once can appear to the code as
multiple presses.
http://www.arduino.cc/en/Tutorial/Debounce
Here is another example illustrating the Debounce technique:
http://danthompsonsblog.blogspot.com/2011/12/arduino-push-button-onoff-example.html
There are pull-up resistors built in to the arduino that will allow you to filter out the erratic electrical signal you get when pressing a button. See the section on INPUT_PULLUP here.
I don't what the exact issue was but, I added a delay in my throw function and it stopped outputting the serial print statement 3 times!
Here is my updated function:
void Throw(char H)
{
bool thrown = false;
H -= '0'; //convert ascii to decimal
H -= 1; // instead of 1,2,3, H is now 0,1,2
byte C = random(0, 3);
sprintf(result, "The Computer chose: %s, You chose: %s", choices[C], choices[H]);
Serial.println(result);
delay(500);
if ( C == H)
Serial.println(F("Its a TIE"));
else
{
switch (C)
{
case 0:
switch (H)
{
case 1:
Serial.println(F("Paper wraps Rock, You WIN!"));
Human++;
break;
return;
case 2:
Serial.println(F("Rock crushes Scissors, You LOSE!"));
Computer++;
break;
}
break;
case 1:
switch (H)
{
case 0:
Serial.println(F("Paper wraps Rock, You LOSE!"));
Computer++;
break;
case 2:
Serial.println(F("Scissors cuts Paper, You WIN!"));
Human++;
break;
}
break;
case 2:
switch (H)
{
case 0:
Serial.println(F("Rock crushes Scissors, You WIN!"));
Human++;
break;
case 1:
Serial.println(F("Scissors cuts Paper, You LOSE!"));
Computer++;
break;
}
break;
}
}
}