Monday, May 31, 2021

ProMicro HID Keyboard Emulator

Quick one this time. The Arduino ProMicro (examples here and here) is based on an Atmel 16u4 MCU and has HID keyboard emulation ready to go--use the keyboard.h functions in your sketch and go. It also has a USB port. That makes creating PC keyboard emulators, which work in parallel to your normal PC keyboard, a breeze. 

A good tutorial for this is here.


Arduino Pro Micro


 I will be using something like this for the continuing PNG sequencer project (part I post for that ongoing project is here) so this time I got a couple of HID emulators working using junk box parts and plastic cases I had lying around.


I used a couple of Hohner harmonica cases to hold the proMicro, switches, and DS3231 timer IC.

The "dtime" button selects the current time off a DS3231 I2C real time clock and fakes the PC into thinking someone typed this date-time in--I'll test it right now!  5/31/2021 16:17:22  Ah!  Works!!

The other 2 buttons can be set to produce a text string, anything you want.


The ProMicro is held in place with a 3D printed case; download the SVG file here. It took about 20 minutes to print. The plastics throughout are easily/sloppily augered out with a dremel grinder.

I used the cheapest parts possible. The ProMicro and DS3231 breakout boards are a $2-$3USD  AliExpress clones. The I2C based RTC holds time OK as long as it has USB power--after that it goes out of time pretty quickly, although doesn't reset itself to zilch. So it kinda works, but not great. 

I guess you get what you pay for right? After a power outage I upload the code into the ProMicro again which gets the clock working accurately; the code sends the time of the last compile to the DS3231 by default.  

Good enough for now, but for the sequencer this has to be fixed.  I assume (?) that if I use a better quality DS3231 timer, better battery etc., this will work; we will see.


You can get the ino Arduino sketch for this emulator below. 

There are many different RTC DS3231 Arduino libraries out there; I used Adafruit's which you can get here. Instructions about how to install this library into Arduino IDE is here.

I assume readers can figure out the ProMicro's wiring--the switches are momentary NO's connected from D pins to ground--from the code. the DS3231 is connected to Power, ground, and ProMicro pins 2 (SDA) and 3 (SCL).   

To get the real time clock programmed: for the first time run the code below.  Make sure to read the comments and comment out statements accordingly--there are different time setting algorithms in this sketch depending on your use case.

Until next time, don't breathe the fumes.


==========================


#include "RTClib.h"

#include <Keyboard.h>


String getdt();


RTC_DS3231 rtc;


char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};


int pin = 10;  // 

int mspin = 9;

int datepin = 7;




void setup()

{

  

 /*

///////////////////RTC CLOCK BS//////////////////////////////

arduinos don't have RTC


we are using RTC3231 from Maxim.

for pro micro here are I2C pins

2 > SDA, 3 > SCL


Library used is this one:

https://learn.adafruit.com/adafruit-ds3231-precision-rtc-breakout/arduino-usage

be careful, there are lots of other 3231 Arduino libraries.  Others probably won't

work with this sketch


*/


    //RTC setup:

    Serial.begin(9600);

    if (! rtc.begin()) 

    {

        Serial.println("Couldn't find RTC");

        Serial.flush();

        abort();

    }


  if (rtc.lostPower()) 

    {

    Serial.println("RTC lost power, let's set the time!");

    /* When time needs to be set on a new device, or after a power loss, the

     following line sets the RTC to the date & time this sketch was compiled

I have found you never need to comment this next line.

  */

    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

    }


  /* UNCOMMENT BELOW TO SET DATE TIME ON RTC TO TIME SKETCH WAS COMPILED FOR THE VERY FIRST TIME.

When time needs to be re-set on a previously configured device, the

following line sets the RTC to the date & time this sketch was compiled. 

HOWEVER!! COMMENT THE LINE BELOW AFTER YOUR DEVICE RTC HAS BEEN PROGRAMMED THE FIRST TIME.  

If you run this next statement on an already programmed RTC I have found the RTC may not work the way you want after a power loss.  

  */

  

  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));


  

  /* 

  UNCOMMENT AND CHANGE NEXT LINE TO SET THE TIME:  y m d h m s

otherwise compile time is blown into RTC at sketch upload.

NOTE! USING THE LINE BELOW MAY NOT ALLOW RTC TO CORRECTLY TRACK TIME AFTER A POWER LOSS.

  */

  

 // rtc.adjust(DateTime(2021, 3, 19, 8, 56, 0));

  

  

  pinMode(pin, INPUT_PULLUP);  // Set the button as an input

  pinMode(mspin, INPUT_PULLUP);  // Set the button as an input

  pinMode(datepin, INPUT_PULLUP);  // Set the button as an input

  

  digitalWrite(pin, HIGH);  // Pull the button high

  digitalWrite(mspin, HIGH);  // Pull the button high

  digitalWrite(datepin, HIGH);  // Pull the button high


  Keyboard.begin();


}




void loop()

{


 

  if (digitalRead(pin) == 0)  // if the button goes low

  {

    

    Keyboard.print("yer-text-0-here");  // 

    delay(1000);  // delay so we have poor mans debounce

  }


    if (digitalRead(mspin) == 0)  // if the button goes low

  {

    

    Keyboard.print("yer-text-1-here");   

    delay(1000);

  }

  


   if (digitalRead(datepin) == 0)  // if the button goes low

  {

    

    String gg = getdt();  


    {

    Keyboard.print(gg);  

    }

       

   delay(1000);

  }

   


}  


String getdt()

{


 DateTime now = rtc.now();


    int hour = now.hour();

    String hourStr = String(hour);

    if (hourStr.length() == 1)

       {

        hourStr = "0" + hourStr;

       }

    

    int minute = now.minute();

    String minuteStr = String(minute);

    if (minuteStr.length() == 1)       

       {

        minuteStr = "0" + minuteStr;

       }


    

    int second = now.second();

    String secondStr = String(second);

    if (secondStr.length()== 1)

       {

        secondStr= "0" + secondStr;

       }

       


    String TimeStr;

    TimeStr = hourStr + ":" + minuteStr + ":" + secondStr;


    int day = now.day();

    String dayStr=String(day);


    int month = now.month();

    String monthStr=String(month);


    int year = now.year();

    String yearStr=String(year);


    String DateStr;

    DateStr = monthStr + "/" + dayStr + "/" + yearStr;


    String FinalString;

    FinalString = DateStr + " " + TimeStr;

    return FinalString;

No comments:

Post a Comment

EFM/KORG770 VCF--BUILD: yes, SOUND: no

Ahoy!  This time, I wanted to refine the quick prototyping idea discussed midway through this previous post : Minimal breadboarding--I hate ...