Gyro1
Published © GPL3+

Simple Wireless Keyboard for PC

Keyboard designed specifically for YouTube and Netflix on a PC. Works great with music players as well.

AdvancedShowcase (no instructions)11,246
Simple Wireless Keyboard for PC

Things used in this project

Story

Read more

Custom parts and enclosures

3D models

STL files of all parts

Schematics

Recevier

Schematic for the receiver. Fritzing file

Transmitter

Schematic for the transmitter. Fritzing file

Code

Receiver.ino

Arduino
Code for the receiver
#include <SPI.h>
#include <NRFLite.h>
#include "HID-Project.h"


const static uint8_t RADIO_ID = 7;       // Our radio's id.  The transmitter will send to this id.
const static uint8_t PIN_RADIO_CE = 9;
const static uint8_t PIN_RADIO_CSN = 10;

struct RadioPacket // Any packet up to 32 bytes can be sent.
{
    uint8_t FromRadioId;
    uint32_t OnTimeMillis;
    uint32_t FailedTxCount;
};

NRFLite _radio;
RadioPacket _radioData;

void setup()
{
    if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))  //Checks if radio is connected
    {
        while (1); // Wait here forever.
    }
    Consumer.begin();       //initialization of keyboard. Arduino will act as HID
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
    while (_radio.hasData())          //when data is received over radio
    {
        digitalWrite(LED_BUILTIN,HIGH);
        _radio.readData(&_radioData);
        int msg = _radioData.OnTimeMillis;    //saves received data in msg
        bool YTflag = true;                   //Determines youtube or media mode
        if (msg > 100) {                      //checks if the remote is in youtube or media mode
          YTflag = false;
          msg -= 100;
        }
        switch(msg){                        //Outputs appropriate key presses as keyboard
          case 4:
          Consumer.write(MEDIA_VOLUME_DOWN);
          break;
          case 5:
          Consumer.write(MEDIA_VOLUME_UP);
          break;
          case 6:
          if (YTflag){
            Keyboard.print("f");
          }
          else Consumer.write(MEDIA_PREVIOUS);
          break;
          case 7:
          if (YTflag ){
            Keyboard.press(KEY_LEFT_SHIFT);
            Keyboard.press('n');
            delay(50);
            Keyboard.releaseAll();
          }
          else Consumer.write(MEDIA_NEXT);
          break;
          case 8:
          if (YTflag) Keyboard.print("k");
          else {
                //Consumer.write(MEDIA_PLAY_PAUSE);
                Keyboard.print(" ");
          }
          break;
          case 14:
          if (YTflag) Keyboard.print("j");
          else Consumer.write(MEDIA_REWIND);
          break;
          case 15:
          if (YTflag) Keyboard.print("l");
          else Consumer.write(MEDIA_FAST_FORWARD);
          break;
        }
        digitalWrite(LED_BUILTIN,LOW);
    }
}

Remote.ino

Arduino
Code for the transmitter
#include <SPI.h>
#include <NRFLite.h>
#include "Arduino.h"
#include <avr/sleep.h>
#include <avr/power.h>
#include "RF24.h"

volatile bool input = true;
bool YTmode = true;
long startTime;
int lowBattery = 740;     //Low battery level (740 = 3.65V)

const static uint8_t RADIO_ID = 21;             // Our radio's id.
const static uint8_t DESTINATION_RADIO_ID = 7; // Id of the radio we will transmit to.
const static uint8_t PIN_RADIO_CE = 9;
const static uint8_t PIN_RADIO_CSN = 10;

struct RadioPacket // Any packet up to 32 bytes can be sent.
{
    uint8_t FromRadioId;
    uint32_t OnTimeMillis;
    uint32_t FailedTxCount;
};

RF24 radio(9,10);
NRFLite _radio;
RadioPacket _radioData;

void setup()
{
    //Serial.begin(115200);

    pinMode(2, INPUT);            //interrupt
    pinMode(3, INPUT);     //mode Button
    pinMode(4, INPUT);     //volume down button
    pinMode(5, INPUT);     //volume up button
    pinMode(6, INPUT);     //previous button
    pinMode(7, INPUT);     //next button
    pinMode(8, INPUT);     //play button
/*
Radio    Arduino
CE    -> 9
CSN   -> 10 (Hardware SPI SS)
MOSI  -> 11 (Hardware SPI MOSI)
MISO  -> 12 (Hardware SPI MISO)
SCK   -> 13 (Hardware SPI SCK)
IRQ   -> No connection
VCC   -> No more than 3.6 volts
GND   -> GND
*/
    pinMode(14, INPUT);    //rewind button
    pinMode(15, INPUT);    //skip button
    pinMode(16,OUTPUT);           //backlight LED
    pinMode(17,OUTPUT);           //blue LED
    pinMode(18,OUTPUT);           //red LED

    checkBattery();                                               //checks battery status
    initRadio();                                                  //initialization of radio
    _radioData.FromRadioId = RADIO_ID;
    sendButton(0);
    modeStatus();
    attachInterrupt(digitalPinToInterrupt(2), isr, FALLING);      //Interrupt setup
}

