Código encrava a meio!

Boas, tenho andado a trabalhar num projecto e tenho tido alguns problemas, um deles é quando crio um loop com while(true) todo o código encrava mesmo antes de chegar ao loop, vou exemplificar: Tenho a função A, B e C:

void C(){ while(true){ //código que necessita ficar em loop } }

void B(){ C(); }

void A(){ B(); }

void loop(){ A(); }

Acontece que sempre que crio o loop na função C o código encrava na função B, sem loop o código passa corretamente em todas as funções e volta ao loop principal. Agradecia alguma ajuda se possível! Obrigado

Como sabes que é isso que está a acontecer? Com o código que colocaste não é possível de inferir o que dizes.

Se estás a usar outro código qualquer, coloca o código todo em vez de apenas uma parte.

Já agora, porque é que precisas de mais um loop infinito??

Aproveita e coloca um Serial.print no final da função de setup() e vê se esse Serial.print está a ser enviado repetidamente sem acção por parte do utilizador.

Bom olhando para esse codigo eu diria que isso é de esperar ... Vejamos:

void loop() chama-> funcaoA->chama funçao->B-chama funçaoC ->Este tem loop infinito e fica eternamente aqui ...

.. um deles é quando crio um loop com while(true) todo o código encrava mesmo antes de chegar ao loop

Acontece que sempre que crio o loop na função C o código encrava na função B, sem loop o código passa corretamente em todas as funções e volta ao loop principal.

Esta afirmação é contraditória, pois se afirmas que sem loop passa em todas significa que as funções estão todas a ser chamadas, adicionando o loop na função C é de esperar que la encrave e nunca mais saia de lá ou não? Como sabes que é na funçao B que encrava? eu coloco o meu dinheiro que é na C :) Como o Bubulindo te recomendou tenta adicionar Serial.print("Estou na função X"); em cada função para fazeres algum debug do que está a acontecer

Pessoal peço desculpa se não me fiz entender, aqui está o código completo, pensei que ao simplificar ajudaria em alguma coisa:

#include <Ethernet.h>
#include <SPI.h>
#include <Wire.h>
#include <Keypad.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

byte mac_addr = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress server_addr(192,168,1,137); // IP of the MySQL server here

char user = “teste”; // MySQL user login username
char password = “teste”; // MySQL user login password
float saldo=0;

int first = 0;
int second = 0;
float total = 0;
int inserido = 0;
int pininserido = 0;
float totaldanger=0;
int pin = 0;

const byte ROWS = 4;
const byte COLS = 4;

char keys[ROWS][COLS] = {
{‘1’,‘2’,‘3’,’+’},
{‘4’,‘5’,‘6’,’-’},
{‘7’,‘8’,‘9’,’*’},
{‘A’,‘0’,‘C’,’.’}
};
byte rowPins[ROWS] = {A0,A1,A2,A3}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {9,8,7,6}; //connect to the column pinouts of the keypad

Keypad customKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

String conteudo = “”;

EthernetClient client;
MySQL_Connection conn((Client *)&client);

//------------------------------------------------------------------------------------------

// converter string to float
float StrToFloat(String str)
{
char carray[str.length() + 1];
str.toCharArray(carray, sizeof(carray));
return atof(carray);
}

//-------------------------------------------------------------------------------------------
void confirmarpin(float saldo, int pin) {
char customKey;
while(true)}
customKey = customKeypad.getKey();
switch(customKey)
{
case ‘0’ … ‘9’:

inserido = inserido * 10 + (customKey - ‘0’);
Serial.println(inserido);
break;
//----------------------
case ‘C’:
inserido = (pininserido != 0 ? pininserido : inserido);

Serial.print(“Confirmacao:”);
if (inserido == pin){

Serial.print(“comparacao valida2”);
}
else {
Serial.print(“comparacao invalida2”);
}

Serial.print(pininserido);
inserido = 0;
break;

}
}
}
//-------------------------------------------------------------------------------------------

//pesquisar base dados
void pesqbasedados(String conteudo){
Serial.print("Recebido na funcao seguinte: ");
Serial.println(conteudo);
//------ Converte a string conteudo no char conteudoChar
char conteudoChar[13];
conteudo.toCharArray(conteudoChar, 13);
Serial.print("String to Char: ");
Serial.println(conteudoChar);
//------

char query[128];

MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);

sprintf(query, “SELECT Saldo,PIN FROM gateway.clientes WHERE UID = ‘%s’”,conteudoChar);
// Execute the query
cur_mem->execute(query);
// (dá print do nome da coluna)
column_names *cols = cur_mem->get_columns();
for (int f = 0; f < cols->num_fields; f++) {
Serial.print(cols->fields[f]->name);
if (f < cols->num_fields-1) {
}
}
Serial.println();
// Read the rows and print them
row_values *row = NULL;
do {
row = cur_mem->get_next_row();
if (row != NULL) {
for (int f = 0; f < cols->num_fields; f++) {
row->values[0];
//----------
}

saldo = StrToFloat(row->values[0]);
pin = atoi(row->values[1]);

}

} while (row != NULL);
Serial.println(saldo); //float
Serial.println(pin); //int
//----------

delete cur_mem;

delay(1000);

confirmarpin(saldo, pin); //inserir aqui a proxima função
}

//--------------------------------------------------------------------------------------

// nfc sensor detetar pulseira
void nfcdetc(int howMany, float total){

conteudo = “”;
while( Wire.available()){
conteudo += (char)Wire.read();
}
pesqbasedados(conteudo); //avança para a proxima função, pesquisar na BD a UID

}
//-----------------------------------------------------------------------------------------
void loopnfc() {
Wire.onReceive(nfcdetc);
}
//-----------------------------------------------------------------------------------------

long SecondNumber()
{
char customKey;
while( 1 )
{
customKey = customKeypad.getKey();
if(customKey >= ‘0’ && customKey <= ‘9’)
{
second = second * 10 + (customKey - ‘0’);

Serial.println(second);
}

if(customKey == ‘C’) break;
}
return second;
}
//-------------------------------------------------------------------------------------------

void valorapagar(){

char customKey;
Serial.println(“Insira a montante:”);

while(true){

customKey = customKeypad.getKey();
switch(customKey)
{
case ‘0’ … ‘9’:

first = first * 10 + (customKey - ‘0’);
Serial.print(first);
break;
//---------------------
case ‘.’:
Serial.print(".");
second = SecondNumber();
// Serial.print(second0.1);
total = first;
total+=second
0.1;
totaldanger=total;
Serial.println(total);
Serial.println(“passar tag”);
first = 0, second = 0;
loopnfc();
break;
//--------------------
case ‘A’:

Serial.println(“operacao anulada”);
first = 0, second = 0;
return 0;
break;
}
}
}

//------------------------------------------------------------------------------------------

void loop() {
valorapagar();

}

//-----------------------------------------------------------------------------------------

void setup() {
Serial.begin(115200);
Wire.begin(8);
while (!Serial);
Ethernet.begin(mac_addr);
Serial.println(“Connecting…”);
if (conn.connect(server_addr, 3306, user, password)) {
delay(1000);
}
else
Serial.println(“Connection failed.”);

SPI.begin();// Inicia SPI bus

}

O problema está na função confirmarpin, assim que adiciono a linha while(true) tal como na função valorapagar, a função pesqbasedados encrava logo no inicio, ficando o Serial.print("Recebido na funcao seguinte: ") a meio no serial monitor.
Necessito mesmo que o código do keypad na função comfirmarpin fique em loop, senão ele nunca fica à espera de ser inserido o valor, já tentei fazer um loop de todas as formas possíveis (julgo eu) e o código encrava sempre no mesmo sitio, basta remover a linha while(true), e o código corre todo e volta ao inicio sem parar na função confirmarpin. Julgo que isto possa ser um problema de memória, mas estou a utilizar o Mega que tem mais que suficiente, também tentei adicionar uns delays entre funções na esperança de ele querer alguma coisa, mas os delays são ignorados, pus até de 30s e ele segue sempre. Mais uma vez obrigado pela ajuda.

void confirmarpin(float saldo, int pin) {
char customKey;
while(true)}//--------------->Aqui tens um erro
customKey = customKeypad.getKey();
switch(customKey)
{
case ‘0’ … ‘9’:

Tens um erro de sintaxe aqui, estas a fechar a função, deves ter trocado os dedos :slight_smile:
Olhando para essa função mesmo com isso corrigido, a tua função efectivamente nunca vai sair desse loop ja que nunca interrompes o (while(true))!
Nota que o break apenas te interrompe o switch para não fazer (“falling-through”) não o while .
Supondo que o teu pin tem 4 dígitos como esperas interromper isso?
Em tempos fiz um alarme onde tinha um keypad para colocar o um pin para o desarmar.Vê a lógica que eu usei para capturar os 4 dígitos

void readKeypadCode()
{
  char tempCode[5];
  uint8_t counter = 0;
  while(counter <=4){
  char key = keypad.getKey();
  if (key != NO_KEY)
      {
       tempCode[counter++] = key;
      }
  if(counter >=4){
    Serial.println("The Code is : ");
    tempCode[4] = '\0';
    Serial.println(tempCode);
    for(uint8_t i =0;i<=4;i++){
    code[i] = tempCode[i];
    }
    counter++;
   }
 }
}
char readKeypadButton()
{
  char key = keypad.getKey();
  if (key != NO_KEY)return key;
  else return NO_KEY;

}

Esse erro de sintaxe é devido ao facto de eu ter feito modificações e na hora que fui copiar o codigo para esta página enganei-me, mas não é aí que está o problema. A forma que ele irá sair do loop é quando o utilizador confirma premindo a tecla C e não quando digitar os 4 numeros, de qualquer maneira posso também testar assim. O que eu realmente precisava era que o código não bloqueie logo no inicio da função pesqbasedados, mas se esse código com limite para 4 digitos não encravar, então perfeito! Obrigado

Estás a usar funções sem saberes o que elas fazem, por exemplo:

void loopnfc() {
   Wire.onReceive(nfcdetc);
   }

Podes ver aqui o que o método faz: https://www.arduino.cc/en/Reference/WireOnReceive Basicamente, precisas de chamar esta função uma vez e no setup(). Sempre que houver algo recebido pelo I2C, a função nfcdetc() será chamada. Apesar de tudo, não acho que seja isto que te está a dar problemas apesar de ter potencial para o fazer.

O que, para mim, te causa o bloqueio é esta linha:

 conteudo += (char)Wire.read();

Eu não sei como funciona o teu NFC reader e se ele envia dados em ASCII ou binário, mas se envia dados em binário, isto não é exactamente o que tu julgas que é. Imagina que um caracter é o número 50 enviado em binário... ao fazeres isto o que vai ser passado para o conteudo não é o número 50, mas o caracter "2". Experimenta adicionar isto logo após esse ciclo while:

Serial.print(conteudo);
delay(3000);

O problema pode também estar na ligaçõa à base de dados... mas de global diria que tu estás a fazer copy/paste de várias fontes sem saber exactamente o que estás a colar no código e isso torna tudo bastante mais confuso, e por consequência com probabilidade de erros, para toda a gente. Experimenta o que disse e posta o resultado.

Obrigado pessoal pelas dicas, no entanto julgo ter descoberto o problema, e por acaso não é nada do que destacaram no código, pois testei o código todo por etapas e funcionou na perfeição até ter adicionado o while(true) na função confirmarpin(). A linha: "conteudo += (char)Wire.read();" não é que encrava, e é mesmo necessária para juntar todos os bytes extraídos do BUS I2C numa string para usar na query da BD. Pelas conclusões que tirei, o código encrava numa função devido a alterações que faço em outra que é chamada posteriormente devido à falta de memória RAM. Para tentar resolver este problema vou declarar as variáveis na memória Flash e ver se o problema fica resolvido. Mais uma vez obrigado pelas dicas.

Eu não disse que encravava nessa linha... apenas que podias estar a fazer uma conversão que depois fazia a tua comparação não retornar um valor correcto e bloquear.

Na minha experiência quando o Arduino tem falta de RAM, ele retorna ao inicio... estranho não ter acontecido isso aqui.