Function not running in the code

Hello guys

For my second code I have ever written I decided to play around with bitwise operator and I came up with the idea of simulating an elevator. The code I wrote is working pretty well, even though I realised I need to make one logic change. However my question is regarding a function in the main loop just being ignored.

I have made 2 main functions, one is called “targeting”, which decides where the elevator should go next… and the other is “movimento”, which in theory makes the door open/close and move the elevator. However the function “movimento” is not working at all, as in not running through it. So I need you guys help because I don’t know why it wouldnt work.

To test if it was actually not running through it or it was a programming flaw I have commented out all the “movimento” function and I only made it to be a Serial.print … and it is not even printing anything. Therefore I concluded that for some unknown reason the function is being ignored and I really have no idea why. The function right before it, “targeting”, is working just fine.

Here is part of my code, I am skipping variable declarations, setup and the targeting function for length sake, since the code is over 400 lines. I have bolded the relevant part. (some comments/parts are in portuguese, I am not american)

Thanks in advance =)

//CODE

variables declaration

//funcoes
int targeting ( byte flagIn, byte flagOut, byte andar);
void movimento( byte alvo, long tempo, byte andar, int openFlag);

void setup()
{
skipped
}

void loop()
{
menosUmStateIn = digitalRead (menosUmIn);
groundStateIn = digitalRead (groundIn);
umStateIn = digitalRead (umIn);
doisStateIn = digitalRead (doisIn);
tresStateIn = digitalRead (tresIn);
quatroStateIn = digitalRead (quatroIn);

menosUmStateOut = digitalRead (menosUmOut);
groundStateOut = digitalRead (groundOut);
umStateOut = digitalRead (umOut);
doisStateOut = digitalRead (doisOut);
tresStateOut = digitalRead (tresOut);
quatroStateOut = digitalRead (quatroOut);

tempo = millis(); // marcar tempo

//tests indicador
Serial.print(“andar:”);
Serial.println(andar);
Serial.print(“alvo:”);
Serial.println(alvo);
Serial.print(“estado1:”);
Serial.println(s);
Serial.print(“estado2:”);
Serial.println(e);
Serial.print(“flagin:”);
Serial.println(flagIn);
Serial.print(“flagout:”);
Serial.println(flagOut);
Serial.print("open? ");
Serial.println(openFlag);

// descobrir qual andar que o elevador está, assumindo que ele aperte um limitswitch

if (digitalRead(menosUmPin)==LOW)
{
andar = (B00000001);
}
else if (digitalRead(groundPin) == LOW)
{
andar = (B00000010);
}
else if (digitalRead(umPin)==LOW)
{
andar = (B00000100);
}
else if (digitalRead(doisPin)==LOW)
{
andar = (B00001000);
}
else if (digitalRead(tresPin) == LOW)
{
andar = (B00010000);
}
else if (digitalRead(quatroPin) == LOW)
{
andar = (B00100000);
}

//controle interno usando bitoperator para saber qual pedido esta pendente
//interno
if (menosUmStateIn==LOW)
{
flagIn = (flagIn | (B00000001));
}
if (groundStateIn==LOW)
{
flagIn = (flagIn | (B00000010));
}
if (umStateIn == LOW)
{
flagIn = (flagIn | (B00000100));
}
if (doisStateIn == LOW)
{
flagIn = (flagIn | (B00001000));
}
if (tresStateIn == LOW)
{
flagIn = (flagIn | (B00010000));
}
if (quatroStateIn == LOW)
{
flagIn = (flagIn | (B00100000));
}

//externo
if (menosUmStateOut==LOW)
{
flagOut = (flagOut | (B00000001));
}
if (groundStateOut==LOW)
{
flagOut = (flagOut | (B00000010));
}
if (umStateOut == LOW)
{
flagOut = (flagOut | (B00000100));
}
if (doisStateOut == LOW)
{
flagOut = (flagOut | (B00001000));
}
if (tresStateOut == LOW)
{
flagOut = (flagOut | (B00010000));
}
if (quatroStateOut == LOW)
{
flagOut = ((flagOut) | (B00100000));;
}

//identifica se pedido de flag ja foi atendido
if (flagIn == (flagIn | andar) && flagIn!=0)
{
flagIn = (flagIn ^ andar);
openFlag = 1;
}
else if (flagOut == (flagOut | andar) && flagOut!=0)
{
flagOut = (flagOut ^ andar);
openFlag = 1;
}
else
{
openFlag= 0;
}

** alvo = targeting(flagIn, flagOut, andar);**
** movimento(alvo, tempo, andar, openFlag);**

}

//FUNCOES

int targeting(byte flagIn, byte flagOut, byte andar)
{
skipped code
}

void movimento (byte alvo, double tempo, byte andar, int openFlag)
{
** Serial.print(" jfdklajsdlaksjdlkajs");**
/*
if (openFlag == 1)
{
e = abrir;
}
switch(e)
{
case abrir:
digitalWrite(portaPin, HIGH); // setar a porta para abrir… possivelmente seria uma funcao
if (digitalRead(sensorPortaPin)==LOW)
{
e = aberto;
}
break;

case aberto:
timeout = tempo + 3500;
//esperar pessoas
if (digitalRead(sensorMovPin)==LOW)
{
timeout = tempo + 3000;
}
if (tempo >timeout)
{
e = fechar;
//fechar porta
//nota: por a mao enquanto fecha
}
break;

case fechar:

digitalWrite(portaPin, -HIGH); // setar a porta para fechar… possivelmente seria uma funcao
if (digitalRead(sensorMovPin)==LOW)
{
e = abrir;
}
if (digitalRead(sensorPortaPin)==LOW)
{
e = fechado;
}
break;

case fechado:

if (target<andar)
{
digitalWrite(portaPin, -HIGH);
}
else if (target > andar)
{
digitalWrite(portaPin, HIGH);
}
else
{
digitalWrite(portaPin, LOW);
}
break;
}
return;
*/
}

void setup()
{
  *skipped*
}

Now, that won't even compile!

There are stickies at the top of the forum that you are supposed to read before posting here. It is clear that you didn't read them. Why should we read your post, then?

the whole code exceeds 9000 characters, the maximum allowed lenght. I can post it in 2 comments then, if you want.

// code

/* esse programa simula/controla um elevador funcional. Sistema

  • conta com apenas um elevador funcionando. Assume-se que quem
  • esta nos andares superiores ao terreo querem descer e quem
  • esta no terreo ou subsolo quer subir.
    */

//INPUTS

//detector de andar
const int menosUmPin = 28; //subsolo (D28)
const int groundPin = 32; //terreo (D32)
const int umPin = 36; //primeiro andar (D36)
const int doisPin = 40; //segundo andar (D40)
const int tresPin = 44; //terceiro andar (D44)
const int quatroPin= 48; //quarto andar (D48)

//botoes dentro do elevador para passageiros escolher andar

const int menosUmIn = 29; //D29
const int groundIn = 33;//D33
const int umIn = 37;//D37
const int doisIn = 41;//D41
const int tresIn = 45;//D45
const int quatroIn = 49;//D49
//botoes externos, para pessoas esperando
const int menosUmOut = 30;//D30
const int groundOut = 34;//D34
const int umOut = 38;//D38
const int doisOut = 42;//D42
const int tresOut = 46;//D46
const int quatroOut = 50;//D50

const int sensorMovPin =23; //saber se tem alguem na porta D23
const int sensorPortaPin = 22; // sensor que detecta se porta terminou de abrir D22
//

//OUTPUT

int elevPin = 51; //output do elevador D51
int portaPin = 52; //output da porta D52
//

//variaveis de controle

//interno
int menosUmStateIn = 0; // botao subsolo
int groundStateIn = 0; // botao terreo
int umStateIn = 0; // botao primeiro andar
int doisStateIn = 0; //botao segundo andar
int tresStateIn = 0; //botal terceiro andar
int quatroStateIn= 0; // botao quarto andar
//externo
int menosUmStateOut = 0; // botao subsolo
int groundStateOut = 0; // botao terreo
int umStateOut = 0; // botao primeiro andar
int doisStateOut = 0; //botao segundo andar
int tresStateOut = 0; //botal terceiro andar
int quatroStateOut = 0; // botao quarto andar

// flag armazena andares pendentes

byte flagIn = 0;
byte flagOut = 0;
int openFlag= 0;

byte andar = B00000010; // atual andar do elevador (inicia no terreo)

byte target = B00000010; // proximo lugar a ir (mesmo andar que elevador)
byte targetIn = B00000000; // alvo baseado nos botoes internos
byte targetOut = B00000000; // alvo baseado nos botoes externos
byte alvo = B00000000;
int n = 0; // count de bits para targetOut
enum State {parado, subindo, descendo, abrir, aberto, fechar, fechado};
static State s = parado; // assume-se que elevador comeca parado
static State e = fechado; // assume-se que elevador comeca aberto
long tempo = 0;
long timeout = 0;

//funcoes
int targeting ( byte flagIn, byte flagOut, byte andar);
void movimento( byte alvo, long tempo, byte andar, int openFlag);

void setup()
{

Serial.begin(9600);
pinMode(menosUmPin, INPUT_PULLUP);
pinMode(groundPin, INPUT_PULLUP);
pinMode(umPin, INPUT_PULLUP);
pinMode(doisPin, INPUT_PULLUP);
pinMode(tresPin, INPUT_PULLUP);
pinMode(quatroPin, INPUT_PULLUP);

pinMode(menosUmIn, INPUT_PULLUP);
pinMode(groundIn, INPUT_PULLUP);
pinMode(umIn, INPUT_PULLUP);
pinMode(doisIn, INPUT_PULLUP);
pinMode(tresIn, INPUT_PULLUP);
pinMode(quatroIn, INPUT_PULLUP);

pinMode(menosUmOut, INPUT_PULLUP);
pinMode(groundOut, INPUT_PULLUP);
pinMode(umOut, INPUT_PULLUP);
pinMode(doisOut, INPUT_PULLUP);
pinMode(tresOut, INPUT_PULLUP);
pinMode(quatroOut, INPUT_PULLUP);

pinMode(sensorPortaPin,INPUT_PULLUP);

pinMode(elevPin, OUTPUT);
pinMode(portaPin, OUTPUT);

}

void loop()
{
menosUmStateIn = digitalRead (menosUmIn);
groundStateIn = digitalRead (groundIn);
umStateIn = digitalRead (umIn);
doisStateIn = digitalRead (doisIn);
tresStateIn = digitalRead (tresIn);
quatroStateIn = digitalRead (quatroIn);

menosUmStateOut = digitalRead (menosUmOut);
groundStateOut = digitalRead (groundOut);
umStateOut = digitalRead (umOut);
doisStateOut = digitalRead (doisOut);
tresStateOut = digitalRead (tresOut);
quatroStateOut = digitalRead (quatroOut);

tempo = millis(); // marcar tempo

//tests indicador
Serial.print("andar:");
Serial.println(andar);
Serial.print("alvo:");
Serial.println(alvo);
Serial.print("estado1:");
Serial.println(s);
Serial.print("estado2:");
Serial.println(e);
Serial.print("flagin:");
Serial.println(flagIn);
Serial.print("flagout:");
Serial.println(flagOut);
Serial.print("open? ");
Serial.println(openFlag);

// descobrir qual andar que o elevador está, assumindo que ele aperte um limitswitch

if (digitalRead(menosUmPin)==LOW)
{
andar = (B00000001);
}
else if (digitalRead(groundPin) == LOW)
{
andar = (B00000010);
}
else if (digitalRead(umPin)==LOW)
{
andar = (B00000100);
}
else if (digitalRead(doisPin)==LOW)
{
andar = (B00001000);
}
else if (digitalRead(tresPin) == LOW)
{
andar = (B00010000);
}
else if (digitalRead(quatroPin) == LOW)
{
andar = (B00100000);
}

//controle interno usando bitoperator para saber qual pedido esta pendente
//interno
if (menosUmStateIn==LOW)
{
flagIn = (flagIn | (B00000001));
}
if (groundStateIn==LOW)
{
flagIn = (flagIn | (B00000010));
}
if (umStateIn == LOW)
{
flagIn = (flagIn | (B00000100));
}
if (doisStateIn == LOW)
{
flagIn = (flagIn | (B00001000));
}
if (tresStateIn == LOW)
{
flagIn = (flagIn | (B00010000));
}
if (quatroStateIn == LOW)
{
flagIn = (flagIn | (B00100000));
}

//externo
if (menosUmStateOut==LOW)
{
flagOut = (flagOut | (B00000001));
}
if (groundStateOut==LOW)
{
flagOut = (flagOut | (B00000010));
}
if (umStateOut == LOW)
{
flagOut = (flagOut | (B00000100));
}
if (doisStateOut == LOW)
{
flagOut = (flagOut | (B00001000));
}
if (tresStateOut == LOW)
{
flagOut = (flagOut | (B00010000));
}
if (quatroStateOut == LOW)
{
flagOut = ((flagOut) | (B00100000));;
}

//identifica se pedido de flag ja foi atendido
if (flagIn == (flagIn | andar) && flagIn!=0)
{
flagIn = (flagIn ^ andar);
openFlag = 1;
}
else if (flagOut == (flagOut | andar) && flagOut!=0)
{
flagOut = (flagOut ^ andar);
openFlag = 1;
}
else
{
openFlag= 0;
}

alvo = targeting(flagIn, flagOut, andar);
delay(5);
movimento(alvo, tempo, andar, openFlag);

}

// to be continued

// continued

//FUNCOES

int targeting(byte flagIn, byte flagOut, byte andar)
{{
n=0;

//o alvo vai depender se ele esta parado/se movendo
switch(s)
{
case parado:
if (flagIn!=0 || flagOut!=0)
{
if ((andar<flagIn)|(andar<flagOut)) //flag em andar em baixo do elevador
{
target = min(flagIn,flagOut);
}
if ((andar>flagIn)|(andar>flagOut))
{
target = max(flagIn,flagOut);
}
}
break;

case subindo:

if (flagIn>=andar) //flag interna tem preferencia caso subindo
{
while(((andar<<n) & flagIn)==0) // tenta descobrir diferenca em relacao ao andar do apertado apertado internamente
{
n++;
}
target = (andar<<n);
n=0;
}
else if (flagOut!=0)
{
n=0;
while ((flagOut>>n)!= 0) // tenta descobrir diferenca em relacao ao andar do apertado apertado externamente
{
n++;
}
target = 1<<(n-1);
n=0;
}
break;

case descendo: //flag externa tem preferencia

if (flagOut<andar && flagOut!=0) //checa se andar de cima eh para parar baseado nos botoes internos
{
while (( (andar >> n) & flagOut) == 0)
{
n++;
}
targetOut = (andar>>n);
n=0;
}
if (flagIn<=andar && flagIn!=0)
{
while ((flagIn<<n)!= 0)
{
n++;
}
targetIn = (2^8)/(2^n);
}
target = max(targetIn,targetOut);
break;
}

//definir estado
if (target == andar)
{
s=parado;
}
else if (target>andar)
{
s=subindo;
}
else if (target<andar)
{
s=descendo;
}

return target;
}}

void movimento (byte alvo, double tempo, byte andar, int openFlag)
{
Serial.print(" jfdklajsdlaksjdlkajs");
/* if (openFlag == 1)
{
e = abrir;
}
switch(e)
{
case abrir:
digitalWrite(portaPin, HIGH); // setar a porta para abrir… possivelmente seria uma funcao
if (digitalRead(sensorPortaPin)==LOW)
{
e = aberto;
}
break;

case aberto:
timeout = tempo + 3500;
//esperar pessoas
if (digitalRead(sensorMovPin)==LOW)
{
timeout = tempo + 3000;
}
if (tempo >timeout)
{
e = fechar;
//fechar porta
//nota: por a mao enquanto fecha
}
break;

case fechar:

digitalWrite(portaPin, -HIGH); // setar a porta para fechar… possivelmente seria uma funcao
if (digitalRead(sensorMovPin)==LOW)
{
e = abrir;
}
if (digitalRead(sensorPortaPin)==LOW)
{
e = fechado;
}
break;

case fechado:

if (target<andar)
{
digitalWrite(portaPin, -HIGH);
}
else if (target > andar)
{
digitalWrite(portaPin, HIGH);
}
else
{
digitalWrite(portaPin, LOW);
}
break;
}
return;
*/
}

Hi, welcome to the forum.

Your sketch is hard to read. Please show your sketch between code tags.
Number 7 on this page is about code tags : http://forum.arduino.cc/index.php/topic,148850.0.html

We also have to see the whole sketch, the variables, the setup(), everything.
There is a special website for users that show parts of the sketch : http://snippets-r-us.com/
If you sketch is too big (you get a warning), add it as attachment. If you click the "Reply" button, you see additional options to be able to attach a photo or a sketch.

For your code, I think you should be very clear what a flag is and what not. If you use a 'boolean' for a flag, use it as a 'boolean' with 'true', 'false', and a not with '!', but don't use binary operators.

Do you know there is a "minus HIGH" in your code ? You use that twice.

 digitalWrite(portaPin, -HIGH);          // minus HIGH ! ? ? ?

I have attatched the code.

I use 2 types of variables I call flag… one should be a boolean (openFlag), the other ones (flagIn and flagOut) is where I store in bits if a bottom is pressed or not, because I am storing up to 6 floors of true or falses in one variable.

The way the code work is… first floor is B00000001, second floor is B00000010, third floor B00000100 so on… I am storing all bottoms pressed in this variable flagIn/flagOut (people inside the elevator pressing bottoms and people outside pressing bottoms), so if people inside presses floors 1, 2, 4… flagIn would be B00001011, so it has to be a byte.

The -HIGH was used to “simulate” in this context the elevator going down… as in HIGH = elevator going up and -HIGH = elevator going down, switcing direction of the current so the motor move the other way. Again it is just a simulation, I do not plan on implementing this.

My issue though arenot these. My issue comes with the fact I have this on the code:

alvo = targeting(flagIn, flagOut, andar);
movimento(alvo, tempo, andar, openFlag);

where “targetting” is working just fine, but “movimento” is being skipped.

right now the “movimento” function is only a Serial.print, which is not printing.

Elevador.ino (9.06 KB)

I use 2 types of variables I call flag...

Imagine a flag pole. There is a flag on the pole or there isn't. THAT is what the name flag indicates.

The state information (the switch for floor n was pressed) does not belong in a variable with flag in the name.

I removed all the commented out code, and your program is:

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

void loop() 
{
  alvo = targeting(flagIn, flagOut, andar);
  movimento(alvo, tempo, andar, openFlag);
}

int targeting(byte flagIn, byte flagOut, byte andar)
{
}

void movimento (byte alvo, double tempo, byte andar, int openFlag)
{
  Serial.print(" jfdklajsdlaksjdlkajs");
}

Some questions immediately become obvious. targeting is supposed to return an int, but it does not. Why not?

The value is stored in alvo, which is a byte. Why are you truncating the int you don't actually return to an int?

If you comment out the call to the function that does not fulfill it's promise to return a value, do you see the print statement happening?

Ops I uploaded a test version, my bad…

And you are right about targeting, it is suppoesed to be a byte.

But yes, what you posted is not printing anything at all, that was exactly the point of the test. It is not printing anything to the serial and I don’t know why.

Elevador.ino (3.05 KB)

Load some other simple sketch that uses serial print, to make sure there is nothing wrong with that part.

byte targeting(byte flagIn, byte flagOut, byte andar)
{
}

You've signed a contract saying that the function will return a value. But, you don't. You can NOT expect reasonable behavior from the point in the code where you call this function onward.

I have already loaded another sketch and Serial.print is working just fine. It is also displaying other variables under the " test" part which is currently commented out, so that should not be an issue.

Paul, even if I do

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

void loop() 
{
  alvo = targeting(flagIn, flagOut, andar);
  movimento(alvo, tempo, andar, openFlag);
}

int targeting(byte flagIn, byte flagOut, byte andar)
{
  return andar
}

void movimento (byte alvo, double tempo, byte andar, int openFlag)
{
  Serial.print(" jfdklajsdlaksjdlkajs");
}

it does not print anything after it. I dont understand why it would skip the "movimento" function/why it is not working.

Paul, even if I do … it does not print anything after it.

I’m not surprised, since that won’t even compile.

Is it so difficult to add a Serial.print() statement to setup() to at lease confirm that you are talking to the PC anywhere in the code?

if you read the whole code, there is a part in the main loop that is

  //tests indicador
  Serial.print("andar:");
  Serial.println(andar);
  Serial.print("alvo:");
  Serial.println(alvo);
  Serial.print("estado1:");
  Serial.println(s);
  Serial.print("estado2:");
  Serial.println(e);
  Serial.print("flagin:");
  Serial.println(flagIn);
  Serial.print("flagout:");
  Serial.println(flagOut);
  Serial.print("open? ");
  Serial.println(openFlag);

The code compiles and everything on it works. The only thing that is NOT working is the "movimento" function, which is being ignored. It compiled, it changes the target, it changes states within the targeting function, I can get the inputs from the ports simulating that the stuff is being pressed, elevator changes floor, flags updates as I simulate the elevator getting to places. I can do this all by just grounding the ports and I can check it is working due to this part of the code that I copied. I can keep track that it is working.

The code works.

All I am asking is to understand why the the code on "movimento" is not running.
Also, the code I posted previously does compile, given that I declare all variables before setup, which I did. And still, does not print anything.

All I am asking is to understand why the the code on "movimento" is not running.

I've asked you to modify the simple sketch, to do two things:

  1. Add a Serial.print() statement to setup()
  2. Comment out the call to targeting() in loop().

So far, you've done everything but that. I'm at a loss to understand why I should continue in this thread.

felroger, I'm confused. I don't know anymore which sketch I should test for the movimento function. The names of the variables are not in English, that makes is harder to understand.
I understand this your second code ever. Can you do those things that PaulS wrote about, and give the new sketch (the full sketch), so we can check it ?

to simplify the most I can.

byte flagIn =       0;
byte flagOut =      0;
boolean openFlag=       0;
byte andar =        B00000010; // atual andar do elevador (inicia no terreo)
byte target =       B00000010; // proximo lugar a ir (mesmo andar que elevador)
byte alvo =         B00000000;
long tempo =        0;
//funcoes
byte targeting ( byte flagIn, byte flagOut, byte andar);
void movimento( byte alvo, long tempo,  byte andar, boolean openFlag);

void setup()
{
  Serial.begin(9600);
}
void loop() 
{
  Serial.println("a");
 // alvo = targeting(flagIn, flagOut, andar);
  movimento(alvo, tempo, andar, openFlag);
}
byte targeting(byte flagIn, byte flagOut, byte andar)
{
  return andar;
}
void movimento (byte alvo, double tempo, byte andar, int openFlag)
{
  Serial.print("b");
}

Why would this code only give me "a" and no "b"s? Because that is what is happening with this code I have it right there

If I coment out the targeting function, movimento still does not work.
It does print anything I Serial.print on setup.
It does print anything I Serial.print before, between and after the 2 functions
It does print anything on the loop.
It does not print/run through anything on the movimento function.

I attached the whole code again, but it comes down to this function not working, even if I have only this code… this code gives me "a"s and no "b"s.

byte flagIn =       0;
byte flagOut =      0;
boolean openFlag=       0;
byte andar =        B00000010; // atual andar do elevador (inicia no terreo)
byte target =       B00000010; // proximo lugar a ir (mesmo andar que elevador)
byte alvo =         B00000000;
long tempo =        0;
//funcoes
byte targeting ( byte flagIn, byte flagOut, byte andar);
void movimento( byte alvo, long tempo,  byte andar, boolean openFlag);

void setup()
{
  Serial.begin(9600);
}
void loop() 
{
  Serial.println("a");
  movimento(alvo, tempo, andar, openFlag);
}
byte targeting(byte flagIn, byte flagOut, byte andar)
{
  return andar;
}
void movimento (byte alvo, double tempo, byte andar, int openFlag)
{
  Serial.println("b");
}

Elevador.ino (9.05 KB)

This function prototype exists.

void movimento( byte alvo, long tempo,  byte andar, boolean openFlag);

This function exists:

void movimento (byte alvo, double tempo, byte andar, int openFlag)
{
  Serial.println("b");
}

Why does your function signature not agree with that of your function prototype?

That code does not compile.
You have to step up with your work flow.

When developing a sketch, it is normal to have a few test sketches. You should give them good names, and take care on which you are working.

For example if the project is "SuperMovi", then you can create a temporary sketch "SuperMovi_forum_test1".
Maybe you can add some comment, just to remind yourself:

// --------------------------
// Test sketch for forum.
// --------------------------

PaulS is right again. So I removed the function prototyping and it runs, showing enormous amounts of lines with "ba".

Do you use an old version of the Arduino IDE ?
Do you use a faulty fake clone board ?

My friend, your "problema " is you speaking Portugeese to an Italiano.

And I am sorry for such crude joke.

The plain truth is - Arduino.inc philosophy of NOT requiring prototypes so it is simpler for beginners, strikes again.
You have a mismatch in function prototype and function definition, however, the STUPID, yes I said stupid, IDE won't let compiler to see that !

Either match the prototype to definition ( preffered ) or get rid of the prototypes.
Coding errors happen, but when IDE leads you astray it is a different matter.