void loop() {
  if(input){          //only occurs during isr method which is interrupt
    checkButtons(); 
    delay(10);  
  }
  enterSleep();       //puts arduino to sleep to save power
}


void checkButtons(){        //Scans which button is pressed and sends message
  startTime = millis();
  digitalWrite(16,HIGH);    //backlight on
  checkBattery();           //makes sure battery isn't low
  modeStatus();             //Lights up the mode LEDs(youtube / media)
  radio.powerUp();          //wakes up radio from sleep
  int message = 0;          //message will be send at the of the method
  
  while(millis()-startTime < 3000){  //runs for 3 seconds
    message = 0;
    if(digitalRead(4)) {
      delay(3);                   //debouncing
      while(digitalRead(4)){}     //debouncing
      delay(3);                   //debouncing
      message = 4;                //sets message that is going to be send
      startTime = millis();       //resets timer
    } else if
    (digitalRead(5)) {
      delay(3);
      while(digitalRead(5)){}
      delay(3);
      message = 5;
      startTime = millis();
    }else if (digitalRead(6)) {
      delay(10);
      while(digitalRead(6)){}
      delay(10);
      message = 6;
      startTime = millis();
    }else if (digitalRead(7)) {
      delay(10);
      while(digitalRead(7)){}
      delay(10);
      message = 7;
      startTime = millis();
    }
    else if (digitalRead(8)) {
      delay(10);
      while(digitalRead(8)){}
      delay(10);
      message = 8;
      startTime = millis();
    }else if (digitalRead(14)) {
      delay(10);
      while(digitalRead(14)){}
      delay(10);
      message = 14;
      startTime = millis();
    }else if (digitalRead(15)) {
      delay(10);
      while(digitalRead(15)){}
      delay(10);
      message = 15;
      startTime = millis();
    }else if (digitalRead(3)) {
      delay(10);
      while(digitalRead(3)){}
      delay(10);
      changeMode();             //changes between youtube and media mode
      startTime = millis();
    }

    if(message == 0){}                  //checks if there is any message
    else if(YTmode)sendButton(message); //in youtube mode message gets send normally
    else sendButton(message + 100);     //in media mode message is incremented by 100
    delay(10);
  }
  digitalWrite(16,LOW);                 //turns off backlight
  radio.powerDown();                    //Puts radio to sleep
  input =false;                         //prevents from looping
}

void sendButton(int buttonIndex){     //send data over radio

    _radioData.OnTimeMillis = buttonIndex;

    if (_radio.send(DESTINATION_RADIO_ID, &_radioData, sizeof(_radioData))) // Note how '&' must be placed in front of the variable name.
    {
       // Serial.println("...Success");
    }
    else
    {
       // Serial.println("...Failed");
        _radioData.FailedTxCount++;
    }
}

void isr(){                       //called when interrupt happens which wakes up arduino from sleep
  input = true;
}

void enterSleep(){              //Puts arduino to sleep to save power
  digitalWrite(16,LOW);   //Turns off all LEDs
  digitalWrite(17,LOW);
  digitalWrite(18,LOW);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  //waits until woken up
  sleep_disable();
  power_all_enable();
}

void changeMode(){            //Changes between youtube and media mode
  delay(10);
  while (digitalRead(3)){}
  delay(10);
  YTmode = !YTmode;
  if(YTmode) {
    digitalWrite(17,LOW);
    digitalWrite(18,HIGH);
  }else{
    digitalWrite(17,HIGH);
    digitalWrite(18,LOW);
  }
}

void initRadio(){     //initialization of radio
   if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN)) //if radio can't be found turn on all LEDs and do nothing.
    {
        digitalWrite(16,HIGH);
        digitalWrite(17,HIGH);
        digitalWrite(18,HIGH); 
        while (1); // Wait here forever.
    }
}

void modeStatus(){
  if(YTmode) {                        //setting the mode LED
      digitalWrite(17,LOW);
      digitalWrite(18,HIGH);
    }else{
      digitalWrite(17,HIGH);
      digitalWrite(18,LOW);
    }
}

void checkBattery(){                  //makes sure battery isn't too low
  if (analogRead(A5) < lowBattery){   //if battery is too low blink couple of times
    for(int i=0; i<=4; i++){
      digitalWrite(16,LOW);
      delay(200);
      digitalWrite(16,HIGH);
      delay(200);
    }
    detachInterrupt(0);           // detach interrupt and go to sleep. Arduino cannot be woken after this point. only reset will make it work
    enterSleep();
  }
}

Credits

Gyro1

Gyro1

2 projects • 16 followers

Comments