#Arduino Help

1 messages · Page 10 of 1

old mango
#

oh rip

wary cloak
#

What wasn't master mode still worked alright

old mango
#

oh, i think you still need to put in the return

#

because right now it just prints

wary cloak
#

But it still rejects my card with the og error message

#

It return anyways

#
¿Quiere acceder al modo maestro u operar normal?
1-Modo Maestro
2-Modo Normal
Ingrese la contraseña
Contraseña correcta, acerque la tarjeta al lector
1111111111111111111111111111111111111111111Autenticacion fallida, tarjeta rechazadaProceso Finalizado

¿Quiere acceder al modo maestro u operar normal?
1-Modo Maestro
2-Modo Normal
old mango
#

can you put the whole modoMaestro?

wary cloak
#

As you see again the wrong error message

#

Ok

#
void modoMaestro(){
  char password[] = {'c','a','d','3','6','5','\0'};

  Serial.println("Ingrese la contraseña");

  char user_password[7];
 
  waitForPassword(password, user_password);

  byte verificacion = strcmp(password,user_password);

  if(verificacion == 0){
    Serial.println("Contraseña correcta, acerque la tarjeta al lector");

    MFRC522::MIFARE_Key antiguaKeyA = {keyByte : {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
    MFRC522::MIFARE_Key antiguaKeyB = {keyByte : {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};

    MFRC522::MIFARE_Key nuevaKeyA = {
    keyByte : {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5}};
    MFRC522::MIFARE_Key nuevaKeyB = {
    keyByte : {0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5}};


    const byte sector = 15;
    for(;;){
    if (!mfrc522.PICC_IsNewCardPresent()) {
      Serial.print(!mfrc522.PICC_IsNewCardPresent());
      continue;
    }
   
    if (!mfrc522.PICC_ReadCardSerial()) {
      Serial.print(!mfrc522.PICC_ReadCardSerial());
      continue;
    }

    byte bloqueTrailer = sector * 4 + 3;
    byte buffer[18];
    byte size = sizeof(buffer);

    if (((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false)) && (Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false))) == false) {
      if (((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false)) && (Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false))) == true) {
        Serial.print("La tarjeta ya forma parte del sistema");
      } else {
        Serial.print("Autenticacion fallida, tarjeta rechazada");
      }
    }

    mfrc522.MIFARE_Read(bloqueTrailer, buffer, &size);
old mango
#

Also, quick tip:
you can dump the parentheses immediately around the functions calls;
( function() ) is redundant—all you need is function()

wary cloak
#
if (nuevaKeyA.keyByte != nullptr)
    for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
      buffer[i] = nuevaKeyA.keyByte[i];

    if (nuevaKeyB.keyByte != nullptr)
      for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
       buffer[i + 10] = nuevaKeyB.keyByte[i];


    mfrc522.MIFARE_Write(bloqueTrailer, buffer, 16);

    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();

    Serial.println("\n Proceso Finalizado");
    break;
  }

  } else{
  Serial.println("Contraseña Incorrecta");
  return;
  }
 }
old mango
#

so, originally, you just did if(!Authenticate()) { return false } there, right?
Where did that return false; go?

wary cloak
#

No just return because master mode returns void

old mango
#

ah, right

#

but still, where did that return go?

wary cloak
#

Nowhere but as you see in the output it returns anyways so

#

It doesn't execute all the way it prints the error message and goes back one function

#

Tho the error message is the incorrect one

#

Ah-

#

Wait

#

You are right

old mango
#

it prints the error message but it'll still try to do the read and the write at the moment

wary cloak
#

It finishes the process

old mango
#

regarding the wrong error message, let me take another look

wary cloak
#

Ok I will add the returns but that not the main dish

old mango
#

Welp, that should work, i think??

wary cloak
#

But it does not for some reason

old mango
#

is the card set up correctly?

#

are the keyA and keyB values correct?

wary cloak
#

Wdym?

old mango
#

does the card currently have the keyA and keyB values?

wary cloak
#

Yes I'm testing that one

#

That's why I know it fails

old mango
#

Well, uh

wary cloak
#

I tried the one with the factory passwords and it works fine because authentication works

old mango
#

Oh, one other side note—you should probably call PICC_HaltA and PCD_StopCrypto1() if the inner authentication for the new keys succeeds

#

but, yeah, idk why that's not working

wary cloak
#

Oh ok

#

Tho

#

I don't see why because it keeps working afterwards

old mango
#

oh, it does?

wary cloak
#

And the other returns with the error messages that go one function back doesn't have that too

#

Anyways so

#

What do we do now?

old mango
wary cloak
#

No I would just continue doing stuff ig

old mango
# wary cloak What do we do now?

i dont know
google, ask a more experienced embedded dev, read the datasheet, give up on the feature and return to what you know definitely works are basically your options

wary cloak
#

The only experience embedded dev I know is @madfrog#5492

#

@coral geyser

#

They

old mango
#

also porcucat was good with embedded iirc

coral geyser
#

What's up?

wary cloak
#

Hallo my friens

#

Friend*

coral geyser
#

I just sat down to read

wary cloak
#

We are stucked

#

Something that definitively looks like it should work it doesn't

coral geyser
wary cloak
#

If I had to get you context

#

This is the function you are going to see the code use

#

So it authenticates the key you pass in basically

wary cloak
#

It's the code

#

What matters is the following line

#

Well mines

#

Lines*

#
if ((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false) && Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false)) == false) {
      if (((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false)) && (Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false))) == true) {
        Serial.print("La tarjeta ya forma parte del sistema");
        return;
      } else {
        Serial.print("Autenticacion fallida, tarjeta rechazada");
        return;
      }
    }
#

What we want to do is.

#

First to authenticate that the keys are the one from fabric if they are continue, if they are not, check if they are the ones the master mode will change it too, if they are print that the card it's already on the system if not print that the card it's rejected

#

That's what it should do.

wary cloak
#

And I don't see anything wrong with the conditions

#

That's the context

coral geyser
wary cloak
#

That it prints the "this card is already in the system" Error message and not the "card rejected" Error message

#

If I use the card with the default keys it works as intended it goes on an finishes the function changing the password

#

If I use the card that already have the keys

coral geyser
#

Why the == false and == true, can you walk me through the logic for those if statements?

wary cloak
#

It should print that it is already in the system but it prints the other error case that would be for any other possible password aside from those two

coral geyser
wary cloak
wary cloak
#

What isn't working is something on the conditions logic likely

#

Precisely the second if

#

Because the first works

#

If it has the keys I want it skips all of that if not it enters the second if

coral geyser
wary cloak
#

The first is the one that ask if any are false the second is the one that ask if both are true

coral geyser
#

Also my cat just claimed one of my arms so typing is going to be slower ferrisballSweat

wary cloak
#

Np

#

First I ask, is any of the two keys not the default one I want? 0xFFFFFFF no? Ok keep going, one of them isn't? Ok then if..

#

That works

#

Now the second one which is

#

Ok then are key A and key B the ones my program request already? Yes? Then it's already in the system bye, no? Ok the card rejected you have any other possible password and I don't like that bye

#

Doesn't

coral geyser
#

So, do you know the check key calls work? Like have you been able to get to the branches where they would have to match.

wary cloak
#

Even tho my card has the key A and B my program request already it doesn't print that error message but the other

wary cloak
coral geyser
# wary cloak Sorry I didn't understand the question

The first if statement checks a negative so would pass if the password setup isn't correct anyways, the second if will fail if the password setup is wrong. So I am wonder if you know that the password checking is actually working for the RFID tags

#

Because the described behavior so far just points to it not reading the key a/b from the cards correctly/having the wrong keys on them

#

And there goes the other arm ferrisballSweat

wary cloak
coral geyser
wary cloak
#

I don't know if the check works I guess because it's not in the second if but I don't know why wouldn't it, the authentication function works perfectly

old mango
#

0xffffffffffff is the factory default for both of the keys on the rfid card

coral geyser
#

Thus not matching any of the variables above?

wary cloak
#

So first I can my authenticate function to say hey, are the keys from this cards this one's I'm authenticating against?

#

If not return false

#

So in the and if only one fails

#

It will be false

#

And move to the next

coral geyser
wary cloak
#

As we stated earlier the first if works as intended

wary cloak
#

But here it rejectes even tho I meet the conditions for the already in the system message

coral geyser
wary cloak
#

I mean it would be very inelegant but I could swap the messages out and maybe from the user's POV that would do the same

coral geyser
#

Correct?

wary cloak
#

