Pages: 1 [2] 3 4   Go Down
Author Topic: (Resolved) Continue running one part of code while still checking other inputs?  (Read 5339 times)
0 Members and 1 Guest are viewing this topic.
Western New York, USA
Offline Offline
Faraday Member
**
Karma: 36
Posts: 4307
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Okay, I'll have to do some research on this diode gate stuff, I'm still pretty new at all this.
You really should look into implementing the 'Pin Change Interrupts' that are inherent to the ATmega chip used in the Arduino.  Essentially any of the I/O pins on the chip can be configured to generate an interrupt when the level on that pin changes.  These interrupts are not as configurable as the 'External Interrupts' used by the 'attachInterrupt' function but they do work nicely.  

[EDIT:] I found some information on this at http://forums.trossenrobotics.com/tutorials/how-to-diy-128/an-introduction-to-interrupts-3248/ scroll down to the part headed 'Wait, I ran out of interrupts!'.  Everything there applies equally to the ATmega328 so don't let the reference to the 168 put you off.

Don
« Last Edit: April 09, 2011, 10:12:03 am by floresta » Logged

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay, I think I'm starting to get it. I can have both flash speeds "running" in the background, but only call them when needed and if a time has gone by. I'll draw up a flowchart and post it to see if I can make this all make sense.


Absolutely. It's not that complicated. You really have two things you need to do:

  • Detect switch changes (on/off)
  • Flash lights - how many depends on which switches are on (and the rate might depend on how recently the switch was pushed)

So the interrupts detect the switch up/downs, and the main loop just flashes stuff.
Logged

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In looking into the Interrupts idea you suggested Floresta, I see that I cannot use delay() while inside the interrupt. I'm looking into a workaround, but it seems that if I use the interrupt method I can't do the blinking that I need. Unless there is another method to blink that I am not seeing?
Logged

Western New York, USA
Offline Offline
Faraday Member
**
Karma: 36
Posts: 4307
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I see that I cannot use delay() while inside the interrupt.
In general you never want to do very much inside any interrupt.  What you should do is set some sort of flag to indicate that some condition has been detected and then exit the interrupt as quickly as possible.  Your main program should check the flag and react to the detected condition as required.

Don
Logged

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So how is reacting to a flag any different than reacting to a physical button input? The Arduino will still be able to pump out only one set of LED instructions at a time whether it is triggered by a button or a flag, right? I need lights to react independent of each other, and continuously (overlapping).

I need the brake light to be able to come on and off regardless of whether a blinker is on, and visa versa.

Even with all these fancy tricks, what I'm understanding is that the Arduino will still only be able to react to one input at a time.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 481
Posts: 18742
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It reacts by noticing the input. That doesn't mean it can only do one thing afterwards.

Here's an example. You notice the cat is hungry. So you feed it once a day. You notice the garden needs watering. So you water it once a week. You notice the car needs washing. So you wash it once a month.

But that doesn't mean that if the car needs washing, you don't feed the cat.

As a person you build up in your brain a list of things that need doing from time to time. You may check that list every hour, or minute, or second even. And if the time is up to do something ("oh, time to water the garden") you do it.

So your program does the same thing.
Logged


0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Okay, that makes sense. Problem is, I need to weed the garden while washing the car. Or feed the cat while weeding the garden while washing the car, then stop feeding the cat while still washing the car, and then start feeding the cat again while STILL washing the car and weeding the garden.

Or wash the garden while feeding the car and weeding the cat, even.

It does me no good for my brake light to come on whenever it feels like it. I need my brake light to turn on immediately upon pressing the brake, even if my turn signal is on, and I'd prefer to have the attention grabbing rapid flash sequence fire at the start of either light coming on.

I understand now (I think) how I can have my brake light be turned on or off depending on what it's previous state was, and I think I can do the same with the blinking pattern for the blinkers, but I would have to omit the initial rapid-flash sequence   smiley-sad Which, if that is the case, I'll just chuck the whole Arduino idea and go back to the stock system.

Or am I being a completely infuriating ass and not understanding something here?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 481
Posts: 18742
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Try out this code:


Code:
void setup() {
  pinMode (13,OUTPUT);
} //end of setup

void loop() {

if ((millis () & 0x7F) < 63)
  digitalWrite(13, HIGH);
else
  digitalWrite(13, LOW);

}

As you go through the main loop, it flashes an LED quite fast.

Now put a condition on it:


Code:
void setup() {
  pinMode (13,OUTPUT);
} //end of setup

void loop() {

if ((millis () & 0x7F) < 63 && indicator_button_down)
  digitalWrite(13, HIGH);   // only flash light if indicator button is on
else
  digitalWrite(13, LOW);

}

The condition is what is set in the interrupt routine. And after that you could flash a different LED, at a different rate, depending on if another condition is set.
« Last Edit: April 18, 2011, 11:00:38 pm by Nick Gammon » Logged


