I keep getting "Invalid pin 4 mode" error in the serial monitor and frequent disconnects

Hi Blynkers,

I am using ESP8266 with Arduino Mega.
Sometimes my hardware keeps disconnecting (like every 2 minutes). The debug messages shows the following when the hardware gets disconnected:

Cmd error
Cmd skipped:20
Cmd skipped:20
Cmd skipped:20
Ready (ping: 9925ms)
[198249] <[11|00]b[00]gver[00]0.3.8[00]h-beat[00]10[00]buff-in[00]256[00]dev
[198657] <[00]Arduino Mega[00]cpu[00]ATmega2560[00]con[00]ESP8266
[198964] <[00]build[00]Jul 11 2016 22:57:03[00]
24.19
[199950] <[14|00]c[00|0B]vw[00]2[00]24.188
0.00
[200192] <[14|00]d[00|0A]vw[00]3[00]8.200
[200456] >[14|09|AA|00]/
[200456] >pm[00]4[00]out[00]10[00]out[00]5[00]out[00]9[00]out[00]11[00]out[00]6[00]out[00|FC|FC|F8|FC|FC|FC]
[200530] Invalid pin 4 mode ďż˝	/

I have pin 4 defined as output as it’s controlled by a function, but at the same time I have a button in my application that controls the same pin for manual operation. Does this mean I need to change the pin definition?
By the way I am using the latest Blynk version which was released today.
Below is my code, hope someone can help me:

#define BLYNK_PRINT Serial // Defines the object that is used for printing
#define BLYNK_DEBUG        // Optional, this enables more detailed prints

#include<stdlib.h>
#include <ESP8266_Lib.h> //for Blynk
#include <BlynkSimpleShieldEsp8266.h>//for Blynk
#include <SimpleTimer.h>//for Blynk
#include <OneWire.h> //for temp sensor
#include <DallasTemperature.h> //for temp sensor
SimpleTimer timer; //simple timer for Blynk
#define ONE_WIRE_BUS 8 //pin 8 is for temp sensor
#define BLYNK_PRINT Serial
OneWire oneWire(ONE_WIRE_BUS); //for temp sensor
DallasTemperature sensors(&oneWire); //for temp sensor
//WIFI details
#define SSID "............" //wifi network name
#define PASS "............" //wifi password

//STARTwater flow sensor-------------------------------------------

// which pin to use for reading the sensor? can use any pin!
#define FLOWSENSORPIN 7
#define TONE_PIN 6 // buzzer output is pin 6

// count how many pulses!
volatile uint16_t pulses = 0;
// track the state of the pulse pin
volatile uint8_t lastflowpinstate;
// you can try to keep time of how long it is between pulses
volatile uint32_t lastflowratetimer = 0;
// and use that to calculate a flow rate
volatile float flowrate;
// Interrupt is called once a millisecond, looks for any pulses from the sensor!
SIGNAL(TIMER0_COMPA_vect) {
  uint8_t x = digitalRead(FLOWSENSORPIN);

  if (x == lastflowpinstate) {
    lastflowratetimer++;
    return; // nothing changed!
  }

  if (x == HIGH) {
    //low to high transition!
    pulses++;
  }
  lastflowpinstate = x;
  flowrate = 1000.0;
  flowrate /= lastflowratetimer;  // in hertz
  lastflowratetimer = 0;
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
  }
}

//END water flow sensor--------------------------------------------------------------


//Thingspeak settigs
#define IP "184.106.153.149" // thingspeak.com
String GET = "GET /update?key=...........................&";//Thingspeak update key
//SoftwareSerial monitor(10, 11); // define software monitor pins (RX, TX)
const int updateThingSpeakInterval = 16 * 1000; // Time interval in milliseconds to update ThingSpeak (number of seconds * 1000 = interval)
float tempC;

int selectedwateramount = 0; //for wc
int wcinp = 0; // water change in process
int waterChangeAmount = 0;
int skimmer = 4;
int returnPump = 5;
int reactors = 6;
int ATO = 11;
int wcDrainPump = 10;
int wcFillPump = 9;
int wcFloatSwitch = 3;
const long skimmerDelay = 10000;

float liters = 0;
String enteredstring;
String wcamount;
String wccommandString;
long lastConnectionTime = 0;
long previousMillis = 0; //for temp sensor to read every n second
char auth[] = "...............................................";//Blynk auth code
#define EspSerial Serial1//for Blynk
ESP8266 wifi(&EspSerial);//for Blynk

WidgetLCD lcd(V1); //define Blynk LCD
WidgetTerminal terminal(V5);
char ph_data[20];
byte ph_string_received=0;
byte ph_received_from_sensor=0; 
String inputstring = "";                              //a string to hold incoming data from the PC
String sensorstring = "";                             //a string to hold the data from the Atlas Scientific product
boolean input_string_complete = false;                //have we received all the data from the PC
boolean sensor_string_complete = false;               //have we received all the data from the Atlas Scientific product
float pH;                                             //used to hold a floating point number that is the pH


//++++++++++++++++++++++++++++++++++++++++++++++++++START SETUP++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600); //wifi serial
  Serial3.begin(9600); //PH serial
  
  pinMode(skimmer, OUTPUT);
  pinMode(returnPump, OUTPUT);
  pinMode(reactors, OUTPUT); 
  pinMode(wcDrainPump, OUTPUT);
  pinMode(wcFillPump, OUTPUT);
  pinMode(ATO, OUTPUT);
  pinMode(wcFloatSwitch, INPUT);
  
  digitalWrite(skimmer, HIGH);
  digitalWrite(returnPump, HIGH);
  digitalWrite(reactors, HIGH);
  digitalWrite(wcDrainPump, LOW);
  digitalWrite(wcFillPump, LOW);
  digitalWrite(ATO, LOW); 
 
  
  
  inputstring.reserve(10);                          //PH - set aside some bytes for receiving data from the PC
  sensorstring.reserve(30);                         //PH - set aside some bytes for receiving data from Atlas Scientific product
  Blynk.begin(auth, wifi, "UltraTech", "haidarzeenalinawisam");// for Blynk
  sensors.begin();//Start Temperature sensor
  sendDebug("AT");//test id WIFI is responding
  //delay(5000);
  if (Serial1.find("OK")) {
    Serial.println("RECEIVED: OK");
    //connectWiFi();// connect to WIFI

  }

  pinMode(FLOWSENSORPIN, INPUT);
  //pinMode(3, INPUT); //sump high float switch
  //pinMode(9, OUTPUT); //res pump
 // pinMode(10, OUTPUT); // sump pump

  

 
  
  digitalWrite(FLOWSENSORPIN, HIGH);
  lastflowpinstate = digitalRead(FLOWSENSORPIN);
  useInterrupt(true);
  //timer.setInterval(1500L, sendTempToLcdBlynk);
  timer.setInterval(5000L, sendTempToGraphBlynk);
  //timer.setInterval(4000L, sendPHToLcdBlynk);
  timer.setInterval(7500L, sendPHToGraphBlynk);  
}

//++++++++++++++++++++++++++++++++++++++++++++++++++END SETUP++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void serialEvent3() {                                 //if the hardware serial port_3 receives a PH reading
  sensorstring = Serial3.readStringUntil(13);         //read the string until we see a <CR>
  sensor_string_complete = true;                      //set the flag used to tell if we have received a completed string from the PH sensor
}


//++++++++++++++++++++++++++++++++++++++++++++++++++START VOID LOOP++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void loop() {


Blynk.run(); // run Blynk process
timer.run(); // Initiates SimpleTimer
delay(50);

}

//++++++++++++++++++++++++++++++++++++++++++++++++++END VOID LOOP++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//@@@@@@@functions@@@@@@@@@@@functions@@@@@@@@@@@functions@@@@@@@@@@@functions@@@@@@@@functions@@@@@@@@@


//-------------START send temp Blynk------------//
void sendTempToGraphBlynk()
{
    GetTemperature();
    Serial.println(tempC);   
    char buffer[10]; //buffer for the temperature
    String temperature = dtostrf(tempC, 4, 2, buffer); //convert the temperature to a string
    
    Blynk.virtualWrite(2, tempC);
}

//-------------END send temp Blynk graph------------//



//-------------START send pH on Blynk graph------------//
void sendPHToGraphBlynk()
{
    GetPH();
    Serial.println(pH);  
    
    char pH_buffer[10]; //buffer for the ph

    String pHstring = dtostrf(pH, 3, 2, pH_buffer); //convert the pH to a string
    Blynk.virtualWrite(3, 8.2);

}

//-------------END send pH on Blynk  graph------------//


//-------------Start Get Temperature Function------------//
void GetTemperature()

{
  sensors.requestTemperatures(); // Send the command to get temperatures
  tempC =  sensors.getTempCByIndex(0);
  
 // Serial3.print("t,"); //send temperature to pH circuit
 // Serial3.print(tempC); //send temperature to pH circuit
 // Serial3.print("\r"); //send CR to pH circuit
}
//-------------End Get Temperature Function------------//

//----------START---------Receive command from Blynk terminal and excute accordingly----------------------------------
BLYNK_WRITE(V5)
{
  enteredstring = param.asStr();
  wcamount = enteredstring.substring(13);
  wccommandString = enteredstring.substring(0, 12);
  waterChangeAmount = wcamount.toInt();
  terminal.println(wcamount);
  terminal.println(wccommandString);


  if (String("water change") == wccommandString) {

    
    
    changeWater(waterChangeAmount);
    //terminal.println("I said: 'Polo'") ;
  }

  else if (String("hi") == param.asStr())
  {
  terminal.print("Hi Haidar enter a command please");
  //  changeWater(waterChangeAmount);
  //
  //  wcinp=0;
  }
  
  else if (String("hi") == param.asStr())
  {
  terminal.print("Hi Haidar enter a command please");
  //  changeWater(waterChangeAmount);
  //
  //  wcinp=0;
  }
    else if (String("help") == param.asStr())
  {
  terminal.println("You can enter the following commands:");
  terminal.println("- water change #");
  //  changeWater(waterChangeAmount);
  //
  //  wcinp=0;
  }
  
      else if (String("pumps off") == param.asStr())
  {
  pumpsOff();
  }

      else if (String("pumps on") == param.asStr())
  {
  pumpsOn();
  }

    else if (String("ph temp") == param.asStr())
  {

   for(int a=0; a<2; a++)
   {
    Serial3.print("t,101\r");
    delay(500);
   }
    

//if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been received in its entirety
//   terminal.println(sensorstring);                 
//
//     Serial.println(sensorstring);
//      sensorstring = "";                                  //clear the string:
//      sensor_string_complete = false;       
//}

    terminal.println("Received");



  }
  
      else if (String("cont ph reading on") == param.asStr())
  {

   for(int a=0; a<2; a++)
   {
    Serial3.print("c,1\r");
    delay(500);
   }
    

//if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been received in its entirety
//   terminal.println(sensorstring);                 
//
//     Serial.println(sensorstring);
//      sensorstring = "";                                  //clear the string:
//      sensor_string_complete = false;       
//}

    terminal.println("Received");



  }
  
  else if (String("cont ph reading off") == param.asStr())
  {

   for(int a=0; a<2; a++)
   {
    Serial3.print("c,0\r");
    delay(500);
   }
    

//if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been received in its entirety
//   terminal.println(sensorstring);                 
//
//     Serial.println(sensorstring);
//      sensorstring = "";                                  //clear the string:
//      sensor_string_complete = false;       
//}

    terminal.println("Received");



  }

  //else if (String("haidar") == param.asStr()) {
  //   terminal.println("حيدر") ;
  //
  //terminal.println("I said: 'Polo'") ;
  //  }
  else {
    // Send it back
    terminal.write(param.getBuffer(), param.getLength());
    terminal.print(" is not a valid command, enter help to see available options");
    terminal.println();
  }
  // Ensure everything is sent

  terminal.flush();
}


//----------END---------Receive command from Blynk terminal and excute accordingly----------------------------------



//
//-----------------Start get PH function-----------------//

void GetPH() {
  if (sensor_string_complete == true) {               //if a string from the Atlas Scientific product has been received in its entirety
    //Serial.println(sensorstring);                     //send that string to the PC's serial monitor
    if (isdigit(sensorstring[0])) {                   //if the first character in the string is a digit
      pH = sensorstring.toFloat();                    //convert the string to a floating point number so it can be evaluated by the Arduino
    }
  }
  sensorstring = "";                                  //clear the string:
  sensor_string_complete = false;    //reset the flag used to tell if we have received a completed string from the Atlas Scientific product

}
//-----------------End get PH function-----------------//
//
//-------------update thingspeak----------------------//
void updateTemp(String temperature, String pHstring) {
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  sendDebug(cmd);
  delay(2000);
  if (Serial1.find("Error")) {
    Serial.print("RECEIVED: Error");
    return;
  }
  //cmd = GET;
  //cmd += "field1=";
  //cmd += temperature;
  //cmd += "&field2=";
  //cmd += pHstring;
  //cmd += "\r\n";
  cmd = GET + "&field1=" + temperature + "&field2=" + pHstring + "\r\n";
  Serial1.print("AT+CIPSEND=");
  Serial1.println(cmd.length());
  if (Serial1.find(">")) {
    Serial.print(">");
    Serial.print(cmd);
    Serial1.print(cmd);
    lastConnectionTime = millis();
  } else {
    sendDebug("AT+CIPCLOSE");
    lastConnectionTime = millis();
  }
  if (Serial1.find("OK")) {
    Serial.println("RECEIVED: OK");
  } else {
    Serial.println("RECEIVED: Error");
  }
}
void sendDebug(String cmd) {
  Serial.print("SEND: ");
  Serial.println(cmd);
  Serial1.println(cmd);
}
//-------------update thingspeak----------------------//
//
//
//------------Connect wifi---------------
boolean connectWiFi() {
  Serial1.println("AT+CWMODE=1");
  delay(2000);
  String cmd = "AT+CWJAP=\"";
  cmd += SSID;
  cmd += "\",\"";
  cmd += PASS;
  cmd += "\"";
  sendDebug(cmd);
  delay(5000);
  if (Serial1.find("OK")) {
    Serial.println("RECEIVED: OK");
    return true;
  } else {
    Serial.println("RECEIVED: Error");
    return false;
  }
}
//------------Connect wifi---------------

//------START Water change function---------------------
void changeWater (int selectedwateramount)

{

  terminal.println(selectedwateramount);

  pulses = 0; //added code witout testing
  liters = 0; //added code witout testing

  if (selectedwateramount > 0) {
    terminal.print("System will change ") ;
    terminal.print(waterChangeAmount);
    terminal.println(" liters") ;
    
    tone(2, 3000, 3000);
    pumpsOff();
    wcinp = 1;
    
    terminal.println("Water change started...") ;
    while (liters < selectedwateramount) {
      Blynk.run(); // run Blynk process
      liters = pulses; //flow sensor
      liters /= 7.5; //flow sensor
      liters /= 60.0; //flow sensor
      //Serial.print(liters); Serial.println(" Liters");
      terminal.println("Draining water");


      terminal.print(liters);
      terminal.print(" ltr ");
      //lcd.setCursor(9, 1);
      terminal.print(liters / selectedwateramount * 100);

      terminal.println("%");
      //switch on sump pump
      digitalWrite(wcFillPump, LOW);
      digitalWrite(wcDrainPump, HIGH);
      delay(500);
    }
    wcFloatSwitch = digitalRead(3); //added code witout testing
    while (liters >= selectedwateramount && wcFloatSwitch == LOW) {
      Blynk.run(); // run Blynk process
      wcFloatSwitch = digitalRead(3);
      terminal.println("* Adding water *");
      //switch on res pump
      digitalWrite(wcFillPump, HIGH);
      digitalWrite(wcDrainPump, LOW);
      //blinking adding water text
      delay(500);
    }
    if (wcFloatSwitch == HIGH) {
      //delay(2000); to eliminate sensor sensitivity should be added later somehow
      Blynk.run(); // run Blynk process
      
      tone(2, 1000, 10000);
      pulses = 0;
      liters = 0;
      selectedwateramount = 0;
      digitalWrite(wcFillPump, LOW);
      digitalWrite(wcDrainPump, LOW);
      pumpsOn();
      terminal.println("Water change completed");
      wcinp = 0;
    }


  }
  else {
    terminal.println("Please enter a valid amount");

  }
}

void pumpsOff()
{
  digitalWrite (skimmer,LOW);
  digitalWrite (returnPump,LOW);
  digitalWrite (reactors,LOW);
  digitalWrite (ATO,LOW);
  terminal.println("Pumps are off");
}

void pumpsOn()
{

  int switchedOn = 0;
  digitalWrite (returnPump,HIGH);
  digitalWrite (reactors,HIGH);
  terminal.println("Return pump and reactors switched on");
  
  unsigned long pumpsOnTime = millis();

  terminal.println("Switching on skimmer");
  while (switchedOn !=1)
  {
      unsigned long skimmerOnTime = millis();
  
  
  if (skimmerOnTime - pumpsOnTime >= skimmerDelay) {
  Blynk.run(); // run Blynk process
  digitalWrite (skimmer,HIGH);
  switchedOn =1;
  terminal.println("Skimmmer switched on");
  }
  }
}
  
//------END Water change function---------------------

Please ensure that you have a firm connection between ESP and Arduino.
One more thing -> it seems you are hacking into Blynk protocol by sending commands to ESP manually.
You shouldn’t do that! Blynk doesn’t know that you’re sending commands to ESP and therefore is failing to work with ESP correctly.

I am not sending any commands manually, please let me know which part of the code is sending commands manually.

Every time you do something like Serial1.print(...)

These prints were under a function which I never call in my code (for thigspeak). However I removed this function completely, but I am still getting the same frequent disconnects with the following debug log:

[418246] Cmd error
22.94
[419079] Cmd skipped:20
0.00
[419081] Cmd skipped:20
[424327] <[02|00|01|00] ".......................my Blynk key..................."
22.94
[425327] Cmd skipped:20
0.00
[425328] Cmd skipped:20
[433717] >[00|00|01|00|C8]
[433717] Ready (ping: 9171ms).
[433718] <[11|00|A2|00]gver[00]0.3.8[00]h-beat[00]10[00]buff-in[00]256[00]dev
[434126] <[00]Arduino Mega[00]cpu[00]ATmega2560[00]con[00]ESP8266
[434433] <[00]build[00]Jul 12 2016 20:13:13[00]
22.87
[435521] <[14|00|A3|00|0B]vw[00]2[00]22.875
0.00
[435757] <[14|00|A4|00|0A]vw[00]3[00]8.200
[436011] >[14|17|1A|00]/
[436011] >pm[00]9[00]out[00]11[00]out[00]4[00]out[00]6[00]out[00]5[00]out[00]10[00]out[00|F8|F8|FC|F8|FF|F8]
[436085] Invalid pin 9 mode /

can someone please help? Still can’t figure out where the issue is.

Does this problem appear if you just run the simplest Blynk example code, without your application code?

Hi,

You could try cleaning up the code a bit to make it more readable.

When I look at your setup() I see;

  Blynk.begin(auth, wifi, "UltraTech", "haidarzeenalinawisam");// for Blynk
  sensors.begin();//Start Temperature sensor
  sendDebug("AT");//test id WIFI is responding
  //delay(5000);
  if (Serial1.find("OK")) {
    Serial.println("RECEIVED: OK");
    //connectWiFi();// connect to WIFI

To me that looks like it is sending an “AT” command to the ESP8826 (serial1) via the sendDebug() and waiting for an “OK” response.

I know you’ve said your driving the ESP8826 directly, but it looks like you are to me. Is the ESP8826 on a different port?

Thanks Nick, you are right I need to clean up the code.
I actually removed the below from the setup after vhymanskyy highlighted it, I am still getting the same error in the serial monitor. Could this be a hardware issue?

  sendDebug("AT");//test id WIFI is responding
  //delay(5000);
  if (Serial1.find("OK")) {
    Serial.println("RECEIVED: OK");

Just thought someone would know what the issue is from the error log as it’s not very clear to me. I will try again to upload a simple code as suggested by vhymanskyy to see if I have the same issue.

From looking at the source, it looks like it generates the error when the hardware gets configured from the server.

The server will send a line like;

[436011] >pm[00]9[00]out[00]11[00]out[00]4[00]out[00]6[00]out[00]5[00]out[00]10[00]out[00|F8|F8|FC|F8|FF|F8]

Which reads, set the pin mode (PM) to 9 -Out, 11-Out, 4-Out, etc…

Valid modes are;
in - input
out - output
pwm - also output
pu- input with pullup
pd - input with pulldown.

If the mode doesn’t match any of these it gives the “Invalid pin mode” error with the pin and mode that was requested.

So in your case this looks like

   [436085] Invalid pin 9 mode /

Meaning, it tried to set a pin mode of backslash.

Strange thing is the preceding line indicated that the mode was valid.

My guess would be that there might be a bug in the Blynk library your using, or maybe your ESP is sending in enough rubbish that it is confusing the Blynk libraries, or you have one of those weird buffer overrun errors that is corrupting the program or data somehow.

How about loading one of the simple example programs and leave it run for a while, that should prove that the hardware is correct.

Thanks Nick. I tried the simple code and it was running fine for 2 hours. So look like it’s not a hardware issue. Also the ping time was 82ms, while it was around 10000ms. So would this test help to narrow down the issue?

This may happen because of delays in your code, and other long operations

So does that mean I can’t use Blynk if I have long operations in my project?
One of my functions takes around 15 minutes to finish, therefore I added the Blynk.runt inside this function so it doesn’t get disconnected.
I will try to remove all the delays and replace them by millis() function as I can’t use the simple timer inside a function.

@haidar23 can you please explain what the 15+ minutes function does.

Hi Costas, it’s a function for automated aquarium water change.

I understand that delays can cause Blynk functions not to run and so cause disconnects, how do they cause the API to interpret what looks like a valid pin mode as an invalid one?

@haidar23 can you explain in more detail how the water change occurs and is there a particular part of the sketch that does this? I haven’t looked at the sketch.

It is very likely that you can use Blynk even though you have a function that “runs for more than 15 minutes”.
It may require a modification to the function but as I know nothing about aquariums it is difficult to offer a solution at this point.

but what does the function DO for the 15 minutes?

surely a function should start something, then use another function stops that something?

that’s what i do!

Exactly @Dave1829

I have now looked through the sketch and I’m guessing it takes 15 minutes for the pumps to change the water in the aquarium.

There is a while loop that checks a (pump) switch status and the number of litres of water that flows (in / out of the aquarium). The while loop does have a call to Blynk.run() so this should maintain the 10s heartbeat but I’ve never been a big fan of while loops. I would probably use SimpleTimer at given intervals to check the switch status and volume of water as this way Blynk.run() will be called automatically in the main loop().

1 Like

I know I might need to rewrite the water change function at some point, but the disconnects happen even when the water change function is not running. So i have only 2 functions running continously for temperature and PH reading. All the other functions run only when I send a command through the terminal widget.