Nikon IR remote for Bulb shutter (using Digispark )

本帖最後由 hon829 於 2018-4-27 23:50 編輯

有D低價的藝康相機不設快門線,但有IR remote 口. 用B快門時,按一下開,再按一下關;同線控按著就開放手即關的使用不同,故唯有自行DIY件紅外線遙控.
參考了部份網上資源,有說Nikon IR remote code 及程式編碼等...
(參考: https://www.sbprojects.net/projects/nikon/index.php ... )
( 參考: http://www.instructables.com/id/ ... aps-With-ATtiny-85/ ...)

Nikon IR coding:
Nikon IR.jpg
2018-4-26 14:10



Nikon IR B.jpg
2018-4-26 14:08


程式經編修如下:


//Calibartion the internal RC oscillator first!!!
// ATMEL ATTINY85 / ARDUINO
//
//                  +-\/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2)  Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0
//                  +----+

#include <avr/sleep.h>              // Sleep Modes
#include <avr/power.h>

#ifndef cbi                                           //Clear Bit in I/O Register
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))   //BV=Bit Value
#endif
#ifndef sbi                                           //Setting Bits
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif


#define InterruptPin 0            //pin 5, key button
#define led 1                     //pin 6, led indicate the operation
#define IRledPin 2                //pin 7, connect to IR LED
                            //pin 1
                            //pin 2, USB+  PB3
                            //pin 3, USB-  PB4

int Keychanged = 0;             //temp value

                  
ISR(PCINT0_vect) {                    //Interrupt Service Routine
  Keychanged = 1;
}



void setup()   {  
  OSCCAL = 0x52;                                //RC oscillator Calibartion value
  
  pinMode(InterruptPin, INPUT_PULLUP);         
  pinMode(led, OUTPUT);                                                      
  pinMode(IRledPin, OUTPUT);                    
  
  digitalWrite(IRledPin, LOW);                  
  digitalWrite(led, HIGH);                    
  delay(50);                                   
  digitalWrite(led, LOW);                     
  
  Keychanged = 0;                   //no key pressed
  sbi(GIMSK, PCIE);               
  sbi(PCMSK, PCINT0);            
  sei();                        
}



void loop(){
  system_sleep();                             //sleep for power saving, only wake up when key pressed
  
  while(Keychanged == 0){}                     //no key pressed       <<更正on 27/4 >>
  
  cli();                                    
  SendNikonCode();                            //emit IR, [137.72mS]
  
  delay(50);                                    //camera mini time limit
  while(digitalRead(InterruptPin) == LOW){}   //checking key hold
  
  SendNikonCode();                           
  Keychanged = 0;
  sei();                                      
}


void system_sleep() {                       
  cbi(ADCSRA,ADEN);                          
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);        
  power_all_disable ();                     
  sleep_mode();                             
  sleep_cpu();                          
  sleep_disable();   
  power_all_enable();                       
  sbi(ADCSRA,ADEN);                          
}                                          


void SendNikonCode() {              //for Nikon IR control                                               
  digitalWrite(led, HIGH);      

  pulseIR(2000);                              
  delayMicroseconds(26000);           
  pulseIR(400);                    
  delayMicroseconds(1580);        
  pulseIR(400);                    
  delayMicroseconds(3500);           
  pulseIR(400);                  

  delayMicroseconds(59500);           //delay 63.2mS

  pulseIR(2000);                                   //repeat 1 time
  delayMicroseconds(26000);         
  pulseIR(400);                  
  delayMicroseconds(1580);         
  pulseIR(400);                 
  delayMicroseconds(3500);            
  pulseIR(400);               
  
  digitalWrite(led, LOW);         
}

                        
                                 
void pulseIR(long microsecs) {      //tuned for 38kHz carrier for IR led ON/OFF                                
  while (microsecs > 0) {                  // 38 kHz is about 13.1 microseconds high and 13.1 microseconds low                             
   digitalWrite(IRledPin, HIGH);   
   delayMicroseconds(9);           
   digitalWrite(IRledPin, LOW);     
   delayMicroseconds(8);                                         
   microsecs -= 26;               
  }
}

Digispark 用Attiny85 內置振盪器,故做timing 時不太準確,有D數值要修修補補,試完再試!!
A.jpg
2018-4-26 14:08

B.jpg
2018-4-26 14:08


用落IR始終沒線控那樣反應爽快,只此令操作可近似些!

點解 IR 相關的東西, 用 RC osc? 電壓氣溫一變就好易走, carrier freq 就唔準.

就咁看一看個程式, 你現在的流程是否
Sleep -> 按鍵 -> Send 1 組 IR (2 messages) -> 仲按緊 -> 又 send 多一組 IR (2 messages) -> 跟住又 loop 去 sleep ?
如果係的話, 點解唔係每 59.5ms check 一次按鍵, 有就繼續出 IR? 直至放手?

你覺得唔爽, 大概係因為你每 send 1 組 IR 就要 137.72ms (根據你的 comment), 那是超過 0.1s, 你大概係會感覺倒個 delay 的. 你應該造個 59.5ms 的 loop, 見倒放手就去訓覺. 仲係唔夠的話整多個 26ms 的.

TOP

回覆 2# IanW


見很多IR remote 都用MCU內置RC 振盪,估計不是要求"很"準確吧!
操作係: sleep > 按制醒來及射IR > polling check 是否仍按著 >到放制再射IR後sleep
IR code 只得一組.

TOP

本帖最後由 marlin12 於 2018-4-28 14:08 編輯

首先想鬧Nikon,一個咁簡單既IR遙控,居然賣30歐元(300港元),分明[掠水]!
另外,個protocol又設定得[離譜],有咩理由只送2個code?!仲要make code同break code一樣?!真係想X#YZ佢...

在第一份參考資料(SB-Projects)入面講,程序應該如下:(第二組IR code是在送出第一組IR code後63.2ms送出,唔係等按鈕被放開後才送出。)
按鈕被按下 -> MCU被喚醒 -> 進入ISR -> 離開ISR -> 進入main loop -> 送出第一組IR code -> 延遲63.2ms -> 送出第二組IR code -> 等待按鈕被放開 -> MCU回休眠

我覺得正確既程序應該如下:
按鈕被按下 -> MCU被喚醒 -> 進入ISR -> 離開ISR -> 進入main loop -> 亮著LED(提示已被喚醒) -> debounce按鈕被按下-> 送出第一組IR code -> 延遲63.2ms -> 送出第二組IR code -> 等待按鈕被放開 -> debounce按鈕被放開 -> 息滅LED(提示進入休眠) -> MCU回休眠

另外,你程式的問題如下:
1) 唔好亂用data type。任何會用在ISR的variable,都要用volatile來define。
     [錯] int Keychanged = 0;
     [對] volatile bool isKeyChanged = false;
2) 唔好將assignment operator(=)當作relational operator(==)用。唔好用endless loop。
     [錯] while(Keychanged = 0){}
     [對] if( !isKeyChanged ) { MCU回休眠 }
3) 要debounce按鈕。
     Debounce
4) 用delay來產生波形不準確,ATTINY85有2個timer,一個可以用來產生38KHz載波,另一個可以用來計時。
     Fast PWM on ATTiny85

其實,我覺得直接睇ATTiny85說明書仲好,資料準確、解釋得仲清楚。
ATTiny85說明書

最後,建議唔好用Audrino IDE(唔好用Audrino s/w library),直接用Amtel Studio(直接用AVR s/w library)。咁先至可以真正了解MCU的運作,和用到MCU的真正功能。

TOP

本帖最後由 hon829 於 2018-4-27 23:56 編輯

回覆 4# marlin12


programming 技巧上真冇諗咁多, work左就算
這制作不用debounce的,因撳制後入射IR loop要百多微秒至出來再check key,已多過一般20mS 的debounce time.
基本網上參考全是照仿Nikon 原廠IR remote 模式的, 即按制>射IR>delay 63.2mS>射多次同一IR pattern> 等下次按制   (即只 falling edge trigger)
我現在要加多按制放手果下也射IR  (即falling edge 及rising edge 也trigger一完整次), 以用作B快門的任意長時間曝光的!
現在Nikon ML-L3 紅外線遙控都是國產天下,幾蚊有一個!

TOP

回覆  marlin12
programming 技巧上真冇諗咁多, work左就算
hon829 發表於 2018-4-27 23:41

如果求其work到就得嘅,件野就唔會好似你自己講咁,傻吓傻吓啦!
=當==咁用,根本就做錯野,唔係[技巧問題]喎!
用delay整個唔準確嘅載波出嚟,加上RC clock在温度/濕度影响下嘅漂移,相機好大機會收錯野,影响到[可靠性]喎!

這制作不用debounce的,因撳制後入射IR loop要百多微秒至出來再check key,已多過一般20mS 的debounce time...

按鈕按下嗰時當然無問題,但係放開嗰時,一對IR code已經送完,嗰時接點跳幾吓,MCU就會被叫醒,誤以為再按下,送出另一對IR code。

我現在要加多按制放手果下也射IR(即falling edge 及rising edge 也trigger一完整次), 以用作B快門的任意長時間曝光的!

相影收到一對IR code,就會影一張相。在按鈕放開時送多一對IR code,只會影多一張相,點會變咗[B快門的任意長時間曝光]?!
原本遙控嘅規格都無咁嘅功能,唔明你點會整到囉?!

現在Nikon ML-L3紅外線遙控都是國產天下,幾蚊有一個!

既然咁平買到,你花咁多時間、貴咁多,整嚟做咩?!

TOP

本帖最後由 xiao 於 2018-4-28 21:13 編輯

tiny85 的分頻設定1的話, 跑USB連機順利表示RC震盪很準確可以通1.5MHz USB packet, 紅外線遙控38KHZ應該不是問題, 所以你的程序可能存在邏輯上的問題. 有沒有說38KHz佔空比要30%, 像有的NEC遙控格式偏差20%就不動, 這個程序看來約是9:8=50%.
  1. void pulseIR(long microsecs) {      //tuned for 38kHz carrier for IR led ON/OFF                                
  2.   while (microsecs > 0) {                  // 38 kHz is about 13.1 microseconds high and 13.1 microseconds low                             
  3.    digitalWrite(IRledPin, HIGH);   
  4.    delayMicroseconds(9);           
  5.    digitalWrite(IRledPin, LOW);     
  6.    delayMicroseconds(8);
複製代碼
或者試試看, 以前實測過, delayUs 太長會不太準, 跟編譯器有關, AVR-GCC 後來版本有沒有改過就沒研究了.
  1. //delayMicroseconds(26000);
  2. delay(26); //26ms
複製代碼
另外tiny85可以直接用 pin change interrupt, https://playground.arduino.cc/Main/PinChangeInterrupt
直接寫C的話就參考 atmel datasheet, 用過你會發現比較好

TOP

如果求其work到就得嘅,件野就唔會好似你自己講咁,傻吓傻吓啦!
=當==咁用,根本就做錯野,唔係[技巧問題]喎!

這個知道錯誤了!

用delay整個唔準確嘅載波出嚟,加上RC clock在温度/濕度影响下嘅漂移,相機好大機會收錯野,影响到[可靠性]喎!

IR 的寬容度有待實試.

既然咁平買到,你花咁多時間、貴咁多,整嚟做咩?!

這個就是和原廠有分別的!

用這remote,相機前設B Mode及開IR remote, 或許用過至知作用
A.jpg
2018-4-29 00:10

TOP

回覆 7# xiao

38KHz佔空比是50%的.


或者試試看, 以前實測過, delayUs 太長會不太準, 跟編譯器有關, AVR-GCC 後來版本有沒有改過就沒研究了.

delay不準,感覺係的,所以D數值修正過!

TOP

回覆  xiao

38KHz佔空比是50%的.



delay不準,感覺係的,所以D數值修正過!
hon829 發表於 2018-4-29 00:20


若動作正常,會不會b門就是快速短按兩下

TOP