|
|
|
@ -0,0 +1,303 @@
|
|
|
|
|
/*
|
|
|
|
|
DYNAMIC GLYPH
|
|
|
|
|
keyboard module for text input
|
|
|
|
|
// board info: LilyGO TTGO T8 ESP32-S2 - with SD Card Slot
|
|
|
|
|
// board select: ESP32S2 DEV Module
|
|
|
|
|
|
|
|
|
|
current USB port: 142300
|
|
|
|
|
|
|
|
|
|
Rotary encoder:
|
|
|
|
|
Two pins are for the internal push button (D and E);
|
|
|
|
|
the other two (A and B) provide rotation signal relative to the third pin (C),
|
|
|
|
|
which is normally connected to the ground.
|
|
|
|
|
The output pins A and B should be pulled high which can be done using internal pull up resitors of Arduino.
|
|
|
|
|
Also note that when the encoder is rotated, then lines A and B are mechanical connected to pin C (ground)
|
|
|
|
|
in certain order, which allows to detemine the direction of rotation.
|
|
|
|
|
|
|
|
|
|
tutorial: https://github.com/igorantolic/ai-esp32-rotary-encoder/blob/master/README.md
|
|
|
|
|
(look for: Connecting Rotary Encoder with Switch (no pcb version))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LCD documentation:
|
|
|
|
|
https://github.com/DFRobot/DFRobot_RGBLCD1602
|
|
|
|
|
to make the LCD work on this ESP32, there need to be some manual changes in this library!
|
|
|
|
|
find the file DFRobot_RGBLCD1602.cpp under Dokumente/Arduino/libraries/DFRobot_RGBLCD1602
|
|
|
|
|
search for the line "_pWire->begin" and manually define two pins as SDA pin (here: 34) and as SCL pin (here:33) for IC2 connection
|
|
|
|
|
GND is a ground pin. Connect it to the ground of the ESP32.
|
|
|
|
|
VCC supplies power to the module and LCD. Connect it to the ESP32’s VIN pin or an external 5V power supply.
|
|
|
|
|
SDA is the I2C data pin. Connect it to the ESP32’s I2C data pin.
|
|
|
|
|
SCL is the I2C clock pin. Connect it to the ESP32’s I2C clock pin.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TO DO:
|
|
|
|
|
reread and organize the code and all comments to clean up
|
|
|
|
|
special characters dont work? problematic index[70] and above
|
|
|
|
|
super slow – clean up loop?
|
|
|
|
|
LCD
|
|
|
|
|
document changes in the library
|
|
|
|
|
implement interrupts for all pin so that it doesnt iterate through all code every time butr only if a change is detected
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
//include libaries
|
|
|
|
|
#include "AiEsp32RotaryEncoder.h" //library to use the encoder_value function
|
|
|
|
|
#include "DFRobot_RGBLCD1602.h" //include library for LCD display
|
|
|
|
|
#include <stdio.h> //include library to access a character in a string by referring to its index number
|
|
|
|
|
|
|
|
|
|
//declare LCD display
|
|
|
|
|
DFRobot_RGBLCD1602 lcd(/*lcdCols*/16,/*lcdRows*/2); //16 characters and 2 lines of show
|
|
|
|
|
//library: manually define two pins as SDA pin (here: 34) and as SCL pin (here:33) for IC2 connection (see documentation above)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//rotary encoder
|
|
|
|
|
//define pins and steps
|
|
|
|
|
#define ROTARY_ENCODER_A_PIN 2 // CLK (Output A) determines the amount of rotation. Each time the knob is turned in either direction, the ‘CLK’ output goes through one cycle of going HIGH and then LOW.
|
|
|
|
|
#define ROTARY_ENCODER_B_PIN 3 // DT (Output B) is similar to CLK output, but it lags behind CLK by a 90° phase shift. This output is used to determine the direction of rotation.
|
|
|
|
|
#define ROTARY_ENCODER_BUTTON_PIN 45 // SW is the output of the push button switch (active low). When the knob is depressed, the voltage goes LOW.
|
|
|
|
|
#define ROTARY_ENCODER_STEPS 1 //depends on encoder type, may vary between 1 and 4
|
|
|
|
|
AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_STEPS);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//define pins:
|
|
|
|
|
#define spaceButton 4 //button to submit data to the next module
|
|
|
|
|
#define backspaceButton 5 // button to delete the last glyph in text
|
|
|
|
|
#define clearButton 0 // button to clear text completely
|
|
|
|
|
#define powerDisplay 35 //switch to turn on/off the display
|
|
|
|
|
|
|
|
|
|
//define variables:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//text:
|
|
|
|
|
String glyphs; //declares variable for the array of glyphs
|
|
|
|
|
String text; //declares variable for the text
|
|
|
|
|
|
|
|
|
|
//module in/out data
|
|
|
|
|
String input;
|
|
|
|
|
String newData;
|
|
|
|
|
String output;
|
|
|
|
|
String moduleID = "#DG"; //Dynamic Glyphs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int counter = 0; //counter will change each time the knob is rotated one detent (click).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//define function for rotary encoder (will be called):
|
|
|
|
|
void IRAM_ATTR readEncoderISR()
|
|
|
|
|
{
|
|
|
|
|
rotaryEncoder.readEncoder_ISR();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
|
// put your setup code here, to run once:
|
|
|
|
|
|
|
|
|
|
// set mode for digital input to not give floating values, but either 0 or 1:
|
|
|
|
|
pinMode(ROTARY_ENCODER_A_PIN, INPUT_PULLUP);
|
|
|
|
|
pinMode(ROTARY_ENCODER_B_PIN, INPUT_PULLUP);
|
|
|
|
|
pinMode(ROTARY_ENCODER_BUTTON_PIN, INPUT);
|
|
|
|
|
|
|
|
|
|
pinMode(backspaceButton, INPUT_PULLUP);
|
|
|
|
|
pinMode(clearButton, INPUT_PULLUP);
|
|
|
|
|
pinMode(spaceButton, INPUT_PULLUP);
|
|
|
|
|
pinMode(powerDisplay, INPUT_PULLUP); //on/off toggle switch
|
|
|
|
|
|
|
|
|
|
// initialize serial and serial1 communication at 115200 and 9600 bits per second:
|
|
|
|
|
Serial.begin(115200); //goes to serial monitor, just for debugging purposes
|
|
|
|
|
Serial1.begin(9600); // goes to the next module via patch cable (use transmit pin TX on IO17 and also connect to GND)
|
|
|
|
|
//Serial1.setTimeout(100); // there is a small bug, so there needs to be a checksum?
|
|
|
|
|
|
|
|
|
|
rotaryEncoder.begin();
|
|
|
|
|
rotaryEncoder.setup(readEncoderISR);
|
|
|
|
|
rotaryEncoder.setBoundaries(0, 89, true); //minValue, maxValue, circleValues true|false (when max go to min and vice versa, should be aligned with number of glyphs)
|
|
|
|
|
rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
|
|
|
|
|
|
|
|
|
|
//initialize LCD display (+color) and IIC
|
|
|
|
|
lcd.init();
|
|
|
|
|
lcd.setColorWhite();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//define the array of glyphs
|
|
|
|
|
//note: the array starts at 0 and ends at 90. For certain characters such as " and \ a backspace is added
|
|
|
|
|
glyphs = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,:;?!-_+%=&#*\"'/|()[]{}^<>@"; //90
|
|
|
|
|
|
|
|
|
|
text = "";
|
|
|
|
|
|
|
|
|
|
lcd.setCursor(14,0);
|
|
|
|
|
lcd.blink();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void loop() {
|
|
|
|
|
|
|
|
|
|
//rotary encoder:
|
|
|
|
|
if (rotaryEncoder.encoderChanged()){
|
|
|
|
|
lcd.stopBlink();
|
|
|
|
|
|
|
|
|
|
counter = rotaryEncoder.readEncoder();
|
|
|
|
|
//Serial.println(counter);
|
|
|
|
|
// print to serial monitor for debugging purpose:
|
|
|
|
|
//Serial.println(rotaryEncoder.readEncoder());
|
|
|
|
|
//Serial.println(glyphs[counter]);
|
|
|
|
|
|
|
|
|
|
lcd.setCursor(14,0);
|
|
|
|
|
lcd.print(glyphs[counter]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rotaryEncoder.isEncoderButtonClicked()){
|
|
|
|
|
text += glyphs[counter];
|
|
|
|
|
Serial.println("button was pressed");
|
|
|
|
|
|
|
|
|
|
int len = text.length();
|
|
|
|
|
//Serial.println(len);
|
|
|
|
|
|
|
|
|
|
if (len <= 12) {
|
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
|
lcd.print(text);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
String textCut = text.substring(len-12);
|
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
|
lcd.print(textCut);
|
|
|
|
|
Serial.println(textCut);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//print to serial monitor for debugging purpose:
|
|
|
|
|
//Serial.println("button was pressed, the following letter is added: ");
|
|
|
|
|
//Serial.println(text);
|
|
|
|
|
//Serial.println(textCut);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//powerDisplay: toggle switch display on / off
|
|
|
|
|
// read digital input
|
|
|
|
|
int powerDisplayValue = digitalRead(powerDisplay);
|
|
|
|
|
// redefine range for power:
|
|
|
|
|
if(powerDisplayValue == 0) {
|
|
|
|
|
lcd.noDisplay();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
lcd.display();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//spaceButton: button to add a space to the text string
|
|
|
|
|
// read digital input
|
|
|
|
|
int spaceButtonValue = digitalRead(spaceButton);
|
|
|
|
|
// if space button is pressed, append space to the text variable:
|
|
|
|
|
if(spaceButtonValue == 0) {
|
|
|
|
|
text += " ";
|
|
|
|
|
|
|
|
|
|
int len = text.length();
|
|
|
|
|
//Serial.println(len);
|
|
|
|
|
|
|
|
|
|
if (len <= 12) {
|
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
|
lcd.print(text);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
String textCut = text.substring(len-12);
|
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
|
lcd.print(textCut);
|
|
|
|
|
Serial.println(textCut);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// print to serial monitor for debugging purpose:
|
|
|
|
|
//Serial.println("Space Button was pressed. A space was added to the text: ");
|
|
|
|
|
//Serial.println(text);
|
|
|
|
|
//Serial.println(textCut);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//clearButton: button to clear text variable completely
|
|
|
|
|
// read digital input
|
|
|
|
|
int clearButtonValue = digitalRead(clearButton);
|
|
|
|
|
// if clear button is pressed, clear the text variable:
|
|
|
|
|
if (clearButtonValue == 0){
|
|
|
|
|
text = "";
|
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
|
lcd.print(" "); //replace old text on LCD with empty spaces
|
|
|
|
|
|
|
|
|
|
// print to serial monitor for debugging purpose:
|
|
|
|
|
//Serial.println("Clear Button was pressed. The whole text was deleted.");
|
|
|
|
|
//Serial.println(text);
|
|
|
|
|
//Serial.println(textCut);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// backspaceButton: button to delete the last glyph in text
|
|
|
|
|
// read digital input
|
|
|
|
|
int backspaceButtonValue = digitalRead(backspaceButton);
|
|
|
|
|
// if backspace button is pressed, delete the last character from string:
|
|
|
|
|
if(backspaceButtonValue == 0) {
|
|
|
|
|
int lastIndex = text.length() - 1; //find last character in text string
|
|
|
|
|
text.remove(lastIndex); //delete last character in text string
|
|
|
|
|
lcd.setCursor(lastIndex,0); //move cursor to the position of the last character
|
|
|
|
|
lcd.print(" "); //replace the last character with a space
|
|
|
|
|
|
|
|
|
|
int len = text.length();
|
|
|
|
|
//Serial.println(len);
|
|
|
|
|
|
|
|
|
|
if (len <= 12) {
|
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
|
lcd.print(text);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
String textCut = text.substring(len-12);
|
|
|
|
|
lcd.setCursor(0,0);
|
|
|
|
|
lcd.print(textCut);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// print to serial monitor for debugging purpose:
|
|
|
|
|
//Serial.println("Backspace Button was pressed. The last glyph in text was deleted: ");
|
|
|
|
|
//Serial.println(text);
|
|
|
|
|
//Serial.println(textCut);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Serial.println(text + glyphs[counter]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//put all values in a string to define the new data from this module:
|
|
|
|
|
newData = "&&&" + String(moduleID) + "," + String(text) + "&&&";
|
|
|
|
|
//newData = "&&&" + String(moduleID) + "," + "this text was written with DYNAMIC GLYPH" + "&&&";
|
|
|
|
|
|
|
|
|
|
output = newData;
|
|
|
|
|
Serial.println(output);
|
|
|
|
|
|
|
|
|
|
//Send data to next module (TX):
|
|
|
|
|
Serial1.println(output); //the data received + new data
|
|
|
|
|
|
|
|
|
|
// print to serial monitor for debugging purpose:
|
|
|
|
|
// Serial.println("Dynamic Glyph, new data: " + newData);
|
|
|
|
|
// Serial.println("This is the output I send: " + output);
|
|
|
|
|
|
|
|
|
|
}
|