Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: How to quickly toggle 38kHz signal?

  1. #1

    How to quickly toggle 38kHz signal?

    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.

  2. #2
    Senior Member
    Join Date
    Jan 2014
    Posts
    149
    Gate the output using a timer, or discretely control the signal gate with a dig i/o pin.

  3. #3
    Senior Member
    Join Date
    Jun 2013
    Location
    Torrance CA
    Posts
    397
    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);
            }
        }

  4. #4
    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.

  5. #5
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,343
    i'd choose your 2nd alternative. when you do analogWrite(myPin, 0), the core actually does digitalWrite(pin, LOW);

  6. #6
    Thanks, @manitou!

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    21,356
    Quote Originally Posted by feklee View Post
    How do I quickly modulate the signal, i.e. turn it on an off?
    The IRremote library does this. Maybe look at its code? Or just use IRremote, since it already does this quite well.

  8. #8
    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.

  9. #9
    Junior Member
    Join Date
    Jun 2017
    Posts
    1

    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/17532...PIO_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/bui...th-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.

  10. #10
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •