Is there a paid service that helps people debug their sketches

Hi,
I'm trying to write a program to automate a pressure cooker and I ran into a horrific problem, I'm stuck. My sketch works but when I add one more line of code in any place it stops working. If I delete it, it works again. Is there any place to hire someone easily to help me debug the sketch?

Any help is greatly appreciated.

Post the code, maybe we can help?

If you want to pay for someone to help you click on 'report to moderator' and ask them to move this to 'gigs and collaborations'; that's where you post for paid help.

However, as LightuC says, you can probably get free help here if you want us to help you do it, as opposed to us doing it for you.

Hi LightuC and PerryBebbington, thanks a lot for your response. My problem here is very strange, it is not a little piece of code that's buggy and I can copy-paste here (I already tried and exceeded the allowed length), and there is no compiling error to show. I'm trying to automate a pressure cooker with a thermocouple and SSR. It works as it is right now, but I cannot add a single line of extra code anywhere because it starts to make the same error. It first asks for hours, minutes, and temperature, you enter them via keypad or via software serial from a NodeMCU, then it just controls temperature like a thermostat. My nano is connected to a NodeMCU vía serial and the NodeMCU to Blynk via Wifi. When I add any extra line of code like for example Serial.print("Hello"); anywhere in the code, main loop, or in other functions, instead of reading the correct Hours and Minutes from software serial coming from the NodeMCU, it reads 0, zero as those values. I don't know what is happening but I can't advance because when I make any change, it stops reading these values correctly. Do you think I should use i2c communication instead of serial between the nano and the NodeMCU? My code is too long to paste here so I'll attach it. Thanks Perry, I doubt it will be easy to get help for this specific problem but it's good to know I can go to gigs and collaborations to ask for paid help :smiley: Thanks for the tip!

Autoclave_Controller_nov_2019_20.zip (6.76 KB)

Not enough free dynamic memory, and use of String variables.

Start with using the F() macro in all .print() statements, that cuts your memory usage in half.

FYI OP's code blocks - please post inline if you're smart enough

#include <LiquidCrystal_I2C.h> // Debe descargar la Libreria que controla el I2C
#include<Wire.h>
#include <Keypad_I2C.h>
#include <SPI.h>
#include <SoftwareSerial.h>
SoftwareSerial NodeMCU(2,3);

LiquidCrystal_I2C lcd(0x27,20,4);

#include <max6675.h>         // Incluye libreria del chip del termocople
#include<CountUpDownTimer.h> // librería del timer
CountUpDownTimer T(DOWN, HIGH); // defino objeto timer
CountUpDownTimer T2(DOWN, HIGH);
CountUpDownTimer In(DOWN, HIGH); //Timer del intermedio
float Temperatura = 0; // temperatura actual del Termopar


int TempObjetivo = 0;   // Temp. mínima que se debe mantener, o sea, 121 ªC normalmente
int TempMedia = 0;  // TempMedia = TempObjetivo + 1, se asigna en la función de PideTemp()
// int diferencial = 0.5;  // Puede ser + o - por arriba y debajo de la TempObjetivo, siempre no la usaré
boolean TempObjetivoAlcanzada = false; // Temperatura Objetivo Alcanzada?
boolean EsterFinalizada = false; 
boolean TiempoSeleccionado = false;  
boolean TempSeleccionada = false;    // Temperatura seleccionada? 

boolean SSRPrendido = false; 

#define thermoDO 10
#define thermoCS 11
#define thermoCLK 12
#define pinSolenoide 9
#define pinSSR 13 // SSR grande para la resistencia
//#define TiempoDesfogue 480 // 480 segundos = 8 min de desfogue
#define TiempoCalentamientoMax 5400 // 5400 = 1:30 1 hora 30 min - Si tarda más en llegar a temperatura objetivo, aborta ciclo 
#define TempBoil 97 // Temperatura a la cual empieza a generar vapor normalmente (de la que ya no sube si la válvula de desfogue 
                    // está abierta), puede modificarse si es que algún eliminador o causa hiciera que las lecutras del termopar
                    // fueran diferentes a las que se generan con el actual eliminador de 5V que es Apple grandecito.

int segEfectivos = 0; //Segundos de esterilización efectiva(por encima de temp objetivo) 

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);

#include <Keypad.h>

#define I2CADDR 0x20
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad_I2C keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS, I2CADDR); 

int tecla = 0;
int minutos = 0; //int minutos2 = 0; int minIntermedio = 0; int horasIntermedio = 0;
int horas = 0;   //int horas2 = 0;
int ContadorSolenoide = 0;
int ContadorValvulasCerradas = 0; // Cuenta tiempo para que si a cierto tiempo, aprox 1:10, no se ha llegado a la TempObjetivo, aborte el ciclo para evitar accidentes si es que una válvula estuviera abierta.
int TiempoDesfogue = 0;

void setup(){
  Serial.begin(9600);
  NodeMCU.begin(9600);

  pinMode(pinSolenoide,OUTPUT);
  digitalWrite(pinSolenoide,HIGH); // Solenoide apagada, válvula cerrada
  
  pinMode(pinSSR,OUTPUT);
  digitalWrite(pinSSR,LOW);
  
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0);
  
  keypad.begin();        // GDY120705
  
  
}

void loop(){
  if(TiempoSeleccionado == false)
    PideTiempo();
  
  if(TiempoSeleccionado == true && TempSeleccionada == false)
    PideTemperatura();
    
  if (EsterFinalizada == false)
  {
    CicloEsteril(horas, minutos);
    
  }
  
  if(EsterFinalizada == true){
    Temperatura = thermocouple.readCelsius();
    lcd.setCursor(10,1);
    lcd.print(Temperatura); lcd.print(" C");
    delay(1000);
  }
}

////////////////////////////////////////////////////////////////////////// TERMINA VOID LOOP

continued

Subprogram #1 - PIDETEMP

void PideTemperatura(){
  String dString;
  
  byte posicionDecimal = 0;
  int value = 0;
  
  tecla = 0;

  if(TempSeleccionada == false){
    lcd.setCursor(0,0);
    lcd.print("Introduce ");
    lcd.setCursor(0,1);
    lcd.print("temperatura: ");
    NodeMCU.print("Introduce temperatura: ");  
  }
      
  while(TempSeleccionada == false)
  {
    char customKey = keypad.getKey();
    
    if (customKey != NO_KEY)
    {
      Serial.println(customKey);

      lcd.setCursor(posicionDecimal,2);
      lcd.print(customKey);
      tecla = customKey;
      if (tecla >= 48 && tecla <= 57)
      {
        switch (tecla)
        {
          case 48: tecla = 0; break;
          case 49: tecla = 1; break;
          case 50: tecla = 2; break;
          case 51: tecla = 3; break;
          case 52: tecla = 4; break;
          case 53: tecla = 5; break;
          case 54: tecla = 6; break;
          case 55: tecla = 7; break;
          case 56: tecla = 8; break;
          case 57: tecla = 9; break;
        }
        if (tecla>=0 && tecla<=9)
        {
          value = value*10;
          value = value + tecla;
          posicionDecimal++;
        }
      }
      
      if (customKey == '#')
      {
        Serial.print("Value = ");
        Serial.println(value);
        lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
        posicionDecimal=0;

        if(value > 125 or value < 0)
        {
          lcd.setCursor(0,2); lcd.print("Temp muy alta o baja");
          Serial.println("Temp muy alta o baja");
          Serial.print("Temp alta o baja: "); Serial.println(value);
          delay(1500);
          lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
          value = 0;
          Serial.print("Value nuevo: "); Serial.println(value);
        }
        else
        {
          TempObjetivo = value;
          TempMedia = TempObjetivo + 1;
          TempSeleccionada = true;
          lcd.clear(); lcd.setCursor(0,0);
          value = 0;
          Serial.print("Temp Objetivo= "); Serial.println(TempObjetivo);
          delay(1000);
        }
      }
      
      if (customKey == '*')
      {
        value = 0;
        lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
        posicionDecimal = 0;
        Serial.print("Value after *: "); Serial.println(value);
      }
      
    }

    if(NodeMCU.available()>0)
    {
      while(NodeMCU.available()>0)
      {
        char rdata;
        rdata = NodeMCU.read();
        dString = dString + rdata; 
      }
      Serial.print("dString = "); Serial.println(dString);
      
      int vString = dString.toInt();
      Serial.print("vString = "); Serial.println(vString);
      if(vString > 127 or vString < 0)
      {
        dString = "";
        lcd.setCursor(0,2); lcd.print(vString); lcd.print(" Temp alta/baja"); 
        NodeMCU.print("Temp alta/baja");
        Serial.println("Temp alta/baja");
        delay(1000);
        lcd.setCursor(0,2); lcd.print("                    ");
      }
      else 
      {
        //NodeMCU.print("Temp alta/baja"); Este comando si le meto aquí cualquier comando se chinga el código y deja de funcionar lo de pedir las horas y minutos, empieza a hacer locuras.Entonces no puedo imrimir la temp ni en el lcd ni en el Terminal Blynk
        TempObjetivo = vString;
        TempMedia = TempObjetivo + 1;
        TempSeleccionada = true;
        lcd.clear(); lcd.setCursor(0,0);
        
        value = 0;
        Serial.print("Temp Objetivo= "); Serial.println(TempObjetivo);
        
        delay(1000);
      }
    }
  } 
}

Subprogram #2 - PIDETIEMPO

void PideTiempo()
{
  String dString;
  
  byte posicionDecimal = 0;
  int value = 0;
  
  bool HorasSeleccionadas = false;
  bool MinSeleccionados = false;

  lcd.print("Introduce horas: ");
  NodeMCU.print("Introduce horas: ");
  
  while(HorasSeleccionadas == false)
  {
    char customKey = keypad.getKey();
    
    if (customKey != NO_KEY)
    {
      Serial.println(customKey);
      lcd.setCursor(posicionDecimal,2);
      lcd.print(customKey);
      tecla = customKey;
      if (tecla >= 48 && tecla <= 57){
        switch (tecla){
          case 48: tecla = 0; break;
          case 49: tecla = 1; break;
          case 50: tecla = 2; break;
          case 51: tecla = 3; break;
          case 52: tecla = 4; break;
          case 53: tecla = 5; break;
          case 54: tecla = 6; break;
          case 55: tecla = 7; break;
          case 56: tecla = 8; break;
          case 57: tecla = 9; break;
        }
        if (tecla>=0 && tecla<=9)
        {
          value = value*10;
          value = value + tecla;
          posicionDecimal++;
        }
      }
      
      if (customKey == '#')
      {
        Serial.print("Value = ");
        Serial.println(value);
        lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
        posicionDecimal=0;

        if(value > 40 or value < 0)
        {
          lcd.setCursor(0,2); lcd.print("Tiempo alto o bajo");
          Serial.println("Tiempo muy alto o bajo");
          delay(1500);
          lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
          Serial.print("Value alto o bajo: "); Serial.println(value);
          value = 0;
          Serial.print("Value nuevo: "); Serial.println(value);
        }
        else
        {
          horas = value;
          HorasSeleccionadas = true;
          lcd.clear(); lcd.setCursor(0,0);
          value = 0;
          Serial.print("Value: "); Serial.println(value);
        }
      }
      if (customKey == '*')
      {
        value = 0;
        lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
        posicionDecimal = 0;
        Serial.print("Value after *: "); Serial.println(value);
      }   
    }
    
/// NodeMCU ///////////////////////////////
    
    if(NodeMCU.available()>0)
    {
      while(NodeMCU.available()>0)
      {
        char rdata;
        rdata = NodeMCU.read();
        dString = dString + rdata; 
      }
      Serial.print("dString = "); Serial.println(dString);
      
      int vString = dString.toInt();
      Serial.print("vString = "); Serial.println(vString);
      if(vString > 40 or vString < 0)
      {
        dString = "";
        lcd.setCursor(0,2); lcd.print(vString); lcd.print(" Tiempo alto/bajo"); 
        NodeMCU.print("Tiempo alto o bajo");
        Serial.println("Tiempo alto o bajo");
        delay(1000);
        lcd.setCursor(0,2); lcd.print("                    ");
      }
      else 
      {
        horas = vString;
        HorasSeleccionadas = true;
        Serial.println("Horas Seleccionadas correctamente");
      }
      
      Serial.print("Horas = "); Serial.println(horas);
      if(HorasSeleccionadas == true)
      {
        lcd.setCursor(0,2); lcd.print(horas); lcd.print(" horas");
        NodeMCU.print(horas); NodeMCU.print(" horas");
        delay(1000);
      }
    }

    
  }

  dString = "";
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Introduce minutos: ");
  NodeMCU.print("Introduce minutos: ");

  
  while(MinSeleccionados == false && HorasSeleccionadas == true)
  {
    char customKey = keypad.getKey();
    
    if (customKey != NO_KEY)
    {
      Serial.println(customKey);
      lcd.setCursor(posicionDecimal,2);
      lcd.print(customKey);
      tecla = customKey;
      if (tecla >= 48 && tecla <= 57)
      {
        switch (tecla)
        {
          case 48: tecla = 0; break;
          case 49: tecla = 1; break;
          case 50: tecla = 2; break;
          case 51: tecla = 3; break;
          case 52: tecla = 4; break;
          case 53: tecla = 5; break;
          case 54: tecla = 6; break;
          case 55: tecla = 7; break;
          case 56: tecla = 8; break;
          case 57: tecla = 9; break;
        }
        if (tecla>=0 && tecla<=9)
        {
          value = value*10;
          value = value + tecla;
          posicionDecimal++;
        }
      }
      
      if (customKey == '#')
      {
        Serial.print("Value = ");
        Serial.println(value);
        lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
        posicionDecimal=0;

        if(value > 59 or value < 0)
        {
          lcd.setCursor(0,2); lcd.print("Tiempo alto o bajo");
          Serial.println("Tiempo muy alto o bajo");
          delay(1500);
          lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
          value = 0;
          Serial.print("Value: "); Serial.println(value);
        }
        else
        {
          minutos = value;
          Serial.print("Value: "); Serial.println(value);
          MinSeleccionados = true;
          lcd.clear(); lcd.setCursor(0,0);
        }
      }
      if (customKey == '*')
      {
        value = 0;
        lcd.setCursor(0,2); lcd.print("                    "); lcd.setCursor(0,2);
        posicionDecimal = 0;
        Serial.print("Value: "); Serial.println(value);
      }   
    }

    if(NodeMCU.available()>0)
    {
      while(NodeMCU.available()>0)
      {
        char rdata;
        rdata = NodeMCU.read();
        dString = dString + rdata; 
      }
      Serial.print("dString = "); Serial.println(dString);
      
      int valMin = dString.toInt();
      Serial.print("valMin = "); Serial.println(valMin);
      if(valMin > 59 or valMin < 0)
      {
        dString = "";
        lcd.setCursor(0,2); lcd.print(valMin); lcd.print(" Tiempo alto/bajo"); 
        NodeMCU.print("Tiempo alto o bajo");
        Serial.println("Tiempo alto o bajo");
        delay(1000);
        lcd.setCursor(0,2); lcd.print("                    ");
      }
      else 
      {
        minutos = valMin;
        MinSeleccionados = true;
        Serial.println("Minutos seleccionados correctamente");
      }
      
      Serial.print("Minutos = "); Serial.println(minutos);
      if(MinSeleccionados == true)
      {
        lcd.setCursor(0,2); lcd.print(minutos); lcd.print(" minutos");
        NodeMCU.print(minutos); NodeMCU.print(" minutos");
        delay(1000);
      }
    }
  }

  if (HorasSeleccionadas == true && MinSeleccionados == true)
  {
    TiempoSeleccionado = true;
    Serial.print("Tiempo Seleccionado = true y es: "); Serial.print(horas);
    Serial.print(":"); Serial.print(minutos);
    lcd.clear();           
    lcd.setCursor(0,0);           
    lcd.print(horas);            
    if(horas == 1)             
      lcd.print(" Hora");           
    else             
      lcd.print(" Horas");            
    lcd.setCursor(0,1);           
    lcd.print(minutos); 
    lcd.print(" Minutos");            
    delay(1000);
    lcd.clear(); 
    lcd.setCursor(0,3); lcd.print("Tiempo S. "); lcd.print(horas); lcd.print(":"); lcd.print(minutos);
    lcd.setCursor(0,0);
  }
}

This is a very unreliable way to read a serial port (NodeMCU is a software serial port in the code). There is nothing to indicate the beginning or end of the serial data, and no way to tell if you have received all of it or just the first character or two.

Also note where I added the F() macro to the print statements, that tells the compiler to store the literal text in flash (program) memory instead of dynamic memory, and cuts your dynamic memory usage down to a bit over 900 bytes from the original 1800.

    if(NodeMCU.available()>0)
    {
      while(NodeMCU.available()>0)
      {
        char rdata;
        rdata = NodeMCU.read();
        dString = dString + rdata; 
      }
      Serial.print(F("dString = ")); Serial.println(dString);
      
      int vString = dString.toInt();
      Serial.print(F("vString = ")); Serial.println(vString);
      if(vString > 127 or vString < 0)
      {
        dString = "";
        lcd.setCursor(0,2); lcd.print(vString); lcd.print(F(" Temp alta/baja")); 
        NodeMCU.print(F("Temp alta/baja"));
        Serial.println(F("Temp alta/baja"));
        delay(1000);
        lcd.setCursor(0,2); lcd.print(F("                    "));
      }

Thanks for posting the code in-line.

lastchancename:
FYI OP's code blocks - please post inline if you're smart enough

There is always a risk that one messes something up when posting code over several posts.

If OP would have done it, it would have taken 10 minutes to post it and next copy it back into a new sketch or file to verify that it was complete. In the mean time some would have been all over him/her that it would not compile if he/she made a mistake :wink:

Thank you lastchancename por posting in line and David for that advice, I'll try that macro soon and report back! THANKS!!!