/**
******************************************************************************
@author Arduino development
@version 3.0
@date 21.09.2020
@brief ESP Client - Loutky.cz
*/
#define SERIAL_DEBUG_OUT
#define SERIAL_BAUDRATE 115200
#define SERVER_PORT 80
#define DEBOUNCE_TICKS 20
#define DATA_LENGTH 11
#define ANALOG_X 0
#define ANALOG_Y 1
#define CONNECTION_LED 16
//pinout same as here: https://docs.wemos.cc/en/latest/d1/d1_mini.html
#define ARM_BUTTON_PIN 0 //D3
#define BLINK_BUTTON_PIN 2 //D4
#define MOUTH_POT_PIN A0 //A0
/* keypad definitions */
#define BUTTON_1 '1'
#define BUTTON_2 '2'
#define BUTTON_3 '3'
#define BUTTON_4 '4'
#define T_KEY_DEBOUNCE 20 //ms
#define T_KEY_HOLD 500 //ms
#define NO_KEY_PRESSED '\000'
#define N_KEYPAD_ROWS 2
#define N_KEYPAD_COLS 2
#define PIN_COL_1 15 //D8
#define PIN_COL_2 13 //D7
#define PIN_ROW_1 14 //D5
#define PIN_ROW_2 12 //D6
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ObjectButton.h>
#include <interfaces/IOnPressListener.h>
#include <Adafruit_ADS1X15.h>
#include <Wire.h>
#include <Keypad.h>
const char* ssid = "loutkaAP";
const char* password = "LoutkaAP1234#";
char keyMap[N_KEYPAD_ROWS][N_KEYPAD_COLS] = {
{BUTTON_1, BUTTON_2},
{BUTTON_3, BUTTON_4},
};
uint8_t rowPins[N_KEYPAD_ROWS] = {PIN_ROW_1, PIN_ROW_2};
uint8_t colPins[N_KEYPAD_COLS] = {PIN_COL_1, PIN_COL_2};
Keypad keypad = Keypad(makeKeymap(keyMap), rowPins, colPins, N_KEYPAD_ROWS, N_KEYPAD_COLS);
struct DataOutput {
bool armButton = 0;
bool blinkButton = 0;
bool excitementButton = 0;
bool noseButton = 0;
bool angerButton = 0;
bool surpriceButton = 0;
uint8_t joyLeft = 0;
uint8_t joyRight = 0;
uint8_t joyForward = 0;
uint8_t joyRear = 0;
uint8_t potMouth = 0;
};
uint16_t anValX;
uint16_t anValY;
uint16_t anValXCnt;
uint16_t anValYCnt;
uint8_t txBuffer[DATA_LENGTH];
DataOutput dataOut;
IPAddress server(192, 168, 0, 1);
WiFiClient client;
Adafruit_ADS1115 adConverter;
void adConverterBegin();
void clientBegin();
void connectToAP();
void connectToServer();
void clientRoutine();
void readPeripherals();
void joystickReading();
void potentiometrReading();
void keypadReading();
void processKeypadData(bool state, char key);
void processJoystickData();
void sendData();
class Buttons : private virtual IOnPressListener {
public:
Buttons() = default;
void init();
void update();
private:
void onPress(ObjectButton &button) override;
void onRelease(ObjectButton &button) override;
void onLongPressStart(ObjectButton &button) override {};
void onLongPressEnd(ObjectButton &button) override {};
ObjectButton armButtonObj = ObjectButton(ARM_BUTTON_PIN, true);
ObjectButton blinkButtonObj = ObjectButton(BLINK_BUTTON_PIN, true);
};
void Buttons::onPress(ObjectButton &button) {
switch (button.getId()) {
case ARM_BUTTON_PIN:
dataOut.armButton = true;
break;
case BLINK_BUTTON_PIN:
dataOut.blinkButton = true;
break;
}
}
void Buttons::onRelease(ObjectButton &button) {
switch (button.getId()) {
case ARM_BUTTON_PIN:
dataOut.armButton = false;
break;
case BLINK_BUTTON_PIN:
dataOut.blinkButton = false;
break;
}
}
void Buttons::init() {
armButtonObj.setDebounceTicks(DEBOUNCE_TICKS);
armButtonObj.setOnPressListener(this);
blinkButtonObj.setDebounceTicks(DEBOUNCE_TICKS);
blinkButtonObj.setOnPressListener(this);
}
void Buttons::update() {
armButtonObj.tick();
blinkButtonObj.tick();
}
// buttons instance
Buttons *buttons;
void adConverterBegin() {
// ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default)
adConverter.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV
// ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV
// ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV
// ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV
// ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV
adConverter.begin();
anValYCnt = adConverter.readADC_SingleEnded(ANALOG_Y);
anValXCnt = adConverter.readADC_SingleEnded(ANALOG_X);
//if GAIN_ONE set, DA range is 0 – 65536
anValYCnt = map(anValYCnt, 0, 65536, 0, 255);
anValXCnt = map(anValXCnt, 0, 65536, 0, 255);
}
void clientBegin() {
connectToAP();
connectToServer();
}
void connectToAP() {
WiFi.begin(ssid, password);
Serial.println("CONNECTING TO AP");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(200);
digitalWrite(CONNECTION_LED, HIGH);
delay(20);
}
Serial.println("\nAP CONNECTION ESTABLISHED");
}
void connectToServer() {
Serial.println("CONNECTING TO SERVER");
while (!client.connect(server, SERVER_PORT)) {
Serial.print(".");
delay(200);
digitalWrite(CONNECTION_LED, HIGH);
delay(20);
}
digitalWrite(CONNECTION_LED, LOW);
delay(20);
Serial.println("\nSERVER CONNECTION ESTABLISHED");
}
void clientRoutine() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("CONNECTION WITH SERVER LOST");
clientBegin();
}
readPeripherals();
sendData();
}
void readPeripherals() {
//joystick
joystickReading();
processJoystickData();
//potentiometr
potentiometrReading();
//keypad
keypadReading();
}
void joystickReading() {
anValY = adConverter.readADC_SingleEnded(ANALOG_Y);
anValX = adConverter.readADC_SingleEnded(ANALOG_X);
anValY = map(anValY, 0, 65536, 0, 255);
anValX = map(anValX, 0, 65536, 0, 255);
}
void potentiometrReading() {
uint16_t anMouthVal = analogRead(MOUTH_POT_PIN);
dataOut.potMouth = map(anMouthVal, 0, 1023, 0, 255);
}
void keypadReading() {
if (keypad.getKeys()) {
for (uint8_t i = 0; i < N_KEYPAD_ROWS * N_KEYPAD_COLS ; i++) {
if (keypad.key[i].stateChanged) {
switch (keypad.key[i].kstate) {
case PRESSED:
processKeypadData(true, keypad.key[i].kchar);
break;
case RELEASED:
processKeypadData(false, keypad.key[i].kchar);
break;
default:
break;
}
}
}
}
}
void processKeypadData(bool state, char key) {
switch (key) {
case '1':
(state) ? dataOut.excitementButton = true : dataOut.excitementButton = false;
dataOut.noseButton = false;
dataOut.angerButton = false;
dataOut.surpriceButton = false;
break;
case '2':
dataOut.excitementButton = false;
(state) ? dataOut.noseButton = true : dataOut.noseButton = false;
dataOut.angerButton = false;
dataOut.surpriceButton = false;
break;
case '3':
dataOut.excitementButton = false;
dataOut.noseButton = false;
(state) ? dataOut.angerButton = true : dataOut.angerButton = false;
dataOut.surpriceButton = false;
break;
case '4':
dataOut.excitementButton = false;
dataOut.noseButton = false;
dataOut.angerButton = false;
(state) ? dataOut.surpriceButton = true : dataOut.surpriceButton = false;
break;
}
}
void processJoystickData() {
if (anValY <= anValYCnt) {
dataOut.joyRear = map(anValY, anValYCnt, 0, 0, 255);
dataOut.joyForward = 0;
}
else {
dataOut.joyForward = map(anValY, anValYCnt, 127, 0, 255);
dataOut.joyRear = 0;
}
if (anValX <= anValXCnt) {
dataOut.joyLeft = map(anValX, anValXCnt, 0, 0, 255);
dataOut.joyRight = 0;
}
else {
dataOut.joyRight = map(anValX, anValXCnt, 127, 0, 255);
if (dataOut.joyRight < 150) {
dataOut.joyRight = 0;
}
dataOut.joyLeft = 0;
}
}
void sendData() {
memset(txBuffer, 0, DATA_LENGTH);
txBuffer[0] = dataOut.armButton;
txBuffer[1] = dataOut.blinkButton;
txBuffer[2] = dataOut.excitementButton;
txBuffer[3] = dataOut.noseButton;
txBuffer[4] = dataOut.angerButton;
txBuffer[5] = dataOut.surpriceButton;
txBuffer[6] = dataOut.joyLeft;
txBuffer[7] = dataOut.joyRight;
txBuffer[8] = dataOut.joyForward;
txBuffer[9] = dataOut.joyRear;
txBuffer[10] = dataOut.potMouth;
if (client.connected() != 0) {
client.write(txBuffer, DATA_LENGTH);
client.flush(); //waits for the transmission of outgoing serial data to complete
}
else {
if (WiFi.isConnected() != WL_CONNECTED) {
connectToAP();
}
connectToServer();
}
}
void setup() {
// initialize serial communication
#ifdef SERIAL_DEBUG_OUT
Serial.begin(SERIAL_BAUDRATE);
delay(1);
Serial.println(F("ESP Client - Loutky.cz"));
Serial.println(F("Version 3.0"));
Serial.println(F("Developed by Arduino development"));
Serial.println(F("development.arduino-shop.cz"));
Serial.println();
#endif
pinMode(CONNECTION_LED, OUTPUT);
digitalWrite(CONNECTION_LED, HIGH);
pinMode(MOUTH_POT_PIN, INPUT);
delay(20);
//client setting
clientBegin();
//ad converter setting
adConverterBegin();
//object button setting
buttons = new Buttons();
buttons->init();
//keypad setting
keypad.setDebounceTime(T_KEY_DEBOUNCE);
keypad.setHoldTime(T_KEY_HOLD);
}
void loop() {
buttons->update();
clientRoutine();
}
// #ifdef SERIAL_DEBUG_OUT
//
// #endif
/**
@brief
@param
@retval
*/