How to quickly toggle 38kHz signal?

Status
Not open for further replies.

feklee

Active member
As suggested in the thread Create 38kHz square wave with Teensy LC?, to generate a 38kHz signal, I am using:
Code:
analogWriteFrequency(myPin, 38000);
analogWrite(myPin, 128); // for a 50:50 square wave

How do I quickly modulate the signal, i.e. turn it on an off?

What comes to my mind:
  • Alternate digitalWrite(myPin, LOW) and analogWriteFrequency(myPin, 38000).
  • Alternate analogWrite(myPin, 0) and analogWrite(myPin, 128).
  • Modulate the signal using an external component, e.g. a transistor.

The project is a light barrier with crossing beams to detect motion of a hand. For two reasons I am considering quickly cycling through the beams instead of having them on all the time:
  • To avoid the wrong sensor from being triggered (by reflective objects, or by neighboring beams).
  • To generate bursts. In a message on Electrical Engineering Stack Exchange I was told that the sensor which I am using, the Vishay TSSP4038 only reacts to bursts of 38kHz. That being said, I cannot reproduce the issue. In my current setup, the sensor constantly outputs high when a beam is interrupted, and it constantly outputs low when it sees 38kHz.
 
Gate the output using a timer, or discretely control the signal gate with a dig i/o pin.
 
You could set up an IntervalTimer and flip the state

Code:
IntervalTimer myTimer;

void setup(void) {
    myTimer.begin(Flipper, 10000); // flip the state 100 times per second
    ...
    }

void Flipper(void) {
    static int state=0;

    if (state==0) {
        state=1;
        analogWrite(myPin, 128);
        }
    else {
        state=0;
        analogWrite(myPin,0);
        }
    }
 
Thanks for the suggestions. However, I was not asking how to time the switching. I was asking how to quickly switch, in particular which one of the following methods is quicker:
  • Alternate digitalWrite(myPin, LOW) and analogWriteFrequency(myPin, 38000).
  • Alternate analogWrite(myPin, 0) and analogWrite(myPin, 128).
Or whether it's advisable to modulate the signal using an external component, e.g. a transistor.
 
i'd choose your 2nd alternative. when you do analogWrite(myPin, 0), the core actually does digitalWrite(pin, LOW);
 
The disadvantage of IRremote is that it’s designed for only one IR LED, while we have multiple LEDs that need to be cycled.

I now tried a simple solution:
Code:
analogWrite(myPin, 128); // 50:50 square wave
delayMicroseconds(263);
boolean beamIsInterrupted = digitalRead(sensorPin);
analogWrite(myPin, 0);
This works. In accordance to an application note of the TSSP4056 IR sensor, if I reduce the length of the burst to less than 10/f₀, e.g. with delayMicroseconds(200), then the sensor does not trigger anymore.
 
Raw Write and Raw Read

I was working with IR signals recently on an Atmel 328p (Arduino Uno) to try and duplicate an IR signal; before writing my own, I looked through some of the code on Adafruit and found that they use direct manipulation of the ports.to read and write quickly. There's some info here: https://www.arduino.cc/en/Reference/PortManipulation, but the gist is that you can read or write 8 pins at once with 8 bits. You set the R/W status by storing into the DDRD register, can read with PIND, and write with PORTD.

I haven't done this on a teensy/ARM, and looked for the equivalent registers, which was, happily, covered in this forum: https://forum.pjrc.com/threads/1753...PORT-DDR-D-B-registers-vs-ARM-GPIO_PDIR-_PDOR

IIRC, the IRremote library uses PWM to write, while this post shows how to alternate between low, and toggling high/low quickly to get the same effect: http://www.zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/

I also found it instructive to time many repetitions of various operations. This is all with the 328p, but: digitalWrite/digitalRead turned out to take 4-5 microseconds, while the register store/reads took 1/2 a microsecond. Checking the time, via micros(), took 3, and there were also varying overheads associated with delayMicroseconds, depending on the value passed to that function.
 
Thanks for the suggestions! Instead of delayMicroseconds, I now consider using some sort of timing interrupt, have to read up on that topic. That way the controller can do somthing useful in between.
 
Status
Not open for further replies.
Back
Top