Contents
  1. 1. Photoresistor
  2. 2. Prototype
  3. 3. Sketch
  4. 4. Conclusion

The Hello World! in the Arduino universe is to blink a LED. Often it can be turned on and off with a push putton. Nowadays we use touch gestures instead of physical buttons, which implies the question:

Can the button press be emulated with a touch gesture on Arduino?

Photoresistor

The answer is yes! The physical button can be replaced with a photoresistor, which detects light intensity. The intensity change will emulate the touch - button press - gesture.

The Photoresistor controlling LED blog post is about how one LED can be blinked with a photoresistor.

Can something more advanced be built to demonstrate this idea?

Prototype

The answer is another yes. For instance it would be really cool navigate in menu on a screen with these “buttons”!

First of all the number of the LEDs and the photoresistors have to be tripled. If you work with an Arduino Nano board the end result might look like this:

In order to display a menu, a TFT LCD screen is required. I used the 1.8” Color TFT LCD display from Adafruit. It has to be wired together with the Arduino Nano board based on this page.

Sketch

Once the wiring is an Arduino sketch is required to make the prototype work. The following one can be used:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <Adafruit_GFX.h>    
#include <Adafruit_ST7735.h>
#include <SPI.h>

#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
#define TFT_SCLK 13
#define TFT_MOSI 11

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

char* mainMenu[] = {" Main Menu",
" Breadboard ",
" Photoresistor ",
" Push button ",
" Capacitator ",
" Microcontroller",
" Piezo buzzer "};

#define MENU_SIZE (sizeof(mainMenu)/sizeof(char *))-1
// Postition of first menu item from top of screen
#define MENU_TOP 14

byte selectedMenuItemIndex;
uint16_t currentBackgroundColor = ST7735_BLUE;

void setup(void) {
pinMode(7, OUTPUT);
pinMode(4, OUTPUT);
pinMode(2, OUTPUT);

Serial.begin(115200);
Serial.println("Photoresistor Navigation Test");

tft.initR(INITR_BLACKTAB);
tft.fillScreen(ST7735_BLACK);
tft.setTextWrap(false);

tftMenuInit();

// Select 1st menu item
selectedMenuItemIndex = 1;
tftMenuSelect(selectedMenuItemIndex);
}

void loop() {
// Divides input 0-1023 to resemble to 0-255
int photocellInputSelect = (analogRead(0)/4);
int photocellInputUp = (analogRead(1)/4);
int photocellInputDown = (analogRead(2)/4);

analogWrite(7, photocellInputSelect);
analogWrite(4, photocellInputUp);
analogWrite(2, photocellInputDown);

int maxValue = getMaxInputValue(photocellInputSelect, photocellInputUp, photocellInputDown);
int threshold = 50; //It can be customized!

if (abs(maxValue-photocellInputSelect) > threshold) {
selectButtonPressed();
}
if (abs(maxValue-photocellInputUp) > threshold) {
upButtonPressed();
}
if (abs(maxValue-photocellInputDown) > threshold) {
downButtonPressed();
}

delay(300);
}

int getMaxInputValue(int photocellInputSelect, int photocellInputUp, int photocellInputDown)
{
int maxValue = 0;

if (maxValue < photocellInputSelect) {
maxValue = photocellInputSelect;
}
if (maxValue < photocellInputUp) {
maxValue = photocellInputUp;
}
if (maxValue < photocellInputDown) {
maxValue = photocellInputDown;
}

return maxValue;
}

void selectButtonPressed() {
Serial.println("Selection button pressed!");

currentBackgroundColor = ST7735_RED;
tftMenuSelect(selectedMenuItemIndex);
currentBackgroundColor = ST7735_BLUE;
}

void upButtonPressed() {
Serial.println("Up button pressed!");

if (selectedMenuItemIndex == 1) {
// Position to the last menu item
tftMenuSelect(MENU_SIZE);
} else {
// Move down the selection
tftMenuSelect(selectedMenuItemIndex - 1);
}
}

void downButtonPressed() {
Serial.println("Down button pressed!");

if (selectedMenuItemIndex < MENU_SIZE) {
// Move down the selection
tftMenuSelect(selectedMenuItemIndex + 1);
} else {
// Position to the first menu item
tftMenuSelect(1);
}
}

void tftMenuInit() {
// Clear the screen and set text size
tft.setTextWrap(false);
tft.fillScreen(ST7735_BLACK);
tft.setTextSize(1);

// Display the header of the menu - the header is the first item
tft.setCursor(0, 0);
tft.setTextColor(ST7735_GREEN, ST7735_BLACK);
tft.println(mainMenu[0]);

// Draw separation line
tft.drawLine(0, 9, tft.width()-1, 9, ST7735_GREEN);

// Display other menu items
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
for(int i=1; i<=MENU_SIZE; i++)
{
tft.setCursor(0, ((i-1)*10)+MENU_TOP);
tft.println(mainMenu[i]);
}
}

void tftMenuSelect(byte menuItemIndex) {

// Remove the highlight from the currently selected menu item
tft.setCursor(0, ((selectedMenuItemIndex-1)*10)+MENU_TOP);
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
tft.println(mainMenu[selectedMenuItemIndex]);

// Highlight the new selected menu item
tft.setCursor(0, ((menuItemIndex-1)*10)+MENU_TOP);
tft.setTextColor(ST7735_YELLOW, currentBackgroundColor);
tft.println(mainMenu[menuItemIndex]);

// Save the selection
selectedMenuItemIndex = menuItemIndex;
}

Conclusion

After the sketch upload the prototype will look like this:

The sketch calculates the maximum sensed light value from the three photoresistors. If the difference is above a preset threshold, the right button click will be simulated.

It means the if all of the three values change together no button press will happen.

A small delay also had to be introduced in order to avoid multiple button presses in a small timeframe. This simulates better the behavior of a real life push button.

Contents
  1. 1. Photoresistor
  2. 2. Prototype
  3. 3. Sketch
  4. 4. Conclusion