Skip to content

11. Input devices

This weeks work is intertwined with electronics production week and input devices week. On electronics production week I made the circuit board which has both infrared output and input. So this week I will be trying out reading the input from the IR receiver.

Group work

For this weeks group work we probed both digital and analog sensors with an oscilloscope to see the output.

I was mostly interested in an IR phototransistor which I could use in my final project. However, we were not able to reliably measure the IR phototransistor (The images on the group page is of the visible light photoresistor). The signal from the IR phototransistor was very noisy and there were no evident changes when we used an IR remote controller as the source of IR signals. This could just be that the voltage changes were so small. And/or it could be that the circuit wiring is somehow incorrect.

I think for future IR endeavours I will use an actual IR sensor as all the tutorials I came across use those as well.

Testing the buttons

I used the following script to test the buttons. The NeoPixel related stuff is explained in embedded programming week.

#define NEOPOWERPIN 11 // Provides voltage for the built-in NeoPixel
#define NEOPIXELPIN 12 // Datapin for the the built-in NeoPixel

#define BUTTON1PIN D2
#define BUTTON2PIN D3

Adafruit_NeoPixel pixels(NUMPIXELS, NEOPIXELPIN, NEO_RGB + NEO_KHZ800);

void setup() {
    pinMode(NEOPOWERPIN, OUTPUT); // initialize digital pin NEOPOWERPIN as an output.
    digitalWrite(NEOPOWERPIN, HIGH); // Power for the NeoPixel

    pinMode(BUTTON1PIN, INPUT_PULLUP);
    pinMode(BUTTON2PIN, INPUT_PULLUP);

    pixels.begin();
}

void loop() {
    int red = 0;
    int green = 0;
    int blue = 0;

    if (!digitalRead(BUTTON1PIN)) {
        // Button 1 is pressed
        green = 100;
    } else {
        green = 0;
    }

    if (!digitalRead(BUTTON2PIN)) {
        // Button 2 is pressed
        red = 100;
    } else {
        red = 0;
    }

    pixels.clear();
    pixels.setPixelColor(0, pixels.Color(red, green, blue));
    pixels.show();
}
The buttons on my board are wired with a pullup resistor, thus the defaul value is "HIGH" or "TRUE" and that's why the ! in the if statements.

This is what it looks like without any buttons pressed.

buttons

First button pressed, green light.

buttons

Second button pressed, red light.

buttons

Both buttons pressed, yellow light (seems white in camera).

buttons

So this way the buttons can be used to control things, like the NeoPixel.

IR receiver

I decided to ignore the IR phototransistor for now and go straight into using the separate IR receiver (HW-490) which comes in many common and cheap "arduino sensor kits".

IR sensor

It has three pins: a voltage (+), ground (-) and data (S).

To much of my surprise, the sensor can be just plugged in directly to my board! (Which has the Seeed XIAO SAMD21 this time)

The sensor plugged in

Which is so convenient.

To read the sensor I used this IRremote library which had also a simple example on the page. I only changed the pin identifier:

First example
#include <IRremote.h>

#define RECEIVER_PIN D10

IRrecv irrecv(RECEIVER_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}

Now, that example code prints the HEX values of the signals transmitted from an IR device.

There are some standards in the protocols that for example TVs use. I have an LG TV which has this "magic remote". I was not sure what is the defaul protocol in the receiver, but I tested it directly.

Receiving IR signals

Sadly, all of the buttons in my remote produced FFFFFFFF. However, surprisingly when I opened my phone near the receiver, it printed A0F22FDA constatly when the screen was open. I figured this is from the proximity sensor in the phone as it shouldn't have anything else related to IR. Also if the signal was disturbed it would display something else. This could be used to detect my phone screen opening, not sure how useful that is though.

Reading the signals

This newer, more sophisticated example provides much more information.

Better example
#include <IRremote.hpp>

#define RECEIVER_PIN D10

void setup()
{
  Serial.begin(9600);
  IrReceiver.begin(RECEIVER_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
}

void loop() {
  if (IrReceiver.decode()) {
      // Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); // Print "old" raw data
      // USE NEW 3.x FUNCTIONS
      IrReceiver.printIRResultShort(&Serial); // Print complete received data in one line
      IrReceiver.printIRSendUsage(&Serial);   // Print the statement required to send this data
      IrReceiver.resume(); // Enable receiving of the next value
  }
}

Now when I press the buttons on my remote it tells the protocol is NEC and separates the address and command, among other things. For example when pressing the powerbutton it prints this:

Protocol=NEC Address=0x4 Command=0x8 Raw-Data=0x0F708FB04 32 bits LSB first
Send with: IrSender.sendNEC(0x4, 0x8, <numberOfRepeats>);
Protocol=NEC Address=0x4 Command=0x8 Repeat gap=40000us

And when opening my phone screen:

Protocol=UNKNOWN Hash=0x0A0F22FDA 8 bits (incl. gap and start) received

Recording the necessary signals

These colored buttons are rarely used for anything anymore so those could be useful for custom applications.

Colored buttons on tv remote

Pressing the button and using the previous example allowed me to gather this information.

Button Raw-data Command
Red 0x08D72FB04 0x72
Green 0x08E71FB04 0x71
Yellow 0x09C63FB04 0x63
Blue 0x09E61FB04 0x61

Also, all have the address of 0x4.

Result

With the help of the documentation I knew that I can access the data from IrReceiver.decodedIRData and that allows me to do this:

input.ino
#include <IRremote.hpp>

#define RECEIVER_PIN D10

void setup()
{
  Serial.begin(9600);
  IrReceiver.begin(RECEIVER_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
}

void loop() {
  if (IrReceiver.decode()) {
    if (IrReceiver.decodedIRData.address == 0x4) {
      switch (IrReceiver.decodedIRData.command) {
        case 0x72:
          Serial.println("RED button pressed.");
          break;
        case 0x71:
          Serial.println("GREEN button pressed.");
          break;
        case 0x63:
          Serial.println("YELLOW button pressed.");
          break;
        case 0x61:
          Serial.println("BLUE button pressed.");
          break;

        default:
          Serial.println("Other button pressed.");
          break;
        }
      }
      IrReceiver.resume(); // Enable receiving of the next value
  }
}

source code

And here is the result:

Demonstration of the code

By the way, I also watched this video for reference but most of the code was written by referring to the github page of the library.

Well, this is nice library which makes it trivial to read (and likely send) IR signals both for controlling existing devices and for custom projects. I would expect that for the final project I would need to either go lower level or implement some more complex functionality.

Anyway, that's it for this assignment. I will be taking advantage of this in week 9 which is the output week.

End of week 11.