0

I have an arduino uno that controls a light using an ir remote. The sketch works fine until I pressed button c which is case 0x10EF58A7. This case reads in values and dims the light accordingly but the only problem is i can not exit the case when another button on the ir remote is pressed! what should i do!?

#include <SoftwareSerial.h>

#include <boarddefs.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include <ir_Lego_PF_BitStreamEncoder.h>

#include <TimerOne.h>   

int RECV_PIN = 13;

IRrecv irrecv(RECV_PIN);
decode_results results;
volatile int i=0;               // Variable to use as a counter
volatile boolean zero_cross=0;  // Boolean to store a "switch" to tell us if we have crossed zero
int AC_pin = 7;   
int dim2 = 0;                   // led control
int dim = 128;                  // Dimming level (0-128)  0 = on, 128 = 0ff
int pas = 8;                   // step for count;

int freqStep = 65;
char incomingByte;

void setup() {                
  Serial.begin(9600);
  // initialize the digital pin as an output.
  pinMode(RECV_PIN, INPUT);  
  pinMode(AC_pin, OUTPUT);
  irrecv.enableIRIn(); // Start the receiver
  attachInterrupt(0, zero_cross_detect, RISING);    // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection
  pinMode(AC_pin, OUTPUT);
  Timer1.initialize(freqStep);                      // Initialize TimerOne library for the freq we need
  Timer1.attachInterrupt(dim_check, freqStep);      
  // Use the TimerOne Library to attach an interrupt
}

void zero_cross_detect() {    
  zero_cross = true;               // set the boolean to true to tell our dimming function that a zero cross has occured
  i=0;
  digitalWrite(AC_pin, LOW);
}                                 

// Turn on the TRIAC at the appropriate time
void dim_check() {                   
  if(zero_cross == true) {              
    if(i>=dim) {                     
      digitalWrite(AC_pin, HIGH);  // turn on light       
      i=0;  // reset time step counter                         
      zero_cross=false;    // reset zero cross detection
    } 
    else {
      i++;  // increment time step counter                     
    }                                
  }    
}  

 void translateIR() // takes action based on IR code received 
{

  switch(results.value){

  case 0x10EFD827: 
  //power button 
   dim = 00;
    Serial.println(" full brightness "); 
    break;
  case 0x10EF20DF: 
  //circle button 
  dim = 128;
    Serial.println("off   "); 
    break;
  case 0x10EFF807: 
  // button A
  dim = 95;
    Serial.println(" dim level 1   "); 
    break;

   case 0x10EF7887: 
   //button B
   dim = 50; 
    Serial.println("dim level 2     "); 
    break;

 case 0x10EF58A7:
 // button C 
 {
  while ( Serial.available() > 0) {
 unsigned int num = Serial.parseInt();
 num = map(num, 0, 255, 0, 128);
 unsigned int num1 = map(num, 0, 128, 128, 0);
// num1 = constrain( num1, 0,128);
 dim = num1 ;
   Serial.print(" auto   ");
   Serial.println(dim); 

   delay(800);
   Serial.flush();
    //break;
   }
  break;
}
 break;   

  case 0x10EF10EF:
//button left
    {
    if (dim<127)  
   {
    dim = dim + pas;
    if (dim>127) 
    {
     dim=128;
    }
    }
    }
    Serial.print(" dimming ammount=   " ); 
    Serial.println(dim);
    break;

  case 0x10EF807F:  

  //button right
   {
      {
  if (dim>5)  
  {
     dim = dim - pas;
  if (dim<0) 
    {
      dim=0;  // in vechiul sketch era 1
    }
   }
   }
   }
     Serial.print(" dimming ammount=   "); 
      Serial.println(dim);
    break;

   default: 
    //Serial.print(" unknown button   ");
    //Serial.println(results.value, HEX);
{}
  }

}

void loop(){
  int i=0;
   if (irrecv.decode(&results)) {

   translateIR();
        irrecv.resume(); // Receive the next value

   } 
     delay(700);  
 }
  • What is sending Serial comms to you and how often is it sending? That while loop is checking for something available from serial. So obviously something always is. You also seem to have an extra break after that case and I'm not sure what that is about. – Delta_G Nov 28 '17 at 22:34
  • 1
    Towards the end there are braces all over the place. Often times just formatting the code will reveal logic errors that you couldn't see before. We dont' just line all our blocks and braces up because it is pretty. – Delta_G Nov 28 '17 at 22:36
1

The problem is that calling Serial.parseInt() does not remove data from the buffer. So, Serial.available() will not decrease in your case, but increase with every input you give. You will need to call Serial.read() and then convert the received bytes to a number.

@Majenko generally you're right, but it's okay to use a while loop in this situation. If there is data in the buffer, this data has to be handled. And as the arduino is not capable of multitasking it will need to take the required time, no matter if in the main loop or in a subfunction.

  • I've just tried it on an ESP8266 and figured out, that Serial.parseInt() does not decrease Serial.available(). As I don't think this depends on the device, but the library, I'd say that's the problem. And about the while loops: there is no way that the routine gets stuck in that special case (except one does not clear/read the buffer) and the time needed to accept data is so essential that it's just fine to do it right at that point! And I can't see a call to read() in that loop, btw... – Sim Son Nov 28 '17 at 23:06
  • If you wan't to respond to someone's post, comment under it and don't use your answer for that. This site isn't a discussion forum. And you can edit your own answer to add additional info. Don't put them into the comments. – gre_gor Nov 29 '17 at 2:17
  • And I don't know how you tested that, but Serial.parseInt() does remove bytes from the buffer. pastebin.com/9MSyyJ4U – gre_gor Nov 29 '17 at 2:33
  • @gre_gor I've commented a comment that obviously has been deleted by the author. – Sim Son Nov 29 '17 at 7:46
  • @gre_gor I didn't test it by reading, but by doing it. Whatever it says in your link, try it yourself. I'would be curious if it's a bug on ESP – Sim Son Nov 29 '17 at 7:54
0

You shouldn't have while loops in your switch/case like that.

In fact, you shouldn't really have while loops at all.

Instead, your case should just set a "state" variable which tells the rest of your loop() function how to handle any serial data that arrives.

0

Don't use the while loop, set a boolean when the C has been pressed.

Within the loop (main loop, not the while loop within the C key check), check if the boolean is set, and if so, check if there is serial input. If so, handle it, e.g. after or before checking all keys in the switch statement. This way alternatively keys are checked and serial input is handled.

There are good reasons not to use a while loop:

  • A while loop makes it impossible to do other tasks 'more or less' simultaneously.
  • A while loop can never end, meaning the device stops responding/functioning.
  • A while loop which takes too much time can affect the timing of other parts of your sketch.

IF you need a while loop, think twice, after thinking you need one, make sure it always ends within the condition or with a break

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.