Last Updated or created 2023-03-07
Warning, read the notes!
There are several caveats.
- I was needing ALL GPIO pins, even RX/TX ( see trick below)
When doing so, you can’t use serialprint.
Do NOT enable, your sketch won’t work! - Don’t use pullup on D8, you can’t upload to the wemos if you do that
- Due to library conflicts in keypad.h, DON’T change the order in the source. You will end up with compile errors!
- The keypad has a weird pinout, but there are similar keypads with alternative layouts. Measure this using a multimeter.
- The pull-up resistors will help fighting ghost key presses!
- I2C needs D1/D2
To use RX/TX as GPIO pins you need to do the following:
//Define pins int led = 1; //tx int col = 3; //rx // Change to function mode 3 // see https://www.esp8266.com/wiki/doku.php?id=esp8266_gpio_pin_allocations pinMode(1, FUNCTION_3); pinMode(3, FUNCTION_3); // Revert to normal mode // pinMode(1, FUNCTION0); // Define mode input/output // i'm using led to control the led so thats an output // I'm using col for the keypad column scanner, that's an input pinMode(led, OUTPUT); pinMode(col, INPUT);
Complete code
The (*) clears input
The (#) sends the pin code using MQTT
Sending a 0 or 1 to escape/keypadin topic will toggle the led
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <WiFiClient.h> // Do not change order! #include "Keypad.h" #include <TM1637Display.h> #include <Ethernet.h> #define wifi_ssid "SSID" #define wifi_password "SSIDPASS" #define mqtt_server "MQTTSERVER" #define mqtt_port 1883 #define MSG_BUFFER_SIZE (50) char msg[MSG_BUFFER_SIZE]; int value = 0; const byte ROWS = 4; //four rows const byte COLS = 3; //four columns int led = 1; //tx int col = 3; //rx #define CLK D1 #define DIO D2 #define TEST_DELAY 2000 TM1637Display display(CLK, DIO); char keys[ROWS][COLS] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'}, {'*', '0', '#'} }; byte rowPins[ROWS] = {D3, D5 , D6 , D7 }; byte colPins[COLS] = {D4 , col, D8 }; Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); int keyNum = 0; WiFiClient espClient; EthernetClient ethClient; PubSubClient mqtt(espClient); void setup_wifi() { delay(10); WiFi.mode(WIFI_STA); WiFi.begin(wifi_ssid, wifi_password); while (WiFi.status() != WL_CONNECTED) { delay(500); } } void setup() { setup_wifi(); mqtt.setServer(mqtt_server, mqtt_port); mqtt.setCallback(callback); pinMode(1, FUNCTION_3); pinMode(3, FUNCTION_3); pinMode(led, OUTPUT); pinMode(col, INPUT); // using above? .. then disable serial! // Serial.begin(9600); display.showNumberDec(0, true); delay(TEST_DELAY); WiFiClient espClient; PubSubClient mqtt(espClient); mqtt.setClient(espClient); mqtt.setServer(mqtt_server, 1883); mqtt.setCallback(callback); mqtt.subscribe("escape/keypadin"); } void callback(char* topic, byte* payload, unsigned int length) { // digitalWrite(led, HIGH); String topicStr = topic; byte value = atoi((char*)payload); if (value == 1){ digitalWrite(led, HIGH); }else if (value == 0){ digitalWrite(led, LOW); } } void reconnect() { while (!mqtt.connected()) { // Create a random client ID String clientId = "ESP8266Client-"; clientId += String(random(0xffff), HEX); if (mqtt.connect(clientId.c_str())) { mqtt.publish("outTopic", "hello world"); mqtt.subscribe("escape/keypadin"); } else { delay(5000); } } } void loop() { if (!mqtt.connected()) { reconnect(); } mqtt.loop(); // put your main code here, to run repeatedly: char key = keypad.getKey(); if (key) { if(key=='*'){ keyNum = 0; } else if (key=='#'){ ++value; snprintf (msg, MSG_BUFFER_SIZE, "#%1d", keyNum); mqtt.publish("escape/keypad", msg); } else{ if(keyNum<=999){ keyNum = (keyNum*10) + (int(key)-48); } } // Serial.println(key); display.setBrightness(0x0f); uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 }; display.setSegments(data); display.setSegments(data); display.showNumberDec(keyNum); } }