esp32 - IR intervalometer for Sony a7

Posted on
Page
of 2
/ 2
Next
  • Hi!
    I have an IR intervalometer for a Sony a7 camera on an Arduino Nano. It works great, but I need to implement the same on esp32.

    Arduino simplified code:

    unsigned long TimeBetweenShots = 2000;
    int IRled = 2;
    int Begin = 13;
    
    int SCodeBits[] = {1,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,1,1­};
    
    void setup()
    {
      pinMode(IRled, OUTPUT);
      pinMode(Begin, OUTPUT);
    }
     
    void loop()
    {
      static int delta = 0;
    
      delta+=100;
      
      digitalWrite(Begin, HIGH);
      
      for (int i=1; i <= 3; i++)
      {
        header();
        for (int i=0; i <= 19; i++)
        {
              if(SCodeBits[i] == 1)
              {
                Data_is_One();
              }
              else
              {
                Data_is_Zero();
              }
        }
        delay(11);
      }
      digitalWrite(Begin, LOW);
      delay(TimeBetweenShots+delta);
    }
    
    void burst()
    {
      digitalWrite(IRled, HIGH);
      delayMicroseconds(10);  
      digitalWrite(IRled, LOW);
      delayMicroseconds(8);
    }
    
    void quiet()
    {
      digitalWrite(IRled, LOW);
      delayMicroseconds(18);
    }
    
    void header() 
    {
        for (int i=1; i <= 96; i++){
          burst();
        }
        for (int i=1; i <= 24; i++){
          quiet();
        }
    }
    
    void Data_is_One()
    {
        for (int i=1; i <= 48; i++){
          burst();
        }
        for (int i=1; i <= 24; i++){
          quiet();
        }
    }
    
    void Data_is_Zero()
    {
        for (int i=1; i <= 24; i++){
          burst();
        }
        for (int i=1; i <= 24; i++){
          quiet();
        }
    }
    

    This is JS for Espruino, just for one shot:

    const IRled = D17;
    
    let SCodeBits = [1,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,1,1­];
    
    function shot(){
      pinMode(IRled,"output");
    
      function burst(){
        digitalPulse(IRled,1,[0.01,0.008]);
      }
    
      function quiet(){
        digitalPulse(IRled,0,0.018);
      }
    
      function header(){
        for (let i=0; i < 96; i++){
          burst();
        }
        for (let i=0; i < 24; i++){
          quiet();
        }
      }
      function  Data_is_One(){
        for (let i=0; i < 48; i++){
          burst();
        }
        for (let i=0; i < 24; i++){
          quiet();
        }
      }
      function Data_is_Zero(){
        for (let i=0; i < 24; i++){
          burst();
        }
        for (let i=0; i < 24; i++){
          quiet();
        }
      }
    
      for (let i=0; i < 3; i++){
        setTimeout(function() {
          header();
          for (let j=0; j < 20; j++){
              if(SCodeBits[j] === 1){
                Data_is_One();
              }
              else{
                Data_is_Zero();
              }
          }
          console.log('IR');
        }, 11);
      }
    }
    
    function onInit() {
      setTimeout(function() {
        shot();
      }, 1000);
    }
    

    And this code doesn't work... Where did I go wrong?

  • Sun 2021.09.12

    Hi @lshk it appears you may be the first with this specific device functionality.

    There seems to be an apparent mis-understanding of how Javascript timer events work in comparrison with Arduino delays.

    While Arduino code continually loops and toggles a pin with a delay, the timeout L57-L61 that triggers the L58 shot() function, will run after the timeout interval has elapsed.

    This will take a bit of finagling, but first check out with it's live online 'Try It' windows

    https://www.w3schools.com/js/js_timing.a­sp

  • . . . . also, whould you please post the example/tutorial link along with some sample Arduino output so that we may better understand what event sequecnces we are dealing with.

  • Ok, but that's not the problem here. I removed all delays, commented out digitalPulse, but these loops are very slow. At this cycle rate, the pulse transmission frequency does not correspond to the required.

  • Maybe in this case PWM will be the solution.
    analogWrite(PIN, value, { freq : my_freq_in_hz } )

  • Maybe this is a good starting point

    http://www.espruino.com/pronto

  • I have ESP-WROOM-32 (Wemos D1 R32) and I do not see pins that support PWM. Is it really not implemented in this module?

  • Mon 2021.09.13

    Hi @lshk and thank you for the links post #5 to the overall project idea. I now have a better idea as to what functionality is required.

    re post #1: 'It works great, but I need to implement the same on esp32.'

    I note from your post #1 that you have existing 'C' source for Arduino. As I re-read the above requirement, it dawned on me a very basic question. Why not use the same code and just flash to the ESP32 from within the Arduino IDE?

    I could be missing something very basic, but this stood right out as I read back through the posts.

    Maybe you are in the process of creating an Instructable or tutorial to share here, done in Javascript instead? I'm curious, but it seems that is the easiest way to skin this cat!

  • Mon 2021.09.13

    reply to post #4

    'the pulse transmission frequency does not correspond to the required'

    What is the frequency? How is this being determined? O-Scope? Logic Analyzer?

    I have an example Logic Analyzer image, it is with SPI, but just showing to demo the capturing of example data and frequency.

    Proper technique needed to nest a setWatch()

    Are you able to post something similar?

  • Mon 2021.09.13

    reply to post #6

    analogWrite(PIN, value, { freq : my_freq_in_hz } ) Maybe in this case PWM will be the solution.

    You are on the right track. I see from the code that a width of one complete pulse is around 20usec. (Is that accurate? response from post #10 needed here)

    I'll agree that trying to simulate a pulse train with Javascript might be a bit of a challenge as Espruino is using an Interpreter and isn't compiled, but I was able to get pulse widths down towards 2usec but using a technique that isn't (best I am able to determine) available on non supported boards.

    http://www.espruino.com/Other+Boards



    Read over my thread using the PPI Programmable Peripheral Interconnect that should give you some ideas on the methods used in creating pulses, timing and detection. It wont answer all your questions, but should get you on track.

    Tutorial example output anomaly using low level access PPI

    see also

    http://www.espruino.com/InlineC
    http://www.espruino.com/Assembler



    Be prepared to put in some time reading, coding and experimenting, as some concepts take a bit of getting used to, especially if you are mostly involved in the Arduino environment.

  • Mon 2021.09.13

    reply to post #8

    re post #8   I have ESP-WROOM-32 (Wemos D1 R32) and I do not see pins that support PWM.

    While this forum is primarily directed at Espruino Javascript, I couldn't help but supply the response for this easily mis-understood missed observation.

    A simple Google exercise how to output pwm on wroom revealed this image and explanation:

    https://randomnerdtutorials.com/esp32-pi­nout-reference-gpios/

    16 channel PWM controller and output available on any output pin. Image with well defined labels, and PWM code example link ta' boot!

  • Why not use the same code and just flash to the ESP32 from within the Arduino IDE?

    Because now it is part of a larger project that will be implemented in esp32 and JS.

  • I can do the required functionality without any problems simply by connecting the Arduino Nano to the ESP32. I did it and it works. But I want to implement everything on esp32

  • I tried analogWrite() yesterday, but nothing came of it. Perhaps I just made a mistake somewhere.

    // Header data burst
    // Header Burst Timing is 2.4mS
    // Quiet Timing is 600uS
    
    // Send one data burst
    // Burst Timing is 1.2mS
    // Quiet Timing is 600uS
    
    // Send zero data burst
    // Burst Timing is 600uS
    // Quiet Timing is 600uS
    const IR_ANODE = D17;
    const IR_CATHODE = D16;
    
    const IR_FREQ = 40000;
    const pulse_ratio = 0.25;
    
    //....
    
    var run = function () {
    
    //....
      
        let header_pulses = [2.4, 0.6];
        let command_pulses = [1.2, 0.6, 0.6, 0.6, 1.2, 0.6, 1.2, 0.6, 0.6, 0.6, 1.2, 0.6, 0.6, 0.6];
        let address_pulses = [0.6, 0.6, 1.2, 0.6, 0.6, 0.6, 1.2, 0.6, 1.2, 0.6, 1.2, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 1.2, 0.6, 1.2, 0.6, 1.2, 0.6, 1.2, 0.6];
        let pause = 11;
      
    
        function code(){
            digitalPulse(IR_CATHODE,0,command_pulses­);
            digitalPulse(IR_CATHODE,0,address_pulses­);
            digitalPulse(IR_CATHODE,1,pause); 
        }
    
        function header(){
          digitalPulse(IR_CATHODE,0,header_pulses)­;
        }
    
        function shot(){
            analogWrite(IR_ANODE, pulse_ratio, { freq : IR_FREQ } );
            for (let i=0; i < 3; i++){
                header();
                code();
            }
            digitalPulse(IR_CATHODE, 1, 0);
            digitalRead(IR_ANODE);
        }
    
    //....
        function some_function(){
            //....
            console.log('shot');
            shot();
            //....
        }
    //....
    
    };
    

    1 Attachment

    • sony_IR.jpg
  • Tue 2021.09.14

    reply to post #15

    'Perhaps I just made a mistake somewhere.'

    Nicely written code block @lshk    Neat, concise and self descriptive.

    Nothing stands out.

    'but nothing came of it.'

    What is meant here? The camera just didn't respond and troubleshooting ceased as an O-Scope or Logic Analyzer wasn't available?



    The diagram output now makes more sense. That tid-bit would have assisted immensly initially. But it does appear doable.

    What is the visual output of the code block above, so that we may compare with what the Sony device is expecting?

  • I see a reference to both Cathode and Anode used in code snippet. Is the IR diode connected across both these pins? Backwards? Lacking pullup? Need a current driver like a 2n2222?

    What is the pin mode set to? I don't see those lines of code?

    http://www.espruino.com/Reference#l__glo­bal_getPinMode

    or use dump() on the command line.



    Potential conflict L41 and L47 :: Using both analog and digital on the same pin.

  • Yes, exactly, I don't have an oscilloscope or something like that. Unfortunately.

  • ' I don't have an oscilloscope'

    See post #3 and #4 for images of this handy little device.

    http://forum.espruino.com/conversations/­332295/

    The FX2 Logic Analyzer is inexpensive and helped solved many timing issues. . . .

  • I look at my code and the SIRC description - "The pulses usually have a mark / space ratio of 1: 4, to reduce the current consumption." 0.25 is the wrong ratio, it should be 0.2
    I don't think this might be a problem. I'll try to fix it in the evening

  • I'm not certain about this, but it appears that only whole integers are used in the examples:

    http://www.espruino.com/Reference#l__glo­bal_digitalPulse

    ref: L24 - L27

  • '0.25 is the wrong ratio, it should be 0.2'

    1::4 == 1 / 4 = 0.25


    1 == 1.2ms == 1200usec
    space == 600usec

    Mark/space ratio -- 450usec     1200 + 600 = 1800 / 4 = 450

  • 1:4!=1/4...
    1:4 ratio -> 1+4=5 inetervals. 1/5 and 4/5

  • .

  • .

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

esp32 - IR intervalometer for Sony a7

Posted by Avatar for lshk @lshk

Actions