Author Topic: N00b questions about keyboard library  (Read 30490 times)

forsakenrider

  • Newbie
  • *
  • Posts: 26
N00b questions about keyboard library
« on: March 26, 2013, 01:17:19 pm »
So basically, I want to make my digispark do annoying prank things to my friends.

Where do we find info about how the syntax should be written? for instance to do Windows-R we write it
Code: [Select]
DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);

This is counter intuitive for me. I would expect the MOD_GUI_LEFT to come first. Is there documentation about this?

Also, Ive wanted to add a few keys to the library like Printscreen, Menu, and Tab

Code: [Select]
#define KEY_PrintScreen     70
#define KEY_Menu     118
#define KEY_Tab    43

The menu key doesnt work (I dont think) How do I include it?

Also, I'm new to arduino. How do I make the program only run once and not "loop".

forsakenrider

  • Newbie
  • *
  • Posts: 26
Re: N00b questions about keyboard library
« Reply #1 on: March 26, 2013, 01:33:59 pm »
Basically, I want to make it lock the icons, print screen, save, set as background a thats it. heres the code so far. missing the lock icons because no menu.

when it goes to paste the printscreen it doesnt get pasted, its like MSPAINT isnt the program in view. how do I fix that?

Code: [Select]
#include "DigiKeyboard.h"

void setup() {
  pinMode(1, OUTPUT); //LED on Model A
}


void loop() {
 
  DigiKeyboard.update();
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.delay(5000);
  DigiKeyboard.sendKeyStroke(KEY_D, MOD_GUI_LEFT); //minimize all windows
  DigiKeyboard.delay(100);
  DigiKeyboard.sendKeyStroke(KEY_PrintScreen); //prntscr
  DigiKeyboard.delay(100); 
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);
  DigiKeyboard.delay(100);
  DigiKeyboard.println("mspaint");
  DigiKeyboard.sendKeyStroke(KEY_ENTER);
  DigiKeyboard.delay(1200);
  DigiKeyboard.sendKeyStroke(KEY_V, MOD_CONTROL_RIGHT);
  digitalWrite(1, HIGH);
  DigiKeyboard.delay(500);
  digitalWrite(1, LOW);
  DigiKeyboard.delay(500);
 
}

duckythescientist

  • Newbie
  • *
  • Posts: 27
Re: N00b questions about keyboard library
« Reply #2 on: March 26, 2013, 04:02:59 pm »
You said you are a n00b, so I'll try to give you both the simple and the complex answers.

First, you said that the syntax seems backward. It actually is when you look at how USB sends data, but the library takes care of that. From the library:
Code: [Select]
    reportBuffer[0] = modifiers;
    reportBuffer[1] = keyStroke;

You can see that the order gets reversed. Also, as a side note, if you need multiple modifiers, boolean OR them together. For example:
Code: [Select]
DigiKeyboard.sendKeyStroke(Key_A, MOD_CONTROL_LEFT | MOD_ALT_LEFT);
As for documentation, if you can stomach it, read through the library file DigiKeyboard.h because it will show you how everything happens. If not, just rely on the examples unless there is something in the Wiki about it.

I'm downloading the newest IDE version so I can check your code. Last time I checked, though, DigiKeyboard didn't have a delay function or print capability.


forsakenrider

  • Newbie
  • *
  • Posts: 26
Re: N00b questions about keyboard library
« Reply #3 on: March 26, 2013, 04:08:01 pm »
Thanks for that info. I was trying to read through it. Im a n00b in programing, I'm really more of a hardware guy, but I'm learning


Its does have those two functions now.


The only thing that doesnt work is the ctrl-v. I dont understand why the mspaint is not opened as the "active" window.

forsakenrider

  • Newbie
  • *
  • Posts: 26
Re: N00b questions about keyboard library
« Reply #4 on: March 26, 2013, 07:56:58 pm »
So apparently the "ENTER" after run-mspaint was the problem. Strange.

Anyway, try it out! its good fun!

Code: [Select]
//Wallpaper Prank, modified by DW for use on the digispark

#include "DigiKeyboard.h"



void setup() {
  pinMode(1, OUTPUT); //LED on Model A
 
 
}


void loop() {
 
 
  DigiKeyboard.update();
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.delay(3000);
  DigiKeyboard.sendKeyStroke(KEY_M, MOD_GUI_LEFT); //minimize all windows
  DigiKeyboard.delay(1000);
  DigiKeyboard.sendKeyStroke(KEY_PrintScreen); //prntscr
  DigiKeyboard.delay(50);
  DigiKeyboard.sendKeyStroke(KEY_F10, MOD_SHIFT_LEFT); //Open Menu
  DigiKeyboard.delay(200);
  DigiKeyboard.sendKeyStroke(KEY_V);
  DigiKeyboard.delay(50);
  DigiKeyboard.sendKeyStroke(KEY_D);
  DigiKeyboard.delay(500); 
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT); //run
  DigiKeyboard.delay(100);
  DigiKeyboard.println("mspaint");
  DigiKeyboard.delay(1200);
  DigiKeyboard.sendKeyStroke(KEY_V, MOD_CONTROL_LEFT); //paste
  DigiKeyboard.delay(500); 
  DigiKeyboard.sendKeyStroke(KEY_S, MOD_CONTROL_LEFT); //save
  DigiKeyboard.delay(500); 
  DigiKeyboard.println("%userprofile%\\a.bmp"); //save in users folder
  DigiKeyboard.delay(500);
  DigiKeyboard.sendKeyStroke(KEY_F, MOD_ALT_LEFT); //file
  DigiKeyboard.delay(500);
  DigiKeyboard.sendKeyStroke(KEY_K); //set as desktop
  DigiKeyboard.delay(100); 
  DigiKeyboard.sendKeyStroke(KEY_T); //tile
  DigiKeyboard.delay(1000);
  DigiKeyboard.sendKeyStroke(KEY_F4, MOD_ALT_LEFT); //close paint
  DigiKeyboard.delay(300);
  DigiKeyboard.sendKeyStroke(KEY_M, MOD_GUI_LEFT | MOD_SHIFT_LEFT); //back to desktop as it was
 
  digitalWrite(1, HIGH); //turn on led when program finishes
  DigiKeyboard.delay(90000);
  digitalWrite(1, LOW);
  DigiKeyboard.delay(5000);
 
}
« Last Edit: March 26, 2013, 09:01:24 pm by forsakenrider »

Lami

  • Newbie
  • *
  • Posts: 13
Re: N00b questions about keyboard library
« Reply #5 on: March 27, 2013, 05:35:17 am »
Where do we find info about how the syntax should be written? for instance to do Windows-R we write it
Code: [Select]
DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);
This is counter intuitive for me. I would expect the MOD_GUI_LEFT to come first. Is there documentation about this?
It is not. Modifier is optional parameter, so it can be omited. This is how it is usually achieved (maybe except of Python-like languages where you can specify named function arguments). See your own code:
Code: [Select]
  DigiKeyboard.sendKeyStroke(KEY_M, MOD_GUI_LEFT); //minimize all windows
  DigiKeyboard.delay(1000);
  DigiKeyboard.sendKeyStroke(KEY_PrintScreen); //prntscr
If the parameters were to be reversed and you would need to send simple keystroke without any modifier, you would need something like:
Code: [Select]
  DigiKeyboard.sendKeyStroke(MOD_NONE, KEY_PrintScreen); //prntscrWhich is ugly.

Quote
How do I make the program only run once and not "loop".
Easiest is to end it with infinite loop. Someting like:
Code: [Select]
while (1); // just while loop wih always true condition with empty code block (note the semicolon at the end)

// or

for(;;); // loop with empty condition and empty code - also note semicolon at the end

forsakenrider

  • Newbie
  • *
  • Posts: 26
Re: N00b questions about keyboard library
« Reply #6 on: March 27, 2013, 05:43:38 am »
Thank you, I understand now that it always reads the modifiers first anyway. Just one of those things in the learning curve.

can we digikeyboard.print("stirng litteral %i", somePredifinedInteger); like in C some how?

I would like to make the filename of the saved BMP to have a random number value as its name.

Lami

  • Newbie
  • *
  • Posts: 13
Re: N00b questions about keyboard library
« Reply #7 on: March 27, 2013, 06:31:50 am »
can we digikeyboard.print("stirng litteral %i", somePredifinedInteger); like in C some how?

You need something like this:

Code: [Select]
char buffer[31]; // buffer your formatted text goes into - make sure it is big enough (this fits 30 characters, 1 extra is needed).
sprintf(buffer, "stirng litteral %d", somePredifinedInteger); // formats the string and puts it in the buffer (%d is integer)
digikeyboard.print(buffer);  // sends buffer

Be careful with floats (%f), it is said Arduino's sprintf() (avr-gcc sprintf()) can't handle them. Did not run into it myself, just read it somewhere. Otherwise see about any sprintf() documentation for %whatever documentation. Best is sprintf(3), but is rather complicated: http://linux.die.net/man/3/sprintf

Mark

  • Full Member
  • ***
  • Posts: 196
