风筝
发表于: 2021-4-28 10:26:08 | 显示全部楼层

谁会不喜欢摄影呢!这个创意领域有很多主题,每个主题都是唯一的,让我们选择一个。我们当中有多少人喜欢在《国家地理》或《探索》频道上看到野生动物?是的,我在谈论的是一种广为流传的摄影类型,也是最危险的摄影主题之一,即野生动物摄影(Wildlife Photography)。在野生动物摄影中,靠近动物可能会危及生命或造成危险,但同时需要拍摄照片。在这种情况下,可以从远距离控制摄像机的开关将是有益的。如果它是无线的怎么办?对于摄影师来说,这绝对是非常有帮助的。


因此,在本篇文章中,我们将为数码单反相机(DSLR)制作一个无线控制的快门按钮。为此,我们将使用Arduino UNO和nRF24L01–2.4GHz RF收发器模块,因此我们不需要离DSLR相机近,并且可以在视线以外的地方触发它。


所需的组件

由于该项目涉及无线控制,因此需要无线接收器或发送器。那就是NRF24L01对。通过与微控制器一起使用,可以无线进行数据传输。我们为此使用了Arduino UNO和Arduino NANO。

●    Arduino UNO开发板

●    5V适配器或移动电源的USB电缆

●    Arduino Nano开发板

●    NRF24L01无线模块

●    2.5毫米插孔

●    5V转换器(如果使用7.4V锂电池则需要)


DSLR远程触发器的原理图

下面显示了为DSLR制作的远程触发器的示意图。

DSLR-Remote-Trigger-Schematic-Diagram.png


原理图很简单,分为两部分,使用Arduino和nRF24L01作为接收器,使用Arduino和nRF24L01作为发送器。在接收器部分,按钮处于低电平状态,因此使用了下拉电阻。按下按钮后,D4引脚将从低到高。该数据将通过nRF24L01传输。另一方面,接收器将接收数据并将其传输到2.5mm插孔。发射器和接收器电路设置显示如下。

DSLR-Remote-Trigger-Transmitter.jpg


Remote-Trigger-for-DSLR.jpg


电路说明及工作原理

DSLR支持快门遥控器输入,可以连接现有的有线遥控器来触发快门。可以在下面的照片中看到。

DSLR-Trigger-Pin.jpg


下图显示了该引脚的连接。

DSLR-Shutter-Pin.jpg


插孔与DSLR内部的快门按钮相连。通过使用2.5mm插孔内部的上拉电阻,它处于3.3V电平。现在,当此技巧变为0V或低时,快门按钮将被释放。这是使用Arduino NANO完成的。每当Arduino Nano通过NRF24L01接收到发射器中的开关被按下的数据时,都会立即使连接器的插孔电平变为Low。


另一端,在Arduino UNO上使用了一个上拉电阻。每当按下开关时,连接开关的输入引脚就会变低。 Arduino通过nRF24L01将该数据传输到发送器。同样,发射器一侧的按钮使用防抖功能来解决错误的触发问题。另一个重要模块是NRF24L201。下面是NRF24L01的引脚图。

NRF24L01-Module-Pinout.jpg


可以将其配置为接收器或发送器。它是一种非常廉价的RF收发器模块,使用2.4GHz的RF范围,并且据传输距离非常长,可达50英尺到200英尺。

跳转到指定楼层
风筝
发表于: 2021-4-28 10:40:20 | 显示全部楼层

DSLR远程触发器的Arduino代码

本文使用了两种不同的代码,一种用于发送端,另一种用于接收端。


发送端的代码:

首先包括所需的库文件。

  1. //Include Libraries
  2. #include <SPI.h>
  3. #include <nRF24L01.h>
  4. #include <RF24.h>
  5. #include "printf.h"
  6. #include <ArduinoJson.h>
复制代码

在代码中设置通讯地址,发送端和接收端都必须相同。

  1. //address through which two modules communicate.
  2. const byte address[6] = {0xe1, 0xe1, 0xe1, 0xe1, 0xe1};
复制代码

定义一个布尔值,其中触发状态将从“true”更改为“false”,反之亦然。

  1. volatile bool isTrigger = false;
复制代码

接下来在运行实际应用程序之前启动NRF24L01。在这里,还需要设置RF范围、数据类型和状态。 nRF24L01设置为发射器,并且还设置为具有最大RF功率的远程距离。另外,输入先前设置的地址。

  1. void setup()
  2. {
  3.   Serial.begin(9600);
  4.   printf_begin();
  5.   Serial.println(F("\n\rRF24/examples/scanner/"));
  6.   // Setup and configure rf radio
  7.   radio.begin();
  8.   radio.setAutoAck(false);
  9.   //set the address
  10.   radio.openWritingPipe(address);
  11.   radio.setPALevel(RF24_PA_MIN); //set as: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  12.   radio.setDataRate(RF24_2MBPS); //set as: F24_250KBPS, F24_1MBPS, F24_2MBPS ==>250KBPS = longest range
  13.   radio.setChannel(115); //sets channel from 2.4 to 2.524 GHz in 1 MHz increments 2.483.5 GHz is normal legal limit
  14.   radio.setCRCLength(RF24_CRC_8);
  15.   //  radio.printDetails();
  16.   //Set module as transmitter
  17.   radio.stopListening();
复制代码

设置发送端nRF24L01之后,该设置按钮输入,该按钮输入将在触发期间由用户按下。引脚被设置为输入模式。

  1. pinMode(SHUTT_REMOTE_TRIGGER_PIN, INPUT);   // sets the digital pin "SHUTT_TRIGGER_PIN" as output
  2.   //  attachInterrupt(digitalPinToInterrupt(SHUTT_REMOTE_TRIGGER_PIN), shutter_remote_trigger, LOW);
  3.   //  attachInterrupt(digitalPinToInterrupt(SHUTT_REMOTE_TRIGGER_PIN), shutter_remote_trigger, HIGH  );
  4. }
  5. void shutter_remote_trigger() {
  6.   isTrigger = true;
  7. }
  8. // Variables will change:
  9. int ledState = HIGH; // the current state of the output pin
  10. int buttonState;   // the current reading from the input pin
  11. int lastButtonState = LOW;   // the previous reading from the input pin
  12. // the following variables are unsigned longs because the time, measured in
  13. // milliseconds will quickly become a bigger number than can be stored in an int.
  14. unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
  15. unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
复制代码

loop()函数中,将持续监视按钮状态,并且每当按下按钮状态时,就会将JSON语句发送到接收器。

  1. void loop()
  2. {
  3. // read the state of the switch into a local variable:
  4.   int reading = digitalRead(SHUTT_REMOTE_TRIGGER_PIN);
  5.   // check to see if you just pressed the button
  6.   // (i.e. the input went from LOW to HIGH), and you've waited long enough
  7.   // since the last press to ignore any noise:
  8.   // If the switch changed, due to noise or pressing:
  9.   if (reading != lastButtonState) {
  10.                 // reset the debouncing timer
  11.                 lastDebounceTime = millis();
  12.   }
  13.   if ((millis() - lastDebounceTime) > debounceDelay) {
  14.                 // whatever the reading is at, it's been there for longer than the debounce
  15.                 // delay, so take it as the actual current state:
  16.                 // if the button state has changed:
  17.                 if (reading != buttonState) {
  18.                 buttonState = reading;
  19.                 // only toggle the LED if the new button state is LOW
  20.                 if (buttonState == LOW) {
  21.                 isTrigger = true;
  22.                 }
  23.                 }
  24.   }
  25.   // save the reading. Next time through the loop, it'll be the lastButtonState:
  26.   lastButtonState = reading;
  27.   if (true == isTrigger) {
  28.                 // Allocate the JSON document
  29.                 //
  30.                 // Inside the brackets, 200 is the RAM allocated to this document.
  31.                 // Don't forget to change this value to match your requirement.
  32.                 // Use arduinojson.org/v6/assistant to compute the capacity.
  33.                 StaticJsonDocument<50> doc;
  34.                 doc[SHUTT_TRIGGER_JSON_KEY] = SHUTT_TRIGGER_ACTIVE;
  35.                 //Send message to receiver
  36.                 char send_dt[32] = {0};
  37.                 String output;
  38.                 //serializeJson(doc, Serial);
  39.                 serializeJson(doc, send_dt);
  40.                 Serial.println(send_dt);
  41.                 radio.write(&send_dt, sizeof(send_dt));
  42.                 isTrigger = false;
  43.   }
  44.   delay(10);
  45. }
