1 2 Previous Next 19 Replies Latest reply on Sep 1, 2014 3:01 AM by AllynH

    Simulate 38kHz IR signal for remote on Galileo

    cestlavieww

      Trying to write an IR remote. plugged an LED in pin 3, want to simulate PWM 38kHz. This is the code I'm using, when I print it seems correct, the on/off codes works when i use Arduino, but when I modify the code using simdelays and pulseIR, it just doesn't work. Hoping someone can help me create a 38kHz frequency pulsing function and I can just plug in number of microseconds to pulse at 38kHz. Thanks!


      Original Source taken from: https://learn.adafruit.com/ir-sensor/making-an-intervalometer


      Modified Code:

      // This sketch will send out a Nikon D50 trigger signal (probably works with most Nikons)

      // See the full tutorial at http://www.ladyada.net/learn/sensors/ir.html

      // this code is public domain, please enjoy!

       

      int IRledPin =  3;    // LED connected to digital pin 13

      // The setup() method runs once, when the sketch starts

      unsigned long a = 0;

      unsigned long b = 0;

      unsigned long t1 = 0;

      unsigned long t2 = 0;

       

      void setup()   {               

        // initialize the IR digital pin as an output:

        pinMode(IRledPin, OUTPUT_FAST);     

        Serial.begin(9600);

      }

       

      void loop()                    

      {

        Serial.println("Sending IR signal");

        digitalWrite(IRledPin, LOW);

        delay(1000);

        SendNikonCode();

       

      Serial.println("boo!");

        delay(60*1000);  // wait one minute (60 seconds * 1000 milliseconds)

      }

       

      void simdelay(int wait) {  

        t2 = t1;

        while( (t2-t1) < wait) {

          t2 = micros();

        }

      }

       

       

      // This procedure sends a 38KHz pulse to the IRledPin

      // for a certain # of microseconds. We'll use this whenever we need to send codes

      void pulseIR(long microsecs) {

        // we'll count down from the number of microseconds we are told to wait

       

        //cli();  // this turns off any background interrupts

        noInterrupts();

        while (microsecs > 0) {

          a = micros();

          // 38 kHz is about 13 microseconds high and 13 microseconds low

         //digitalWrite(IRledPin, HIGH);  // this takes about 1.1 microseconds to happen

         fastGpioDigitalWrite(GPIO_FAST_IO3, HIGH);

         b = micros();

         while ( (b-a) < 13) {

           b= micros();

         }

         //simdelay(11);         // hang out for 10 microseconds, you can also change this to 9 if its not working

         fastGpioDigitalWrite(GPIO_FAST_IO3, LOW);

         //simdelay(11);         // hang out for 10 microseconds, you can also change this to 9 if its not working

       

       

         while ( (b-a) < 26) {

           b= micros();

         }

         // so 26 microseconds altogether

         microsecs -= (b-a); //= 26;

        }

        interrupts();

        //sei();  // this turns them back on

      }

       

       

      void SendNikonCode() {

        // This is the code for my particular Nikon, for others use the tutorial

        // to 'grab' the proper code from the remote

       

        pulseIR(8880);

        simdelay(4320);

        pulseIR(640);

        simdelay(480);

        pulseIR(640);

        simdelay(480);

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(480);

        pulseIR(560);

        simdelay(480);

        pulseIR(640);

        simdelay(480);

        pulseIR(640);

        simdelay(480);

        pulseIR(560);

        simdelay(560);

        pulseIR(560);

        simdelay(1600);

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(480);

        pulseIR(640);

        simdelay(1600);

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(1600);

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(1520);

        pulseIR(640);

        simdelay(480);

        pulseIR(640);

        simdelay(480);

        pulseIR(560);

        simdelay(560);

        pulseIR(560);

        simdelay(1600);

        pulseIR(560);

        simdelay(560);

        pulseIR(560);

        simdelay(480);

        pulseIR(640);

        simdelay(480);

        pulseIR(640);

        simdelay(480);

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(1600);

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(480);

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(1600); 

        pulseIR(560);

        simdelay(1600);

        pulseIR(640);

        simdelay(1600);

        pulseIR(560);

        simdelay(39040);

        pulseIR(8800);

        simdelay(2160);

        pulseIR(640);

      Serial.println("done!");

      }


        • 1. Re: Simulate 38kHz IR signal for remote on Galileo
          JPMontero_Intel

          Hi cestlavieww

           

          Check out this post https://communities.intel.com/thread/51413 in there AllynH describes how he created an IR remote control for a camera. I hope you find it useful and let me know if this is what you are looking for.

           

          Regards,
          JPMontero_Intel

          1 of 1 people found this helpful
          • 2. Re: Simulate 38kHz IR signal for remote on Galileo
            SpiderKenny

            I think a lot of people new to Galileo get disappointing results when they try to bring over other Arduino sketches.

            Possibly the single main issue that people have time and time again is the timing of GPIO signals.

            There is a lot of FUD about why the timings on Galileo are not as precise as other Arduino UNO boards, and people use it as a reason to criticize the Galileo.

             

            In order to understand why the Galileo is different, you need to understand how the galileo is different from other Arduino UNO systems.

            First, most other Arduino Uno Systems have a micro-controller on board, directly connected to the header pins, and that's about it.

            They have deterministic timing of everything due to the fact that it runs at a fixed speed, executing a single thread of instructions from the Sketch.

            The Galileo however is not a micro-controller with a header slapped on. It is a full computing system. It has an operating system, hardware abstraction layers, a file system and storage. It even has USB Host Mode and Client Mode built right in. The processor does not execute a single thread of instructions like the other systems, it runs an embedded Linux distro. Your Sketch is simply one process in amongst the dozens of others which get scheduled to run on the processor. And guess what? When the Linux scheduler sees a nice delay loop it's an opportunity for it to de-schedule your process and schedule some of the others. Therefore the timing on Galileo is non-deterministic. In other words, you cannot use delay loops to time GPIO transisitons.

             

            At this point, all those who have only used processors (including microcontrollers) up til now, and have never used a full computing system in embedded electroncs throw their arms in the air and shout "what a load of crock! I can't do basic signal timing on this thing?!?" - but they are wrong. The mistake they made was to chose a computing system to do the job of a micro-controller.

             

            Think of the Galileo more as an efficient, lean, and inexpensive "computer" (a much mis-used term, which I'm using here to mean: Desktop PC).

            How would you interface an IR Transmitter to a Desktop PC? - You'd use an interface. You wouldn't open up the PC and hook it directly to one of it's IO Pins on the expansion header!!

             

            With Galileo you have to think in those terms, ie similar to a PC, not in terms of micro-controllers.

             

            Intel's marketing for Galileo clearly states that it runs Linux - which is your clue that this is a computing system, not a micro-controller. It's horses-for-courses, chose the right device to do your job.

             

            Lets say for example that all you want to do is spit out a specific IR Remote control code when someone presses a button. A cheap 8-Bit PIC12F629 would be a much better choice for that, than a Galileo!

             

            However, say the IR Transmitter is just a small part of a bigger project, with sensors and displays and all kinds of wonderful other things. Then a Galileo might be a good choice, but you'd use an interface for the IR transmitter and then your code to transmit a single IR code might be one line of code, to send the data to the interface using UART, SPI or I2C, and would not waste the processors time doing delay loops.

             

            In summary, the Galileo is fully equipped PC in a small form factor. Do you really need a Full PC to transmit IR Codes? Probably not, given that most Remote Controls can spit out dozens of different IR codes, and flash an LED, using only a cheap sub-dollar chip with an RC oscillator.

             

            **Edited to fix some spelling/Grammar mistakes**

            • 3. Re: Simulate 38kHz IR signal for remote on Galileo
              AllynH

              Hi cestlavieww,

               

              I have created an IR remote control for a Nikon camera using the Galileo.

              I have a blog with the full build instructions, as well as the results of some GPIO experiments I ran to generate different value clocks.

              I also have a webserver running on my Galileo so I can control the camera via my iPad / phone, I'll be updating my blog with build instructions for that too.

              I have details on how I made some time-lapse movies there too.

               

              I used the OUTPUT_FAST mode to create a 477KHz waveform and then divided it down to create a 38.4Khz clock.

               

              Create a 38.4KHz waveform:

              void setup() {

                // put your setup code here, to run once:

                pinMode(2, OUTPUT_FAST);

              }

               

              void pulseLoop(int pulses, int SHINE)

              {

                // Integers for loops:

                int i;

                int n;

                // delayValue is used to delay the clock from 477KHz to 38.4KHz:

                int delayValue = 12;

               

                register int x = 0;

               

                // Loop to control the number of pulses created

                // Number is multiplied by 2 to create both the low and high period of the pulse:

                for(n=0; n<(pulses*2); n++)

                {

                  // Loop to delay the digitalWrite to 38.4KHz:

                  for(i=0; i<delayValue; i++)

                    {

                      // SHINE only activated the IR LED when we are supposed to pulse, deactivates for the delay:

                      digitalWrite(2, (x & SHINE));

                    }

                  x =!x;

              }

              }

               

              Full build instructions:

              http://allynh.com/blog/making-an-ir-remote-control-for-a-nikon-camera/

               

              My Nikon IR remote code on GitHub:

              Nikon_IR_Remote_Intel_Galileo/Nikon_Remote.ino at master · AllynH/Nikon_IR_Remote_Intel_Galileo · GitHub

               

              Video:

              1 of 1 people found this helpful
              • 4. Re: Simulate 38kHz IR signal for remote on Galileo
                AllynH

                SpiderKenny wrote:

                 

                Do you really need a Full PC to transmit IR Codes? Probably not, gicen that most Remote Controls can spit out dozens of different IR codes, and flash an LED, using only a cheap sub-dollar chip with an RC oscillator.

                 

                Probably not - but it fun to do it

                • 5. Re: Simulate 38kHz IR signal for remote on Galileo
                  cestlavieww

                  Hi SpiderKenny,

                   

                  Thanks for the response and yes I agree you should pick the right tools for the right job. I am trying to implement this as part of a larger project centered around home automation. All other things, as you mentioned, work really well and was fairly straightforward to implement (basically creating a voice controlled "smart" device that knows what to do when i say something and that plugs nicely into legacy remote controlled devices, eg. lights, garage, fan, etc. anything that has a remote). This is the only component left that I'm having some trouble with, but I know there must be some kind of workaround to get it working. Hoping to find it here. Thanks!

                  • 6. Re: Simulate 38kHz IR signal for remote on Galileo
                    cestlavieww

                    Thanks JPMontero_Intel, this is exactly what i'm looking for. I'm trying this out right now. Hoping to get it to work. Thanks!

                    • 7. Re: Simulate 38kHz IR signal for remote on Galileo
                      cestlavieww

                      Thanks so much AllynH, I plugged in your code but it's still not quite working. Here's the updated code snippet, any ideas? I've modified it to take microseconds rather than pulses, does that look correct? Are you using a galileo Gen 1 or Gen 2? For the 8880, 4320, 640, 480 pulse I'm reading 9681, 8131, 4452, and 4222 microseconds instead.. Thanks!

                       

                      int IRledPin =  2;


                      void setup()   {               

                        // initialize the IR digital pin as an output:

                        pinMode(IRledPin, OUTPUT_FAST);     

                        Serial.begin(9600);

                      }

                       

                      void loop()                    

                      {

                        Serial.println("Sending IR signal");

                        delay(1000);

                        SendNikonCode();

                       

                        delay(60*1000);  // wait one minute (60 seconds * 1000 milliseconds)

                      }

                       

                       

                      void pulseIR(int usec, int SHINE)

                      {

                        // Integers for loops:

                        int i;

                        int n;

                        int pulses = usec / 26;

                        // delayValue is used to delay the clock from 460KHz to 38.4KHz:

                        int delayValue = 12;

                       

                        register int x = 0;


                        // Loop to control the number of pulses created

                        // Number is multiplied by 2 to create both the low and high period of the pulse:

                        for(n=0; n<(pulses*2); n++)

                        {

                          // Loop to delay the digitalWrite to 38.4KHz:

                          for(i=0; i<delayValue; i++)

                            {

                              // SHINE only activated the IR LED when we are supposed to pulse, deactivates for the delay:

                              digitalWrite(IRledPin, (x & SHINE));

                            }

                          x =!x;

                      }

                      }


                      void SendNikonCode() {

                        // This is the code for my particular Nikon, for others use the tutorial

                        // to 'grab' the proper code from the remote

                       

                        pulseIR(8880, 1);

                        pulseIR(4320, 0);

                        pulseIR(640, 1);

                        pulseIR(480, 0);

                        pulseIR(640, 1);

                        pulseIR(480, 0);

                        pulseIR(560, 1);

                           // etc...

                      Serial.println("done!");

                      }

                      • 8. Re: Simulate 38kHz IR signal for remote on Galileo
                        AllynH

                        Hi cestlavieww,

                         

                        My code works on both Gen 1 and Gen 2 Galileo's.

                         

                        Did you try my code directly? It should work on all Nikon cameras...

                        How are you measuring the outgoing signal? I used a Saleae Logic analyzer, which was very accurate,

                        I believe there was another post about reading IR signals using an IR receiver and the poster had issues with timing too.

                         

                        Rather than modifying it to take microseconds, I would use the full code and modify the array to contain the pulse count - this should work for any 38Khz signal.

                        So, if you wanted to port this to another remote / SLR camera / IR receiver, you only need to add another command array.


                        // Create an array for the pulse values:

                        int nikonCommand[16] = {76, 1058, 15, 61, 15, 137, 15, 1078, 76, 1058, 15, 61, 15, 137, 15, 1078};

                         

                        void takePicNikon()

                        {

                        for(int x=0; x<sizeof(nikonCommand)/sizeof(int); x++)

                          {

                            int y = x + 1;

                              pulseLoop(nikonCommand[x], (y%2));

                          }

                        }


                        One more thing:

                        I know the println statements added a big delay to my code and broke everything, so try moving the "Serial.println("done!");" inside the main() {} after the SendNikonCode();

                         

                        AllynH

                        • 9. Re: Simulate 38kHz IR signal for remote on Galileo
                          SpiderKenny

                          cestlavieww and AllynH

                          I think this is indicative of the non-deterministic nature of GPIO Timing on Galileo (any every other OS based system). If the board is doing anything different between the two runs then the timings will be different.

                          For example, if there is a network connection open, an FTP or SCP in progress, if the kernel decides to flush the SD Card buffers at just the wrong moment, and any number of other things will affect the GPIO timing because the thread of your Sketch will get de-scheduled and re-scheduled all the time.

                           

                          Don't get me wrong, the sketch based approach is absolutely fine if you can get it working and stable for you, but if you want to incorporate that into another project, port to another board, or even run on another board which may have a slightly different firmware version, then you will need to adjust the code each time. You could probably build in some calibration routines to help with that.

                           

                          But if you want a rock solid solution that is guaranteed to work every time without fail, my recommendation would be to build a small interface board, with a small low cost PIC, ATMega or similar and hook it up to a single 'trigger' IO pin on the galileo. You are going to be building/hacking some kind of hardware together anyway and this would cost just a few pennies extra. Here in the UK a PIC12F629 costs £0.77

                           

                          Here is an IR Transmitter I found on Goolge which can send out any 4 different codes:

                          3ch_remote.PNG

                           

                          I found that at this page. The code there could be modified to send any IR Commands. You could probably even do away with the crystal and caps and still have it work very reliably using the PICs RC oscillator.

                           

                          Finally, just for citation, I have done a great deal of work designing IR Repeaters, IR Learners and IR Pass-Thru systems for industrial control and home entertainment systems. If there's anything you disagree with, or would like to ask more please feel free to get in touch, anytime.

                          • 10. Re: Simulate 38kHz IR signal for remote on Galileo
                            cestlavieww

                            Hi AllynH,

                             

                            I ended up borrowing an oscilloscope to ensure I'm sending at the right frequency. Basically confirming SpiderKenny's comment "I think this is indicative of the non-deterministic nature of GPIO Timing on Galileo (any every other OS based system)." Even though I turn off interrupts it still shifts around quite a bit. There's no way to get a stable frequency like the Arduino. Looking at the oscilloscope, constantly writing HIGH's and LOW's seem to introduce greater noise as well as more shifts in the frequency. What I've found was that using fastGpioDigitalWrite(GPIO_FAST_IO3, HIGH/LOW) with a simdelay function of 12 microseconds (which I based off of the response from DinoT_Intelin this post: pulseIn ) seemed to be most stable. But even then, it did not work consistently. The workaround I applied was basically send the signal multiple times over a very short period of time. Testing with my setup, this worked 99% of the time. Your posts were super helpful in terms of understanding the I/O issues for Galileo, so many thanks to you!

                            • 11. Re: Simulate 38kHz IR signal for remote on Galileo
                              AllynH

                              Also,

                              Further to SpiderKenny's post - if you wanted to go the interface route for a Nikon - here is one of the links I was working from:

                              This guy "BigMike" creates an IR remote using an ATTiny2313: http://www.bigmike.it/ircontrol/

                               

                              The interface route is pretty interesting, for my project it was a bit overkill, but it may be something you could look into!

                              I was running my remote from a Web Server and was controlling the camera and displaying the picture count in the HTML, I didn't see any issues with stability and the camera fired 100% of the time.

                              However once you scale up from this, it may be come an issue. I may try to run a stress test later and see just how much the Galileo can handle

                              • 12. Re: Simulate 38kHz IR signal for remote on Galileo
                                kurjak

                                Hi AllynH,

                                I found your code very interesting.

                                As I'm not good in programming (just the basic things), I would ask you that you can modify it a bit to send just a pulses train at the same frequency, no different pulses.

                                I tried to do it, but ... nothing.

                                Practically I need a pulse train and the possibility to change frequency from consolle. I'm sure it's very simple but I miss knowledge!

                                The range of frequency is from 1KHz to 100KHz so your program should be perfect.

                                Thank you.

                                Best Regards.

                                 

                                Cris

                                • 13. Re: Simulate 38kHz IR signal for remote on Galileo
                                  AllynH

                                  Hi Kurjak,

                                   

                                  I'm not sure I understand what you're asking.

                                  Are you using the Arduino IDE?

                                  How do you want to modify the frequency? Using the Serial console?


                                  The pinMode(xxx, OUTPUT_FAST) sets the max GPIO frequency to 477KHz, I divide this number by 12 to get the 38.4KHz signal.

                                  The code below will give you a 38.4KHz clock signal, if you want you can use the Serial.read() function to input a new value and change the delay.

                                   

                                  Change this delay value:

                                  // delayValue is used to delay the clock from 460KHz to 38.4KHz:

                                  int delayValue = 12;

                                   

                                  // Setup the pin used for the IR LED:

                                  int pinIR_LED = 2;

                                   

                                  // Setup pin to fast mode:

                                  void setup(){

                                      pinMode(pinIR_LED, OUTPUT_FAST);

                                  }

                                   

                                  void loop()

                                  {

                                    // Integers for loops:

                                    int i;

                                    int n;

                                   

                                    register int x = 0;

                                   

                                    // Loop to control the number of pulses created

                                    // Number is multiplied by 2 to create both the low and high period of the pulse:

                                    for(n=0; n<(pulses*2); n++)

                                    {

                                      // Loop to delay the digitalWrite to 38.4KHz:

                                      for(i=0; i<delayValue; i++)

                                        {

                                          // SHINE only activated the IR LED when we are supposed to pulse, deactivates for the delay:

                                          digitalWrite(2, (x & SHINE));

                                        }

                                      x =!x;

                                  }

                                  }

                                   

                                  If you do want to use the Serial console, have a look at this artical:

                                  http://arduino.cc/en/Serial/read

                                   

                                  Let me know if this is working for you!

                                  • 14. Re: Simulate 38kHz IR signal for remote on Galileo
                                    kurjak

                                    Hi AllynH

                                    thank you for your answer.

                                    I'm using the Arduino IDE ... built for Galileo and I have a Galileo 1st generation.

                                    I took your original code and i modified it.

                                    I understood that to decrees the frequency from "pinMode(pinIR_LED, OUTPUT_FAST)" 477 MHz, there is this relation: "out_frequency = 477000/delayValue"

                                    So I connected the pin 2 to the "audio in" port of my macbook pro and using Audacity and iSpectrum I got on my display the generated wave form.

                                    I assumed that "out_frequency = 477000/delayValue" is not really linear. At 1000  Hz it is perfect, but more the frequency is high, the real value is more and more distant from the calculated value. At this moment, it doesn't really matter for my application.

                                    What is important, indeed, is the really bad wave form. Using the audio card of my mac, I cannot go over 20 KHz, but around that the wave looks really different from a square wave; but it might be a problem of the audio card. Unfortunately I don't own an oscilloscope.

                                    About consolle, I think i can easily perform it.

                                    Thank you again for your suggestion. I will try your code, exactly as you posted, and i will verify the wave form again.


                                    Best Regards


                                    Cris

                                     

                                    1 2 Previous Next