手把手教你DIY尼康ML-L3红外遥控器

简介: 手把手教你DIY尼康ML-L3红外遥控器

项目介绍

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

640.jpg


拆解ML-L3遥控器

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


官方遥控器PCB板:

640.jpg


山寨遥控器PCB板:

640.jpg


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

640.png


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

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

640.png


基于Arduino的实现

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

640.jpg


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

#include<Adafruit_CircuitPlayground.h>  
#define IR_Pin      25
#defineLed_Pin13
#defineButtonA_Pin4
#defineButtonB_Pin5
#define LED_ON      digitalWrite(Led_Pin, LOW)
#define LED_OFF     digitalWrite(Led_Pin, HIGH)
#define LED_SET(x)  digitalWrite(Led_Pin, x)
#define IR_ON     digitalWrite(IR_Pin, HIGH)
#define IR_OFF    digitalWrite(IR_Pin, LOW)
#define GET_BUTTONA()  digitalRead(ButtonA_Pin)
#define GET_BUTTONB()  digitalRead(ButtonB_Pin)
int sts = 0;
void setup()
{
  pinMode(IR_Pin, OUTPUT);
  pinMode(Led_Pin, OUTPUT);
  pinMode(ButtonA_Pin, INPUT_PULLDOWN);
  pinMode(ButtonB_Pin, INPUT_PULLDOWN);
Serial.begin(9600);
}
//Nikon ML-L3 红外遥控器快门编码:38KHz=26us
void loop()
{
if(GET_BUTTONA())
{
    delay(10);
if(GET_BUTTONA())
{
      sts = !sts;
      LED_SET(sts);
Serial.println("Right button pressed!");
OneShot();
}
}
while(GET_BUTTONA());  //等待松开
}
voidOneShot()
{
int i = 0;
for(i = 76; i > 0; i--)  //2100ms
{
    IR_ON;      //13.5
    delayMicroseconds(12);
    IR_OFF;     //13.7
    delayMicroseconds(12);
}
  IR_OFF;
  delay(28);  //2803us
for(i = 15; i > 0; i--) //393us
{
    IR_ON;
    delayMicroseconds(12);
    IR_OFF;
    delayMicroseconds(12);
}
  IR_OFF;
  delayMicroseconds(1580);    //1611us
for(i = 15; i > 0; i--)
{
    IR_ON;
    delayMicroseconds(12);
    IR_OFF;
    delayMicroseconds(12);
}
  delayMicroseconds(3580);
for(i = 15; i > 0; i--)
{
    IR_ON;
    delayMicroseconds(12);
    IR_OFF;
    delayMicroseconds(12);
}
  IR_OFF;
}


基于STM32的实现

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

//根据Nikon ML-L3红外遥控器编码协议,产生快门指令
voidOneShot(void)
{
int i = 0;
for(i = 76; i > 0; i--)   //2100ms
{
        IR_ON;      //13.5
        delay_us(12);
        IR_OFF;     //13.7
        delay_us(12);
}
    IR_OFF;
    delay_ms(28);  //2803us
for(i = 15; i > 0; i--)  //393us
{
        IR_ON;
        delay_us(12);
        IR_OFF;
        delay_us(12);
}
    IR_OFF;
    delay_us(1580);    //1611us
for(i = 15; i > 0; i--)
{
        IR_ON;
        delay_us(12);
        IR_OFF;
        delay_us(12);
}
    delay_us(3580);
for(i = 15; i > 0; i--)
{
        IR_ON;
        delay_us(12);
        IR_OFF;
        delay_us(12);
}
    IR_OFF;
}


基于FPGA的实现

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

Verilog文件

module ml_l3_pulse_gen(
input clk_50M,  //20ns
input rst_n,
input trig,     //negedge trig
output pulse
);
parameter T1_2000US  = 100000;
parameter T2_28000US = 1400000;
parameter T3_400US   = 20000;
parameter T4_1580US  = 79000;
parameter T5_400US   = T3_400US;
parameter T6_3580US  = 179000;
parameter T7_400US   = T3_400US;
parameter T1_STS = 1;
parameter T2_STS = 2;
parameter T3_STS = 3;
parameter T4_STS = 4;
parameter T5_STS = 5;
parameter T6_STS = 6;
parameter T7_STS = 7;
parameter T8_STS = 8;
parameter T0_STS = 0;
parameter TIME_38KHZ = 658;
reg [7:0] cur_sts;
reg [31:0] cnt_38khz;
reg [31:0] cnt;
reg [31:0] cnt_max;
reg en;
reg pwm_38k;
reg trig_reg;
assign pulse = (en) ? pwm_38k : 0;
always @ (posedge clk_50M)
begin
    trig_reg <= trig;
end
always @ (posedge clk_50M)
begin
if(!rst_n)
        cnt_max <= 0;
else 
begin
case(cur_sts)
            T0_STS : cnt_max <= 0;
            T1_STS : cnt_max <= T1_2000US;
            T2_STS : cnt_max <= T2_28000US;
            T3_STS : cnt_max <= T3_400US;
            T4_STS : cnt_max <= T4_1580US;
            T5_STS : cnt_max <= T5_400US;
            T6_STS : cnt_max <= T6_3580US;
            T7_STS : cnt_max <= T7_400US;
default: cnt_max <= 0;
        endcase
end
end
always @ (posedge clk_50M)
begin
if(!rst_n)
        en <= 0;
else
begin
case(cur_sts)
1,3,5,7: en <= 1;
2,4,6,0: en <= 0;
default: en <= 0;
        endcase
end
end
always @ (posedge clk_50M)
begin
if(!rst_n)
        cnt <= 0;
else
begin
if(cur_sts != T0_STS && cnt < cnt_max)
            cnt <= cnt + 1;
else 
            cnt <= 0;
end
end
always @ (posedge clk_50M)
begin
if(!rst_n)
        cur_sts <= T0_STS;
else 
begin
case(cur_sts)
            T0_STS:
if(trig_reg & !trig)
                    cur_sts <= T1_STS;
            T1_STS:
if(cnt == T1_2000US)
                    cur_sts <= T2_STS;
            T2_STS:
if(cnt == T2_28000US)
                    cur_sts <= T3_STS;
            T3_STS:
if(cnt == T3_400US)
                    cur_sts <= T4_STS;
            T4_STS:
if(cnt == T4_1580US)
                    cur_sts <= T5_STS;
            T5_STS:
if(cnt == T5_400US)
                    cur_sts <= T6_STS;
            T6_STS:
if(cnt == T6_3580US)
                    cur_sts <= T7_STS;
            T7_STS:
if(cnt == T7_400US)
                    cur_sts <= T0_STS;
default:
                cur_sts <= T0_STS;
        endcase
end
end
/* 38KHz counter */
always @ (posedge clk_50M)
begin
if(!rst_n)
        cnt_38khz <= 0;
else 
begin
if(en && cnt_38khz < TIME_38KHZ)
            cnt_38khz <= cnt_38khz + 1;
else 
            cnt_38khz <= 0;
end
end
/* generate 38KHz pwm */
always @ (posedge clk_50M)
begin
if(!rst_n)
        pwm_38k <= 0;
elseif(cnt_38khz == TIME_38KHZ)
        pwm_38k <= ~pwm_38k;
end
endmodule


仿真test bench 文件