0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So in this way all the speeds of flashing are running in the background, but aren't actually being called until needed? Okay, I can see that. I have some "yea, but"s about it still, but I'll play with it first to see if I can answer my own questions before asking.

Thanks for your help and patience!
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26250
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So in this way all the speeds of flashing are running in the background
In a way, yes.
Stop and think about it.
Once a LED is lit, or shut off, it stays in that state - you don't have to refresh it, and it stays in that state for the vast majority of the time.
The only time the processor is involved is at the transitions from on to off or vice versa, and these transitions take very little time; just long enough to toggle a variable and write to a port.
A microsecond or so, allowing for Arduino overheads.
You could do thousands of these transitions per second, and a human user would perceive all the operations as concurrent
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Except if I were running a pulse width modulation, right? Yes, those thousands of transitions would be happening every second, but the processor would be stuck thinking about that transition and not much else. Or is that also so "slow" that other operations could still continue?

I guess the solution there would just be to drop the PWM pulsing of the brake light and go for normal on/off blink.

I think I'm slowly coming around to seeing how this is possible. Once I wrap my head around that then I should be able to program it in.
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 481
Posts: 18742
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think you have to PWM brake lights. My own tests show that much faster than around 50Hz is invisible (that is, too fast to see). And the processor clock is 16 MHz.
Logged


Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 302
Posts: 26250
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Except if I were running a pulse width modulation, right?
Even if you were running PWM, so yes, wrong.

The processor isn't involved in the PWM operation, beyond setting the registers - all the PWM is handled by logic, as a simple peripheral, just like the processor isn't sampling the serial input at 16 times the baud rate to find the initial edge and middle of a start bit.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 62
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, cool then. I had assumed that the processor was handling all that, but if it's just throwing that bone to another component then we are in business. I'm still working in what I think is the right direction, so we'll see where I end up. Thanks for your help.
Logged

Smithfield, Rhode Island
Offline Offline
God Member
*****
Karma: 3
Posts: 843
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you really need an interupt?

Code:
#include "Led.h"
#include "constants.h"
#include <WProgram.h>

Led::Led(unsigned char pin, unsigned char initialState, unsigned short fi, unsigned short si)
{
  this->pin = pin;
  mode = initialState;
  pinMode(pin, OUTPUT);

  fastInt = fi;
  slowInt = si;

  update();
}

Led::~Led(){}

void Led::setFastInterval(unsigned short fi)
{
  fastInt = fi;
}

void Led::setSlowInterval(unsigned short si)
{
  slowInt = si;


void Led::slow()
{
  mode = LED_SLOW_BLINK;
  update();
}

void Led::fast()
{
  mode = LED_FAST_BLINK;
  update();
}

void Led::on()
{
  mode = LED_ON;
  update();
}

void Led::off()
{
  mode = LED_OFF;
  update();
}   

void Led::reverse(void)
{
  if(mode != LED_ON && mode != LED_OFF)
  {
    mode = LED_ON;
  }

  if(mode == LED_ON)
  {
    mode = LED_OFF;
  }
  else
  {
    mode = LED_ON;
  }
 
  update();
 
}


void Led::update(void)
{
  short interval = 0;
   
  if(mode == LED_ON)
  {
    state = LED_ON;
  }

  if(mode == LED_OFF)
  {
    state = LED_OFF;
  }
 
  if(mode == LED_FAST_BLINK)
  {
    interval = fastInt;   
  }

  if(mode == LED_SLOW_BLINK)
  {
    interval = slowInt;
  }

  if(mode == LED_SLOW_BLINK || mode == LED_FAST_BLINK)
  {

    if(millis() - lastMs > interval)
    {
      // save the last time you blinked the LED
      lastMs = millis();   

      // if the LED is off turn it on and vice-versa:
      if(state == LED_ON)
      {
        state = LED_OFF;
      } 
      else
      {
        state = LED_ON;
      }
    } 
  }

  if(state == LED_ON)
  {
    digitalWrite(pin, LOW);
  }

  if(state == LED_OFF)
  {
    digitalWrite(pin, HIGH);   
  }
}

Code:
// Led.h

#ifndef LED_H
#define LED_H

#include "constants.h"

class Led
{
  public:

  Led(unsigned char pin, unsigned char initialState = LED_OFF, unsigned short fi = 100, unsigned short si = 750);
  ~Led(void);
 
  void setFastInterval(unsigned short fi);
  void setSlowInterval(unsigned short si);
  void slow(void);
  void fast(void);
  void on(void);
  void off(void);
  void reverse(void);

  void update(void);

  private:
 
  unsigned char pin;
  unsigned long lastMs;
  unsigned char mode;
  unsigned char state;
  unsigned short millDiff;
 
  unsigned short fastInt;
  unsigned short slowInt;
};

#endif
       
Logged

Pages: 1 [2] 3 4   Go Up
Jump to: