Photoshop mini-control Pad---DIY with Digispark

本帖最後由 hon829 於 2019-1-5 11:41 編輯

參考了網上開源項目,用ATiny85模擬keyboard送出Photoshop的shortcut key:
https://www.indiegogo.com/projec ... n-workflow-design#/

Signals Type:
Knob: "[" , "]"        //編碼開關轉左或右分別送出中括號

Switch: "b", "e"     //按鍵(用編碼開關按鈕代替),分別送出代表選取Brush或Eraser tools的"b"及"e"

用Digispark組裝樣子:
1.jpg
2019-1-4 11:00

2.jpg
2019-1-4 11:00


有了概念亦用慣Arduino IDE,故沒跟作者電路及程序,自己很簡單的編寫如下:

#include "DigiKeyboard.h"
#include <avr/wdt.h>

#define encoder0PinA  0                                                                       //Interrupt input
#define encoder0PinB  2                                                                       //regular input
#define encoder0Btn   1                                                                       //button input, 1 = has not been pressed
                                    //pin 2, USB+  PB3
                                    //pin 3, USB-  PB4

int valRotary = 0;
bool Toggle_button = 0;



void doEncoder() {                                                                            //Interrupt Service Routine                                          
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)){                                //two input same, CW
    valRotary=2;}                                                                           
  else{ valRotary=1; }
}



void setup() {
  pinMode(encoder0PinA, INPUT_PULLUP);
  pinMode(encoder0PinB, INPUT_PULLUP);
  pinMode(encoder0Btn, INPUT_PULLUP);

  watchdogSetup(1);                                                                           //watchdog setup on, for 1 second
  
  attachInterrupt(0, doEncoder, CHANGE);                                                      //attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); UNO pin 2(int.0)/3(int.1)
}




void loop() {
  DigiKeyboard.update();
  
  if( digitalRead(encoder0Btn) == LOW ){
    if( Toggle_button ==0 ){
      DigiKeyboard.sendKeyStroke(KEY_E);                                                     //KEY_E, 0x08 // e
      Toggle_button =1;}
    else{
      DigiKeyboard.sendKeyStroke(KEY_B);                                                     //KEY_B, 0x05 // b
      Toggle_button =0;}
    DigiKeyboard.delay(300);}                                                                //It's better to use DigiKeyboard.delay() over the regular Arduino delay()
  
  
  if(valRotary == 2){                                                                         //CW
    DigiKeyboard.sendKeyStroke(KEY_R_BRACKET);                                               //0x30 "]"
    DigiKeyboard.delay(100);
    valRotary=0;}


  if(valRotary == 1) {                                                                        //CCW
    DigiKeyboard.sendKeyStroke(KEY_L_BRACKET);                                               //0x2F "["
    DigiKeyboard.delay(100);
    valRotary=0;}
  

  wdt_reset();                                                                                //periodically reset the watchdog timer
  
}






void watchdogSetup(boolean on_off){
  cli();                                                                                      // disable all interrupts
  wdt_reset();                                                                                // reset the WDT timer
  WDTCR |= (1<<WDCE) | (0<<WDE);                                                              // Enter Watchdog Configuration mode:
  WDTCR = (on_off<<WDIE) | (1<<WDE) | (0<<WDP3) | (1<<WDP2) | (1<<WDP1) | (0<<WDP0);          // Set Watchdog settings:
  sei();
/*
WDTCSR configuration:

WDIE = 1: Interrupt Enable
WDE = 1 :Reset Enable

WDP3  WDP2  WDP1  WDP0      Number of WDT Oscillator Cycles     Typical Time-out at VCC = 5.0V
  0     0     0     0               2K (2048) cycles                    16 ms
  0     0     0     1               4K (4096) cycles                    32 ms
  0     0     1     0               8K (8192) cycles                    64 ms
  0     0     1     1               16K (16384) cycles                  0.125 s
  0     1     0     0               32K (32764) cycles                  0.25 s
  0     1     0     1               64K (65536) cycles                  0.5 s
  0     1     1     0               128K (131072) cycles                1.0 s
  0     1     1     1               256K (262144) cycles                2.0 s
  1     0     0     0               512K (524288) cycles                4.0 s
  1     0     0     1               1024K (1048576) cycles              8.0 s
*/
}


是可以如設計般操作的,唯間歇性的Windows不能辨識裝置.
3.jpg
2019-1-4 11:00


為以防程序hang故加了watchDog作reset部份,讓它呆一陣!暫不知程序那部份出了問題?
(或許是USB lib.出事 但看不懂!)
4.jpg
2019-1-4 11:24

你說特意加了 WDT, 那沒有 WDT 是不是就沒有問題?

TOP

換成USB-A

TOP

回覆 2# IanW


當然是有問題後至加看門狗

TOP

回覆 3# xiao


應該唔關接觸不良或電流量問題.

TOP

以為clock的頻率不準,試了cal. OSCCAL值,都沒改善!
以為Digispark個boot loader影響, 剷走都沒改善!

用USB分析軟件check此device如下:
Device Descriptor:
Connection Information
Port: 1
Speed: Low Speed
Device address: 3
Open pipes: 1
Connection status: Device connected

Device Descriptor
USB version: 1.10
Device class: 0x0 - (Defined at Interface level)
Device subclass: 0x0 - Unknown
Device protocol: 0x0 - Unknown
Control pipe max size: 8 bytes
Vendor ID: 0x16c0 (Van Ooijen Technische Informatica)
Product ID: 0x27db (Keyboard)
Product version: 1.0
Manufacturer: digistump.com
Product: DigiKey
Serial Number: Not specified
Configurations: 1





HID Descriptor
Usage Page: 1 (Generic Desktop Controls)
Usage: 6 (Keyboard)
Collection
Usage Page: 7 (Keyboard)
Usages (224-231): Control Left, Shift Left, Alt Left, GUI Left, Control Right, Shift Right, Alt Right,
GUI Right
Logical Minimum: 0
Logical Maximum: 1
Report Size: 1
Report Count: 8
Input: 2 (Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position)

Report Count: 6
Report Size: 8
Logical Maximum: 101
Usages (0-231): No Event, Keyboard ErrorRollOver, Keyboard POSTfail, Keyboard Error Undefined, A,
B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
1 and ! (One and Exclamation), 2 and @ (2 and at), 3 and # (3 and Hash), 4 and $ (4 and Dollar Sign),
5 and % (5 and Percent Sign), 6 and ^ (6 and circumflex), 7 and & (Seven and Ampersand),
8 and * (Eight and asterisk), 9 and ( (Nine and Parenthesis Left), 0 and ) (Zero and Parenthesis Right),
Return (Enter), Escape, Delete (Backspace), Tab, Space Bar, - and _ (Minus and underscore),
= and + (Equal and Plus), [ and { (Bracket and Braces Left), ] and } (Bracket and Braces Right),
\ and | (Backslash and Bar), # and ~ (Hash and Tilde, Non-US Keyboard near right shift),
; and : (Semicolon and Colon), ? and " (Accent Acute and Double Quotes), ` and ~ (Accent Grace and Tilde),
, and < (Comma and Less), . and > (Period and Greater), / and ? (Slash and Question Mark),
Caps Lock, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, Print Screen,
Scroll Lock, Pause, Insert, Home, Page Up, Delete Forward (without Changing Position),
End, Page Down, Right Arrow, Left Arrow, Down Arrow, Up Arrow, Num Lock and Clear,
Keypad / (Division Sign), Keypad * (Multiplication Sign), Keypad - (Subtraction Sign),
Keypad + (Addition Sign), Keypad Enter, Keypad 1 and END, Keypad 2 and Down Arrow,
Keypad 3 and Page Down, Keypad 4 and Left Arrow, Keypad 5 (Tactilei Raised),
Unknown, Keypad 6 and Right Arrow, Keypad 7 and Home, Keypad 8 and Up Arrow,
Keypad 8 and Page Up, Keypad . (decimal delimiter) and Delete, \ and | (Backslash and Bar, UK and Non-US Keyboard near left shift),
Keyboard Application (Windows Key for Win95 or Compose), Power (not a key),
Keypad = (Equal Sign), F13, F14, F15, F16, F17, F18, F19, F20, F21, F22, F23,
F24, Execute, Help, Menu, Select, Stop, Again, Undo, Cut, Copy, Paste, Find,
Mute, Volume Up, Volume Down, Locking Caps Lock, Locking Num Lock, Locking Scroll Lock,
Keypad Comma, Keypad Equal Sign (AS/400), International 1 (PC98), International 2 (PC98),
International 3 (PC98), International 4 (PC98), International 5 (PC98), International 6 (PC98),
International 7 (Toggle Single/Double Byte Mode), International 8, International 9,
LANG 1 (Hangul/English Toggle, Korea), LANG 2 (Hanja Conversion, Korea), LANG 3 (Katakana, Japan),
LANG 4 (Hiragana, Japan), LANG 5 (Zenkaku/Hankaku, Japan), LANG 6, LANG 7,
LANG 8, LANG 9, Alternate Erase, SysReq/Attention, Cancel, Clear, Prior, Return,
Separator, Out, Open, Clear/Again, CrSel/Props, ExSel, Unknown, Unknown, Unknown,
Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown,
Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown,
Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown,
Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown,
Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown,
Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown,
Unknown, Unknown, Control Left, Shift Left, Alt Left, GUI Left, Control Right,
Shift Right, Alt Right, GUI Right
Input: 0 (Data,Array,Absolute,No Wrap,Linear,Preferred State,No Null Position)