`timescale 1ns/100ps
module ml_l3_pulse_gen_tb;
parameter SYSCLK_PERIOD = 20;// 50MHZ
reg SYSCLK;
reg NSYSRESET;
reg trig;
wire pulse;
initial
begin
    SYSCLK = 1'b0;
    NSYSRESET = 1'b0;
    trig = 0;
end
initial
begin
    #(SYSCLK_PERIOD * 10 )
        NSYSRESET = 1'b0;
        trig = 0;
    #(SYSCLK_PERIOD * 1000 )
        NSYSRESET = 1'b1;
    #(SYSCLK_PERIOD * 10 )
        trig = 1;
    #SYSCLK_PERIOD
        trig = 0;
end
always @(SYSCLK)
    #(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;
ml_l3_pulse_gen ml_l3_pulse_gen_0 (
    // Inputs
    .clk_50M(SYSCLK),
    .rst_n(NSYSRESET),
    .trig(trig),
    // Outputs
    .pulse(pulse)
);
endmodule


实际使用效果

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

640.jpg


总结

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

目录
相关文章
|
1月前
|
人工智能 数据可视化 搜索推荐
Katalist官网体验入口 生成式AI视觉故事板工具
【2月更文挑战第26天】Katalist官网体验入口 生成式AI视觉故事板工具
106 4
Katalist官网体验入口 生成式AI视觉故事板工具
|
10月前
|
机器学习/深度学习 人工智能 API
LabVIEW AI开发者福音:LabVIEW OpenVINO AI加速工具包,不来看看?
LabVIEW AI开发者福音:LabVIEW OpenVINO AI加速工具包,不来看看?
215 1
LabVIEW AI开发者福音:LabVIEW OpenVINO AI加速工具包,不来看看?
|
1月前
|
人工智能 机器人 Linux
超级炫酷的AI绘图工具—MidJourney入门使用教程
超级炫酷的AI绘图工具—MidJourney入门使用教程
|
存储 JSON 前端开发
2、从零开始构建基于ChatGPT的嵌入式(Embedding)本地医疗客服问答机器人模型(看完就会,看到最后有惊喜)
本文中我使用的是后端语言golang,来调用的所有外部接口,但它们均是restful api,所以如果你使用的是其他语言,那么是完全可以替换的,包括nodejs或者直接使用前端请求都是可以实现我的功能的。后面有机会会使用vue3来添加一个页面,现在主要通过postman或者apifox来调试接口,主要为了验证逻辑想法。
1329 0
|
存储 人工智能 算法
【MindStudio训练营第一季】MindStudio 高精度对比随笔
训练场景下,迁移原始网络 (如TensorFlow、PyTorch) ,用于NPU上执行训练,网络迁移可能会造成自有实现的算子运算结果与用原生标准算子运算结果存在偏差。
168 1
|
语音技术 开发者 芯片
【MindStudio训练营第一季】MindStudio 专家系统随笔
专家系统(Mindstudio Advisor) 是用于聚焦模型和算子的性能调优Top问题,识别性能瓶颈,重点构建瓶颈分析、优化推荐模型,支撑开发效率提升的工具。专家系统当前已经支持针对推理、训练、算子场景的瓶颈分析模型,包括内部团队开发的模型&算子瓶颈分析和优化推荐知识库、针对onnx模型的自动调优知识库,以及基于生态开发者开发的生态知识库。
125 2
|
机器学习/深度学习 人工智能 数据可视化
【MindStudio训练营第一季】MindStudio 可视化AI应用开发体验随笔
Mind Studio 提供一站式AI开发环境,依靠工具与性能调优,采用插件化扩展机制,打造高效、便捷的全流程开发工具链。目前最新版本是5.0.RC3,发布于2022年20月,对应的昇腾社区版本:6.0.RC1,新增众多特性。
292 1
|
编解码 Windows
多媒体系统导论 实验二 基于Premiere的视频处理
多媒体系统导论 实验二 基于Premiere的视频处理
178 0
多媒体系统导论 实验二 基于Premiere的视频处理
|
存储 数据采集 传感器
ROS中阶笔记(五):机器人感知—机器视觉(上)
ROS中阶笔记(五):机器人感知—机器视觉
591 0
ROS中阶笔记(五):机器人感知—机器视觉(上)
|
算法 机器人 Unix
ROS中阶笔记(五):机器人感知—机器视觉(下)
ROS中阶笔记(五):机器人感知—机器视觉
631 0
ROS中阶笔记(五):机器人感知—机器视觉(下)