复制代码

接收端的代码:

该代码与发送端相似,但是在接收到数据后,将为触发提供数据。


首先包括所需的库文件。

  1. //Include Libraries
  2. #include <SPI.h>
  3. #include <nRF24L01.h>
  4. #include <RF24.h>
  5. #include "printf.h"
  6. #include <ArduinoJson.h>
复制代码

如前所述,设置通讯地址,发送端和接收端的地址必须相同。之前在发送端地址部分中也给出了该信息。

  1. //address through which two modules communicate.
  2. const byte address[6] = {0xe1, 0xe1, 0xe1, 0xe1, 0xe1};
复制代码

接下来是在运行实际应用程序之前启动nRF24L01。此处,RF范围、数据类型和状态也设置为与发送端部分相同,但在此将其设置为接收器而不是发送器。它还设置为具有最大RF功率的远程距离。

  1. void setup()
  2. {
  3.   Serial.begin(9600);
  4.   printf_begin();
  5.   //Serial.println(F("\n\rRF24/examples/scanner/"));
  6.   // Setup and configure rf radio
  7.   radio.begin();
  8.   radio.setAutoAck(false);
  9.   radio.openReadingPipe(0, address);
  10.   radio.setPALevel(RF24_PA_MIN); //set as: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  11.   radio.setDataRate(RF24_2MBPS); //set as: F24_250KBPS, F24_1MBPS, F24_2MBPS ==>250KBPS = longest range
  12.   radio.setChannel(115); //sets channel from 2.4 to 2.524 GHz in 1 MHz increments 2.483.5 GHz is normal legal limit
  13.   radio.setCRCLength(RF24_CRC_8);
  14.   // Get into standby mode
  15.   radio.startListening();
复制代码

设置接收器nRF24L01之后,如果接收到的JSON包含按下按钮的信息,则这时将快门引脚设置为低电平。

  1. void loop()
  2. {
  3.   digitalWrite(SHUTT_TRIGGER_PIN, HIGH);
  4.   //Read the data if available in buffer
  5.   if (radio.available())
  6.   {
  7.                 // Allocate the JSON document
  8.                 //
  9.                 // Inside the brackets, 200 is the capacity of the memory pool in bytes.
  10.                 // Don't forget to change this value to match your JSON document.
  11.                 // Use arduinojson.org/v6/assistant to compute the capacity.
  12.                 StaticJsonDocument<50> doc;
  13.                 char recv_dt[32] = {0};
  14.                 radio.read(&recv_dt, sizeof(recv_dt));
  15.                 Serial.println(recv_dt);
  16.                 // Deserialize the JSON document
  17.                 DeserializationError error = deserializeJson(doc, recv_dt);
  18.                 // Test if parsing succeeds.
  19.                 if (error) {
  20.                 Serial.print(F("deserializeJson() failed: "));
  21.                 Serial.println(error.f_str());
  22.                 //return;
  23.                 } else {
  24.                 // Fetch values.
  25.                 //
  26.                 // Most of the time, you can rely on the implicit casts.
  27.                 // In other case, you can do doc["time"].as<long>();
  28.                 char s_trig_stat = doc[SHUTT_TRIGGER_JSON_KEY];
  29.                 if (SHUTT_TRIGGER_ACTIVE == s_trig_stat) {
  30.                 Serial.println("Set Shutter pin Low");
  31.                 digitalWrite(SHUTT_TRIGGER_PIN, LOW); // sets the digital pin "SHUTT_TRIGGER_PIN" on
  32.                 digitalWrite(LED_BUILTIN, HIGH);
  33.                 delay(250);  // waits for a 250 millisecond
  34.                 }
  35.                 }
  36.                 digitalWrite(LED_BUILTIN, LOW);
  37.   }
  38. }
复制代码

测试

为了测试电路,需要正确搭建发射端和接收端的电路。 2.5mm单声道插孔与DSLR一起使用,并经过电路操作测试。

Wireless-Trigger-for-DSLR.jpg


如果您对此项目有任何疑问,请在本帖下面留下您的评论。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1480



手机版|

GMT+8, 2024-4-17 06:26 , Processed in 0.215597 second(s), 9 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表