Re: N00b questions about keyboard library
« Reply #8 on: March 27, 2013, 01:06:36 pm »
Quote
How do I make the program only run once and not "loop".

If you place the code in the void setup() section it will run once.
You still need to have void loop() but it doesn't need to contain anything except the brackets { }

Mark

forsakenrider

  • Newbie
  • *
  • Posts: 26
Re: N00b questions about keyboard library
« Reply #9 on: March 27, 2013, 06:54:25 pm »
Wow, Im learning so much! thank you a lot and thank you digistump for coming up with this simplistic board!



forsakenrider

  • Newbie
  • *
  • Posts: 26
Re: N00b questions about keyboard library
« Reply #10 on: March 27, 2013, 07:37:23 pm »
So the sprintf is confusing with % characters used for %userprofile% when saving, so I did it like this:

Code: [Select]
  DigiKeyboard.print("%userprofile%\\a");
  int number = random(300);
  char buffer[31]; // buffer your formatted text goes into - make sure it is big enough (this fits 30 characters, 1 extra is needed)
  sprintf(buffer, "%d", number); // formats the string and puts it in the buffer (%d is integer)
  DigiKeyboard.print(buffer); //save in users folder with random number
  DigiKeyboard.delay(100);
  DigiKeyboard.sendKeyStroke(KEY_ENTER);

Problem is now my random number is never random and always 7, why is that?

Tommy_2Tall

  • Newbie
  • *
  • Posts: 13
Re: N00b questions about keyboard library
« Reply #11 on: March 28, 2013, 12:15:46 am »
Hi!

That's a common issue in a lot of languages/environments.
random( .. ) isn't really random on it's own so you need to supply it with a "seed" that is as random or un-recurring as you can come up with (e.g. based on millis(), which is probably predicatable and unsecure in some other cases).
Something like this should work (assuming that the time since the DigiSpark booted up until calling these lines isn't exactly the same every execution):
Code: [Select]
randomSeed( millis() );
int number = random(300);

Quote
Note: If it is important for a sequence of values generated by random() to differ, on subsequent executions of a sketch, use randomSeed() to initialize the random number generator with a fairly random input, such as analogRead() on an unconnected pin.

 
Conversely, it can occasionally be useful to use pseudo-random sequences that repeat exactly. This can be accomplished by calling randomSeed() with a fixed number, before starting the random sequence.
http://arduino.cc/en/Reference/Random

Oh.. and another tip:
since you're already using "%userprofile%" in your path you could just continue along those lines and insert "%date%" somewhere in the typed filename/path.
It's commonly used in batch files to created date-based log-file names and so on.
There is a "%time%" variable available as well but since it will contain colons and commas it would have to be "cleaned up" before usage in a path/filename.. so that would just complicate things in this case.
« Last Edit: March 28, 2013, 12:26:19 am by Tommy_2Tall »

Lami

  • Newbie
  • *
  • Posts: 13
Re: N00b questions about keyboard library
« Reply #12 on: March 28, 2013, 01:19:34 pm »
So the sprintf is confusing with % characters used for %userprofile% when saving, so I did it like this:

To print "%" character, just write it twice. Like sprintf("%%userprofile%%\\a%d", number). % character in sprintf() is like "\" character in string literals. For example "\n" for newline character, but to get "\" itself, write "\\".

Bluebie

  • Sr. Member
  • ****
  • Posts: 486
Re: N00b questions about keyboard library
« Reply #13 on: March 28, 2013, 04:45:33 pm »
fwiw sprintf and related functions use up quite a bit of memory in digisparks and aren't very fast, so usually it's recommended you just do it as forsakenrider has anyway.


millis() will probably always be 0 or maybe 1 during your setup function. random seeds are hard. It's easier just to store some numbers in eeprom and increment them on each startup and seed off that.

forsakenrider

  • Newbie
  • *
  • Posts: 26
Re: N00b questions about keyboard library
« Reply #14 on: March 28, 2013, 07:42:38 pm »
Almost there! I still cant figure out how to print an int in my .println string. It wont compile how I expect it to.

Code: [Select]
DigiKeyboard.println("%userprofile%\\&d.bmp", value);

Thats how it would work in C (I think) so how do I get the "value" in my string literal? The easiest way i found was three lines of DigiKeyboard.print to do it.

Code: [Select]
  DigiKeyboard.print("%userprofile%\\"); //save in users folder
  DigiKeyboard.print(value); //number saved in eeprom + 1
  DigiKeyboard.println(".bmp");

heres a little youtube video showing what it does: https://www.youtube.com/watch?v=UYVKxJKPLfg