End Collection


感覺應該是操作到某程序program hang了,要reset隻ATiny85就冇事!

TOP

本帖最後由 Charcoal99 於 2019-1-4 23:58 編輯

你在Loop 及 interrupt 都調用了digitalRead(), 有沒有確認過這function 是否reentrant 的?
此外, valRotary 這變數是16-bit 的, ATtiny 是8-bit MCU, 在 Loop 裡面 valRotary 當有interrupt 來時也不保證可以 atomic Read or Write, 而 interrupt 裡面也會修改 valRotary, 即使不Hang 機, 也是不safe 或會出錯的.

TOP

回覆 7# Charcoal99

明白了
以為用中斷可增加對編碼開關的反應,但反而影響了USB的通訊,在轉動太頻密時使USB傻了!


#include "DigiKeyboard.h"

#define encoder0PinA  0                                                                       //Interrupt input
#define encoder0PinB  2                                                                       //regular input
#define encoder0Btn   1                                                                       //button input, 1 = has not been pressed
                                    //pin 2, USB+  PB3
                                    //pin 3, USB-  PB4


bool Toggle_button = 0;
int encoder0PinALast = LOW;
int n = LOW;


void setup() {
  pinMode(encoder0PinA, INPUT_PULLUP);
  pinMode(encoder0PinB, INPUT_PULLUP);
  pinMode(encoder0Btn, INPUT_PULLUP);
}


void loop() {
  DigiKeyboard.update();
  
  if( digitalRead(encoder0Btn) == LOW ){
    if( Toggle_button ==0 ){
      DigiKeyboard.sendKeyStroke(KEY_E);                                                      //KEY_E, 0x08 // e
      Toggle_button =1;}
    else{
      DigiKeyboard.sendKeyStroke(KEY_B);                                                      //KEY_B, 0x05 // b
      Toggle_button =0;}
    DigiKeyboard.delay(200);}                                                                 //It's better to use DigiKeyboard.delay() over the regular Arduino delay()
  

  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {                                                     //two input same, CW
      DigiKeyboard.sendKeyStroke(KEY_R_BRACKET);                                                //0x30 "]"
      DigiKeyboard.delay(50);}
    else {                                                                                      //CCW
      DigiKeyboard.sendKeyStroke(KEY_L_BRACKET);                                               //0x2F "["
      DigiKeyboard.delay(50);}
  }
  encoder0PinALast = n;

  
}


程序改回用polling後,一切都很暢順了

TOP

我成日都想自己整啲shortcut key係公司用, 因為公司有IT管, 所以用唔到Admin裝野, 有師兄喱嗰方法, 有時間試下先

TOP

回覆 8# hon829


厲害....恭喜達陣

TOP