#Arduino Help
1 messages · Page 10 of 1
What wasn't master mode still worked alright
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
can you put the whole modoMaestro?
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);
Also, quick tip:
you can dump the parentheses immediately around the functions calls;
( function() ) is redundant—all you need is function()
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;
}
}
so, originally, you just did if(!Authenticate()) { return false } there, right?
Where did that return false; go?
No just return because master mode returns void
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
it prints the error message but it'll still try to do the read and the write at the moment
It finishes the process
regarding the wrong error message, let me take another look
Ok I will add the returns but that not the main dish
Welp, that should work, i think??
But it does not for some reason
Wdym?
does the card currently have the keyA and keyB values?
Well, uh
I tried the one with the factory passwords and it works fine because authentication works
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
oh, it does?
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?
it more because if the authentication succeeded, you want to log out afterwards, right? altho idk if you're hardware works that way or not
No I would just continue doing stuff ig
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
also porcucat was good with embedded iirc
What's up?
I just sat down to read
Then sleep 💤
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
And here
And here
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.
Everything works excepts that it prints the wrong error message
And I don't see anything wrong with the conditions
That's the context
What does working look like here?
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
Why the == false and == true, can you walk me through the logic for those if statements?
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
Ofc
Does this suggest that programming the keys onto the cards is not working?
So if any of the authentications of the "antiguaKeyA/B" Which is the fabric keys fails then it goes into an other if an ask ok if that aren't the keys then, and tries to authenticate to the global Key A and B and if both of them succeds that means card is on the system in any of them fails card gets rejected
It is working, because if the card has the default keys so it passes the first authentication it changes the keys and the card that didn't work on the program now does
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
Is it the == true?
The first is the one that ask if any are false the second is the one that ask if both are true
Also my cat just claimed one of my arms so typing is going to be slower 
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
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.
Even tho my card has the key A and B my program request already it doesn't print that error message but the other
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 
It doesn't pass anyways, if the card doesn't have key A and B 0xFFFFFFF it won't pass so it would ask the other if
Which variables above are the 0xffff... Value?
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
0xffffffffffff is the factory default for both of the keys on the rfid card
Thus not matching any of the variables above?
In Modo maestro antiguaKeyA and antiguaKeyB are set to that meanwhile nuevaKeyA, nuevaKeyB and the global keyA and keyB have my passwords 0xC1 bla bla
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
So it passes the first if, meaning at least one of the keys is not ffff... But we haven't confirmed their actual value?
As we stated earlier the first if works as intended
No the key could be whatever with the condition that one isn't 0xFFFF so then I ask ok it's keyA 0xC.. And also keyB 0xD... If they both are then the card is in the system if any other scenarios happens then the card is rejected
But here it rejectes even tho I meet the conditions for the already in the system message
Which would indicate that key A or B are not ffff or 0xC/0xD
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
Correct?
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
How do you know it has those keys on it?
Because of this code
The cat has let me go 
#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
Have you attempted to print what authenticate() sees when you call it in the code above?
The card works on the other functions of the program that on my work with said key
If you mean this one no
It has the error handling built into it
No the one in the real code
No, but I know what it return because of the library
It return status code
Status code OK if it works
This works perfectly
Ah so this auth thing is hidden by the library
Authentication merely returns the status code
yeah, the actual authentication is performed on-chip in the RFID card
Wait these parenthesis are not right
, or am I going crazy? (Which is somewhat likely)
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
oh, yeah, those parentheses are wrong
Were?
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++
This idk if it's the same you sent
For God's sake-
it's the same in rust, and almost any language you'll run into
So how do we fix it then?
I thought thought parenthesis fixed that
in this one, which i copied from the last time you texted modoMaestro's code, it's fine
i think
lemme double check
Wdym is fine if we are discussing why it's not working (?
There is one extra set here (around each function call) but other than that this looks right
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
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
Well, if you switch the boolean state it's checking, it's going to go on the other path of the if statements 
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
Yeah, fair warning my sleep meds have kicked in so you have limited time before I fall asleep
so, possible causes based on what we've seen:
- keyA and/or keyB is/are wrong, or the card has the wrong keys
- it's due to the RFID card or the library
- ??
The parenthesis are ok, the function too, the logic too, the keys too
- we already confirmed it not to be this case
- indeed
Everything looks fine as has been explained to me, so I don't have any insight to the possible issue
maybe it's a timing issue due to consecutive Authenticates? that's the only thing i'm thinking of at this point
That is possible
Though I would have hoped that the library would have been smart enough to handle that, but 🤷♂️
I hope the rust one does..
could also try adding a HaltA and StopCrypto1 between the if's as well
If it's a timing thing then you may need it between the ones inside the if condition as well
it's different keys and those work for the outer if so that case seems to be okay?
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) {
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
or just do if(!Authenticate(factoryKey, false)) { Serial.print("Rejected card: not factory-keyed"); return }
When you can't find the bug, just remove the bugged code
, best trick in the book
sometimes, you just don't have have enough magic 😔
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
💤 👋.
Gn
you'll also need a ';' after that return
i was typing sloppy pseudocode
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
yeah, "tarjeta rechazada-se esperó las claves de fábrica" or whatever
Now I mean I don't want him to know that only factory ones work (tho I could) and the important thing is that the card you are inserting is already fine that was it
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
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?)
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
ah, okay
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
but the actual keys for the RFID are hard coded?
And also with the EEPROM we can tell it's the first time
Yes
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
Ofc as you see new cards not used ones with whatever password
I'm no magician
okay, cool
I can quickly explain you how the library works it's very simple
that's just arduino's builtin EEPROM, right?
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
should just be this (https://docs.arduino.cc/learn/built-in-libraries/eeprom), right?
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
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
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
so write would be basically the same as update in that case
Yeah but I prefer wearing two helmets instead of one(?
what do you mean by this?
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
yes for the first one, but i don't get what you're saying with the second one
So
We are storing one ASCII character per adress
Remember we are storing a password
yeah, what i don't get was specifically what you meant with the '7-element char array'
Current hard coded password is the char array 'c', 'a', 'd', '3', '6', '5', '/0'
uh huh
Just to say an example of the limits of what can be stored on an adress
well, you'd just use 7 bytes of EEPROM for that
do you want to allow the user to have arbitrary length password or no?
Well that's how it works so we are on the same boat when we do it(?
I think yes but I guess we should at the very least place a top like not more than 20 characters if for example
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
welp, that's quite simple to do
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?
i'm good
The other one that needs this rfid functionality
At least I made a nice lcd function so it is way easier to work with
you had madfrog helping with that right?
also i think porcucat offered to help on that side
Because what concerns me the most is the limit of what the display can show
He was helping me with the rust re write
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
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
** 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
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
If you switch the order of the authenticates, what happens?
I tried other stuff but gave up, is impossible the only thing I succeed at is that now is more elegant
Btw
Yes is this one
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
Well, go to the EEPROM first ig
Yeah
Ok what you think would be first step? I personally think
Like i said yesterday it's really rather simple
Managing to know if it's the first time turning it on or not
That sounds like a good first step
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
Okay, let me clarify something real quick: what is the purpose of the first_time?
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*
Aight a detail; have you completely read through the documentation for EEPROM.read?
And !first_time>0 is a confusing condition; what exactly did you mean there?
if(EEPROM.read(255) == 255){
Serial.print("It is the first time");
EEPROM.update(255,0);
}
Like this better?
Hmm. Are you sure you want != there?
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
Sounds like it'd work
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?
Well, how is modoMaestro going to know how many characters long the password is?
Hmmm
Also, EEPROM.update--should that be [] or ()?
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
Syntax
COPY
EEPROM.update(address, value)
COPY?
Was talking about inside the for loop here
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?
Well, whatever it is, it'd have to be stored in EEPROM
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);
}
Also why do you have the char in char EEPROM.update(...);?
Originally there wasn't an EEPROM update there and I keep forgetting-
How about now?
Okay, that indeed should work
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?
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
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?
Now I changed this
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){
Unless the return value of the function is being changed inside the loop, don't call functions in the loop condition but rather move them outside
Okay, so the issue with this is that there's no \0 stored in EEPROM
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
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?
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?
password_len - 1 then?
Well, that would work if it the array had length password_len
Mmmm...
But..
Shouldn't the array be one character longer than password_len to store the '\0'?
Well, it already is, yeah?
char password[password_len+1] is how you declared it
Yes
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
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'
Where should I place this?
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
In the setup? In the loop? Before?
Yeah totally
Well, how many times do you want it to run?
It will run only once quite literally
So which of these would fit that?
Sure, that's entirely up to you
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?
Looks so
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
I think you might need to add a password_len = password_len + 1; before the break
Why?
Since I'm fairly sure the password_len++ doesn't trigger when you break
Oh, nevermind, you don't need that
Well it shouldn't, should it? If at that iteration you write # that's it the numbers of the last iteration is the length
Yeah, right on
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
Good thinking, ah
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?
I think you're basically clear at that point?
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?
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
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
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
Don't necessarily need that in eeprom, right?
Well since the code will always execute I guess it would be the same
If it's hardcoded can't you just make it a global variable like the keys?
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
You forgot the type but yeah
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?
Uh, what would be in verificacion if neither of the ifs gets triggered?
Whatever that isn't 0 triggers the else
.
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
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
My point here is that if neither of the ifs get triggered, do you know for sure that what's in verificacion isn't 0?
Sure
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
Minimum password length
Why?
A super weak password can be worse than no password at all
Mmmm
But entirely your choice
It's basically about how seriously you're taking security in this project
It makes sense but to be honest I feel lazy and idk how try hard I wanna be
Not like I'm selling this or even keeping it myself so
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
You're done with the c++ at this point, yeah?
What's the last bit then?
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?
Honestly should be easy?
Or at least not hard
If it already works it's just joining stuff together
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
Or between tomorrow and Tuesday because tomorrow between 21:30 and likely 23:30 I have an after class and I can't stay much time awake after that
My original intention was to help out with the c++ only
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?
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
@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
@old mango @hallow hinge @coral geyser @oblique bridge any of you available rn?
@dreamy trellis do you know cpp?
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
and the code in question?
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
I will pass the file because it's really long
I guess they aren't used that much but they are really cool
remove the semicolon at the end of line 552
Ooooh
that should end the statement, but you still have yet to complete the ternary
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);
^~~~~~
hm
tricky
actually no
that keypad function takes non const arrays but you passed it all const arrays
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
perhaps try printing out every character to the screen
This is a UTF-8 problem

but you might just be screwed
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
Idk if I prefer that or writting "contrasena"
For now let's do that
Man I wish so much I was english(?
its 0b11110001
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
^^ use ñ instead of whatever you were using before
oh i see
Well I will now be testing the project if it works fine we will see the ñ deal
Give me a few
To make it perfect basically
\xf1 instead of ñ
Time to read the data sheet > - <"
https://www.sparkfun.com/datasheets/LCD/HD44780.pdf pages 17 and 18 for others
You have all the time in the world
I wonder what that means.
it should work
You can try, but I'm pretty sure it will spit out q
You'll want to add an lcd.createChar(0x01, [...]); somewhere in your setup code.
And then instead of using ñ, use \x01
Like that or what goes inside [...]
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
});
So I paste that as is in my setup and the everytime I would use an "ñ" use "\x01" And it would count as a character?
I'd hope so lol
[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
██ █
█ █
█ ██
██ █
█ █
█ █
█ █
What would that be?
Oh, the code itself is not important. I just wanted to show how it would look like on the display
And for curiosity how did you do it? How do you do and know how to do a custom character?
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
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?
For the bit combination, it's more of just me guessing it
1 = on, 0 = off
Luckily frog's pdf shows an enye already
So I just copied that.
You can try it out yourself
And then convert binary to hex
Also, turns out it's actually on the next page lol
I think it's the kind of thing I would do on a paper or something tho
That's how all letters are written?
But didn't the lcd have 6 data bits? And then enable reset
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
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
Well, I'm available for a bit
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
Okay gimme a sec, this code is kinda messy so I'm formatting it to be easier to read
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
Why is there a return true halfway through comprar()?
I'm saying all this case for us to find a connection to fix it later
No i mean half of the function will never execute
Wait what
Before the imprimir call for preparando
Now it did
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
Globally because before it said I cannot find precio so I made it global
Look inside the loop where you actually set precio
A bit higher
Oh
You see what's happening now?
But doesn't it get override by the other one below that sets it to 400? Since only case 1 works
Could you explain what you mean by this?
When I select 1
This happens
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
This should execute
And now precio be 400
Let me rephrase: how many variables named precio are there?
Yep
So I maybe had override the wrong other one or whatever
It's just wrong what I did
Ok now it works
Aight, what other problems are there?
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
2
.
Oh maybe it was
We just solved 2 tho?
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
I mean it might just be your hardware
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
If you reset the arduino, and on that fresh state, you ran leerSaldo() it and it didnt work the first couple times?
Okay, do it 10 more times and see if any of them fail