No because I know for certain that the card I'm checking has the passwords, but if I believed this code yes that would be the case that would mean my cars has whatever other password combination just not those too, but I know it has the 0xC/0xD for certain

coral geyser
wary cloak
#

Because of this code

coral geyser
#

The cat has let me go ferrisUwU

wary cloak
#
#include <SPI.h>
#include <MFRC522.h>
 
#define RST_PIN 5 
#define SS_PIN 53 
 
MFRC522 mfrc522(SS_PIN, RST_PIN); 
MFRC522::MIFARE_Key keyA = {keyByte : {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5}};

void infoToSerial(MFRC522::Uid *uid, MFRC522::MIFARE_Key *key) {
  
  mfrc522.PICC_DumpDetailsToSerial(uid);
  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(uid->sak);
  mfrc522.PICC_DumpMifareClassicToSerial(uid, piccType, key);
  Serial.println();
  mfrc522.PICC_HaltA();
}
 
void setup() {
    Serial.begin(9600); 
    while (!Serial); 
    SPI.begin(); 
    mfrc522.PCD_Init(); 
    delay(4); 
    mfrc522.PCD_DumpVersionToSerial(); 
    Serial.println("Escanea la tarjeta para ver su UID,SAK, tipo y los bloques de datos...");
}
 
void loop() {
    
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
        return;
    }
 
    
    if ( ! mfrc522.PICC_ReadCardSerial()) {
        return;
    }
 
    
    infoToSerial( &(mfrc522.uid), &keyA);
    
}
#

If I

#

Get that card with this code

#

The output is the following

#

Firmware Version: 0x92 = v2.0
Escanea la tarjeta para ver su UID,SAK, tipo y los bloques de datos...
Card UID: A2 DE AA 1B
Card SAK: 08
PICC type: MIFARE 1KB
Sector Block 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 AccessBits
15 63 00 00 00 00 00 00 FF 07 80 69 E0 E1 E2 E3 E4 E5 [ 0 0 1 ]
62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
60 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
14 59 00 00 00 00 00 00 FF 07 80 69 E0 E1 E2 E3 E4 E5 [ 0 0 1 ]
58 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
57 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 0 0 0 ]
56 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [

#

And well it keeps going you get it

#

But when I use the other card that has another password (factory in this case)

#

Card UID: E3 BD CD 1B
Card SAK: 08
PICC type: MIFARE 1KB
Sector Block 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 AccessBits
15 63 PCD_Authenticate() failed: Timeout in communication.
14 59 PCD_Authenticate() failed: Timeout in communication.
13 55 PCD_Authenticate() failed: Timeout in communication.
12 51 PCD_Authenticate() failed: Timeout in communication.
11 47 PCD_Authenticate() failed: Timeout in communication.
10 43 PCD_Authenticate() failed: Timeout in communication.
9 39 PCD_Authenticate() failed: Timeout in communication.
8 35 PCD_Authenticate() failed: Timeout in communication.
7 31 PCD_Authenticate() failed: Timeout in communication.
6 27 PCD_Authenticate() failed: Timeout in communication.
5 23 PCD_Authenticate() failed: Timeout in communication.
4 19 PCD_Authenticate() failed: Timeout in communication.
3 15 PCD_Authenticate() failed: Timeout in communication.
2 11 PCD_Authenticate() failed: Timeout in communication.
1 7 PCD_Authenticate() failed: Timeout in communication.
0 3 PCD_Authenticate() failed: Timeout in communication.

#

And also

coral geyser
#

Have you attempted to print what authenticate() sees when you call it in the code above?

wary cloak
#

The card works on the other functions of the program that on my work with said key

wary cloak
#

It has the error handling built into it

coral geyser
#

No the one in the real code

wary cloak
#

No, but I know what it return because of the library

#

It return status code

#

Status code OK if it works

#

This works perfectly

coral geyser
wary cloak
#

Authentication merely returns the status code

old mango
#

yeah, the actual authentication is performed on-chip in the RFID card

wary cloak
#

We had to manually

#

Make error handling

#

And it worked everywhere the function works

coral geyser
#

Wait these parenthesis are not right ferrisSus , or am I going crazy? (Which is somewhat likely)

wary cloak
#

We went through such an adventure to get the parenthesis right so the compiler would shut up-

#

But maybe it's good in syntax

#

But not logic

old mango
#

oh, yeah, those parentheses are wrong

wary cloak
#

Were?

coral geyser
#

== happens before &&

#

In c++

old mango
#

Current is this, I believe

    if (((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false)) && (Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false))) == false) {
      if (((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false)) && (Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false))) == true) {
        Serial.print("La tarjeta ya forma parte del sistema");
      } else {
        Serial.print("Autenticacion fallida, tarjeta rechazada");
      }
    }
#

and yes, == does happen before && in C++

wary cloak
wary cloak
old mango
#

it's the same in rust, and almost any language you'll run into

wary cloak
#

So how do we fix it then?

wary cloak
old mango
#

i think

#

lemme double check

wary cloak
#

Wdym is fine if we are discussing why it's not working (?

coral geyser
old mango
#
if (
  (
    (
      Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false)
    ) && (
      Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false)
    )
   ) == false
) {
  if (
    (
      (
        Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false)
      ) && (
        Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false)
      )
    ) == true
) {
        Serial.print("La tarjeta ya forma parte del sistema");
      } else {
        Serial.print("Autenticacion fallida, tarjeta rechazada");
      }
    }
#

yeah, that's correct

wary cloak
#

So then that's not the error cause

#

Btw

#

If I change the condition to be false instead of true it works

#

But I think not for good reason tho

#

And it doesn't make logic sense

coral geyser
wary cloak
#

Oh yes

#

Well there's that and

#

Ofc changing were the messages are placed

#

But it's like it works but don't test it further

#

It's not really working

#

It's just making it seem good enough that it's working

#

Because I don't think we are testing it with another random password to see if the other message is printed

coral geyser
#

Yeah, fair warning my sleep meds have kicked in so you have limited time before I fall asleep

wary cloak
#

Np

#

But well what else can we say really

old mango
#

so, possible causes based on what we've seen:

  1. keyA and/or keyB is/are wrong, or the card has the wrong keys
  2. it's due to the RFID card or the library
  3. ??
wary cloak
#

The parenthesis are ok, the function too, the logic too, the keys too

#
  1. we already confirmed it not to be this case
#
  1. indeed
coral geyser
#

Everything looks fine as has been explained to me, so I don't have any insight to the possible issue

old mango
#

maybe it's a timing issue due to consecutive Authenticates? that's the only thing i'm thinking of at this point

coral geyser
#

That is possible

wary cloak
#

I could place a delay if you want

#

Between the first and second if'a

#

If's*

coral geyser
#

Though I would have hoped that the library would have been smart enough to handle that, but 🤷‍♂️

wary cloak
#

I hope the rust one does..

old mango
#

could also try adding a HaltA and StopCrypto1 between the if's as well

coral geyser
old mango
#

it's different keys and those work for the outer if so that case seems to be okay?

wary cloak
#
if ((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false) && Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false)) == false) {
      delay(1000);
      if (((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false)) && (Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false))) == true) {
old mango
#

yeah

#

worst case, you leave it with the generc error message

wary cloak
#

I think I would go with the

#

I make it seem to work

#

Ig

#

Well I could choose

#

One sincerely works

#

The other one appears to work

old mango
#

or just do if(!Authenticate(factoryKey, false)) { Serial.print("Rejected card: not factory-keyed"); return }

wary cloak
#

Huh

#

That seems nice

#

I will try this delay thingy then that

coral geyser
#

When you can't find the bug, just remove the bugged code ferrisHotTake , best trick in the book

old mango
#

sometimes, you just don't have have enough magic 😔

wary cloak
#
if(!Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false)) { Serial.print("Rejected card: not factory-keyed"); return }```
#

Like that?

#

And with key B also

old mango
#

yeah

#

gn frog

wary cloak
old mango
#

you'll also need a ';' after that return

wary cloak
#

The thing was that

old mango
#

i was typing sloppy pseudocode

wary cloak
#

If the card already had the password it rejected saying it was part of the system so even if it worked we would be changing the objective

#

Also I don't want the teacher to know that master mode doesn't work with any card in existence because maybe he wants that maybe because he thinks code is magic or smth(?

#

But anyways I 'm going to test it

#

Well anyways I think in worst case

#

I'm staying with the one that it works if you don't go to deep

old mango
#

yeah, "tarjeta rechazada-se esperó las claves de fábrica" or whatever

wary cloak
#

Btw

#

What you suggested works

#

I had to push the card 8 times because of the weird annoying inconsistencies

#

But that's another thing

#

Well then I guess we give up

#

Tomorrow we do the last thing the last functionality of the prototype that's the EEPROM and that's it

old mango
#

also—regarding what you were talking about with being able to change the keys in EEPROM—what happens when you convert a card from factory key to the current key, then change the key in EEPROM?
(or am i misunderstanding the function of the EEPROM?)

wary cloak
#

I will explain the EEPROM part

#

It detects if it's the first time turning on the project

#

And if it is

#

It ask you to enter a password

#

Oh

#

I see your doubt

#

The password you enter

#

Is for entering master mode

#

That rn is hard coded

old mango
#

ah, okay

wary cloak
#

Well now the user will be able to set it's own

#

And ofc it will need to be saved

#

He also with his current password will be able to change it again and that new password will be saved in place of the other

#

And if he forgot

#

There will be a saved hard coded password that technician would know about to fix the issue

old mango
#

but the actual keys for the RFID are hard coded?

wary cloak
#

And also with the EEPROM we can tell it's the first time

wary cloak
#

We aren't playing with that.

#

If you want to add more cards you buy use master mode

#

Which only you the user will be able to access

wary cloak
#

I'm no magician

old mango
#

okay, cool

wary cloak
#

I can quickly explain you how the library works it's very simple

old mango
#

that's just arduino's builtin EEPROM, right?

wary cloak
#

Yes..?

#

we use a library but it's Arduino's EEPROM

#

So

#

We have available adresses to save memory in the EEPROM from 0 to 255

#

Quite the limitation maybe but not for use

old mango
wary cloak
#

We have EEPROM read just pass in the address and it read it easy, EEPROM write, pass the address and what to write in it, EEPROM same as write but if what you want to write it's already there it does nothing

#

Now, playing with the EEPROM could be dangerous like it has a limited amount of how many times you can write to it

#

So say you are in a loop using write

#

With the Arduino speed

#

Say bye bye to you Arduino

#

That's why

#

We will use update

#

So we don't do unnecessary writes

#

And read is safe ofc there's no write in there

#

Oh and also

old mango
#

umh
strictly speaking that shouldn't be an issue
since you're only doing this once in the board's lifetime
and it should be okay for ~100,000 writes

wary cloak
#

You can only write in one adress up until 255 bits so since we are going to store ASCII it will be one character per adress

old mango
#

so write would be basically the same as update in that case

wary cloak
#

Yeah but I prefer wearing two helmets instead of one(?

wary cloak
#

You can't store the number 256 in an adress or a 7 element char array

#

ASCII characters are around like 126 or smth when turned into intergers

old mango
#

yes for the first one, but i don't get what you're saying with the second one

wary cloak
#

So

#

We are storing one ASCII character per adress

#

Remember we are storing a password

old mango
#

yeah, what i don't get was specifically what you meant with the '7-element char array'

wary cloak
#

Current hard coded password is the char array 'c', 'a', 'd', '3', '6', '5', '/0'

old mango
#

uh huh

wary cloak
old mango
#

well, you'd just use 7 bytes of EEPROM for that

wary cloak
#

Yeah

#

One next to the other

#

And I would read the adresses in a for loop

#

Or smth

old mango
#

do you want to allow the user to have arbitrary length password or no?

wary cloak
#

Well that's how it works so we are on the same boat when we do it(?

wary cloak
#

Not like it's gonna be 6 and you are gonna like it

#

But maybe yeah, ok as long as you don't go above this number do as you please

#

I think that's the best approach

old mango
#

welp, that's quite simple to do

wary cloak
#

See?

#

Better than this mess for sure

#

So tomorrow we finally finish the prototype and all rfid functionalities

#

Then the only last step to say bye bye forever to rfid

#

Is to merge that already working code with the other already working code of the project the one with the lcd and stuff

#

You want to see the code now?

old mango
#

i'm good

wary cloak
#

The other one that needs this rfid functionality

#

At least I made a nice lcd function so it is way easier to work with

old mango
#

you had madfrog helping with that right?
also i think porcucat offered to help on that side

wary cloak
#

Because what concerns me the most is the limit of what the display can show

wary cloak
#

After we finished re writting the base functionality

#

I was going to do rfid in rust too but

#

I since this one was close to finishing I wanted to finish it so I could relax and concentrate in other stuff and stop being a slave of my need to have all work done(?

#

Respecting Arduino I asked him help with that too but it seems he had been busy this days if it weren't for you I would be where I started still

#

And now we are a step away from finishing the prototype

#

Only with the asterisks of the error handling thing and

#

The inconsistencies

#

But I will leave them like that I guess

#

Because there's nothing else that's possible and can be done

#

Anyways it's time to sleep tomorrow let's do the EEPROM then we'll see depending on the hour if idk, I can came up with another solution for what happened today or any other detail

#

Or maybe I just start doing the merging

wary cloak
#
if (( Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false) == false || Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false) == false)) {
      if ((Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false)) == true && (Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false)) == true) {
        Serial.print("La tarjeta ya forma parte del sistema");
        return;
      } else {
        Serial.print("Autenticacion fallida, tarjeta rechazada");
        return;
      }
    }
#

Tried this

#

Failed too

#

in the same way

#

Now I maded this way

#

Exactly the same result

#

But now is way more elegant and easier to debug

#
void modoMaestro(){
  char password[] = {'c','a','d','3','6','5','\0'};

  Serial.println("Ingrese la contraseña");

  char user_password[7];
 
  waitForPassword(password, user_password);

  byte verificacion = strcmp(password,user_password);

  if(verificacion == 0){
    Serial.println("Contraseña correcta, acerque la tarjeta al lector");

    MFRC522::MIFARE_Key antiguaKeyA = {keyByte : {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
    MFRC522::MIFARE_Key antiguaKeyB = {keyByte : {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};

    MFRC522::MIFARE_Key nuevaKeyA = {
    keyByte : {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5}};
    MFRC522::MIFARE_Key nuevaKeyB = {
    keyByte : {0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5}};


    const byte sector = 15;
    for(;;){
    if (!mfrc522.PICC_IsNewCardPresent()) {
      Serial.print(!mfrc522.PICC_IsNewCardPresent());
      continue;
    }
   
    if (!mfrc522.PICC_ReadCardSerial()) {
      Serial.print(!mfrc522.PICC_ReadCardSerial());
      continue;
    }

    byte bloqueTrailer = sector * 4 + 3;
    byte buffer[18];
    byte size = sizeof(buffer);
    const bool authDefaultA = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false);
    const bool authDefaultB = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false); 
#
if (authDefaultA && authDefaultB) {
          mfrc522.MIFARE_Read(bloqueTrailer, buffer, &size);

          if (nuevaKeyA.keyByte != nullptr)
            for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
              buffer[i] = nuevaKeyA.keyByte[i];

          if (nuevaKeyB.keyByte != nullptr)
            for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
              buffer[i + 10] = nuevaKeyB.keyByte[i];


          mfrc522.MIFARE_Write(bloqueTrailer, buffer, 16);

          mfrc522.PICC_HaltA();
          mfrc522.PCD_StopCrypto1();

          Serial.println("\n Proceso Finalizado");
    } else {
      const bool authSelfA = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false);
      const bool authSelfB = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false);
  
      (authSelfA && authSelfB)
       ?  Serial.print("La tarjeta ya forma parte del sistema")
       :  Serial.print("Autenticacion fallida, tarjeta rechazada");
  
  return;
    }
    
    break;
  }

  } else{
  Serial.println("Contraseña Incorrecta");
  return;
  }
 } 
#

It's pretty clear the issue is coming from the logic

#

Because now there's no doubt we are asking correctly

wary cloak
#

** Remember to call PCD_StopCrypto1() after communicating with the authenticated PICC - otherwise no new communications can start.*

#

Thought this was it so I did

#
bool Authentication(MFRC522::PICC_Command command, MFRC522::MIFARE_Key *key, bool print_error_message){
  estado = mfrc522.PCD_Authenticate(command, bloqueTrailer, key, &(mfrc522.uid));
  mfrc522.PCD_StopCrypto1();

  if (estado != MFRC522::STATUS_OK) {
    if(print_error_message == true){Serial.print("Autenticacion fallida, tarjeta rechazada");}
    return false;
  } else {
    return true;
  }
}
#

But it also didn't work god damn it-

#
else {
      mfrc522.PCD_StopCrypto1();
      const bool authSelfA = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false);
      const bool authSelfB = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false);
  
      (authSelfA && authSelfB)
       ?  Serial.print("La tarjeta ya forma parte del sistema")
       :  Serial.print("Autenticacion fallida, tarjeta rechazada");
  
  return;
    } 
#

Neither like this

#

I thought that it would solve it to see what the library had to say

#

I'm running out of ideas

wary cloak
#

Now I did this

#
const bool authDefaultA = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &antiguaKeyA, false);
    const bool authDefaultB = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &antiguaKeyB, false);
    Serial.print(authDefaultA);
    Serial.print(authDefaultB); 
#
const bool authSelfA = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_A, &keyA, false);
      const bool authSelfB = Authentication(MFRC522::PICC_CMD_MF_AUTH_KEY_B, &keyB, false);
      Serial.print(authSelfA);
      Serial.print(authSelfB); 
#

Got this output

#
¿Quiere acceder al modo maestro u operar normal?
1-Modo Maestro
2-Modo Normal
Ingrese la contraseña
Contraseña correcta, acerque la tarjeta al lector
0000Autenticacion fallida, tarjeta rechazada
¿Quiere acceder al modo maestro u operar normal?
1-Modo Maestro
2-Modo Normal 
#

It makes sense the first two 0's because it's not fabric key but the second two 0's doesn't make sense because it has the key A and B, really weird

old mango
#

If you switch the order of the authenticates, what happens?

wary cloak
#

I tried other stuff but gave up, is impossible the only thing I succeed at is that now is more elegant

#

Btw

wary cloak
#

And I re read it

#

There's another useful thing there

#

We can treat EEPROM as array, that helps sooooo much

#

as an*

#

So @old mango how about we do the EEPROM deal and finish this once and for all

#

Tho ofc maybe as a little detail if possible maybe we could get rid of inconsistencies but anyways

old mango
#

Well, go to the EEPROM first ig

wary cloak
#

Ofc

#

Remember what we have to do?

old mango
#

Yeah

wary cloak
#

Ok what you think would be first step? I personally think

old mango
#

Like i said yesterday it's really rather simple

wary cloak
#

Managing to know if it's the first time turning it on or not

old mango
#

That sounds like a good first step

wary cloak
#

Well I don't know how to do it but I think the following

#

Have a boolean global variable

#

first_time

#

And an if to see if it's false or true

#

If it's false then write to the EEPROM true or something

#

And then all the times we turn it on now

#

It will already be true

#

So the if won't execute

#

Something like that I can think of

old mango
#

Okay, let me clarify something real quick: what is the purpose of the first_time?

wary cloak
#

Oh I think we don't needed it

#

I think it could be like this let me pseudo code

#
bool first_time = EEPROM.read(255)

if(!first_time>0){
  Serial.print("It is the first time")
}
#

I thought this

#

What do you think?

#

Tho in place of the serial print

#

We would have the code to ask the user a password and store it on the EEPROM

#

If it isn't the first time it won't execute again

#

What do you think?

#

Oh and at the end of the function we should write something to tha adress

#

To make sure it doesn't execute again

#

That*

old mango
#

Aight a detail; have you completely read through the documentation for EEPROM.read?

wary cloak
#

Oh

#

I see what you mean

#

If nothing has been written

#

It's 255

#

Ok then

old mango
#

And !first_time>0 is a confusing condition; what exactly did you mean there?

wary cloak
#
if(EEPROM.read(255) == 255){
  Serial.print("It is the first time");
  EEPROM.update(255,0);
}
#

Like this better?

old mango
#

Hmm. Are you sure you want != there?

wary cloak
#

Ah-

#

Right

#

Now?

old mango
#

Yeah, looks good?

#

So, what is your next step?

wary cloak
#

Ok imagine we know can say if it's the first time

#

Now

#

Inside that if

#

We should ask the user for a password and store it in the EEPROM then change the modo maestro function to compare with those characters

#

I think first

#

We should ask what length

#

Then ask please that it's less than 10 for example

#

If we detect the number is bigger than then ask again

#

Then when we get our number

#

We receive inputs from the user and write to the EEPROM in a for loop

#

And finally set the address 255 to 0 so this code doesn't execute again

#

After that we change master mode to verify with this new password

#

And that will finish this step

old mango
#

Sounds like it'd work

wary cloak
#

Now I have to see how I would actually implement it-

#

I mean

#

I'm not that bad with ideas

#

But only that

#

Let's first focus in asking for the length and confirming it isn't bigger than 10

#

About waiting for user inputs

#

I guess we can use this function

#
char waitForOption(void)
{
  while (!Serial.available());
  char dato = Serial.read();
  while (Serial.read() != 10);
  return dato;
}
#

Ik

#

Instead of asking again if he goes over

#

It should stop at ten

#

But

#

We should indicate a character to finish if you want it to be less

#

Ok let me see..

#
if(EEPROM.read(255) == 255){
  Serial.print("Ingresa una contraseña de no mas de 10 caracteres, ingrese # para terminar");
  for(int i = 0; i < 10; i++){
    char input = waitForOption();
    if(input != '#'){
      char EEPROM.update[i,input];
    }
  }
  EEPROM.update(255,0);
}
#

What do you think of this?

#

Is there something wrong or missing?

old mango
#

Well, how is modoMaestro going to know how many characters long the password is?

wary cloak
#

Hmmm

old mango
#

Also, EEPROM.update--should that be [] or ()?

wary cloak
#

Some way we should give back the value of i

#

And actually

#

Call it

#

password_len

#

In case we have other i's for other for loops just in case

wary cloak
old mango
#

COPY?

old mango
wary cloak
#

Oh

#

I forgot to change that

#
if(EEPROM.read(255) == 255){
  Serial.print("Ingresa una contraseña de no mas de 10 caracteres, ingrese # para terminar");
  for(int password_len = 0; password_len < 10; password_len++){
    char input = waitForOption();
    if(input != '#'){
      char EEPROM.update(password_len,input);
    }
  }
  EEPROM.update(255,0);
}
#

Could we later use a reference to password_len?

old mango
#

Well, whatever it is, it'd have to be stored in EEPROM

wary cloak
#

Oh well

#

That works too ig

#
if(EEPROM.read(255) == 255){
  Serial.print("Ingresa una contraseña de no mas de 10 caracteres, ingrese # para terminar");
  for(int password_len = 0; password_len < 10; password_len++){
    char input = waitForOption();
    if(input != '#'){
       EEPROM.update(password_len,input);
    }
  }
  EEPROM.update(254,password_len);
  EEPROM.update(255,0);
}
old mango
wary cloak
#

How about now?

old mango
#

Okay, that indeed should work

wary cloak
#

Ok so next step

#

In master mode it currently works like this

#
char password[] = {'c','a','d','3','6','5','\0'};

  Serial.println("Ingrese la contraseña");

  char user_password[7];
 
  waitForPassword(password, user_password);

  byte verificacion = strcmp(password,user_password);

  if(verificacion == 0){
#

Let me see

#

While doing changes

#

I will also need to change this function

#
char* waitForPassword(char* password, char* user_password){
  int i;
  for(i=0;i<strlen(password);i++){
    char input = waitForOption();
    user_password[i] = input;
  }
  user_password[i] = '\0';
  return user_password;
}
#

I changed the function to this

#
char* waitForPassword(char* user_password){
  int i;
  for(i=0;i<EEPROM.read(254);i++){
    char input = waitForOption();
    user_password[i] = input;
  }
  user_password[i] = '\0';
  return user_password;
}
#

Do you agree?

old mango
#

Yeah

#

Although I'd do the EEPROM.read before the loop and store it in a var, so you're not calling EEPROM.read in every iteration of the loop but rather once at the beginning

wary cloak
#
char* waitForPassword(char* user_password){
  int i;
  int password_len = EEPROM.read(254)
  for(i=0;i<password_len;i++){
    char input = waitForOption();
    user_password[i] = input;
  }
  user_password[i] = '\0';
  return user_password;
}
#

Like this?

old mango
#

Ye

#

That's a very common pattern in any programming language

wary cloak
#

To this

#
int password_len = EEPROM.read(254)
  
  Serial.println("Ingrese la contraseña");

  char user_password[password_len+1];
 
  waitForPassword(user_password);

  char password[password_len];

  for(int i = 0; i < password_len; i++) {
    password[i] = EEPROM.read(i);
  }

  byte verificacion = strcmp(password,user_password);

  if(verificacion == 0){
old mango
old mango
wary cloak
#

Yeah

#

I was thinking about that

#

We could

#

Store it

#

Do we do it?

old mango
#

That's an option, yes.
It's not strictly necessary since we also have the password_len, so you could also just make password 1 char longer and insert the \0 after the for loop

wary cloak
#

Yeah let's do that

#

I like it better

#
int password_len = EEPROM.read(254)
  
  Serial.println("Ingrese la contraseña");

  char user_password[password_len + 1];
 
  waitForPassword(user_password);

  char password[password_len + 1];

  for(int i = 0; i < password_len; i++) {
    password[i] = EEPROM.read(i);
  }

  password[password_len + 1] = '\0'

  byte verificacion = strcmp(password,user_password);

  if(verificacion == 0){
#

How about now?

old mango
#

Ah, okay, still a slight issue: arrays start from zero, so an array with length 1 has only an element at the 0 position
Similarly, an array with length N will have its last element at the N-1 position

#

Therefore, when the length is password_len+1, where should it be writing the \0 to?

wary cloak
#

password_len - 1 then?

old mango
#

Well, that would work if it the array had length password_len

wary cloak
#

Mmmm...

#

But..

#

Shouldn't the array be one character longer than password_len to store the '\0'?

old mango
#

Well, it already is, yeah?

wary cloak
#

Then

#

Password len only?

old mango
old mango
wary cloak
#

Ok all of this I have been writting it in another place

#

Now we could actually try it

#

To see if it works

#

If it does we can move on to the final two steps

old mango
#

You can think of it as password_len characters followed by a '\0' character; saying password[password_len] is like 'the element in the array after exactly password_len characters'

old mango
#

It's kinda unintuitive; in fact there's an entire category of bugs just called 'off-by-one errors'; it's just one of those things that you figure it out with time and experience

wary cloak
#

In the setup? In the loop? Before?

old mango
#

Well, how many times do you want it to run?

wary cloak
#

It will run only once quite literally

old mango
wary cloak
#

Setup

#

Should er

#

We*

#

Make it a function?

#

So it doesn't look ugly in setup

old mango
#

Sure, that's entirely up to you

wary cloak
#
void CreatePassword(void) {
  if(EEPROM.read(255) == 255){
    Serial.print("Ingresa una contraseña de no mas de 10 caracteres, ingrese # para terminar");
    for(int password_len = 0; password_len < 10; password_len++){
      char input = waitForOption();
      if(input != '#'){
        EEPROM.update(password_len,input);
      }
    }
    EEPROM.update(254,password_len);
    EEPROM.update(255,0);
  }
 }
#
void setup() {
  Serial.begin(9600);
  while (!Serial);      
  SPI.begin();
  mfrc522.PCD_Init();
  CreatePassword();
}
#

Is it ok?

old mango
#

Looks so

wary cloak
#

Ok it's the moment of truth

#

If it works we are like halfway through or more

#

Had to fix some errors-

#

Ok it's uploaded

#

Password is going to be again

#

cad365

#

It's already not working

#

I passed in cad365 separated ofc

#

Then passed # and it didn't stop

#

I forgot a break or something fuck-

#
void CreatePassword(void) {
  if(EEPROM.read(255) == 255){
    Serial.print("Ingresa una contraseña de no mas de 10 caracteres, ingrese # para terminar");
    int password_len;
    for(password_len = 0; password_len < 10; password_len++){
      char input = waitForOption();
      if(input != '#'){
        EEPROM.update(password_len,input);
      } else {
        break;
      }
    }
    EEPROM.update(254,password_len);
    EEPROM.update(255,0);
  }
 }
#

Maybe now

old mango
#

I think you might need to add a password_len = password_len + 1; before the break

wary cloak
#

Why?

old mango
#

Since I'm fairly sure the password_len++ doesn't trigger when you break

#

Oh, nevermind, you don't need that

wary cloak
#

Well it shouldn't, should it? If at that iteration you write # that's it the numbers of the last iteration is the length

old mango
#

Yeah, right on

wary cloak
#

Ok now

#

Let's open the serial monitor again

#

This time it shouldn't call the function tho

#

Tho..

#

Since I clossed it before finishing

#

Likely it didn't get to the EEPROM. update(255,0)

#

Let's see

#

Ok it ask for it again

#

Ok it worked now

#

Let's test if it enters master mode with my password

#

It does

#

Ok now I will disconnect and connect the Arduino

#

See if it ask again, if not, if it still works

#

It works

#

Ok we can move on to the next step

#

Now we need to make the user capable of changing the password and this one needs to the override the previous one

#

I have only one suggestion

#

That asking if it's the first time isn't in create password

#

But rather

#

The the if is inside setup to whatever call it or not

#

That way

#

We can use that function to change the password

#

Since it's going to be the same address and so

old mango
#

Good thinking, ah

wary cloak
#

Now

#

Next up is

#

Where to ask for a change of password

#

I suppose at the beginning

#

Master mode normal mode or change password

#

Then we ask for the current password and we can basically copy what we do in master mode

#

And then call create password

#

And I think that's it?

#

Any other idea or criticism of the idea?

old mango
#

I think you're basically clear at that point?

wary cloak
#

Ok let's try to implement it then

#
void CreatePassword(void) {
   Serial.print("Ingresa una contraseña de no mas de 10 caracteres, ingrese # para terminar");
   int password_len;
   for(password_len = 0; password_len < 10; password_len++){
     char input = waitForOption();
     if(input != '#'){
       EEPROM.update(password_len,input);
     } else {
       break;
     }
   }
   EEPROM.update(254,password_len);
   EEPROM.update(255,0);
 }
#
void setup() {
  Serial.begin(9600);
  while (!Serial);      
  SPI.begin();
  mfrc522.PCD_Init();
  if(EEPROM.read(255) == 255){  CreatePassword(); }
}
#

This first

#

Now this

#
void loop() {
  Serial.println("\n¿Quiere acceder al modo maestro, operar normal o cambiar su contraseña?");
  Serial.println("1-Modo Maestro");
  Serial.println("2-Modo Normal");
  Serial.println("3-Cambiar Contraseña");

  char input = waitForOption();

  switch (input) {
    case '1':{
      modoMaestro();
      return;
    }
    case '2':{
      modoNormal();
      return;
    }
    case '3':{
      cambiarContraseña();
      return;
    }
    default:
      Serial.println("Elija una opcion valida");
      return;
  }
}
#

And finally this

#
void cambiarContraseña(){
  int password_len = EEPROM.read(254);
  
  Serial.println("Ingrese su contraseña actual");

  char user_password[password_len + 1];
 
  waitForPassword(user_password);

  char password[password_len + 1];

  for(int i = 0; i < password_len; i++) {
    password[i] = EEPROM.read(i);
  }

  password[password_len] = '\0';

  byte verificacion = strcmp(password,user_password);

  if(verificacion == 0){
    CreatePassword()
  } else {
    Serial.print("Contraseña Incorrecta");
    return;
  }
}
#

I did a lot of copy paste you see

#

So I'm not 100% sure it works

#

What do you think?

old mango
#

Yeah, should be fine
The only thing I'd be worried about is whether arduino accepts the 'ñ' character in cambiarConrraseña
Might work, might not

wary cloak
#

Ah thank you

#

No, it doesn't

#

My variables are called password and not contraseña because of a huge wall or errors I didn't know how to solve back then

#

Ever since I said

#

Ok no more Spanish name, embrace Great Britain

#

Butt this code has now like two months old working on it

#

That's the reason it's a horrible mess

#

The re write in rust is being so beautiful

#

It works

#

Let me do another quick check disconnecting the Arduino again

#

Ok it works

#

So

#

Last step

#

Now in case the user forgets it's password we need a hard coded password on the EEPROM that also works for the changePassword function

old mango
# wary cloak Ok no more Spanish name, embrace Great Britain

Again, other versions of C++ would be fine with it; arduino uses avr-gcc which i think is comparatively older, so newer and more mainstream versions of c++ are generally okay with non-english characters; fairly sure it's the same way for rust as well

old mango
wary cloak
#

Well since the code will always execute I guess it would be the same

old mango
#

If it's hardcoded can't you just make it a global variable like the keys?

wary cloak
#

Right

#

So I will make a new global variable I'll see where

#

Like this

#
master_password [] = 'b', 'a', 'c', '8', '7', '6', '\0';
#

Tho it doesn't need to be globak

#

Could be inside the change password function

old mango
#

You forgot the type but yeah

wary cloak
#

Now we would only need the comparing logic

#
byte verificacion;

  if(strcmp(password,user_password) == 0){verificacion = 0;}
  if(strcmp(master_password,user_password) == 0){verificacion = 0;}

  if(verificacion == 0){
#

How about that?

old mango
#

Uh, what would be in verificacion if neither of the ifs gets triggered?

wary cloak
#

Whatever that isn't 0 triggers the else

wary cloak
#

But strcmp gives back 0,1 and -1 if I recall but I only care for the 0 case

#

Even if it gives back a credit card number it goes to the else

old mango
#

If i remember libc spec, strcmp can technically give -255 to 255 according to libc spec

#

But that's not super important here, since you're just checking against 0

wary cloak
#

Yeah

#

So it's fine?

old mango
wary cloak
#

Oh I see

#

Ok I will initialize it to a value like 5 for example

old mango
#

Sure

wary cloak
#

Ok let's try it

#

It works

#

But we are not done

#

We need to think a little bit more

#

This is though so

#

The user forgot it's password

#

Then it should be able to go back so his machine isn't stuck or needs to be disconnected and re connected that first

#

Because what he needs to do is call to help

#

And a technician who would know it

#

Should come and do it

#

Because if we leave it in the manual or whatever maybe whoever can change the user's password

#

So only people working for the company or whatever should now

#

Oh wait..

#

If he gets a wrong password it just returns

#

...

#

Then I guess

#

We are done

#

So..

#

Since it's done

#

Anything else we could make better, fix now that there's nothing else to do idk

#

To be perfectionist since the most crucial stuff has been dealt with

#

Idk whatever, I can't think of anything

#

The financial system seems perfect to me

#

I gave up the issue we had yesterday

#

And I can't think of anything else ig

old mango
#

Minimum password length

wary cloak
#

Why?

old mango
#

A super weak password can be worse than no password at all

wary cloak
#

Mmmm

old mango
#

But entirely your choice

#

It's basically about how seriously you're taking security in this project

wary cloak
#

It makes sense but to be honest I feel lazy and idk how try hard I wanna be

wary cloak
#

And ig in any case I can make changes like that when I want

#

I will send it to myself to mail so I have it for school

#

Now I will show you the next step to say bye bye to rfid technology

#

I don't think I'm starting today that because again

#

Kinda lazy

old mango
#

You're done with the c++ at this point, yeah?

wary cloak
#

I wish

#

But no

#

I'm almost done if not already , with the hardest part

old mango
#

What's the last bit then?

wary cloak
#

Now I will show you

#

The base functionality of the project in the cpp version

#

The rust one got to that point base functionality only

#
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

#define PIN_ALCHOHOL 6
#define PIN_ACOMPANANTE1 4
#define PIN_ACOMPANANTE2 3
#define PIN_ACOMPANANTE3 2

struct PrintOptions {
  String toPrint;
  int pos;
};

const PrintOptions empty = {"", 0};

LiquidCrystal_I2C lcd(0x27, 20, 4);

const byte FILAS = 4;
const byte COLUMNAS = 4;

const char keys[FILAS][COLUMNAS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};

const byte pinColumnas[COLUMNAS] = {22, 23, 24, 25};
const byte pinFilas[FILAS] = {26, 27, 28, 29};

Keypad keypad(makeKeymap(keys), pinFilas, pinColumnas, FILAS, COLUMNAS);

char tecla;
bool confirmacion=0;

void imprimirFila(byte posY, byte posX, String fila){
  if(fila != ""){
    byte caracteres_restantes = 20 - fila.length();

    if(caracteres_restantes<0){
      lcd.print("muy largo 1");
    }
  byte posicionX = posX == 'c'? (caracteres_restantes/2) : posX;
  lcd.setCursor(posicionX,posY);
  lcd.print(fila);

  }
}

void imprimir(PrintOptions fila1 = empty, PrintOptions fila2 = empty, PrintOptions fila3 = empty, PrintOptions fila4 = empty) {
  imprimirFila(0, fila1.pos, fila1.toPrint);
  imprimirFila(1, fila2.pos, fila2.toPrint);
  imprimirFila(2, fila3.pos, fila3.toPrint);
  imprimirFila(3, fila4.pos, fila4.toPrint);
}

void Barman (int delay_alchohol, int delay_acompanante1 , int delay_acompanante2, int delay_acompanante3){
      digitalWrite(PIN_ALCHOHOL,HIGH);
      delay(delay_alchohol);
      digitalWrite(PIN_ALCHOHOL,LOW);
      delay(1000);
      digitalWrite(PIN_ACOMPANANTE1,HIGH);
      delay(delay_acompanante1);
      digitalWrite(PIN_ACOMPANANTE1,LOW);
      delay(1000);
      digitalWrite(PIN_ACOMPANANTE2,HIGH);
      delay(delay_acompanante2);
      digitalWrite(PIN_ACOMPANANTE2,LOW);
      delay(1000);
      digitalWrite(PIN_ACOMPANANTE3,HIGH);
      delay(delay_acompanante3);
      digitalWrite(PIN_ACOMPANANTE3,LOW);
      delay(1000);
}
#
void setup() {
  pinMode(2, OUTPUT);
  pinMode(3,OUTPUT);
  pinMode(4,OUTPUT);
  pinMode(6,OUTPUT);
  lcd.init();
  lcd.backlight();
}

void loop(){ 

  do{
    imprimir(
    { "Elija una bebida",  'c' },
    { "1-Fernet con Coca",  0  },
    { "2-Sex on the beach", 0  },
    { "3-Agua",             0  }
    );
    

    tecla=keypad.waitForKey();
    if(tecla=='1'){
      confirmacion=1;
    }
    else if(tecla=='2'||tecla=='3'){
      lcd.clear();
      imprimir(
      { "Bebida", 'c'},
      { "No Disponible", 'c'}
      );
      confirmacion=0;
      delay(1000);

    }
    else{
      lcd.clear();
      imprimir(
      { "elija un", 'c'},
      { "valor valido", 'c'}
      );
      confirmacion=0;
      delay(1000);
    }
  } while(confirmacion!=1);

  do{
    lcd.clear();
    imprimir(
    { "Elija la intensidad", 'c'},
    { "1-Suave", 0},
    { "2-Medio", 0},
    { "3-Fuerte", 0}
    );
    tecla=keypad.waitForKey();
    if(tecla=='1'||tecla=='2'||tecla=='3'){
      confirmacion=1;
    }
    else{
      lcd.clear();
      imprimir(
      { "elija un", 'c'},
      { "valor valido", 'c'}
      );
      confirmacion=0;
      delay(1000);
    }
  } while(confirmacion!=1);

  lcd.clear();
  imprimir(
    empty,
    { "preparando...", 'c'}
    );
  lcd.cursor();
  lcd.blink();
#
if(confirmacion==1){
    int delay_alchohol;
    int delay_acompanante1;
    int delay_acompanante2;
    int delay_acompanante3;

    switch(tecla){
      case '1':{
      delay_alchohol = 2000;
      delay_acompanante1 = 4000;
      delay_acompanante2 = 4000;
      delay_acompanante3 = 4000;
      Barman (delay_alchohol, delay_acompanante1, delay_acompanante2, delay_acompanante3);
      break;
      }
      case '2':{
      delay_alchohol = 5000;
      delay_acompanante1 = 3000;
      delay_acompanante2 = 3000;
      delay_acompanante3 = 3000;
      Barman (delay_alchohol, delay_acompanante1, delay_acompanante2, delay_acompanante3);
      break;
      }
      case '3':
      {
      delay_alchohol = 8000;
      delay_acompanante1 = 2000;
      delay_acompanante2 = 2000;
      delay_acompanante3 = 2000;
      Barman (delay_alchohol, delay_acompanante1, delay_acompanante2, delay_acompanante3);
      break;
      }
    }
  }
  lcd.noCursor();
  lcd.noBlink();
}
#

This is the base functionality of the project, the best version that has functions to make things easier

#

The lcd function is something that I going to make my life easier and I'm proud about

#

Well now I have to move all that prototype RFID code to this, merge them, so my project has now that functionality also, up until now we needed to make the rfid available to work by it's own and test how it worked and bla bla

#

Now with that we have to implement it here

#

What I'm the most concerned about it's the character limit of the LCD

#

But aside from that

#

I hope it's mostly copy paste -

#

And after that

#

I have to work with two types of sensors, and that would be it, but the sensor parts is way way easier that all I've been doing until this point

#

So now I have to merge and with that, finally my rfid nightmare would've finish

#

And the hardest part of the project

#

Would've been overcome

#

How hard you think this last step is going to be?

old mango
#

Honestly should be easy?

#

Or at least not hard

#

If it already works it's just joining stuff together

wary cloak
#

That's what I expected

#

I would like to make that tomorrow

#

So when I have my class in Wednesday

#

I can see all the sensor part, which to buy and bla bla

#

And start that

#

Tho maybe we won't start right away with the sensor part

#

So in the meantime now totally relax

#

I could continue the rust counterpart

#

Which would be the RFID prototype from scratch-

#

I hope it's easier in rust of that the library is similar and with all I suffered it's faster now

#

Think you can help with that one? We found the library for the RFID in Arduino-HAL

wary cloak
old mango
#

My original intention was to help out with the c++ only

wary cloak
#

Well as long as frog will still help me it's fine for me, after all the cpp is the one I do for obligation the rust one I do it for learning purposes

#

Another thing

#

When I finish my python Django course, the Cpp project, the rust project

#

I was planning to finally jump into learning cpp, think you could help with that?

old mango
#

Uhm, honestly, I don't think i have the time for that

#

Like, just this is already a few hours a day; it's okay for a couple days but certainly not more

wary cloak
#

@old mango I was thinking on how to do this last thing

#

And I think

#

The structure and logic is going to remain mostly the same, what I current have in the project would be inside the buy function ofc with some changes to update it

#

So I think what's most important

#

It's to replace the serial monitor with lcd and keypad

#

Gladly I already ask for help to so the lcd stuff with that I mean, grab all the things that I need to print an adapt it to the lcd printing limitations

#

So that has been dealt with

#

And thanks to my lcd function it will be easier for perform

#

Now what's left to be able to start is replace the serial port with the keypad

#

If I don't get it wrong or forgot anything

#
char waitForOption(void)
{
  while (!Serial.available());
  char dato = Serial.read();
  while (Serial.read() != 10);
  return dato;
}

bool obtenerPlata(char *plata){
    int i;
    for (i = 0; i < 15; ++i)
    {
        char input = waitForOption();
        if (input >= '0' && input <= '9') {
          plata[i] = input;
        } else break;
    }

    plata[i] = '\0';
    return i;
   
  }

char* waitForPassword(char* user_password){
  int i;
  int password_len = EEPROM.read(254);
  for(i=0;i<password_len;i++){
    char input = waitForOption();
    user_password[i] = input;
  }
  user_password[i] = '\0';
  return user_password;
}  
#

This are the functions that take care of all that is receiving inputs in general

#

Now correct me if I'm wrong

#

But I think maybe we could kill the wait for input function in favor of the wait for key one in the keypad.h library and the rest of the functions and stuff doesn't need any change just use wait for key

#

I'm right?

#

If I am then we could have all to start and I guess it should be easier than what we did yesterday so I hope to finish it quickly and easily

#

I hope I won't need help but basically maybe I can make some silly mistake or smth or maybe it works first try like yesterday

wary cloak
#

@old mango @hallow hinge @coral geyser @oblique bridge any of you available rn?

#

@dreamy trellis do you know cpp?

dreamy trellis
#

not well

#

i took a class about 5 years ago

wary cloak
#

I have some error messages that are likely something stupid but I can't sort out

#

Everytime I get an "expected primary expression before.. " I die

#
C:\Users\fuchi\OneDrive\Documentos\Arduino\bartender_sin_sensores\bartender_sin_sensores.ino: In function 'void modoMaestro()':
bartender_sin_sensores:552:14: error: expected ':' before ';' token
             );
              ^
bartender_sin_sensores:552:14: error: expected primary-expression before ';' token
bartender_sin_sensores:553:8: error: expected primary-expression before ':' token
        :  imprimir(
        ^
bartender_sin_sensores:554:35: error: expected primary-expression before ',' token
             { "La tarjeta",  'c' },
                                   ^
bartender_sin_sensores:555:13: error: expected primary-expression before '{' token
             { "ya forma parte", 'c' },
             ^
bartender_sin_sensores:555:38: error: expected primary-expression before ',' token
             { "ya forma parte", 'c' },
                                      ^
bartender_sin_sensores:556:13: error: expected primary-expression before '{' token
             { "del sistema", 'c' }
             ^
bartender_sin_sensores:557:13: error: expected primary-expression before ')' token
             );
             ^
exit status 1
expected ':' before ';' token
#

This error messages

dreamy trellis
#

and the code in question?

wary cloak
#

I also have warnings but I want to at least solve this so I can test the logic of the program if it works and then I get to fix warnings and so

wary cloak
dreamy trellis
#

what is that colon supposed to be doing

#

nvm

wary cloak
#

There I'm calling a function "I'm primitive"

#

Oh ok

#

"Imprimir"*

dreamy trellis
#

i forgot about ternaries

#

it has been a hot minute

wary cloak
dreamy trellis
#

remove the semicolon at the end of line 552

wary cloak
#

Issue..

#

I don't have lines in Arduino IDE

dreamy trellis
#

you have a semicolon in the middle of your ternary

wary cloak
#

Ooooh

dreamy trellis
#

that should end the statement, but you still have yet to complete the ternary

wary cloak
#

I will compile again to see what errors are left

#

Oh it uploads now, so the really important errors are out of the way

#

Think you could help with the warnings maybe?

#
C:\Users\fuchi\OneDrive\Documentos\Arduino\bartender_sin_sensores\bartender_sin_sensores.ino:37:71: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'byte* {aka unsigned char*}' [-fpermissive]
 Keypad keypad(makeKeymap(keys), pinFilas, pinColumnas, FILAS, COLUMNAS);
                                                                       ^
In file included from C:\Users\fuchi\OneDrive\Documentos\Arduino\bartender_sin_sensores\bartender_sin_sensores.ino:2:0:
C:\Users\fuchi\OneDrive\Documentos\Arduino\libraries\Keypad\src/Keypad.h:78:2: note:   initializing argument 2 of 'Keypad::Keypad(char*, byte*, byte*, byte, byte)'
  Keypad(char *userKeymap, byte *row, byte *col, byte numRows, byte numCols);
  ^~~~~~
C:\Users\fuchi\OneDrive\Documentos\Arduino\bartender_sin_sensores\bartender_sin_sensores.ino:37:71: warning: invalid conversion from 'const byte* {aka const unsigned char*}' to 'byte* {aka unsigned char*}' [-fpermissive]
 Keypad keypad(makeKeymap(keys), pinFilas, pinColumnas, FILAS, COLUMNAS);
                                                                       ^
In file included from C:\Users\fuchi\OneDrive\Documentos\Arduino\bartender_sin_sensores\bartender_sin_sensores.ino:2:0:
C:\Users\fuchi\OneDrive\Documentos\Arduino\libraries\Keypad\src/Keypad.h:78:2: note:   initializing argument 3 of 'Keypad::Keypad(char*, byte*, byte*, byte, byte)'
  Keypad(char *userKeymap, byte *row, byte *col, byte numRows, byte numCols);
  ^~~~~~
dreamy trellis
#

hm

#

tricky

#

actually no

#

that keypad function takes non const arrays but you passed it all const arrays

wary cloak
#

Oh

#

Let's see now

#

Btw..

#

Lcd doesn't recognize "ñ" Nor "¿"?

#

That got rid of the wanrnings thank you very much now I can test how it works

dreamy trellis
hallow hinge
dreamy trellis
#

but you might just be screwed

hallow hinge
#

This is an HD44780

#

There's a way around

#

But you'll need to publish your own character set

#

and use some cursed extended ASCII localization idea

wary cloak
#

Idk if I prefer that or writting "contrasena"

#

For now let's do that

#

Man I wish so much I was english(?

hallow hinge
dreamy trellis
#

its 0b11110001

hallow hinge
#

So apparently there's a createChar

#

So at least you'll be use that.

#

The problem then becomes localization

#

How do you convince the Arduino IDE to spit out extended ASCII

#

Give me a few

#

I guess it should be doable using \x01

dreamy trellis
#

oh i see

wary cloak
#

Well I will now be testing the project if it works fine we will see the ñ deal

hallow hinge
#

Give me a few

wary cloak
#

To make it perfect basically

hallow hinge
#

I'm pretty sure I have an idea on how to fix this

dreamy trellis
#

\xf1 instead of ñ

hallow hinge
#

Time to read the data sheet > - <"

dreamy trellis
hallow hinge
#

Ay nice. :)

#

There's also "ROM Code" though

wary cloak
#

You have all the time in the world

hallow hinge
#

I wonder what that means.

wary cloak
#

Cause I forgot a lot of

#

Lcd.clear()

#

And have to find them

hallow hinge
#

Nah

#

\xf1 won't work

#

ROM is hardcoded

dreamy trellis
#

it should work

hallow hinge
#

You can try, but I'm pretty sure it will spit out q

dreamy trellis
#

oh youre right

#

damn

hallow hinge
#

You'll want to add an lcd.createChar(0x01, [...]); somewhere in your setup code.

#

And then instead of using ñ, use \x01

wary cloak
hallow hinge
#
lcd.createChar(0x01, {
0x0d, //0,0,0,0,1,1,0,1
0x12, //0,0,0,1,0,0,1,0
0x00, //0,0,0,0,0,0,0,0
0x16, //0,0,0,1,0,1,1,0
0x19, //0,0,0,1,1,0,0,1
0x11, //0,0,0,1,0,0,0,1
0x11, //0,0,0,1,0,0,0,1
0x11, //0,0,0,1,0,0,0,1
});
wary cloak
wary cloak
#

Ok after testing other stuff I will try it

#

Wait a few minutes please (?

hallow hinge
#
[myrl@myrl-ryzen:/tmp/tmp.ZQaNomtst3]$ cat test
0x0d, //0,0,0,0,1,1,0,1
0x12, //0,0,0,1,0,0,1,0
0x00, //0,0,0,0,0,0,0,0
0x16, //0,0,0,1,0,1,1,0
0x19, //0,0,0,1,1,0,0,1
0x11, //0,0,0,1,0,0,0,1
0x11, //0,0,0,1,0,0,0,1
0x11, //0,0,0,1,0,0,0,1

[myrl@myrl-ryzen:/tmp/tmp.ZQaNomtst3]$ sed 's|.*//\(.*\)|\1|g;s/1,\?/█/g;s/0,\?/ /g' <test
    ██ █
   █  █ 
        
   █ ██ 
   ██  █
   █   █
   █   █
   █   █
wary cloak
#

What would that be?

hallow hinge
#

Oh, the code itself is not important. I just wanted to show how it would look like on the display

wary cloak
#

And for curiosity how did you do it? How do you do and know how to do a custom character?

hallow hinge
#

I was into electronics a lot before, so I'm familiar with the HD44780

#

Frog sent a link befor

#

And if you want to know how your library works then

wary cloak
#

So there's a function called create char that receives as a parameter the name of the chat and the bit combination say

#

And you know how to do that bit combination looking into the datasheet what each bit does ig?

hallow hinge
#

For the bit combination, it's more of just me guessing it

#

1 = on, 0 = off

#

Luckily frog's pdf shows an enye already

wary cloak
#

Oh

#

Btw..

#

Think you could also do..

#

"¿"

hallow hinge
#

So I just copied that.

#

You can try it out yourself

#

And then convert binary to hex

wary cloak
#

Oh I think I more or less get it

#

Oh so it's

#

"Easier"

#

Than I thought

hallow hinge
#

Also, turns out it's actually on the next page lol

wary cloak
#

I think it's the kind of thing I would do on a paper or something tho

#

That's how all letters are written?

hallow hinge
#

Yep! :)

#

Except others are in character rom, not CGRAM.

wary cloak
#

But didn't the lcd have 6 data bits? And then enable reset

old mango
#

This is sending the graphics data into the LCD, and assigning it a certain code
Then, when you tell it to print that code, it'll use that graphics data

#

So it's not transmitting that pixel data to the LCD when you print but rather configuring it ahead of time

wary cloak
#

Lux we have to later fix inconsistencies rn I pressed for the second time to see my money available and it got stuck and had to reset that happens kinda often that you just get stuck, but the problem is idk why

#

Ofc not now first I wanna see

#

All works just like in the prototype but combined with the other

#

And the fix bugs

old mango
#

Well, I'm available for a bit

wary cloak
#

Rn I'm testing all works

#

Adding the lcd clears and delays

#

I found I need when testing

#

And then I will do all that personalize char thing

#

In any case here you have the file for now tho I will likely will need to keep adding lcd.clears and delays

#

But just so you get familiar with it

#

In any case you already now the two codes that are merging

#

Likely the inconsistencies have to do with lack of stop crypyo or something

#

Because normally first time all works but then sometimes the third time I'm using an rfid function it gets stuck

#

For example before

#

I used see money once

#

It worked

#

Twice it got stuck

#

Now I used see money twice

#

Charge money

#

Then again

#

And then it got stuck

#

That kind of stuff

#

Now I saw how much money I had then tried to buy

#

Same happened

#

It happens at random

#

Mmm I have problems in buy

#

When I buy without enough money

#

It seems like it shows a message but it fades quickly even tho I have a delay

#

And it also corrupts my text even tho I have a lcd.clear at the end

#
if(saldo < precio){
        lcd.clear();
        imprimir(
          { "Su saldo", 'c'},
          { "es insuficiente", 'c'}
          );
        delay(10000);
        lcd.clear();
        mfrc522.PICC_HaltA();
        mfrc522.PCD_StopCrypto1();
        return true;
      }
#

This doesn't get to show

old mango
#

Okay gimme a sec, this code is kinda messy so I'm formatting it to be easier to read

wary cloak
#

Sure

#

I would love if IDE had the auto format

#

Man this inconsistencies are so annoying I can't advance and have to reset all the time.

#

This time I didn't event use it before and it didn't work

#

Man

#

Well it seems only buy doesn't work

#

Which is predictable

#

Well I will test last two things

#

Now I charged money then wanted you see how much I had now

old mango
#

Why is there a return true halfway through comprar()?

wary cloak
#

Again got stucked

#

Remember that comprar returns a boolean

wary cloak
old mango
#

No i mean half of the function will never execute

wary cloak
#

Wait what

old mango
#

Before the imprimir call for preparando

wary cloak
#

Now reading money is just not working like at all

#

It doesn't read

#

It's untestable

wary cloak
#

Ok got rid of it

wary cloak
#

Magic

#

Ok so

#

Problems

#

1- inconsistencies, lots of times it gets stuck when I need to read the card

2- when you buy without enough money it just comes back it doesn't print that you haven't enough money

3- when you buy something you retain the money

#

That are the three things that don't work

old mango
#

I see why 2 is happening

#

Where is precio declared?

wary cloak
#

Globally because before it said I cannot find precio so I made it global

old mango
#

Look inside the loop where you actually set precio

wary cloak
#
if(tecla=='1'){
      precio = 400;
      confirmacion=1;
    }
#

This?

old mango
#

A bit higher

wary cloak
#

Oh

old mango
#

You see what's happening now?

wary cloak
#

But doesn't it get override by the other one below that sets it to 400? Since only case 1 works

old mango
wary cloak
#

When I select 1

wary cloak
#

It should change it's value

#

And it's below

#

I mean

#

If there was a set to 0 below that if

#

I get it

#

But it's above

#

When I press one

wary cloak
#

And now precio be 400

old mango
#

Let me rephrase: how many variables named precio are there?

wary cloak
#

Mmmm

#

It said int precio so I declared another one?

old mango
#

Yep

wary cloak
#

So I maybe had override the wrong other one or whatever

#

It's just wrong what I did

#

Ok now it works

old mango
#

Aight, what other problems are there?

wary cloak
#

We just need to solve 2 and the merge would be successful because problem 1 is from the original not from now

#

Ofc we have to solve it but at least

#

The merge would be completed

wary cloak
#

Oh maybe it was

old mango
#

We just solved 2 tho?

wary cloak
#

Because of this?

#

Let me see

#

Yes we did

#

That shit caused the two problems

#

Ok so only 1

#

The inconsistencies

#

And also

#

I would have to do all the create char stuff for completion

#

But most important problem 1

#

So as you maybe had noticed

#

I had sent messages explaining different scenarios where this happened

#

And it wouldn't read the card and get stuck

#

But not like

#

Always in certain scenario

#

No more like

#

The exact same scenario

#

Like when without doing anything else I went to check how much money I had and it didn't read my card twice

#

Then a third time it worked

#

And so on so forth

old mango
#

I mean it might just be your hardware

wary cloak
#

Why you think so? For me it should be code like the need for another stop crypto somewhere and not being able to do so many communications one after the other

#

Like how authenticate technically needs a stop crypto after every one acording to this

#

But I don't necessarily do it

#

Idk something among those lines

old mango
#

If you reset the arduino, and on that fresh state, you ran leerSaldo() it and it didnt work the first couple times?

wary cloak
#

Let me reset the Arduino with the button and try read saldo

#

It works

old mango
#

Okay, do it 10 more times and see if any of them fail