Pages: 1 [2]   Go Down
Author Topic: Stuck in a loop  (Read 1218 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

herp derp. if you read his code, you'd see that he already has stop coded to make on = 0 and start coded to make on = 1, the problem lies with the fact that the LED's are not continuously blinking, because his for statement only runs once before hitting a massive delay. Thus he started the topic asking how to make the chip pay attention to the ir sensor while the While loop was running so he could manipulate the variable on via button press. But getting rid of the while loop causes a massive delay as the chip processes everything and only runs the if once. It isn't about "Making sense" yes it makes sense but your not looking at what he wrote.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4036
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

He had the led chase code dependent on the code that sets On = 1 just having been run.
I gave him a piece of the fix, separating action code from control code.
Now he needs to change what makes On = 0... too bad I stuck that else in, I was -only- trying to show how to disentangle the code blocks because if he knew he needs to do that then he wouldn't have the problem in the first place.

POSENG, get rid of that else I wrote that sets On = 0, does that do the trick? I really wasn't and still am not sure what IRcompare() does, and I'd rather not be if I don't need to. I saw you lost and I'd rather leave you knowing more how to find your way than to just give you a code fix.

Logged

Examples can be found in your IDE.

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I removed the else statment and no the code still runs just once per button push. I am tring to turn on my project with an old tv remote.  I have the correct codes to do this.

This code

Code:
]if (IRcompare(numberpulses, Play,sizeof(Play)/4)) {
    On = 1;
    if (On == 1) {
      do{
        for (int thisPin = 4; thisPin < 8; thisPin++) {
          // turn the pin on:
          digitalWrite(thisPin, HIGH);  
          delay(DelayP);                  
          // turn the pin off:
          digitalWrite(thisPin, LOW);    
        }
      }
      while(On ==1);         //<<<<<<<<<<<<<<HERE is the mistake

    }
  }

makes the leds chase with a on button push. The problem is I can't turn them off with the wireless remote. The IRcommamd reads the codes sent from the remote.

Here is a copy of the complete code:

Code:
#define IRpin_PIN      PIND
#define IRpin          2


#define MAXPULSE 65000
#define NUMPULSES 50




#define RESOLUTION 20


#define FUZZINESS 20


uint16_t pulses[NUMPULSES][2];  
uint8_t currentpulse = 0;


#include "ircodes.h"

int Speed = 1;
int DelayP = (40*Speed);
int On = 0;

void setup(void) {
  for (int thisPin = 4; thisPin < 8; thisPin++)  {
    pinMode(thisPin, OUTPUT);      
  }
}

void loop(void) {
  int numberpulses;

  numberpulses = listenForIR();


  if (IRcompare(numberpulses, Play,sizeof(Play)/4))
  {
    On = 1;
  }
//  else
//  {
//    On = 0; // because logically.... do I really have to spell it out?
//  }
  if (IRcompare(numberpulses, Speedup,sizeof(Speedup)/4)) {
  Speed = Speed /= .5;
  }
  if (IRcompare(numberpulses, Slowdown,sizeof(Slowdown)/4)) {
   Speed = ++Speed;
  }
  if (IRcompare(numberpulses, Stop,sizeof(Stop)/4)) {
    On = 0;
  }
  
// and this part works the leds --- it has been taken OUT of the control change { } block
  if (On == 0)
  {
    for (int thisPin = 4; thisPin < 8; thisPin++)
    {
          // turn the pin on:
          digitalWrite(thisPin, HIGH);  
         delay(40);                  
          // turn the pin off:
          digitalWrite(thisPin, LOW);    
    }
  }    // notice how the opens { and closes } have easy to see matching indents?

}

//KGO: added size of compare sample. Only compare the minimum of the two
boolean IRcompare(int numpulses, int Signal[], int refsize) {
  int count = min(numpulses,refsize);

  for (int i=0; i< count-1; i++) {
    int oncode = pulses[i][1] * RESOLUTION / 10;
    int offcode = pulses[i+1][0] * RESOLUTION / 10;


    if ( abs(offcode - Signal[i*2 + 1]) <= (Signal[i*2 + 1] * FUZZINESS / 100)) {

    }
    else {
      return false;
    }
  }
  // Everything matched!
  return true;
}

int listenForIR(void) {
  currentpulse = 0;

  while (1) {
    uint16_t highpulse, lowpulse;  // temporary storage timing
    highpulse = lowpulse = 0; // start out with no pulse length
    while (IRpin_PIN & (1 << IRpin)) {
      // pin is still HIGH

      // count off another few microseconds
      highpulse++;
      delayMicroseconds(RESOLUTION);

      // If the pulse is too long, we 'timed out' - either nothing
      // was received or the code is finished, so print what
      // we've grabbed so far, and then reset

      // KGO: Added check for end of receive buffer
      if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
        return currentpulse;
      }
    }
    // we didn't time out so lets stash the reading
    pulses[currentpulse][0] = highpulse;

    // same as above
    while (! (IRpin_PIN & _BV(IRpin))) {
      // pin is still LOW
      lowpulse++;
      delayMicroseconds(RESOLUTION);
      // KGO: Added check for end of receive buffer
      if (((lowpulse >= MAXPULSE)  && (currentpulse != 0))|| currentpulse == NUMPULSES) {
        return currentpulse;
      }
    }
    pulses[currentpulse][1] = lowpulse;

    // we read one high-low pulse successfully, continue!
    currentpulse++;
  }
}
//void callback()
//{
//  digitalWrite(10, digitalRead(10) ^ 1);
//}
« Last Edit: August 12, 2012, 10:18:53 pm by POSENG1911 » Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 13
Posts: 779
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The way you have listenForIR() written makes it a blocking function.  It's not going to return until it receives a valid signal.

