Go to Post FIRST robots are not six week projects. They are never ending projects where the requirements are changed on an annual basis. - ChrisH [more]
Home
Go Back   Chief Delphi > Technical > Control System > Sensors
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Reply
Thread Tools Rate Thread Display Modes
  #1   Spotlight this post!  
Unread 13-01-2008, 13:45
BradAMiller BradAMiller is offline
Registered User
AKA: Brad
#0190 ( Gompei and the Herd)
Team Role: Mentor
 
Join Date: Mar 2004
Location: Worcester, MA
Posts: 592
BradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant future
Programming the Infrared board

Hi -

I wrote a quick sample program that reads the infrared board connected to 4 digital inputs. The problem is that the pulses are 100ms from the board so it's easy to miss one if your program is in a Wait.

The quick solution was to register a repeating timer - so every 30 milliseconds the code checks the four ports (4, 5, 6, and 7 in this case) and if the value changed from off to on, it sets a corresponding bit in a char variable. This all happens in the interrupt service routine for the timer. Then you can read the values in your code that may not be checking as often.

This particular program is build for Vex, but everything but the header files is the same.

Code:
#include "BuiltIns.h"
#include "ifi_picdefs.h"
#include "Vex_ifi_aliases.h"

volatile static unsigned char irCommands = 0;
volatile static unsigned char previous = 0;

// Timer interrupt service routine
// Poll the remote receiver input ports every 30ms and check if a recognized code
// came in. This will work even if the main program is in a Wait statement or doing
// other things. The IR receiver pulses for 100ms when a valid code is received.

// This will potentially show multiple hits
void CheckIR(void)
{
	unsigned char current = 0;
	unsigned char changed;
	if (rc_dig_in05) current |= 1;
	if (rc_dig_in06) current |= 2;
	if (rc_dig_in07) current |= 4;
	if (rc_dig_in08) current |= 8;
	
	changed = previous ^ current;
	irCommands |= (~previous) & current;
}

// Sample test program to 
void main(void)
{
	RegisterRepeatingTimer(30, CheckIR);
	while (1)
	{
		Wait(4000);
		printf("_____________________\r\r");
		if (irCommands & 1) 
		{
			irCommands &= ~1;
			printf("Command 1\r");
		}
		if (irCommands & 2)
		{
			irCommands &= ~2;
			printf("Command 2\r");
		}
		if (irCommands & 4)
		{
			irCommands &= ~4;
			printf("Command 3\r");
		}
		if (irCommands & 8)
		{
			irCommands &= ~8;
			printf("Command 4\r");
		}
	}
}
__________________
Brad Miller
Robotics Resource Center
Worcester Polytechnic Institute
Reply With Quote
  #2   Spotlight this post!  
Unread 13-01-2008, 21:33
Kingofl337's Avatar
Kingofl337 Kingofl337 is offline
You didn't see anything....
AKA: Adam
FRC #0501 (Power Knights)
Team Role: Mentor
 
Join Date: Feb 2005
Rookie Year: 1998
Location: Manchester, NH
Posts: 861
Kingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond repute
Send a message via Yahoo to Kingofl337
Re: Programming the Infrared board

Looks good Brad I'll have to try it out.
__________________
FIRST Team 501 PowerKnights - Mentor
FIRST Team 40 Checkmate - Mentor Alum
FIRST Team 146 Blue Lightning - Alumni
Reply With Quote
  #3   Spotlight this post!  
Unread 14-01-2008, 18:05
Abrakadabra Abrakadabra is offline
Here We Go !!!
AKA: Scott Kukshtel, Mr. K
FRC #3467 (The Windham Windup!)
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2002
Location: Windham, New Hampshire
Posts: 160
Abrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant future
Re: Programming the Infrared board

Hi Brad -

Thanks for doing this. This is also a good example of showing that you can use the IFI headers in a WPILib program, something that's not so apparent on first glance.

Some questions:

- I think I understand what RegisterRepeatingTimer() does, although it is not really documented. The header file says that timer interrupt handlers are "called with interrupts disabled". However, do you not also need to disable interrupts when you access the shared globals in the main( ) routine?

- The variables "changed" and "previous" in your ISR don't seem to do anything? Again, I think I understand what you are trying to do (e.g. collect all the commands in between times that the program actually checks for them), but "previous" never gets set to anything other than zero, and "changed" is calculated, but then not used. Would it not be simpler to just say:
Code:
 irCommands |= current;
and then the main() routine can turn off each bit as it gets processed? I think that's what the code is essentially doing now, since "previous" is always zero.
Reply With Quote
  #4   Spotlight this post!  
Unread 14-01-2008, 18:28
BradAMiller BradAMiller is offline
Registered User
AKA: Brad
#0190 ( Gompei and the Herd)
Team Role: Mentor
 
Join Date: Mar 2004
Location: Worcester, MA
Posts: 592
BradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant futureBradAMiller has a brilliant future
Re: Programming the Infrared board

Quote:
Originally Posted by Abrakadabra View Post
Hi Brad -

Thanks for doing this. This is also a good example of showing that you can use the IFI headers in a WPILib program, something that's not so apparent on first glance.

Some questions:

- I think I understand what RegisterRepeatingTimer() does, although it is not really documented. The header file says that timer interrupt handlers are "called with interrupts disabled". However, do you not also need to disable interrupts when you access the shared globals in the main( ) routine?
You're right... not documented, I'll try to fix that. It is called as an interrupt service routine so you want the code to be fast. As far as the shared globals in the main routine... good question. I don't think it's a problem because the interrupt service routine never turns them off and there is only a single value. If you wanted to count the number of times the IR code was received in the ISR and decrement the count in the main program, then it would have to be protected. As it is, I don't think you lose anything, but I could be wrong.

Quote:
Originally Posted by Abrakadabra View Post
- The variables "changed" and "previous" in your ISR don't seem to do anything? Again, I think I understand what you are trying to do (e.g. collect all the commands in between times that the program actually checks for them), but "previous" never gets set to anything other than zero, and "changed" is calculated, but then not used. Would it not be simpler to just say:
Code:
 irCommands |= current;
and then the main() routine can turn off each bit as it gets processed? I think that's what the code is essentially doing now, since "previous" is always zero.
You are so right about the previous variable not being set... I must have been sleeping. And I showed it to a few people and nobody else noticed. What I was trying to do was only set the bit on a change from off to on so. I didn't want two polls to look like two events. If you just OR the new value into the result, then if in one ISR call the bit is set, then before the next 30ms period, the main program clears the bit, then the next timer interrupt notices that the bit is still set, it would like to two button presses.

Thanks for noticing the problem!

Brad
__________________
Brad Miller
Robotics Resource Center
Worcester Polytechnic Institute
Reply With Quote
  #5   Spotlight this post!  
Unread 22-01-2008, 20:02
d235j d235j is offline
Registered User
FRC #4454
 
Join Date: Jan 2008
Rookie Year: 2008
Location: Philadelphia, PA
Posts: 25
d235j has a spectacular aura aboutd235j has a spectacular aura about
Re: Programming the Infrared board

When using WPILib with the IFI headers, which headers should I include? Also, do I need to specify whether a digital I/O is used for INPUT or OUTPUT? And can the code in the first post be used as a standalone program? which headers should be included for it?
EDIT: This is for use with an FRC controller (not Vex).
Thank you
Reply With Quote
  #6   Spotlight this post!  
Unread 31-01-2008, 17:39
Karl200 Karl200 is offline
Registered User
FRC #1785
 
Join Date: Jan 2008
Location: Blue Spring
Posts: 5
Karl200 is an unknown quantity at this point
Re: Programming the Infrared board

Could you please put up the header files that you used and what header file do we need to use instead of the vex one.
__________________
Karl (C.S.I. Fanatic and Hardcore Gamer)
Reply With Quote
  #7   Spotlight this post!  
Unread 04-02-2008, 16:20
popnbrown's Avatar
popnbrown popnbrown is offline
FIRST 5125 HOTH Lead Mentor
AKA: Sravan S
FRC #5125 (Hawks on the Horizon)
Team Role: Mentor
 
Join Date: Feb 2007
Rookie Year: 2007
Location: Illinois
Posts: 367
popnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond repute
Re: Programming the Infrared board

I understand your program Brad, however our IR Board sends a value of 0 to digital inputs 1, 2, 4 and a 1 to digital input 3. When the button for the corresponding inputs are pressed the values stay and do not change.

Instead of using the rc_dig_in variables that Kevin Watson uses. I use the WPILib function GetDigitalInput().
Code:
	
if(GetDigitalInput(IR_IN1))
	printf("IR #1\n");
else if(GetDigitalInput(IR_IN2))
	printf("IR #2\n");
else if(GetDigitalInput(IR_IN3))
	printf("IR #3\n");
else if(GetDigitalInput(IR_IN4))
	printf("IR #4\n");
I also understand that for the DigitalInputs to work I have to set whether they are used as inputs are outputs correct? so therefore I use SetDirection() for the used Digital Ports.
Code:
SetDirection(IR_IN1, INPUT);
SetDirection(IR_IN2, INPUT);
SetDirection(IR_IN3, INPUT);
SetDirection(IR_IN4, INPUT);
The port parameters all refer to macros, defined like:
Code:
#define IR_IN1 2
#define IR_IN2 3
#define IR_IN3 4
#define IR_IN4 5
One last thing, in CheckIR()
Code:
void CheckIR(void)
{
	unsigned char current = 0;
	unsigned char changed;
	if (rc_dig_in05) current |= 1;
	if (rc_dig_in06) current |= 2;
	if (rc_dig_in07) current |= 4;
	if (rc_dig_in08) current |= 8;
	
	changed = previous ^ current;
	irCommands |= (~previous) & current;
}
after each if statement could you not just do whatever each button does right after the statement, instead of using three different variables. For example,
Code:
void CheckIR(void)
{
	unsigned char current = 0;
	unsigned char changed;
	if (rc_dig_in05) Autonomous1(); //Autonomous1() is a function that does what command one is intended to be used for
	if (rc_dig_in06) current |= 2;
	if (rc_dig_in07) current |= 4;
	if (rc_dig_in08) current |= 8;
	
	changed = previous ^ current;
	irCommands |= (~previous) & current;
}
Thanks for your help ahead of time,
Sravan
Reply With Quote
  #8   Spotlight this post!  
Unread 04-02-2008, 22:10
Abrakadabra Abrakadabra is offline
Here We Go !!!
AKA: Scott Kukshtel, Mr. K
FRC #3467 (The Windham Windup!)
Team Role: Mentor
 
Join Date: Jan 2007
Rookie Year: 2002
Location: Windham, New Hampshire
Posts: 160
Abrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant futureAbrakadabra has a brilliant future
Re: Programming the Infrared board

Sravan,

The reason that the CheckIR() function is written that way is that it is an Interrupt Service Routine (ISR) and needs to be as fast as possible. It is called every 30ms, and while it is running, no other interrupts can occur.

Using GetDigitalInput() is good to use in your code that runs in the normal service loop, if for no other reason than it aids in program readability.
However, all it really does is access the same rc_dig_inXX variables that Brad's (and Kevin's) code uses. The function call has the disadvantage of having to use additional clock cycles to put the parameter, the return value, and the return address on the call stack, something you don't want to do if you don't have to when time is of the essence.

The time critical nature of the routine is also why you especially don't want to call any other functions from within it to do your work. If you do, then the entire system will slow down waiting for your code to finish. Instead, you want to just get in, check the ports of interest, put the found information in a place that's easy to access later, and get out. That's also why Brad is using the bitwise operators to save his information, rather than the more normal arithmetic operators - bitwise operations are much quicker!

Karl200 & d235j,

You should only need to include ifi_aliases.h and ifi_defaults.h. They can be found in the IFI default code package. They will also pull in a few other header files from the mcc18/h directory, so it is important to include that directory in your compile line include path. This old thread may be of some interest:
http://www.chiefdelphi.com/forums/sh...ad.php?t=42407

Brad,

While I'm here - I got rid of the changed variable and modified the last two lines of the ISR to look like this:

Code:
irCommands |= (~previous) & current;
previous = irCommands;
Does that do what you originally intended?

Last edited by Abrakadabra : 04-02-2008 at 22:15.
Reply With Quote
  #9   Spotlight this post!  
Unread 05-02-2008, 06:30
popnbrown's Avatar
popnbrown popnbrown is offline
FIRST 5125 HOTH Lead Mentor
AKA: Sravan S
FRC #5125 (Hawks on the Horizon)
Team Role: Mentor
 
Join Date: Feb 2007
Rookie Year: 2007
Location: Illinois
Posts: 367
popnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond reputepopnbrown has a reputation beyond repute
Re: Programming the Infrared board

I see.

If i do use the rc_dig_inXX variables will they not provide the same input as GetDigitalInput(XX)? The reason I'm asking is that when I press the remote button the light on the IR Sensor lights up but it doesn't show anything.

By using the if structure:
Code:
	
if(GetDigitalInput(IR_IN1))
	printf("IR #1\n");
else if(GetDigitalInput(IR_IN2))
	printf("IR #2\n");
else if(GetDigitalInput(IR_IN3))
	printf("IR #3\n");
else if(GetDigitalInput(IR_IN4))
	printf("IR #4\n");
I would be able to see when buttons 1, 2, 3, or 4 are pushed correct.

What I originally had was the code above in a very long loop to just see if any of the above printf() commands would work however they did not.

I will try using the rc_dig_inXX variables and after that implement a quicker Check() function.

Thanks for all the help.
Reply With Quote
  #10   Spotlight this post!  
Unread 06-02-2008, 20:31
ranman96734's Avatar
ranman96734 ranman96734 is offline
The Ranman
AKA: Randall Hunt
FRC #2090 (Punahou Robotics)
Team Role: Programmer
 
Join Date: Dec 2006
Rookie Year: 2006
Location: Hawaii
Posts: 4
ranman96734 is an unknown quantity at this point
Send a message via AIM to ranman96734 Send a message via MSN to ranman96734 Send a message via Yahoo to ranman96734
Re: Programming the Infrared board

1. this is my first post
2. I have a broken wrist ans this post was typed with one hand... sorry
3. i am a java programmer, not a c programmer
4. using mplab, which i've never used before

I'm using Kevin's code and I don't think it has the RegisterRepeatingTimer() ...
also there is no wait()
method or some thing b/c I can't build. I'm not a total noob to programming I've just never programmed for first. So if you guys could help me out with why this isn't working or point me to a general tutorial i'd appreciate it.

do i need to include WPILib or someting?
Error:
Code:
MPLINK 4.12, Linker
Copyright (c) 2007 Microchip Technology Inc.
Error - could not find definition of symbol 'RegisterRepeatingTimer' in file ~:\~~\~~~~\~~~~\Robotics\Programs\ifi_frc_sensor_30\autonomous.o'.
Errors    : 1

Link step failed.
BUILD FAILED: Wed Feb 06 15:22:07 2008
__________________
Strawberry Shortcake!
Reply With Quote
  #11   Spotlight this post!  
Unread 06-02-2008, 22:47
Kingofl337's Avatar
Kingofl337 Kingofl337 is offline
You didn't see anything....
AKA: Adam
FRC #0501 (Power Knights)
Team Role: Mentor
 
Join Date: Feb 2005
Rookie Year: 1998
Location: Manchester, NH
Posts: 861
Kingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond reputeKingofl337 has a reputation beyond repute
Send a message via Yahoo to Kingofl337
Re: Programming the Infrared board

You may want to start with easyC to get you started espcially with the ship date less then 10 days away. easyC has 12 tutorials in the help file. You can download it at http://www.intelitekdownloads.com/easyCPRO
__________________
FIRST Team 501 PowerKnights - Mentor
FIRST Team 40 Checkmate - Mentor Alum
FIRST Team 146 Blue Lightning - Alumni
Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
pic: Programming prototyping board Andrew Schuetze Extra Discussion 3 08-12-2007 18:30
Perf Board = BS2-IC Carrier Board? indieFan Electrical 2 16-09-2004 08:28
What is the true field infrared emitter? scottm87 Programming 4 20-04-2004 18:22
Ordering the TSOP34840 Infrared Receivers yaman Electrical 5 23-01-2004 02:10
Infrared Beacon Board AlphaOmega870 Electrical 5 23-01-2004 01:58


All times are GMT -5. The time now is 17:33.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi