Recently, I've been trying to get a phototransistor to detect light from an infrared led. They both work fine, and I have the phototransistor connected to an analog input on my Uno. The readings I get over the serial port only change by around twenty when I block or disconnect the LED. My fear is that because I will be using this combo to search for nodes (LED on node, phototransistor on robot) that the robot won't be able to detect the IR from the node. Does anyone know a way I could amplify the LED or the input? Could I simply multiply the input variable to make it, and therefore the difference, bigger? These are the parts I'm using.
What you are seeing could be due to the phototransistor being swamped by ambient IR. The general solution to this is to modulate the IR LED (normally at 38kHz) and only respond to a received signal that matches this.
Use a 38kHz IR receiver module (it has a PIN photodiode with amplifier and demodulator built-in) and send data by modulating a 38kHz carrier on the IR LED.
I tried using the LEDs again today, but for some reason they refused to work. They worked yesterday, but not today. Oh, temperamentality...
Anyway, fungus, I was (when the thing worked) powering the LED with the 3.3v power supply on the Uno because I put my 3v battery pack in a very safe place and promptly forget where that very safe place was. Sirch and polymorph, how would I modulate the LEDs? Would I be able to get an analog reading of the IR?
How are you driving the LED? If you are doing so directly from a battery or an Arduino pin without a current limiting resistor, you may have destroyed the LED, and possibly damaged your Arduino. You must use something to limit current. An LED is just a diode that drops more voltage across it. In fact, if you look at a glass cased diode like a 1N914 or 1N4148, you'll see it glowing in IR. An IR LED typically drops something closer to 1.5V and emits IR at a shorter wavelength than a standard silicon diode.
As for the carrier and modulation, I'm not a software guy, but I'm working on it. You could use the Tone library to generate the proper frequency, it is good up to 60kHz, I think. Then AND that with another pin. Use that pin to output serial data as if it were going to an RV transmitter (non-return to zero, Manchester encoding, whatever you'd do for that). What comes out of the AND gate will be the serial data with a 38kHz turned on and off by the serial data.
Use that to drive a logic level MOSFET, source to ground, drain connected to the IR LED(s) and current limiting resistor. Now you have an IR transmitter that sends out a 38kHz signal modulated by the serial data from the Arduino.
On the other end, an IR receiver module. Radio Shack has them, Farnell does I'm sure, just about every mail order electronics place will have them.
Someone more skilled in the art of programming can likely tell you how to avoid using an external AND gate to do this.
So how would modulation work? Could I get an analog reading of the IR? I don't want the LEDs to transmit data. AT ALL. They just need to be turned on so my robot can detect (using analog input) which direction the node is in. So then when you get into the whole modulation thing, every piece of kit you can find is designed to transmit data. I want my nodes to simply be a battery pack, a current limiting resistor and then a bunch of IR LEDs in parallel, which would keep it simple. I just need a way to amplify the input or to make the sensor more sensitive to the IR LEDs. Can anyone help me out here?
I suggest you modulate the transmitting LEDs at a low frequency, such as a few hundred Hz or a couple of kHz, avoiding multiples of your local mains frequency. You can generate this using an Arduino or a 555 timer. At the robot, feed the received IR signal to the ADC and use a Goertzel filter or similar algorithm to detect that frequency. See Frequency Detection. If the robot has 2 or more sensors pointing in 2 slightly different directions, then from the relative amplitudes, you can work out which way to turn in order to line up with the transmitter.
So I did a bit of research and thinking, and I might have come up with a solution. (I hope. :))
Could I use something like this as the receiver? I picked it because it won't drop a continuous signal. Its peak sensitivity is 950nm.
Would any of that work? Would I be able to detect the signal using an analog input? Its very important that I can detect the strength of the IR signal.
dc42, I had a look, and to be honest, I think that algorithm (and possibly any other) is a bit beyond me at this stage. Also, the way my robot works is that it turns in definite relative positions. e.g. turn 45 degrees to the left, so that it can easily re-trace its steps. Therefore, that kind of tracking wouldn't work too well on the robot I was planning.
You can certainly use that type of receiver. However, it will only give you an on/off indication, i.e. tell you that a 38kHz modulated IR signal is there or not. So you can't measure how strong the received signal is, and you can't measure the relative intensity of the signals picked up by two or more different signals. Can you manage with just a present/not present indication?
Actually dc42, I think I could. If I put a ring of the sensors on top of the robot I could eliminate the need for a servo to scan and still keep the directional functionality. Thanks!
Now my question is, how can I use a dedicated attiny84 to modulate the LEDs at 38khz?
GeekyD00d:
Now my question is, how can I use a dedicated attiny84 to modulate the LEDs at 38khz?
Why use an attiny84 when you only need 1 output pin? Here is the code I use on an attiny45. Just call setFrequency(38000u) and then call on(). It's written for AVR Studio, so if you want to use it with an Arduino code for attiny25/45/85, remove the definition of F_CPU
#include <avr/io.h>
#define F_CPU (8000000UL) // 8MHz
// Set the frequency that we will get on pin OCR1A but don't turn it on
void setFrequency(uint16_t freq)
{
uint32_t requiredDivisor = (F_CPU/2)/(uint32_t)freq;
uint16_t prescalerVal = 1;
uint8_t prescalerBits = 1;
while ((requiredDivisor + prescalerVal/2)/prescalerVal > 256)
{
++prescalerBits;
prescalerVal <<= 1;
}
uint8_t top = ((requiredDivisor + (prescalerVal/2))/prescalerVal) - 1;
TCCR1 = (1 << CTC1) | prescalerBits;
GTCCR = 0;
OCR1C = top;
}
// Turn the frequency on
void on()
{
TCNT1 = 0;
TCCR1 |= (1 << COM1A0);
}
// Turn the frequency off and turn off the IR LED.
// We let the counter continue running, we just turn off the OCR1A pin.
void off()
{
TCCR1 &= ~(1 << COM1A0);
}
Alternatively, use a 555 timer. The frequency does not have to be very accurate.
Why use an attiny84 when you only need 1 output pin?
Oh, just because I have two lying around already, so its just handier to use them. Your code looks pretty complicated. I don't get any of it at all(). Would this (arduino) code work instead?
int ledpin = 1; //initialise led control pin
void setup(){
pinMode (ledpin, OUTPUT); //set as output, yada yada
}
void loop(){
digitalWrite(ledpin, HIGH); //on
delayMicroseconds(13);//wait
digitalWrite(ledpin, LOW);//off
delayMicroseconds(13);//wait
}
Also, how many LEDs could I power from one of the IO pins on the attiny84? Would I be able to connect 10 of them to one pin in parallel through a current-limiting resistor or would I have to control the ten of them with a transistor?
That code won't work very well (although possibly well enough, because the exact frequency isn't critical), because the time it takes to do the digitalWrite calls will mess up the timing. It should work better if you change it to use direct port I/O and disable the timer 0 interrupt. But it is better to learn how to program one of the timers to generate the frequency you want directly.
IR LEDs usually need 60-100mA to run at full power, so you can't drive them directly from the microcontroller pins unless you accept a lower power output. But you can drive them using an NPN transistor or N-channel mosfet..