Your highpulse loop will run until it sees a pulse, so your sketch is blocked there till you send it a command.  Your lowpulse would do the same thing, if the highpulse weren't blocking first.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The way you have listenForIR() written makes it a blocking function.  It's not going to return until it receives a valid signal.

Your highpulse loop will run until it sees a pulse, so your sketch is blocked there till you send it a command.  Your lowpulse would do the same thing, if the highpulse weren't blocking first.

Not sure what you mean.

I have been stuck on this for weeks before I dicided to post.

Is there anyway that you could fix the program so I could better understand what I did wrong?
Logged

New Hampshire
Offline Offline
God Member
*****
Karma: 13
Posts: 779
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've never worked with IR remotes myself, so I'm not that familiar with what the code should do, but I can clarify where your problem exists.

Your listenForIR function has two loops, each attempting to measure the duration of a series of high and low pulses.

Let's take a look at the loop for low pulses, since that's likely where it's getting blocked:

Code:
while (! (IRpin_PIN & _BV(IRpin))) {
      // pin is still LOW
      lowpulse++;
      delayMicroseconds(RESOLUTION);
      // KGO: Added check for end of receive buffer
      if (((lowpulse >= MAXPULSE)  && (currentpulse != 0))|| currentpulse == NUMPULSES) {
        return currentpulse;
      }
    }

This while loop will run for as long as
Code:
!(IRpin_PIN & _BV(IRpin))
is true.  If you are not issuing a command from your remote, then this is always going to be true.  The signal is always going to be low.

Now inside your loop you do have an if() statement that will return from the function under the right conditions, but the problem is, if you are not issuing a command from your remote, those conditions will never be met.  The function will return IF one of two conditions are met.  The last,
Code:
currentpulse == NUMPULSES
obviously isn't going to be met if there's no command.

The first
Code:
(lowpulse >= MAXPULSE)  && (currentpulse != 0)
also isn't going to be met because currentpulse will always be 0.

It's possible that all you need to do is remove
Code:
&& (currentpulse != 0)
So that your conditional is just this:
Code:
if (lowpulse >= MAXPULSE || currentpulse == NUMPULSES)
That would need to be made in both your highpulse and lowpulse loops.  Your code does not include the definitions of Play, Speedup, Slowdown, Stop, so it's not clear what affect that would have on your IRcompare calls, as you would be passing in a value of 0 for numpulses. 
Logged


California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Misuse/misunderstanding of while() loops and delays tend to be the cause of a lot of problems with Arduino sketches. If your code is intended to have any type of multitasking it's best to re-implement your code to not use them.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's possible that all you need to do is remove
Code:
&& (currentpulse != 0)
So that your conditional is just this:
Code:
if (lowpulse >= MAXPULSE || currentpulse == NUMPULSES)


jraskell,

 I removed the && (currentpulse != 0) from both the high and low pluse loops but it doesn't seem to have any effect on the sketch. It still runs only once per button push.


Arrch,

 Have any ides on how I could remove the while() loops?
 
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4036
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

IrDA uses long pulse for a 1 bit and short (3/16 width) pulse for 0 bit. Will you catch that reliably?

The modules aren't too expensive, are dependable, and take a load off the MCU:
https://www.adafruit.com/products/157

Logged

Examples can be found in your IDE.

Shipley, West Yorkshire
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wouldn't setting a boolean flag work to hold the on/off state of the lights? EG Once it receives the on code from the remote, flip the value of the variable and then once the off code is received, flip it back to false and then have your code surrounded in an if loop that doesn't run if the variable is false with the IR receiving code outside the loop?
Just my 10 cents...

Callum
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

IrDA uses long pulse for a 1 bit and short (3/16 width) pulse for 0 bit. Will you catch that reliably?

The modules aren't too expensive, are dependable, and take a load off the MCU:
https://www.adafruit.com/products/157

The TSOP38238 receiver is the one that I am using. I got part and the IR code from:
https://www.adafruit.com/
http://learn.adafruit.com/ir-sensor


uberdum50,


That sounds like a good idea, I will give it a try and post back.
Logged

California
Offline Offline
Faraday Member
**
Karma: 82
Posts: 3123
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wouldn't setting a boolean flag work to hold the on/off state of the lights? EG Once it receives the on code from the remote, flip the value of the variable and then once the off code is received, flip it back to false and then have your code surrounded in an if loop that doesn't run if the variable is false with the IR receiving code outside the loop?
Just my 10 cents...

Callum

That's actually what has been suggested, but the problem is that the call to check for IR received data is blocking.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 58
Posts: 4036
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yah, the variable On is either 0 or 1. That is the flag/switch.

There were at least 2 bugs which isn't bad. Get used to it new guys, debugging is part of programming. It's kind of like breathing is part of life. You might write something trivial and get it right the first time, especially if you've done the like before but you can probably hold your breath for a while too. Debugging skills are one sign of programming experience, sort of your 'fighting scars'.

Logged

Examples can be found in your IDE.

Pages: 1 [2]   Go Up
Jump to: