Chat freely about anything...

User avatar
By marcosda87
#79073 Hi guys! I'm working on a system that uses a Wemos D1 Mini Pro based on ESP8266F.X (1.0.0) and a rotary encoder, wemos count the steps and shout the data trhow wifi using TCP protocol to a client (PC).
Every 20 seconds, wemos send a "life signal" to pc in order to keep the client connected. That part works actually very well; I let both (wemos and PC) on all night long and everything went fine.
When I start to mess around with the encoder, problems begin... I move the encoder and data is sent, but if a start moving the encoder REAL FAST back and forward, gives me and exception and everything fails. I've tried to limitate the time between packets, but problems keep going...
I commented the line part when I send the data -"client.println (mensaje);"- and doing the same action mentioned I have no exception, so, I thing problem is on the sending part... (I think...)
How can I manage this issue? Thanks in advance!

Code: Select all//---------------------------------------------Librerías para incluir
#include <ESP8266WiFi.h>

//---------------------------------------------Definición de variables
#define pinD1 D1
#define pinD2 D2
#define pinD7 D7
#define pinD5 D5
#define pinD6 D6

WiFiClient client;

int contador = 0;
int lastEncState = LOW;
String tempMsg;
unsigned long timeout;
int countPackets;

unsigned long lastIndState = 0;
unsigned long lastPacket = 0;
int lastPacketMin = 0;           //Tiempo mínimo entre paquetes para envio

const char* ssid = "ProyeccionesCorp";      //Nombre de la RED WIFI a conectarse (SSID)
const char* password = "cordoba392";        //Contraseña de RED WIFI

const String Wemos0 = "enc0";
const String Wemos1 = "enc1";
const String Wemos2 = "enc2";
const String Wemos3 = "enc3";
      String mainVar = "";

bool useDHCP = false;                       //Indica si obtiene dirección IP del servidor DHCP, de lo contrario, carga los siguiente valores
  IPAddress staticIP (192, 168, 0, 0);
 
  IPAddress staticIP0(192, 168, 50, 201);     //IP estática de ésta terminal Wemos (0)
  IPAddress staticIP1(192, 168, 50, 202);     //IP estática de ésta terminal Wemos (1)
  IPAddress staticIP2(192, 168, 50, 203);     //IP estática de ésta terminal Wemos (2)
  IPAddress staticIP3(192, 168, 50, 204);     //IP estática de ésta terminal Wemos (3)
  IPAddress gateway(192, 168, 1, 1);       //IP del Ruter (Gateway)
  IPAddress subnet(255, 255, 255, 0);      //Máscara de SubRed

IPAddress ipDestino(192, 168, 50, 174);      //Dirección IP a donde se enviarán paquetes UDP
const int puertoRemoto = 4445;              //Puerto remoto para enviar UDP

const char* deviceName = "WemosD1ProMini";  //Nombre del Dispositivo

char  replyPacket[] = "A";                  //Buffer de carga para envio de mensajes UDP

//---------------------------------------------SETUP
void setup() {
  ESP.wdtEnable(1000);
  Serial.begin(115200);
  delay(100);

  bool A, B;
  int temp;
 
  A = digitalRead (pinD5);
  B = digitalRead (pinD6);
 
  if (!A && !B) {temp = 0;}
  if (A && !B) {temp = 1;}
  if (!A && B) {temp = 2;}
  if (A && B) {temp = 3;}

    switch (temp){
      case 0:
        staticIP = staticIP0;
        mainVar = Wemos0;
        break;
      case 1:
        staticIP = staticIP1;
        mainVar = Wemos1;
        break;
      case 2:
        staticIP = staticIP2;
        mainVar = Wemos2;
        break;
      case 3:
        staticIP = staticIP3;
        mainVar = Wemos3;
        break;
    }
 
  pinMode(pinD7, INPUT);
  pinMode(pinD1, INPUT);
  pinMode(pinD2, INPUT);
  pinMode(pinD5, INPUT);
  pinMode(pinD6, INPUT);
 
  attachInterrupt(digitalPinToInterrupt(pinD1), doEnc, RISING );          //Seteo de Interrupcion para Encoder A
  attachInterrupt(digitalPinToInterrupt(pinD2), doEnc, RISING );          //Seteo de Interrupcion para Encoder B
  attachInterrupt(digitalPinToInterrupt(pinD7), doInductivo, RISING  );   //Seteo de Interrupcion para Encoder B

  Serial.printf("Enviando datos a IP %s, en el Puerto %d", ipDestino.toString().c_str(), puertoRemoto);
  Serial.print (F(" con la variable "));
  Serial.println (mainVar);
  Serial.print ("Se utilizará la dirección IP ");
  Serial.println (staticIP);
  Serial.println("Sistema Listo");
}

void connectWIFI(){
if (WiFi.status() == 6) {
    Serial.print("Conectando a la red ");
    Serial.println(ssid);
 
    WiFi.mode(WIFI_STA);
    WiFi.config(staticIP, subnet, gateway);
    WiFi.begin(ssid, password);
 
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
 
    Serial.println("WiFi conectado!");
    Serial.print("IP Local: ");
    Serial.println(WiFi.localIP());
  }
}

//---------------------------------------------LOOP
void loop(){
  if (WiFi.status() != WL_CONNECTED){
    connectWIFI();
  }else{
       if (client.connected() == 0){
          Serial.println("Cliente desconectado. Intentando Conectar...");
          connectToWO (3040);
       }else{
        unsigned long temp = millis() - lastPacket;
            if (temp > 20000){
              sendTCP("authenticate 1", 3039);
              sendTCP("authenticate 1", 3040);
            }
      }
  }
}

//---------------------------------------------CONNECTTOWO
void connectToWO (int port){
  Serial.print("Conectando a ");
  Serial.print(ipDestino);
  Serial.print(':');
  Serial.println(port);
 
  if (!client.connect(ipDestino, port)) {
    Serial.println("Falló la conexión");
    delay(1000);
    return;
  }else{
    Serial.print ("Conectado exitosamente a ");
    Serial.println (ipDestino);
    timeout = millis();
    sendTCP("authenticate 1", 3039);
    sendTCP("authenticate 1", 3040);
  }
}

//---------------------------------------------SENDUDP
void sendTCP(String mensaje, int puerto){
long temp = millis() - lastPacket;
if (temp >= lastPacketMin){
    if (client.connected() == 0){
      Serial.println("Cliente desconectado. Intentando Reconectar...");
      connectToWO (puerto);
    }else{ 
      Serial.print(F("Enviando a "));
      Serial.print(ipDestino);
      Serial.print(F(":"));
      Serial.print(puerto);
      Serial.print(F(" el valor: "));
      Serial.println (mensaje);
         client.println (mensaje);
      lastPacket = millis();
    }
  }else{
    Serial.println ("Port Overflow");
  }
}

//---------------------------------------------DOENC
void doEnc(){
  ESP.wdtFeed();
  int A = digitalRead (pinD1);
  int B = digitalRead (pinD2);
 
    if ((lastEncState == LOW) && (A == HIGH)) {
      if (B == LOW) {
        contador--;
      } else {
        contador++;
      }
      tempMsg = "setInputs 0 " + mainVar + " " + String(contador);
      sendTCP(tempMsg, 3040);
    }
    lastEncState = A;
}

//---------------------------------------------DOINDUCTIVO
void doInductivo(){
  if (millis () - lastIndState > 1000){
    contador = 0;
    Serial.println(F("+++ Inductivo activado +++"));
    lastIndState = millis();
  }
}
User avatar
By schufti
#79086 Hi,
be carefull with interupts:
a) ISR should be placed in iram to be allways available
void ICACHE_RAM_ATTR doEnc();
b) keep ISR as short as possible to avoid recursing calls or disable interupts in ISR
(keybouncing could be a cause, use R/C on rot.enc.)
User avatar
By btidey
#79092 It is also good to use a state machine on the rotary encode handler as this then deals well with ambiguous states caused by bounce.

I would also just maintain position in the isr and then use the foreground to check position and send updates as required. That way any reporting delays do not compromise the rotary encode handling.

See, for example, viewtopic.php?f=11&t=18681

The rotary encoder library is also at https://github.com/roberttidey/RotaryEncoderArray