Multitasking

Hey!

I’m trying to put use an IR LED and a IR Sensor together in the same program. And I’m having some problems while attempting to do so.

I tried to use the Scheduler Library but it said it could not be found.

Here is what I have so far (Most of it’s from here):

#define IRledPin 13

#define IRpin_PIN PIND
#define IRpin 2

#define MAXPULSE 65000
#define RESOLUTION 20

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

void setup()
{
  pinMode(IRledPin, OUTPUT);
  
  Serial.begin(9600);
  Serial.println("Ready to decode IR!");
}

int lastShot = 0;

void loop()
{
  //TODO: Use scheduler
  if(lastShot < (millis() - (1000 * 2)))
  {
    lastShot = millis();
    Serial.println("Sending IR signal");
    SendNikonCode();
    delay(100);
  }
  
  uint16_t highpulse, lowpulse;
  highpulse = lowpulse = 0;
  
    while (IRpin_PIN & (1 << IRpin))
    {
     highpulse++;
     delayMicroseconds(RESOLUTION);

     if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  
  pulses[currentpulse][0] = highpulse;
  
  while (! (IRpin_PIN & _BV(IRpin)))
  {
     lowpulse++;
     delayMicroseconds(RESOLUTION);
     if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  pulses[currentpulse][1] = lowpulse;
 
  currentpulse++;
}

void printpulses()
{
  Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
  for (uint8_t i = 0; i < currentpulse; i++)
  {
    Serial.print(pulses[i][0] * RESOLUTION, DEC);
    Serial.print(" usec, ");
    Serial.print(pulses[i][1] * RESOLUTION, DEC);
    Serial.println(" usec");
  }
  
  Serial.println("int IRsignal[] = {");
  Serial.println("// ON, OFF (in 10's of microseconds)");
  for (uint8_t i = 0; i < currentpulse-1; i++)
  {
    Serial.print("\t"); // tab
    Serial.print(pulses[i][1] * RESOLUTION / 10, DEC);
    Serial.print(", ");
    Serial.print(pulses[i+1][0] * RESOLUTION / 10, DEC);
    Serial.println(",");
  }
  Serial.print("\t"); // tab
  Serial.print(pulses[currentpulse-1][1] * RESOLUTION / 10, DEC);
  Serial.print(", 0};");
}

void pulseIR(long microsecs)
{
  cli();
  
  while (microsecs > 0)
  {
   digitalWrite(IRledPin, HIGH);
   delayMicroseconds(10);
   digitalWrite(IRledPin, LOW);
   delayMicroseconds(10);
   
   microsecs -= 26;
  }
 
  sei();
}
 
void SendNikonCode()
{
  pulseIR(2080);
  delay(27);
  pulseIR(440);
  delayMicroseconds(1500);
  pulseIR(460);
  delayMicroseconds(3440);
  pulseIR(480);
 
 
  delay(65);
 
  pulseIR(2000);
  delay(27);
  pulseIR(440);
  delayMicroseconds(1500);
  pulseIR(460);
  delayMicroseconds(3440);
  pulseIR(480);
}

Your explanation is weak. What should the program accomplish? What are these "some problems" you're having?

Oops, I want to be able to send an IR code when ever I want to, not having to wait until sensor is done. Allowing the sensor to run at all times. Sort of like multithreading in java.

How does the sensor work? When is it "done"?

Just saw the Adafruit link, that gives some clues to the sensor. Both the transmit and receive code depend on delays, i.e. either delay() or delayMicroseconds().

While these delay functions are doing their thing, the microcontroller can do nothing else. I'm not familiar with the Scheduler library, but on top of this code, it can't possibly help. And while the pulseIR() function is running, with interrupts inhibited, nothing else will happen, for a couple milliseconds in some cases.

Are you aware of the famous BlinkWithoutDelay example? Basically all calls to delay() and delayMicroseconds() need to be removed and replaced with the timing technique used in BlinkWithoutDelay. Then, while one section of the code is waiting on one thing, another section of the code can still be doing useful work.

I also believe there are some IR libraries out there but I am unfamiliar with them. I don't know whether they'd be any help. This project may be a bit of a challenge since the timings are relatively fast. I might consider using one of the AVR's hardware timers to generate the output pulses, this would relieve the code of that processing and then it would just have to turn the timer on and off at the proper times.

I'd still like a better overview. Describe the whole system, the inputs, the outputs, and how they relate. Certainly receiving the IR codes is not enough, they will need decoding and then something will be done based on what is received.

You may be interested in several things at a time which is an extended demo of BWoD.

...R

Get the IRLib or IRremote library and use the sendRAW functions to send the IR signals on your behalf.

In most situations it doesn't really make sense to send & recieve IR at the same time - as the tx will interfere with the signal being rxed.

For that reason, rx is automatically disabled when sending IR in the libraries above.

For your solution, unless you are attempting something very exotic, doing both things one after another will appear as if they happen together, so a normal loop should suffice...like the following 'pseudo' example

loop start
?anything rxed....if yes ...take relevant action
?anything to send...if yes ...send it
loop end...back to loop start

I suggest you work through all of the examples provided with the libraries mentioned & you will be better informed about how to implement your solution.

As already mentioned the blinkwithoutdelay Arduino example might also be worth studying.

Okay, I have switched over to IRremote. Because it looks easy to use than what I’m trying.

However I have another problem(this could of been what was happening before). Once the Arduino sends the first IR code out, it does not want to receive any more from anything, the LED or a Apple Remote I’m using to test.

Here’s the code so far:

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

const int RECV_PIN = 2;
IRrecv irrecv(RECV_PIN);
decode_results results;

IRsend irsend;

long previousMillis = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("Started...");
  
  pinMode(3, OUTPUT); //No where did I see this is needed, but the IR LED won't blink without it.
  
  irrecv.enableIRIn(); // Start the receiver
  irrecv.blink13(true);
}

void loop()
{
  if(irrecv.decode(&results))
  {
    Serial.println("Value:\t\tLen:");
    
    Serial.print(results.value, HEX);
    Serial.print("\t");
    Serial.println(results.rawlen);
    
    Serial.println("\nRawBuf:");
    for(int i=0; i<sizeof(results.rawbuf); i++)
    {
      Serial.println(results.rawbuf[i]);
    }
    
    Serial.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
    
    irrecv.resume(); // Receive the next value
  }

  if(millis() - previousMillis > 5000)
  {
    previousMillis = millis();  
    
    unsigned int codes1[2] = {60931, 181};
    irsend.sendRaw(codes1, 68, 38);
    
    delay(100);
    
    unsigned int codes2[2] = {717, 181};
    irsend.sendRaw(codes2, 44, 38);
    
    Serial.println("Sent code");
  }
}

For a likely solution see point 8 (last bullet point) of the

Arduino: 10 common pitfalls with Infrared Remote Control

link via my signature.