手把手教你做一个相机红外遥控器

嵌入式大杂烩 2021-11-09 21:30

ML-L3是用于尼康部分型号相机的无线红外遥控器,可以通过红外方式来控制快门的释放,支持B门拍摄。官方售价100RMB左右,山寨版售价10RMB左右。虽然也能实现基本的遥控功能,但是功能还是比较单一,如不能实现定时拍摄,即用来拍摄制作延时视频的素材。本篇文章介绍如何通过Arduino、MCU或FPGA来控制红外发射器,产生快门指令从而实现无线遥控快门的功能。

拆解ML-L3遥控器

为了实现ML-L3遥控器的功能,我们首先要了解无线遥控器的原理。当然最好的方式就是拆解一个ML-L3,然后看看内部的电路,然后测出红外的编码。但是手头又没有这样的一个遥控器,有国外的网友已经拆解了并且测出了红外编码的波形,如下图。

官方遥控器PCB板:

山寨遥控器PCB板:

从PCB板来看,果然还是官方的用料更足一些,通过测量红外发射引脚,在按下按钮时,红外发射头会发出一串脉冲信号,如下图所示:

其中黑色的部分是38KHz的PWM方波,空白部分是低电平,以上波形就表示一个快门指令。

红外遥控协议主要有两种:NEC协议和Philips RC-5协议,NEC采用PWM方式调制,RC-5采用PPM方式调制。其中使用最多的是NEC协议,38KHz载波,一般是由引导码+地址码+地址反码+数据+数据反码构成。其中逻辑0和逻辑1的编码如下:

基于Arduino的实现

好了,知道了快门指令的红外波形,我们只需要写个函数实现这一串脉冲信号就可以了。Arduino开发板,我手头上有的是Circuit Playground Express这款开发板,板载一对红外发射接收头,和两路按键,对于我们的功能已经是足够用了。在使用前需要先安装Cortex-M0的库。

程序非常简单,按下按键时,发出一个快门指令:

  1. #include<Adafruit_CircuitPlayground.h>


  2. #define IR_Pin 25

  3. #defineLed_Pin13

  4. #defineButtonA_Pin4

  5. #defineButtonB_Pin5


  6. #define LED_ON digitalWrite(Led_Pin, LOW)

  7. #define LED_OFF digitalWrite(Led_Pin, HIGH)

  8. #define LED_SET(x) digitalWrite(Led_Pin, x)


  9. #define IR_ON digitalWrite(IR_Pin, HIGH)

  10. #define IR_OFF digitalWrite(IR_Pin, LOW)


  11. #define GET_BUTTONA() digitalRead(ButtonA_Pin)

  12. #define GET_BUTTONB() digitalRead(ButtonB_Pin)


  13. int sts = 0;


  14. void setup()

  15. {

  16. pinMode(IR_Pin, OUTPUT);

  17. pinMode(Led_Pin, OUTPUT);

  18. pinMode(ButtonA_Pin, INPUT_PULLDOWN);

  19. pinMode(ButtonB_Pin, INPUT_PULLDOWN);


  20. Serial.begin(9600);

  21. }


  22. //Nikon ML-L3 红外遥控器快门编码:38KHz=26us

  23. void loop()

  24. {

  25. if(GET_BUTTONA())

  26. {

  27. delay(10);

  28. if(GET_BUTTONA())

  29. {

  30. sts = !sts;

  31. LED_SET(sts);

  32. Serial.println("Right button pressed!");

  33. OneShot();

  34. }

  35. }

  36. while(GET_BUTTONA()); //等待松开

  37. }


  38. voidOneShot()

  39. {

  40. int i = 0;

  41. for(i = 76; i > 0; i--) //2100ms

  42. {

  43. IR_ON; //13.5

  44. delayMicroseconds(12);

  45. IR_OFF; //13.7

  46. delayMicroseconds(12);

  47. }

  48. IR_OFF;

  49. delay(28); //2803us

  50. for(i = 15; i > 0; i--) //393us

  51. {

  52. IR_ON;

  53. delayMicroseconds(12);

  54. IR_OFF;

  55. delayMicroseconds(12);

  56. }

  57. IR_OFF;

  58. delayMicroseconds(1580); //1611us


  59. for(i = 15; i > 0; i--)

  60. {

  61. IR_ON;

  62. delayMicroseconds(12);

  63. IR_OFF;

  64. delayMicroseconds(12);

  65. }

  66. delayMicroseconds(3580);

  67. for(i = 15; i > 0; i--)

  68. {

  69. IR_ON;

  70. delayMicroseconds(12);

  71. IR_OFF;

  72. delayMicroseconds(12);

  73. }

  74. IR_OFF;

  75. }

基于STM32的实现

在STM32F103上的实现也是非常简单,主要用到了GPIO控制和精确延时函数。红外控制引脚和按键引脚可根据需要来调整。

  1. //根据Nikon ML-L3红外遥控器编码协议,产生快门指令

  2. voidOneShot(void)

  3. {

  4. int i = 0;

  5. for(i = 76; i > 0; i--) //2100ms

  6. {

  7. IR_ON; //13.5

  8. delay_us(12);

  9. IR_OFF; //13.7

  10. delay_us(12);

  11. }

  12. IR_OFF;

  13. delay_ms(28); //2803us

  14. for(i = 15; i > 0; i--) //393us

  15. {

  16. IR_ON;

  17. delay_us(12);

  18. IR_OFF;

  19. delay_us(12);

  20. }

  21. IR_OFF;

  22. delay_us(1580); //1611us


  23. for(i = 15; i > 0; i--)

  24. {

  25. IR_ON;

  26. delay_us(12);

  27. IR_OFF;

  28. delay_us(12);

  29. }

  30. delay_us(3580);

  31. for(i = 15; i > 0; i--)

  32. {

  33. IR_ON;

  34. delay_us(12);

  35. IR_OFF;

  36. delay_us(12);

  37. }

  38. IR_OFF;

  39. }

基于FPGA的实现

对于FPGA来说,这种波形的产生,时间可以控制的更精确,这取决于FPGA的时钟,时钟越高精度越高,而且可控性更强一些,就是实现起来稍微麻烦一些。

Verilog文件

  1. module ml_l3_pulse_gen(


  2. input clk_50M, //20ns

  3. input rst_n,

  4. input trig, //negedge trig


  5. output pulse

  6. );


  7. parameter T1_2000US = 100000;

  8. parameter T2_28000US = 1400000;

  9. parameter T3_400US = 20000;

  10. parameter T4_1580US = 79000;

  11. parameter T5_400US = T3_400US;

  12. parameter T6_3580US = 179000;

  13. parameter T7_400US = T3_400US;


  14. parameter T1_STS = 1;

  15. parameter T2_STS = 2;

  16. parameter T3_STS = 3;

  17. parameter T4_STS = 4;

  18. parameter T5_STS = 5;

  19. parameter T6_STS = 6;

  20. parameter T7_STS = 7;

  21. parameter T8_STS = 8;

  22. parameter T0_STS = 0;

  23. parameter TIME_38KHZ = 658;


  24. reg [7:0] cur_sts;

  25. reg [31:0] cnt_38khz;

  26. reg [31:0] cnt;

  27. reg [31:0] cnt_max;


  28. reg en;

  29. reg pwm_38k;

  30. reg trig_reg;


  31. assign pulse = (en) ? pwm_38k : 0;


  32. always @ (posedge clk_50M)

  33. begin

  34. trig_reg <= trig;

  35. end


  36. always @ (posedge clk_50M)

  37. begin

  38. if(!rst_n)

  39. cnt_max <= 0;

  40. else

  41. begin

  42. case(cur_sts)

  43. T0_STS : cnt_max <= 0;

  44. T1_STS : cnt_max <= T1_2000US;

  45. T2_STS : cnt_max <= T2_28000US;

  46. T3_STS : cnt_max <= T3_400US;

  47. T4_STS : cnt_max <= T4_1580US;

  48. T5_STS : cnt_max <= T5_400US;

  49. T6_STS : cnt_max <= T6_3580US;

  50. T7_STS : cnt_max <= T7_400US;

  51. default: cnt_max <= 0;

  52. endcase

  53. end

  54. end


  55. always @ (posedge clk_50M)

  56. begin

  57. if(!rst_n)

  58. en <= 0;

  59. else

  60. begin

  61. case(cur_sts)

  62. 1,3,5,7: en <= 1;

  63. 2,4,6,0: en <= 0;

  64. default: en <= 0;

  65. endcase

  66. end

  67. end


  68. always @ (posedge clk_50M)

  69. begin

  70. if(!rst_n)

  71. cnt <= 0;

  72. else

  73. begin

  74. if(cur_sts != T0_STS && cnt < cnt_max)

  75. cnt <= cnt + 1;

  76. else

  77. cnt <= 0;

  78. end

  79. end


  80. always @ (posedge clk_50M)

  81. begin

  82. if(!rst_n)

  83. cur_sts <= T0_STS;

  84. else

  85. begin

  86. case(cur_sts)

  87. T0_STS:

  88. if(trig_reg & !trig)

  89. cur_sts <= T1_STS;

  90. T1_STS:

  91. if(cnt == T1_2000US)

  92. cur_sts <= T2_STS;

  93. T2_STS:

  94. if(cnt == T2_28000US)

  95. cur_sts <= T3_STS;

  96. T3_STS:

  97. if(cnt == T3_400US)

  98. cur_sts <= T4_STS;

  99. T4_STS:

  100. if(cnt == T4_1580US)

  101. cur_sts <= T5_STS;

  102. T5_STS:

  103. if(cnt == T5_400US)

  104. cur_sts <= T6_STS;

  105. T6_STS:

  106. if(cnt == T6_3580US)

  107. cur_sts <= T7_STS;

  108. T7_STS:

  109. if(cnt == T7_400US)

  110. cur_sts <= T0_STS;

  111. default:

  112. cur_sts <= T0_STS;

  113. endcase

  114. end

  115. end


  116. /* 38KHz counter */

  117. always @ (posedge clk_50M)

  118. begin

  119. if(!rst_n)

  120. cnt_38khz <= 0;

  121. else

  122. begin

  123. if(en && cnt_38khz < TIME_38KHZ)

  124. cnt_38khz <= cnt_38khz + 1;

  125. else

  126. cnt_38khz <= 0;

  127. end

  128. end


  129. /* generate 38KHz pwm */

  130. always @ (posedge clk_50M)

  131. begin

  132. if(!rst_n)

  133. pwm_38k <= 0;

  134. elseif(cnt_38khz == TIME_38KHZ)

  135. pwm_38k <= ~pwm_38k;

  136. end


  137. endmodule

仿真test bench 文件

  1. `timescale 1ns/100ps


  2. module ml_l3_pulse_gen_tb;


  3. parameter SYSCLK_PERIOD = 20;// 50MHZ


  4. reg SYSCLK;

  5. reg NSYSRESET;

  6. reg trig;


  7. wire pulse;


  8. initial

  9. begin

  10. SYSCLK = 1'b0;

  11. NSYSRESET = 1'b0;

  12. trig = 0;

  13. end


  14. initial

  15. begin

  16. #(SYSCLK_PERIOD * 10 )

  17. NSYSRESET = 1'b0;

  18. trig = 0;

  19. #(SYSCLK_PERIOD * 1000 )

  20. NSYSRESET = 1'b1;

  21. #(SYSCLK_PERIOD * 10 )

  22. trig = 1;

  23. #SYSCLK_PERIOD

  24. trig = 0;

  25. end


  26. always @(SYSCLK)

  27. #(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;


  28. ml_l3_pulse_gen ml_l3_pulse_gen_0 (

  29. // Inputs

  30. .clk_50M(SYSCLK),

  31. .rst_n(NSYSRESET),

  32. .trig(trig),


  33. // Outputs

  34. .pulse(pulse)

  35. );


  36. endmodule

实际使用效果

对于实际的脉冲时间,不用特别的精确,误差不要太大就行,最好使用示波器测量以下脉冲的时间。对于制作好的遥控器,只需要在相机周围按下按钮就可实现遥控快门。相机机身的红外接收头前后各有一个,可以方便在不同的位置遥控。如下图所示。

总结

这款尼康ML-L3红外遥控器的实现原理非常简单,可扩展性强,可以根据需要自己添加功能,如添加固定时间间隔拍摄,固定张数拍摄,用于拍摄制作延时视频所需要的图片素材。当然,也可以使用手机上的遥控器来实现这个功能。

代码获取

以上代码已经开源在Github和Gitee平台,地址如下。

  • Github开源地址:

    https://github.com/whik/nikon-wireless-remote-control-ML-L3-DIY.git

  • Gitee开源地址 : 

    https://gitee.com/whik/nikon-wireless-remote-control-ML-L3-DIY.git

没有使用代码托管平台的朋友,可以在公众号后台回复【尼康遥控器】也可以获取代码。

参考资料

文中的ML-L3拆解图,Arduino代码参考自以下链接内容。

  • http://www.bigmike.it/ircontrol/

  • https://www.sbprojects.net/projects/nikon/index.php

  • https://learn.adafruit.com/ir-sensor/making-an-intervalometer

嵌入式大杂烩 专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!
评论
  • 电竞鼠标应用环境与客户需求电竞行业近年来发展迅速,「鼠标延迟」已成为决定游戏体验与比赛结果的关键因素。从技术角度来看,传统鼠标的延迟大约为20毫秒,入门级电竞鼠标通常为5毫秒,而高阶电竞鼠标的延迟可降低至仅2毫秒。这些差异看似微小,但在竞技激烈的游戏中,尤其在对反应和速度要求极高的场景中,每一毫秒的优化都可能带来致胜的优势。电竞比赛的普及促使玩家更加渴望降低鼠标延迟以提升竞技表现。他们希望通过精确的测试,了解不同操作系统与设定对延迟的具体影响,并寻求最佳配置方案来获得竞技优势。这样的需求推动市场
    百佳泰测试实验室 2025-01-16 15:45 285浏览
  • 80,000人到访的国际大展上,艾迈斯欧司朗有哪些亮点?感未来,光无限。近日,在慕尼黑electronica 2024现场,ams OSRAM通过多款创新DEMO展示,以及数场前瞻洞察分享,全面展示自身融合传感器、发射器及集成电路技术,精准捕捉并呈现环境信息的卓越能力。同时,ams OSRAM通过展会期间与客户、用户等行业人士,以及媒体朋友的深度交流,向业界传达其以光电技术为笔、以创新为墨,书写智能未来的深度思考。electronica 2024electronica 2024构建了一个高度国际
    艾迈斯欧司朗 2025-01-16 20:45 177浏览
  • 随着消费者对汽车驾乘体验的要求不断攀升,汽车照明系统作为确保道路安全、提升驾驶体验以及实现车辆与环境交互的重要组成,日益受到业界的高度重视。近日,2024 DVN(上海)国际汽车照明研讨会圆满落幕。作为照明与传感创新的全球领导者,艾迈斯欧司朗受邀参与主题演讲,并现场展示了其多项前沿技术。本届研讨会汇聚来自全球各地400余名汽车、照明、光源及Tier 2供应商的专业人士及专家共聚一堂。在研讨会第一环节中,艾迈斯欧司朗系统解决方案工程副总裁 Joachim Reill以深厚的专业素养,主持该环节多位
    艾迈斯欧司朗 2025-01-16 20:51 137浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 143浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 69浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 26浏览
  • 百佳泰特为您整理2025年1月各大Logo的最新规格信息,本月有更新信息的logo有HDMI、Wi-Fi、Bluetooth、DisplayHDR、ClearMR、Intel EVO。HDMI®▶ 2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新规范将支持更高的分辨率和刷新率,并提供更多高质量选项。更快的96Gbps 带宽可满足数据密集型沉浸式和虚拟应用对传输的要求,如 AR/VR/MR、空间现实和光场显示,以及各种商业应用,如大型数字标牌、医疗成像和
    百佳泰测试实验室 2025-01-16 15:41 188浏览
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 195浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 102浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 110浏览
我要评论
1
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