#Arduino Help
1 messages · Page 8 of 1
this message broke my brain ðŸ§
Before:
Low: nothing, for no short circuit
High: 0, to match the other 0 when a input is pressed because it's default it's 5 volts
Now:
Low: 0 volts (which before was our high)
High: 5 volts but not at all
We need a cero and another cero for a key pressed but now cero is not column high but low
Is inverted
I think I get the question. The Now case with the High gets pulled to 0v
it wants to be like 4.5v but it doesn't have much force to keep it there
the 0v output can drive it to 0v without much current flowing
That's what I can't understand
So you are saying
That high would be almost 5 volts first but then it will drop to 0?
Hence behaving like before?
I would need to get into electronic theory to explain better
yes
close enough to that for our purposes
I'm ashamed to be a close to technician in electronics and having this difficulties -
Ok so let's say high is 0 like before
like I could draw up a circuit diagram of it, but I don't know if it will help or not
But what about low, isn't it 0 also? You answered it was an absolute 0, but why is it an absolute 0 and not plain 0,and what's the difference?
Hard 0*
It's a 50/50 gamble honestly because I understand them but there's always a chance that that one I don't
My question are:
-what's a hard 0, and why it's different from a normal 0 volt?
-why when low is our pin a hard 0 and not just 0?
-why high goes down to 0 volt? (Or close enough)
-how do we avoid short circuit? (Tho maybe by understanding the above this isn't necessary)
(This is miss labeled, tine internal pull up resistance, should be huge ...)
I tried
I don't have a circuit drawing app on this computer
Well I need to go to sleep like 2 hours ago so I need to leave
I leave this question
About tomorrow
We can finish understanding that
Having rested
And about code well
Next step it's to make lcd and keyboard work together which I hope should be as easy as, kill read_char function and replace where it was called with wait_for_key
I really hope that's all
And then depending on what was choosen as the intensity toggle the pins of the relay modules a certain delay it should take like 10 minutes
And finally..
The base functionality of the project
Would be done
Anyways tomorrow we do that and understand this
It's that four questions I sended basically
Good night and thanks for the support
- for this discussion: "hard" means that the wire can sink a lot of current; "soft" means that there is a large resistance the current needs to flow through. Which means for a "soft" voltage not much current can flow
- An output pin looks like this (simplified). When set to low the "switch for low" is connected. Thus resulting in a "Hard" 0v on the output
- the "soft" high pin gets directly connected to ground making it 0v
3./4. If we had a normal Output where high was a "hard" 5v then you would have this setup. Here a large amount of current flows directly from 5v to 0v which is a short circuit
In the figure for 3. the current is small because it goes through a large resistor first
the circuit for the ouput/input connected looks like
@coral geyser are you available?
Hi. :)
@wary cloak I'm glad this seems to be working out for you. I also do embedded stuff. Feel free to ping me in case.
Thanks, and yeah sure thing I'm glad to have more than one tutor
🥳
@hallow hinge @coral geyser are you available?
Oh I was checking something from the C++ version of this project see if I finally make something work
After we can continue getting rusty
Today's objective is finally finishing the base functionality of the project
I am on/off I will be working extra for the rest of the afternoon
Wdym on/off(?
I am on my own time, so can answer questions, but I won't have discord open all the time so may miss pings
Oh ok
So you are here but more or less it depends
Well today's objective should be fairly easy I suppose
Yeah, I have a few hundred lines of code to write today
First we should merge the lcd and keypad I hope the only thing I would have to do is get out read char and replace it with wait_for_key and that's it
That should be it -
Yeah, should be
Tho the thing is were we instanciate our keypad "object"
Because it will be used in the status machine
Any clue where?
And also..
What should I call this new project?
Because it ain't it's final form
But only the one without rfid
Simple bartender maybe
Oh I'm having dinner
Brb
Tho soon after I come back I'm having my class about github we will see how we manage it-
I got confused for a fraction of a second
Well
A small question
Have you by chance read what we were working on?
Not really, the backlog here is like veerryyy large lol
Ofc because I'm in it(?
It's a bit impossible to check because Discord doesn't index threads.
Though
Can you give me a summary? :)
Well it would be nice if I could find the message explaining what is the project and then I could say and we did this already
Well the search words is for the whole server and not just this thread that's trouble some 
Yeah, it's annoying. You can at least do in:#rust-help
But there's no way to check for this specific thread
It doesn't matter. This is what I'm using as a search query rn
from: λ Azazel#5874 RFID in: rust-help
That maybe isn't helping much because I write a lot(?
Oh they are calling me to clean the plates
Brb again
Tho my class starts soon but
Maybe I will be able to give insight at least
Okay. :3 Just @ me when you start talking, because I mostly just check if #offtopic has activity before tabbing to another Discord lol
Sure
@hallow hinge I'll be busy for the next two hour because of my class but I may have a break
I'm making an automatic bartender
First I'll explain the base functionality of the project which I what we are about to finish
Aruduino MEGA
Yes
TIL
Also it's a school project
I'm glad to hear that though. :)
Because in this last year we have a subject for that
Can you show me your Cargo.toml btw?
I'm in my last year or secondary school to be a technician in electronics
Which one
Well I guess
They were equal in both projects more or less
Just that I had to add an lcd dependency for the other
My computer is slow
[package]
name = "keypad"
version = "0.1.0"
authors = []
edition = "2021"
license = "MIT OR Apache-2.0"
[[bin]]
name = "keypad"
test = false
bench = false
[dependencies]
panic-halt = "0.2.0"
ufmt = "0.1.0"
nb = "0.1.2"
embedded-hal = "0.2.3"
[dependencies.arduino-hal]
path = "avr-hal/arduino-hal"
features = ["arduino-mega2560"]
# Configure the build for minimal size - AVRs have very little program memory
[profile.dev]
panic = "abort"
lto = true
opt-level = "s"
[profile.release]
panic = "abort"
codegen-units = 1
debug = true
lto = true
opt-level = "s"
I get how you feel lol. It's been like half a decade though, huh. I used to have a 2003 computer as my daily driver.
Thanks. :)
And there's also .cargo
As you'll notice this is for the keypad project
Tho it has one key difference is that we are using Arduino hal locally because of something we had to change from it because Arduino Mega is a special boy
[build]
target = "avr-specs/avr-atmega2560.json"
[target.'cfg(target_arch = "avr")']
runner = "ravedude mega2560 -b 57600"
[unstable]
build-std = ["core"]
This is .cargo
Thanks. :) That's so cool.
Also, you can try opt-level = "z" if you need even more PROM.
We could try but for now works decent
So
It's an automatic bartender and it would be like this
First we turn it on
The users sees in the lcd
Which drink you want?
And three options
If he presses whatever
It will say that, that's an unvalid key
Invalid*
And go back
If you press option 2 and 3
It will say drink not available because at least for now it's made to work in one case tho we could easily expand it
And ofc go back
So you can only select drink 1
Idk about alcoholic drinks so names are temptative
With the matricial keyboard the users gives the comand
And we go to the next screen
How intense you want it?
Hard, medium, soft
Same
When you chose intensity
A waiting message would be displayed on screen
Preparing..
With a blinking cursor
And we would active relay modules
To open... "Electrovalvulas" (Idk how to say it in English)
So the liquid in that bottle or recipient
Will fall to the glass
Then the next
And the delay depends on the intensity the order of activition is always the same
We had the lcd and keyboard working
Today we should make the lcd and keyboard work together
So we don't need to use serial
And do the logic for depending the choice of intensity how many times each relay is high
That's the two parts of what I was planning today ofc
Cool. :) Can you reply to the part which you've already done?
One issue aside from that it works on one case only
Is that the times are by calculation "lazo abierto"it's not sensed so.. It'll be a deal
Lcd works, shows what it has to and we send it commands by the serial port to test it, the keyboard also works, we detect the correct key and print it to the serial monitor
Lcd and keyboard by their own done
Today lcd+keyboard together and relay logic
My class just started so if I disappear you know
Thanks. This seems fun. :)
Any other question about what we are doing or need to do or has been done or whatever maybe?
I'll enable all notifications here lol so that I get notified when people message here even without @ing.
The last thing would be explaining what will be the final project, this is base functionality
Oh I forgot one other thing aside that
And is why I'm re writting this project and the fact that I'm re writting it
Everything seems to make sense to me. :) But yeah, would have to see your actual code to judge.
I could send what has been done as a zip if you wanted to(?
Sure thing.
Sure after the class I'll do it
And also explain why re writting in rust and what the end goal is
excited to see all of it
Well this project is ofc originally done in Arduino IDE (C++) I got stuck, I sometimes struggle to advance, hate compile error messages in Chinese, and I really depend on a programmer friend I know that now is not active to advance because he is good at programming and can help a lot even tho he barely knows C and nothing of embedded, thing is, I learned rust which I became really excited about, I wanted to use it in practice, become a real good true rust programmer, maybe being able to be more independent or less insecure about trying to code and also less afraid of errors, and maybe with rust I wouldn't get stuck, and also I would like to be able to do what little I know to do in C++ also in rust so I could keep going in rust, give it usage, and as a low level systems programming doing embedded with it makes sense and I love embedded, tho it's an expensive hobby and economy here is one of the worst of the world so likely I won't be able to do much more embedded until I have my desired programmer money(?
Tho I see that the ecosystem for embedded rust I really inmature and stuff so I guess I would have to stick with the gigantic C++ ecosystem- but I wanna finish doing this at me at a this project, learn how to, I wanted to know how to program Arduino in rust (later raspberry Pi pico, I'm buying it soon)
Well more or less that's the deal ig
Good that I want to try out web development and for any reason a low level programming has a way bigger ecosystem for web dev than embedded (?
Yeah. Though, personally, I find that the Rust libraries, while relatively sparse, are of better quality than the C++ counterparts. Also, it's much easier to modify them.
Problem is there aren't sometimes, the struggle we went through for the keyboard
When in Arduino was
Install library
Little setup to instanciate the object
Done
Here well because of the weird open drain behavior we had all this issues
Also the serial monitor works really bad
It's too inmature
Which is a shame because I really want to use rust for everything and get use to it
So I hope I love web dev and also rust there
Anyways more or less that's the thing tho
I'm still working on the Arduino version
But I can't on my own so I'm stuck
Which sucks because I'm so close to finish-
Think you could maybe help with that on&
Yeah me neither
That's a thing
I don't know C++
I actually really learned programming and got into this world like..
4 months ago or so
And this is like my first project-
No, thing is pandemic (?
In a normal scenario
I would 'be learn decently well C
Some C++
And done some projects in Arduino small ofc in comparison
But for example I would have known how to do lcd and matricial keyboard work already and stuff
And since I would likely had love it
Alternate me
Has already 2 years of programming experience and can likely do all this by it's own at learn Arduino version
I may go in insight over that after my class because I can't concentrate now
But for this year we are suppose to have technically two years of experience and now C, to some extent C++ and have Arduino experience
So it should be doable or at least we aren't clueless like
What's programming?
I just was so unlucky
Ahhh :/ so basically, this should have been already be a part of your formal studies?
The two most important years of the career more or less
I should be a big ballsy programmer by now km
(? *
But I'm a newby
And most importantly
I don't know a thing about Cpp
Which to understand the rfid hell
Would've been careful
Helpful*
Oh yeah, actually. How does RFID relate to your project? You didn't mention it a while ago
Until rfid I did the whole thing in a week, then rfid came and a month and so
(Or are you learning that for a separate project?)
That's why
If you need some c++ help i'm fairly decent at it? I use arduino for the odd this and that, too, although my electronics skills aren't quite as good
Ahhh thanks. :)
I'm good at electronics, so if it's related to that, then just ping me. :3
Well even if it wasn't for electronics I want to learn cpp in general so you surely could help with that objective thanks
Pandemic not only fucked me up with programming but also electronics ofc so I surely don't know so many things I should and it's a shame because I ain't seeing it again and it was really interesting or maybe I would have love it and follow it but know I wouldn't know
I could've been really good at electronics and I would've been so proud -
And it would also help a lot with my embedded career say or knowledge or programming or whatever
Anyways I'm compressing the two already done projects
So you can get a look
Ok there should be the keypad program
Wait a little bit for the second one(?
Which would actually be the first done but whatever
Oh no-
It says it's too heavy :(
That's annoying
Because basically what we are going to do is add those two codes and then write on top
So you having the bases would be useful
Understanding how everything works and being up to date
Ah yes
I'm in class and my computer it's slow I can't do much
I forgot about it
So sorry but the keypad one has the target folder -
I hope that isn't annoying
Tell me when you have seen it and if you have any doubts with the code or how it works
We just worked on it so scrolling up you could see something interesting but ofc lcd is much up there
The lcd code was easier to make work but we made like overkill and made a state machine and all
So it's really clean
?? Seen what
I just said that if there's any issues with understanding the keyboard it could scroll a little up to see when we did that and why
Tho ofc I would answer questions in any case
I'm not sure what you're looking for here?
Yeah, it's a lot of stuff
@hallow hinge ok now you can check both codes and that's mostly it the only thing left would be to explain you the end project
But that's not necessary for today's objective
But yes for tomorrow's in case today we do what I expected
Oh there's also another small detail
Thanks. :)
I only have that subject on Wednesdays so tomorrow
So what I care about the most
Is completing a goal for Wednesday
And then there's a whole week to work with
I still have 30 minutes of class so check it at your pace
Any questions feel free
Ok I'm finished
So
If you are ready there's one last thing I want to tell you and we can start working
With that basically like there's not more context to be given
Sure thing. I'm still currently reading it.
Well basically the end project
After this my professor said
Hey wouldn't it be cool if it had a payment system
And an Innocent me said yes it would be
So I bought the MFRC522 I think it was called
For read/write data
The first code was the one who read the data from the rfid and printed it our
Out*
Then
A code to change the password of one sector
To be safe and it's important to know
But what happened
The base code for reading works only with a base just bought card with the default password that all have
So go into the fit repository of the library
And create more or less our own function
So it can read with the password I want
Small detail
All sectors should have the same password
So
Create a new code on top of the other one
To change passwords for all sectors
Now that we can change the password of our card and read the data in it
The next step was the prototype of the functionality so knowing how to do it I later add it to the base functionality of the project
Normally we would have one device to charge money and another to buy from bit for economics and scope reason this one do both of them.
So
What would the project be like now?
Well first the lcd will display
Do you want to
Buy? Charge money? Or see how much money you got?
If you say buy
Everything it's like always
But now when you choose a drink
You have to put the card so it discounts you the money and let's you move on
Or after the intensity actually
It checks if you have enough
If not it says, not enough money and sends you back to the beginning
If not well that money is consumed
If you chose to check how much many you got
You put the card in the reader
And it shows you in decimal numbers how much money you got
And then goes back
Finally you can say I wanna charge money
So you do
And then it says
How much?
And with the matricial keyboard you type the number
Then get the card on the reader
It's charge and it goes back to the beginning
I already made this work in Arduino the prototype
That's base rfid the payment system
Ofc this all works with my card only because I changed it's password
But my teacher told me to add another functionality which is where I'm stuck now
He said it would be a pain to manually change the passwords of all cards to be usable for my project
We discussed different ways of doing this so I'm going to tell you the one I'm doing
There's another starting menu.
Do you want normal mode or master mode?
Normal mode, do what you always did
Master mode, you can get your new bought card to the reader and it will change it's password so easy and fast you can know use also that card in my machine
But ofc
Not anyone can enter
First time it turns one (yes I will have to know it's the first time)
It will ask you via matricial keyboard to type in a password
So know that password will be stored in the EEPROM and you can enter master mode with said password
Also you can change your password using ofc the one you already have
But if you forget
There should be a master password in the EEPROM that only technician will now about to fix your problem
Phew
Ah and also
This is my add but
I want that when you get a card that can already be use it prints
This card it's already on the system
And goes back
Also you can as many as you want then press something and go back
That's all the rfid stuff
Now there's one last thing to the project but it's way easier
We will have an "infrarrojo" Sensor to check if there's a glass or not
If there's not it won't server
And also ultrasonic sensors on top of the recipients
To check the distance between the top and the liquid
When there's no more liquid
It will ask you to fill it and it won't work
It has to be fool proof
So that's the final goal
Any questions?
Sure, the good thing is
Up until now I finished doing something and there was more
But now there's a confirmed finished condition which are the sensors
That's sooo good
Any doubts on the code?
Still also reading it. :P
I'm preparing the new project
Will probably give you some thoughts in like ~8 hours maybe? Since will have to work in a bit.
Shamefully I can't stay awake this much (or shouldn't) but tomorrow's Wednesday and I test in the actual built stuff like real scenario not only components the base functionality of the Arduino project I want to take the opportunity to test rust as well and show the rest writting is viable
Sure
Also..
@coral geyser are you here now? Because now I can finally start working
Well I created the new project I merged both mains, for now I copied all the module, I copied the Avr specs, .cargo, avr-hal, the toml from keypad and only added the lcd dependency now I'm going to run cargo build
To have an idea of what is like
well in the meantime
We have an issue
Ofc to call wait for key
We need to have instanciated our strict
Struct*
We have to use wait for key in status.rs
But it doesn't make sense to instanciate it there but idk how I would pass it, does my status struct take ownership of it?
Put it in the Bartender struct 
So it would be
pub struct Bartender<Serial> {
state: State,
selected_drink: Option<Drink>,
selected_intensity: Option<Intensity>,
lcd: Display<LcdConnection>,
serial: Serial,
keypad: Keypad,
}
Right? And I leave the declaration in main
Also soon we are getting rid of the serial struct and it's declaration of mean I suppose and also that requirement in function parameters and impl block and so
Well that it's going to be a little bit of a mess
But anyways, so far so good?
Yep
And new would look like
impl<Serial> Bartender<Serial> where Serial: Read<u8> + Write<u8> {
pub fn new(lcd: Display<LcdConnection>, serial: Serial, keypad: Keypad) -> Self {
Self {
state: State::SelectDrink,
selected_drink: None,
selected_intensity: None,
lcd,
serial,
keypad,
}
}
Ofc until removing serial
Ok so I think I will just do it
And tell you when something bad happena
Happens*
?
Idk why I always have scope issues-
It's infuriating-
Ok I got rid of all the serial stuff so
How do I fix that error?
I think it's that and.. We could test it
I hope it isn't annoying I just ping you again just in case because you said you wouldn't receive all notifications or smth like that @coral geyser
I use a use statement to all the module, the struct own keypad, wait for key is public, what else does it want for me how the hell isn't it in scope -
owns*
Isn't it self.keypad.wait_for_key() 
Keypad::wait_for_key(...) Is the long form
Yeah
Yeah when calling a method the thing to the left of the . Becomes self in the method
Ok cargo check now because I see no errors
It compiled
Excellent
Let's test it
If it works we have no much left to do :')
?eval ```rust
#[derive(Debug)]
struct A;
impl A {
fn test(&self) {
dbg!(self);
}
}
let x = A;
x.test();
Running `target/debug/playground`
[src/main.rs:7] self = A
()
Delay's too long
But it seems to be working
It completely woooorks
Ok now let's talk about the last thing
Now
We need to get the relays part
Basically
When you choose intensity and while " preparing.. "
Is showing
You start sending highs to the relays
One at a time
Same order
The code it's the same for each case
Only thing that changes it's the delay
So I will show you
How I did the code first time the messy manual repetitive way
And then how I did a function for it
We adapt it to rust and
That's it
No library no nothing
Just togglin 4 pins a certain delay
On here I look for them show them to you and we do it and.. That would be it for today
switch(tecla){
case '1':
digitalWrite(4,HIGH);
delay(2000);
digitalWrite(4,LOW);
delay(1000);
digitalWrite(3,HIGH);
delay(4000);
digitalWrite(3,LOW);
delay(1000);
digitalWrite(2,HIGH);
delay(4000);
digitalWrite(2,LOW);
delay(1000);
break;
case '2':
digitalWrite(4,HIGH);
delay(3000);
digitalWrite(4,LOW);
delay(1000);
digitalWrite(3,HIGH);
delay(3000);
digitalWrite(3,LOW);
delay(1000);
digitalWrite(2,HIGH);
delay(3000);
digitalWrite(2,LOW);
delay(1000);
break;
case '3':
digitalWrite(4,HIGH);
delay(6000);
digitalWrite(4,LOW);
delay(1000);
digitalWrite(3,HIGH);
delay(2000);
digitalWrite(3,LOW);
delay(1000);
digitalWrite(2,HIGH);
delay(2000);
digitalWrite(2,LOW);
delay(1000);
break;
}
}
This is the repetitive way
Tho in this version I only toggled three pins now they are four
Now
This is the function I made
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);
}
and this the implementation
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;
}
}
}
So.. How do we start? Another module, or a method of the bartender struct?
Probably a method on the bartender struct
Ok so I will do it below do show waiting screen
How do we call it?
And also, a public function? Or a private one
I mean
Update will take care or this too?
I know, serve_drinks ;)
Well so that, will it be public or will it be private?
Tho thing is this.
It will be serving the drink and while it's doing it
It will be displaying the waiting message
That means it's status will still be waiting so..
In the update signature
Do I add brackets to the match state waiting first call do show waiting screen and then serve_drinks?
And also.. So I remove the state change to serve drinks?
Because you know if that's the case we could directly call waiting screen in the update function because do show waiting screen called waiting screen and changed state so..
I will tell you my idea
So..
We get rid of do show waiting screen
Then in the match expression we add brackets to the waiting screen state
First we call show waiting screen
Then we call serve drinks
So the function is private
And inside serve drinka
Drinks *
We will change the state back to select drinks
Do you agree with that?
And if you do the thing is how do we implement the function, do we have to declare in main aside from the pins, 4 variables representing each delay initialized as 0?
Will our struct take owner ship of the pins it needs to toggle?
I have so many questions-
Because then pins would need to be an array but then delays too
So..
This first
Btw @coral geyser should I ping you for questions or let you be and wait? Because I have notifications off and I really don't know how annoying it could be or that
Yep just take ownership of the pins like what Keypad does
Are the delays configurable at runtime?
It won't be at runtime
Pinging is good
As you see in the code I showed you I enter a switch that sets the delays for each case instead of high low high low each time basically
Then you can just hard code it in the method right? (Or the method that calls the method)
Well yeah the idea was depending on the intensity selected we could check the enuma
Only delay changes
Not the pins not the order
Just the delay
match ... {
... => self.dispense(100, 300, 500),
...
}
But first of all
Do you agree with my idea?
Of getting rid of
Do show waiting screen
In update call waiting screen and then serve drink and serve drink would change states
Sure sounds reasonable
Is it pub?
It is
and I have another important question after this one regarding the pins but ofc this first
but basically how do i declare the pins an add them to the struct?
btw the pins are 6,4,3,2
and are activated in that order
so.. I did the following
in main this
let pins = [
pins.d2.into_output().downgrade(),
pins.d3.into_output().downgrade(),
pins.d4.into_output().downgrade(),
pins.d6.into_output().downgrade(),
];
let mut bartender = Bartender::new(lcd, keypad, pins);
in the struct definition this
pub struct Bartender {
state: State,
selected_drink: Option<Drink>,
selected_intensity: Option<Intensity>,
lcd: Display<LcdConnection>,
keypad: Keypad,
pins: RelayPins,
}
type RelayPins = [Pin<Output, Dynamic>; 4];
ofc adding the use statements needed
and in new this
impl Bartender {
pub fn new(lcd: Display<LcdConnection>, keypad: Keypad, pins: RelayPins) -> Self {
Self {
state: State::SelectDrink,
selected_drink: None,
selected_intensity: None,
lcd,
keypad,
pins,
}
}
@coral geyser did I do all the pins deal right?
Since my program is sending the 1 and so well it should be output and you know why dynamic
well i will go to sleep i hope maybe we can work it out before i go or smth idk in any case
i will leave what else i did
so
the update functions is this now
pub fn update(&mut self) {
match self.state {
State::SelectDrink => self.do_show_drinks(),
State::SelectIntensity => self.do_show_intensity(),
State::Waiting => {
self.show_waiting_screen(&mut self.lcd);
self.serve_drinks(&mut self, pins);
}
}
}
and i did the function serve drinks or at least most of it
fn serve_drinks(&mut self, self.pins:RelayPins) {
match self.selected_intensity {
Intensity::Strong => {
pins[0].toggle();
arduino_hal::delay_ms(8000);
pins[0].toggle();
arduino_hal::delay_ms(1000);
pins[1].toggle();
arduino_hal::delay_ms(2000);
pins[1].toggle();
arduino_hal::delay_ms(1000);
pins[2].toggle();
arduino_hal::delay_ms(2000);
pins[2].toggle();
arduino_hal::delay_ms(1000);
pins[3].toggle();
arduino_hal::delay_ms(2000);
pins[3].toggle();
arduino_hal::delay_ms(1000);
}
Intensity::Medium => {
pins[0].toggle();
arduino_hal::delay_ms(5000);
pins[0].toggle();
arduino_hal::delay_ms(1000);
pins[1].toggle();
arduino_hal::delay_ms(3000);
pins[1].toggle();
arduino_hal::delay_ms(1000);
pins[2].toggle();
arduino_hal::delay_ms(3000);
pins[2].toggle();
arduino_hal::delay_ms(1000);
pins[3].toggle();
arduino_hal::delay_ms(3000);
pins[3].toggle();
arduino_hal::delay_ms(1000);
}
Intensity::Weak => {
pins[0].toggle();
arduino_hal::delay_ms(2000);
pins[0].toggle();
arduino_hal::delay_ms(1000);
pins[1].toggle();
arduino_hal::delay_ms(4000);
pins[1].toggle();
arduino_hal::delay_ms(1000);
pins[2].toggle();
arduino_hal::delay_ms(4000);
pins[2].toggle();
arduino_hal::delay_ms(1000);
pins[3].toggle();
arduino_hal::delay_ms(4000);
pins[3].toggle();
arduino_hal::delay_ms(1000);
}
}
self.state = State::SelectDrink;
}
And finally, the errors
The one from before and idk why it says it expectes three arguments when they are clearly 2
And it says missing type but... It's clearly there
And finally I will show you the errors but via cargo check
Checking simple_bartender v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\simple_bartender)
error: unexpected `self` parameter in function
--> src\state.rs:110:32
|
110 | fn serve_drinks(&mut self, self.pins:RelayPins) {
| ^^^^ must be the first parameter of an associated function
error: expected one of `)`, `,`, or `:`, found `.`
--> src\state.rs:110:36
|
110 | fn serve_drinks(&mut self, self.pins:RelayPins) {
| ^
| |
| expected one of `)`, `,`, or `:`
| help: missing `,`
error[E0415]: identifier `self` is bound more than once in this parameter list
--> src\state.rs:110:32
|
110 | fn serve_drinks(&mut self, self.pins:RelayPins) {
| ^^^^ used as parameter more than once
error[E0425]: cannot find value `pins` in this scope
--> src\state.rs:57:46
|
57 | self.serve_drinks(&mut self, pins);
| ^^^^ help: you might have meant to use the available field: `self.pins`
error[E0599]: no method named `show_waiting_screen` found for mutable reference `&mut state::Bartender` in the current scope
--> src\state.rs:56:22
|
56 | self.show_waiting_screen(&mut self.lcd);
| ^^^^^^^^^^^^^^^^^^^ help: there is an associated function with a similar name: `do_show_waiting_screen`
Some errors have detailed explanations: E0415, E0425, E0599.
For more information about an error, try `rustc --explain E0415`.
error: could not compile `simple_bartender` due to 5 previous errors
Lok
I fixed all but one
In the end the function is like this
fn serve_drinks(&mut self, pins:RelayPins) {
match self.selected_intensity {
Some(Intensity::Strong) => {
pins[0].toggle();
arduino_hal::delay_ms(8000);
pins[0].toggle();
arduino_hal::delay_ms(1000);
pins[1].toggle();
arduino_hal::delay_ms(2000);
pins[1].toggle();
arduino_hal::delay_ms(1000);
pins[2].toggle();
arduino_hal::delay_ms(2000);
pins[2].toggle();
arduino_hal::delay_ms(1000);
pins[3].toggle();
arduino_hal::delay_ms(2000);
pins[3].toggle();
arduino_hal::delay_ms(1000);
}
Some(Intensity::Medium) => {
pins[0].toggle();
arduino_hal::delay_ms(5000);
pins[0].toggle();
arduino_hal::delay_ms(1000);
pins[1].toggle();
arduino_hal::delay_ms(3000);
pins[1].toggle();
arduino_hal::delay_ms(1000);
pins[2].toggle();
arduino_hal::delay_ms(3000);
pins[2].toggle();
arduino_hal::delay_ms(1000);
pins[3].toggle();
arduino_hal::delay_ms(3000);
pins[3].toggle();
arduino_hal::delay_ms(1000);
}
Some(Intensity::Weak) => {
pins[0].toggle();
arduino_hal::delay_ms(2000);
pins[0].toggle();
arduino_hal::delay_ms(1000);
pins[1].toggle();
arduino_hal::delay_ms(4000);
pins[1].toggle();
arduino_hal::delay_ms(1000);
pins[2].toggle();
arduino_hal::delay_ms(4000);
pins[2].toggle();
arduino_hal::delay_ms(1000);
pins[3].toggle();
arduino_hal::delay_ms(4000);
pins[3].toggle();
arduino_hal::delay_ms(1000);
}
_ => {}
}
self.state = State::SelectDrink;
}
Forgot selected intensity was optional, pins didn't need self, but yes when calling it but not another self parameter, I also didn't cover the none case
I also got rid of do show waiting screen
And I have that little annoying one error left
Checking simple_bartender v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\simple_bartender)
error[E0599]: no method named `show_waiting_screen` found for mutable reference `&mut state::Bartender` in the current scope
--> src\state.rs:56:22
|
56 | self.show_waiting_screen(&mut self.lcd);
| ^^^^^^^^^^^^^^^^^^^ method not found in `&mut state::Bartender`
For more information about this error, try `rustc --explain E0599`.
error: could not compile `simple_bartender` due to previous error
well say i solve it doing this
crate::lcd::show_waiting_screen(&mut self.lcd);```
tho I still do not know why here was necessary and not before but, as long as it works
tho i had other issues
forgot to get leds to be mutable that is ok I fixed
the function now recieves a mutable reference to the array pins but i says mismatched types
Checking simple_bartender v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\simple_bartender)
error[E0308]: mismatched types
--> src\state.rs:57:35
|
57 | self.serve_drinks(&mut self.pins);
| ------------ ^^^^^^^^^^^^^^ expected array of 4 elements, found mutable reference
| |
| arguments to this function are incorrect
|
= note: expected array `[avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
found mutable reference `&mut [avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
note: associated function defined here
--> src\state.rs:104:8
|
104 | fn serve_drinks(&mut self, &mut pins:RelayPins) {
| ^^^^^^^^^^^^ --------- -------------------
help: consider removing the borrow
|
57 - self.serve_drinks(&mut self.pins);
57 + self.serve_drinks(self.pins);
|
error[E0308]: mismatched types
--> src\state.rs:104:32
|
104 | fn serve_drinks(&mut self, &mut pins:RelayPins) {
| ^^^^^^^^^----------
| | |
| | expected due to this
| expected array of 4 elements, found `&mut _`
| help: did you mean `pins`: `&[avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
|
= note: expected array `[avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
found mutable reference `&mut _`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `simple_bartender` due to 2 previous errors
K so..
The variable in main did not need to be mutable
But it said in the signature
So now it is
serve_drinks(&mut self, mut pins:RelayPins)```
But now I have a new error and this time I don't feel like I can fix it
Checking simple_bartender v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\simple_bartender)
error[E0507]: cannot move out of `self.pins` which is behind a mutable reference
--> src\state.rs:57:35
|
57 | self.serve_drinks(self.pins);
| ^^^^^^^^^ move occurs because `self.pins` has type `[avr_hal_generic::port::Pin<Output, Dynamic>; 4]`, which does not implement the `Copy` trait
error[E0505]: cannot move out of `self.pins` because it is borrowed
--> src\state.rs:57:35
|
57 | self.serve_drinks(self.pins);
| ------------------^^^^^^^^^-
| | |
| | move out of `self.pins` occurs here
| borrow of `*self` occurs here
Some errors have detailed explanations: E0505, E0507.
For more information about an error, try `rustc --explain E0505`.
error: could not compile `simple_bartender` due to 2 previous errors
@old mango any idea?
@hallow hinge or maybe you?
And why not @dreamy trellis
Can you do it as a mut ref?
When I'm calling the function or in the signature?
In any case I think it will display the error mismatched types again
It'd naturally be for both?
I will do it so you see the errors
First I will show how they are rn
And then well do the mutable referencea
Rn they are
Signature
self.serve_drinks(self.pins);```
Calling
Now let's change it
fn serve_drinks(&mut self, &mut pins:RelayPins)```
self.serve_drinks(&mut self.pins)
Nvm, with the way you're calling that borrowck will refuse
It'd be something like cannot move out of ref for the original and can't borrow twice for the changed, right?
Can you get rid of the pins argument and just use self.pins inside serve_drinks?
no, mistmatched types i think is the error
error[E0308]: mismatched types
--> src\state.rs:57:35
|
57 | self.serve_drinks(&mut self.pins);
| ------------ ^^^^^^^^^^^^^^ expected array of 4 elements, found mutable reference
| |
| arguments to this function are incorrect
|
= note: expected array `[avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
found mutable reference `&mut [avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
note: associated function defined here
--> src\state.rs:104:8
|
104 | fn serve_drinks(&mut self, &mut pins:RelayPins) {
| ^^^^^^^^^^^^ --------- -------------------
help: consider removing the borrow
|
57 - self.serve_drinks(&mut self.pins);
57 + self.serve_drinks(self.pins);
|
error[E0308]: mismatched types
--> src\state.rs:104:32
|
104 | fn serve_drinks(&mut self, &mut pins:RelayPins) {
| ^^^^^^^^^----------
| | |
| | expected due to this
| expected array of 4 elements, found `&mut _`
| help: did you mean `pins`: `&[avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
|
= note: expected array `[avr_hal_generic::port::Pin<Output, Dynamic>; 4]`
found mutable reference `&mut _`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `simple_bartender` due to 2 previous errors
First of all
I get rid of the mut references then?
Tho that's basically what the compiler suggests
Oh, your syntax is off; in that case, you'd want pins: &mut RelayPins
Although it still wouldn't work because that would be taking two mutable references to self, which the borrowck won't allow
Smart pointers (?
fn serve_drinks(&mut self) {
And then inside the function, instead of using the pins parameter, you'd use self.pins
You know how rust only lets you take one mutable reference to an object at a time, right?
And also you cant move a value out of a variable while you hold a reference to it?
When you say "let a = b" in rust, when b isnt a reference, it moves the value from the binding b to the binding a; the value can no longer be accessed through b because b doesnt own that value anymore
God f damn it the code works but in a weird way and I can't seem to determine the issue -
Ok yes
Unless it implements copy
When you transfer ownership like that, any references you had to the value, that are references to b, stop being valid
This is because the value isnt in b anymore, it's in a now, and the references have no way of knowing that
Yep!
Ok I get that
Therefore, when you transfer ownership (move the value), old references to the value from before the move stop being valid
Rust makes sure you can't accidentally still use one of those references by saying "if there's still a reference to it, you don't get to transfer the ownership of that value"
Mmm ok
Awesome
Aight, now, looking at the original signature of serve_drinks, it's serve_drinks(&mut self, mut pins: RelayPins)
The pins parameter here, since it's not a reference, will take ownership of whatever is passed in that parameter
So when you call
self.serve_drinks(self.pins), it can't comply
Wait
Was I
Taking a mutable reference to self
While also
Asking for owner ship?
Yup
Mutable reference, and asking for ownership
In the other hand I asked only one mutable reference to self inside I could refer to things from self so
Ah btw
Also, i'm guessing that the place where this function call occurs is another function on the same struct?
I fixed 89% of what I just said of the code working but doing it weirdly
Well serve drinks is a method of the struct and it's called on the function update so yes
If the self in self.serve_drinks(self.pins) is a mut ref in the first place, it's completely impossible to move out of it
Now 100%
Man I can't believe it if this was Arduino I would've gotten stuck but with rust I could confidently solve and figure out 90% of the errora
Errors*
What a pleasure
Also now I can't live without modules
This is because a mutable reference isn't ownership; to give serve_drinks ownership of that object, you'd have to have ownership of the object already, but since it's a mutable reference, you can't do that.
For the function knows, when it returns and that &mut self goes out of scope, the actual owner of self will keep on using it
Oh of
So if you wanted to transfer ownership all the way down, you'd need to use fn my_fn(self, <other parameters>) all the way down
Update already takes a mutable reference to self also
And that also wouldn't work, because it's in a loop, so after you call it, it'll get called again, except the ownership would've already been transferred, and you wouldnt have anything to call the function on anymore
Thus, the only option all along was to pass &mut self all the way down
Any other questions or are you good for now?
Aight, awesome

No probs
@coral geyser it didn't work again-
C:/Users/Taller03/Desktop/simple_bartender # cargo check
Updating crates.io index
Downloaded paste v1.0.8
error: failed to unpack package `paste v1.0.8`
Caused by:
failed to unpack entry at `paste-1.0.8/.cargo_vcs_info.json`
Caused by:
failed to unpack `D:/rust_toolchain/.cargo\registry\src\github.com-1ecc6299db9ec823\paste-1.0.8\.cargo_vcs_info.json`
Caused by:
failed to set mtime for `D:/rust_toolchain/.cargo\registry\src\github.com-1ecc6299db9ec823\paste-1.0.8\.cargo_vcs_info.json`
Caused by:
El parámetro no es correcto. (os error 87)
C:/Users/Taller03/Desktop/simple_bartender #
Why this time ;;
Windows PowerShell
Copyright (C) Microsoft Corporation. Todos los derechos reservados.
Prueba la nueva tecnologÃa PowerShell multiplataforma https://aka.ms/pscore6
PS C:\Users\Taller03> cd D:/
PS D:\> cd rust_toolchain
PS D:\rust_toolchain> .\busybox.exe ash setup_rust_arduino.sh
Directory of rust toolchain: D:/rust_toolchain
Starting configured ash shell, run 'exit' to exit the shell.
D:/rust_toolchain $ cd ..
D:/ $ cd simple_bartender
D:/simple_bartender $ cargo check
error: failed to download `paste v1.0.8`
Caused by:
unable to get packages from source
Caused by:
failed to unpack package `paste v1.0.8`
Caused by:
failed to unpack entry at `paste-1.0.8/.cargo_vcs_info.json`
Caused by:
failed to unpack `D:/rust_toolchain/.cargo\registry\src\github.com-1ecc6299db9ec823\paste-1.0.8\.cargo_vcs_info.json`
Caused by:
failed to set mtime for `D:/rust_toolchain/.cargo\registry\src\github.com-1ecc6299db9ec823\paste-1.0.8\.cargo_vcs_info.json`
Caused by:
El parámetro no es correcto. (os error 87)
D:/simple_bartender $
Here in PowerShell
Even with not embedded projects like guessing_game it doesn't work-
error: failed to unpack package `winapi-x86_64-pc-windows-gnu v0.4.0`
Caused by:
failed to unpack entry at `winapi-x86_64-pc-windows-gnu-0.4.0/Cargo.toml`
Caused by:
failed to unpack `D:/rust_toolchain/.cargo\registry\src\github.com-1ecc6299db9ec823\winapi-x86_64-pc-windows-gnu-0.4.0\Cargo.toml`
Caused by:
failed to set mtime for `D:/rust_toolchain/.cargo\registry\src\github.com-1ecc6299db9ec823\winapi-x86_64-pc-windows-gnu-0.4.0\Cargo.toml`
Caused by:
El parámetro no es correcto. (os error 87)
Um, try adding a --offline to the cargo command
I was busy the rest of the class -
What do we do?
It has been two weeks it's so shitty that it's only one class a week
We just can't get it to work-
^?
But
That's for the embedded scenario or not embedded scenario
Because the error messages were different
And also we can't test it now that I'm at home, I hope we could so this didn't happen again
Are you use there's nothing else we might need?
I don't think anything else is needed, though this is my first time attempting this so
both
well, actually the usb drive isn't setup to do not embedded
but is should be able to do it anyways
the main issue seems to be cargo really hates being on a fat32 filesystem
which we can only salve by reformatting the usb
which we could do
Since it isn't my maybe we shouldn't-
I have one to be mine but not the time to go through all that pain again
So instead of cargo check, cargo check --offline?
That would be it?
yeah, though i am not sure if it will actually fix it more of like the best next step to check
The thing is if it doesn't work and it's another week
Btw
Think you could help me with the Arduino version? It's just, it's kinds close to finish and I want sooo badly to get it out of the way
what is the issue?
Did I told you what I was doing with the rfid why it's there?
yeah
Well I'm stuck in the last functionality that is the password system
It can tell if the password you enter is correct or not
But then it doesn't perform the password change.
And I got prints every where to see where's stuck
And I got out of ideas of what to do
And it's weird I more or less copy pasted from my change password code that works
So the fact that this one doesn't
Is weird
What's left to do is
For the thing to actually change the password when the password is correct
To the error handling so if you get a card that it's already fine it tells you, hey this one's already good and goes back
And the whole EEPROM deal..
But it seems decently simple to work with the EEPROM
And after that's done
I should get that and all the other the rfid functionality I already have working like buying and stuff
To the base functionality of the project
After that, well the sensors which are really easy to work with today I learned how to work with the ultrasound one
And tested that it worked for water too
And the other is likely easier than that one so
As you see, it's so close to be finished
can I get the code?
Sure
I have plenty rfid codes
-reading for default password
-reading for password I want
-change password of one sector
-change password of all sectors
-and this one the prototype of the functionality
I'm building the passwords an all on top of that one
You want the full code or the function?
Tho have you worked with that library before? It was so hard for me to understand and it was a whole deal to more or less get it and start actually doing something
Because I think I have over there the git repository if you'd like
full code is better
Sure
#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}};
MFRC522::MIFARE_Key keyB = {keyByte: {0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5}};
byte sector = 15;
byte numBloque = 60;
byte bloqueTrailer = 63;
void mostrarByteArray(byte* buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
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* 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;
}
int obtenerSaldo(){
unsigned char datosBloque[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte arraySize = 18;
mfrc522.MIFARE_Read(numBloque,datosBloque,&arraySize);
String saldo_actual = String((char*)(datosBloque));
int saldoActual = saldo_actual.toInt();
return saldoActual;
}
void setup() {
Serial.begin(9600);
while (!Serial);
SPI.begin();
mfrc522.PCD_Init();
}
void loop() {
Serial.println("\n¿Quiere acceder al modo maestro u operar normal?");
Serial.println("1-Modo Maestro");
Serial.println("2-Modo Normal");
char input = waitForOption();
switch (input) {
case '1':{
modoMaestro();
return;
}
case '2':{
modoNormal();
return;
}
default:
Serial.println("Elija una opcion valida");
return;
}
}
void modoNormal() {
Serial.println("\n¿Quiere cargar plata, comprar o verificar su saldo?");
Serial.println("1-Cargar Plata");
Serial.println("2-Comprar");
Serial.println("3-Ver estado de saldo");
char input = waitForOption();
switch (input) {
case '1':{
cargarSaldo();
return;
}
case '2':{
comprar();
return;}
case '3':{
leerSaldo();
return;}
default:
Serial.println("Elija una opcion valida");
return;
}
}
void cargarSaldo() {
char plata[16];
unsigned char datosBloque[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
Serial.println("ingrese la cantidad de dinero que desea cargar y finalice con cualquier letra");
bool esNumero = obtenerPlata(plata);
if(esNumero == false){
Serial.println("No ingreso un numero");
return;
}
Serial.println("Ahora acerque la tarjeta para cargarle plata");
while(!mfrc522.PICC_IsNewCardPresent());
while(!mfrc522.PICC_ReadCardSerial());
mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, bloqueTrailer, &keyA, &(mfrc522.uid));
String plataAEscribir = String(obtenerSaldo() + String(plata).toInt());
plataAEscribir.toCharArray((char*)datosBloque, 16);
mostrarByteArray(datosBloque,16);
mfrc522.MIFARE_Write(numBloque,datosBloque,16);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
return;
}
void comprar() {
unsigned char datosBloque[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
Serial.println("Elija un producto");
Serial.println("1-Fernet con Coca 400$");
Serial.println("2-Sex on the beach 250$");
Serial.println("3-Agua 100$");
char input = waitForOption();
int precio = 0;
switch (input) {
case '1':
precio = 400;
break;
case '2':
precio = 250;
break;
case '3':
precio = 100;
break;
default:
Serial.println("Elija una opcion valida");
return;
}
Serial.println("Ahora acerque la tarjeta para reaizar su pago");
while(!mfrc522.PICC_IsNewCardPresent());
while(!mfrc522.PICC_ReadCardSerial());
mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, bloqueTrailer, &keyA, &(mfrc522.uid));
int saldo = obtenerSaldo();
if(saldo < precio){
Serial.print("Su saldo es insuficiente");
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
return;
}
String plataADescontar = String(obtenerSaldo() - precio);
plataADescontar.toCharArray((char*)datosBloque, 16);
mfrc522.MIFARE_Write(numBloque,datosBloque,16);
Serial.println("Proceso terminado disfrute de su bebida");
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
return;
}
void leerSaldo() {
Serial.println("Apoye su tarjeta para ver su saldo");
while(!mfrc522.PICC_IsNewCardPresent());
while(!mfrc522.PICC_ReadCardSerial());
mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, bloqueTrailer, &keyA, &(mfrc522.uid));
int saldo = obtenerSaldo();
Serial.print("Su saldo actual es ");
Serial.print(saldo);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
return;
}
And this last function I'm going to send
Is ther one I was trying to debug
void modoMaestro(){
char password[] = {'c','a','d','3','6','5','\0'};
Serial.println("Ingrese la contraseña");
char user_password[6];
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 keyA = {keyByte : {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
MFRC522::MIFARE_Key keyB = {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;
}
Serial.print(" chau if's");
byte bloqueTrailer = sector * 4 + 3;
byte buffer[18];
byte size = sizeof(buffer);
Serial.print(" chau variables");
mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, bloqueTrailer, &keyA, &(mfrc522.uid));
mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, bloqueTrailer, &keyB, &(mfrc522.uid));
Serial.print(" chau autenticacion");
if (nuevaKeyA.keyByte != nullptr)
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
buffer[i] = nuevaKeyA.keyByte[i];
Serial.print(" chau primer null");
if (nuevaKeyB.keyByte != nullptr)
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
buffer[i + 10] = nuevaKeyB.keyByte[i];
Serial.print(" chau segundo null");
mfrc522.MIFARE_Write(bloqueTrailer, buffer, 16);
Serial.print(" chau escritura");
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
Serial.print(" chau stops");
Serial.println("Proceso Finalizado");
Serial.print(" chau funcion");
break;
}
} else{
Serial.println("Contraseña Incorrecta");
return;
}
}
Do you want the place where I got the library from and the git repository?
Here I saw it and the examples
Understanding the code there and all was mostly all I had
And here's the git repository which well
When I didn't know about cpp and OOP it wasn't that useful
Not like it is that much now but
If you know about normal cpp Arduino you could help in this other thing too @hallow hinge
@old mango do you think you might be able to help with this? Not rn tho
I am about to go back to sleep so yeah not rn
When i wake up, prolly?
What exactly is it that you need?
Make that code work(?
Only this part doesn't
And also the functionality it would provide it's one I did I a code dedicate only to that and it worked but here copying code from there
Why's this but in c++, btw?
Didn't
I didn't understand the question but yes this is normal Arduino so cpp
Was just wondering since i thought the project was in rust; or maybe I'm misunderstanding
I'll take a look at the code in ~8 horas
Sure
This the original the rust one is a re write
Ah
But since this one is so close to finish I want to finish it once and for all
And also you said I asked you help for cpp issues
@coral geyser will you be able in some minutes?
Available*
Hi. :3
This time I'm available fr
I had some things to do irl so I was unavailable
Sure
Anything to say about the rust one?
Question or whatever
The only thing that happened is that the base functionality was completed
But now as you may see I really want to end the original Arduino one, I'm sick of it at least sick of the rfid part
Tho when finishing the rfid part is almost like finishing the project because the sensors are easy
And I keep struggling to be able to use rust elsewhere in school so I can't show my rust's projects
@hallow hinge @coral geyser are any of you two available now or maybe like in 40 minutes? Both work fine
Tho it you don't I get to sleep earlier today so in any case (?
if you*
Yes but I won't code tonight
We could like.. The setup talk
Details, doubts, preparing to be able to code
So next time likely tomorrow
We can get right into it
Just above I sent the whole code, aside from that the place where I got the library from, and most importantly, the git repository
So, uh, quick issues I saw on a quick readthrough of modoMaestro:
// WRONG: `password[]' has 7 chars (including the '\0'), and waitForPassword will write 6 chars + a '\0', so this will in fact overwrite some unrelated location in memory!!!
// BAD PRACTICE: if the length of `password[]' changes, it could potentially cause the above problem to become even worse.
// VERDICT: This is a buffer overrrun, seriously not good. You might not see any effects, but this is a really bad thing to have.
char user_password[6];
// BETTER VERSION:
// NOTE: sizeof(password) returns the size of password in *bytes*, not the size in terms of the elements in it. While for a char[] array, these two will be the same, this is a better practice.
char user_password[sizeof(password) / sizeof(char)];
// WRONG: `strcmp' returns a signed `int', but `byte' is unsigned.
// PROBLEM 1: `byte < 0' is always false because `byte' is unsigned, which discards part of the functionality of `strcmp'.
// PROBLEM 2: `int' is larger than `byte'. Therefore, when you assign an `int' to a `byte', it will truncate whatever parts of the `int' that the `byte' cannot hold. Therefore, certain values of int, like -256, for example, would actually turn into 0 when you try to convert them to a byte. Now, due to the specification of `strcmp', this shouldn't actually happen here, but it's still bad practice.
// VERDICT: Works okay, but only due to technicalities and the fact that your code only does an equality check with 0.
byte verification = strcmp(password, user_password); // CURRENT
// BETTER VERSION:
int verification = strcmp(password, user_password);
// PROBABLE BUG: This is using `keyB' but the command is `PICC_CMD_MF_AUTH_KEY_A'; I think you might be supposed to use `PICC_CMD_MF_AUTH_KEY_B'?
mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, bloqueTrailer, &keyB, &(mfrc522.uid));
(part 1/2)
// Stylistic issue
if (nuevaKeyA.keyByte != nullptr)
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
buffer[i] = nuevaKeyA.keyByte[i];
Serial.print(" chau primer null");
// With braces, it's the following, which seems to go against the indentation your using.
if (nuevaKeyA.keyByte != nullptr) {
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
buffer[i] = nuevaKeyA.keyByte[i];
}
}
Serial.print(" chau primer null");
Also, not sure what's up with your buffer.
It's declared to be 18 bytes, but the documentation says the sectors are 16 bytes, and MIFARE_Write says it will write exactly 16 bytes.
I'm also unsure about the buffer[i+10] = nuevaKeyB.keyByte[i];
Reading the file you linked (MFRC522.h), this would mean that buffer would be AAAAAA????BBBBBB where the A's are the bytes of keyA, the B's are bytes of keyB, and the ? are literally just random bytes of garbage floating around in the Arduino's memory.
Since buffer isn't initialised to anything, it's value will literally just be whatever happened to be written to memory at that location before, which is essentially going to be random. I didn't look over the rest of your code since you said it was modoMaestro you were looking for help with, but if having random junk written there is a problem, you'll want to memset(buffer, 0, 16); or change the declaration to byte buffer[/* whatever the size is */] = { 0, 0, /* ... */, 0 };.
Anyway, when/if you have questions, just ping me; I have a couple thousand lines of typescript to finish refactoring atm so I'll be getting back to that.
@old mango well I more or less read it, I'm still asleep so I don't get it at all but
I may answer some stuff
First
Read needs an 18 byte buffer, why? I don't remember but it was in the documentation and if I used a 16 byte one it would say that the buffer was small
Hi. :3 are you available rn? Because if so, I'm available too lol
Oh wait
Is this C++ tho?
yat
Also the majority of the code there is from a code only dedicated to changing the password that worked perfectly but I don't know why it does now
Doesn't now*
The other thing was..
Ah you see those prints
To debug
"Chau autenticacion"
Is the last one I see when running the code
I have no idea why the null ptr is there I tried to remove it but it doesn't seem to be that and it could cause it not your work
Not to*
Ahh, that makes a lot more sense
Though, MIFARE_Write really only uses 16 bytes, yeah.
bufferSize Buffer size, must be at least 16 bytes. Exactly 16 bytes are written.
Also for now the password isn't going to change but ofc in the future when the basic part of that working it will
And yeah I don't remember since I did this long ago
Why I'm only verifying key A
But it worked, it's the key I need I guess because for sector 15 A has the right to write and read ig
huh
Well there's that, if it helped I could also bring here the code that does what modo maestro should and worked
aight, sounds good
I see almost no difference between the two aside from removing all the not necessary stuff like status code and so
For now because I can't advance if that function doesn't work but after that I need to do more
I have to wash my face and brush my teeth after that I'll look for the message where I explained RFID functionalities in my project
No, only for talking so we are prepared to code after school
Ah. :3
doesn't have the time to talk about architecture >-<"
(Also, you probably shouldn't talk about architecture with me either. : P I have extended 20 minute meetings into 1 hour in $WORK)
Here I'm done talking about the base functionality of the project and start talking about what the RFID would do
We aren't talking about architectue but for example what the code does what's the issue and so on
i would love to talk about architecture but i also i don't think i know enough to be interesting conversation 😔
So you can go there and see what the RFID is supposed to do so you understand the end goal of the code and in which stage are we
Close to finish if what's left isn't that hard
And later after you read that I can bring in the other code
so, you have an RFID card that lets you store data onboard?
just making sure i understood everything correctly
then you store a password on that card?
also you have somewhere a financial system, where that card acts as an identifier
this is the code to set that password on the card
and additionally there's a master password stored in the mega EEPROM that's set at first boot
More or less yes
Now we are making so that the master mode when the password is correct and the checking the password works so
It changes the password of the card read
To have the password that it's allowed in my project
So I don't change all of them manually via the other code
Honestly for me, with the financial system it was enough
My teacher wanted this
Took long enough to make work and I did it finally-
balance is in sector 60 as a 15-digit number (btw, that's potentially an issue—an int on an arduino Mega is 16 bits, and 10^15 is much greater than 2^15-1)
and then password is in sector 63?
We first have to make it so when in master mode, passwords in sector 15 are changed that doesn't happen now, then the error handling and finally the work with EEPROM so the user can set it's own password and change it
If I run the code and run master mode
I see this
¿Quiere acceder al modo maestro u operar normal?
1-Modo Maestro
2-Modo Normal
¿Quiere cargar plata, comprar o verificar su saldo?
1-Cargar Plata
2-Comprar
3-Ver estado de saldo
Apoye su tarjeta para ver su saldo
Su saldo actual es 0
¿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
1111111111111111111111111111111111 chau if's chau variables chau autenticacion
It get's stuck at the null ptr part
Ah yes that time I got first the the normal one
Then master
Now if you want I can show you the change password in one sector code that works
sure
yeah, if it's only getting to 'chau autenticacion' something weird is going on
there don't seem to be any divergence points there
#include <MFRC522.h>
#include <SPI.h>
#include <stdarg.h>
#define RST_PIN 5
#define SS_PIN 53
MFRC522 mfrc522(SS_PIN, RST_PIN);
void mostrarByteArray(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
void imprimir(char *format, ...) {
const byte size = 500;
char buffer[size];
va_list args;
va_start(args, format);
vsnprintf(buffer, size, format, args);
Serial.print(buffer);
va_end(args);
}
void setup() {
MFRC522::MIFARE_Key keyA = {keyByte : {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5}}; //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
MFRC522::MIFARE_Key keyB = {keyByte : {0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5}}; //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
Serial.begin(9600);
while (!Serial);
SPI.begin();
mfrc522.PCD_Init();
imprimir("%s\n%s\n%s",
"Acerca la tarjeta al lector para escanear.",
"Las claves de esta tarjeta deben ser:",
"Key-A: "
);
mostrarByteArray(keyA.keyByte, MFRC522::MF_KEY_SIZE);
Serial.print("\nKey-B: ");
mostrarByteArray(keyB.keyByte, MFRC522::MF_KEY_SIZE);
imprimir("\n%s\n%s\n",
"MUY IMPORTANTE: durante el proceso de actualización de las claves ",
"no separes la tarjeta del lector hasta que no termine."
);
MFRC522::MIFARE_Key nuevaKeyA = {
keyByte : {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}//0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5
};
MFRC522::MIFARE_Key nuevaKeyB = {
keyByte : {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}//0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5
};
const byte sector = 15;
Sorry I got mixed because of the annoying word limit of discord
Let me think were was I at
for (;;) {
if (!mfrc522.PICC_IsNewCardPresent()) {
continue;
}
if (!mfrc522.PICC_ReadCardSerial()) {
continue;
}
Serial.print(F("UID de la tarjeta:"));
mostrarByteArray(mfrc522.uid.uidByte, mfrc522.uid.size);
boolean resultado = cambiarKeys(&keyA, &keyB, &nuevaKeyA, &nuevaKeyB, sector);
MFRC522::MIFARE_Key *keyAToPrint = resultado? &nuevaKeyA : &keyA;
MFRC522::MIFARE_Key *keyBToPrint = resultado? &nuevaKeyB : &keyB;
imprimir("%s %d\n%s",
"Claves del sector", sector,
"Key-A: "
);
mostrarByteArray(keyAToPrint->keyByte, MFRC522::MF_KEY_SIZE);
Serial.print("\nKey-B: ");
mostrarByteArray(keyBToPrint->keyByte, MFRC522::MF_KEY_SIZE);
Serial.println();
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
Serial.println(F("Proceso finalizado. Ya puedes retirar la tarjeta del lector RFID"));
}
}
boolean cambiarKeys(MFRC522::MIFARE_Key *antiguaKeyA,
MFRC522::MIFARE_Key *antiguaKeyB,
MFRC522::MIFARE_Key *nuevaKeyA,
MFRC522::MIFARE_Key *nuevaKeyB, int sector) {
MFRC522::StatusCode estado;
byte bloqueTrailer = sector * 4 + 3;
byte buffer[18];
byte size = sizeof(buffer);
imprimir("\nModificando sector: %d\n", sector);
estado = mfrc522.PCD_Authenticate(
MFRC522::PICC_CMD_MF_AUTH_KEY_A, bloqueTrailer, antiguaKeyA,
&(mfrc522.uid)
);
if (estado != MFRC522::STATUS_OK) {
Serial.print(F("Fallo en la autenticación Key-A: "));
Serial.println(mfrc522.GetStatusCodeName(estado));
return false;
}
Serial.println(F("Información en el sector: "));
mfrc522.PICC_DumpMifareClassicSectorToSerial(
&(mfrc522.uid), antiguaKeyA, sector
);
Serial.println();
imprimir("Leyendo datos del bloque %d...\n", bloqueTrailer);
estado = mfrc522.MIFARE_Read(bloqueTrailer, buffer, &size);
if (estado != MFRC522::STATUS_OK) {
Serial.print(F("Fallo al leer el bloque: "));
Serial.println(mfrc522.GetStatusCodeName(estado));
return false;
}
imprimir("Información en el bloque %d:\n", bloqueTrailer);
mostrarByteArray(buffer, 16);
Serial.print("\n\n");
estado = mfrc522.PCD_Authenticate(
MFRC522::PICC_CMD_MF_AUTH_KEY_B, bloqueTrailer,
antiguaKeyB, &(mfrc522.uid)
);
if (estado != MFRC522::STATUS_OK) {
Serial.print(F("Fallo en la autenticación Key-B: "));
Serial.println(mfrc522.GetStatusCodeName(estado));
return false;
}
if (nuevaKeyA != nullptr)
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
buffer[i] = nuevaKeyA->keyByte[i];
if (nuevaKeyB != nullptr)
for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++)
buffer[i + 10] = nuevaKeyB->keyByte[i];
estado = mfrc522.MIFARE_Write(bloqueTrailer, buffer, 16);
if (estado != MFRC522::STATUS_OK) {
Serial.print(F("Fallo al escribir el bloque Trailer: "));
Serial.println(mfrc522.GetStatusCodeName(estado));
return false;
}
return true;
}
Ok done
As you will see I only used the relevant parts in modo maestro
But maybe I missed something I didn't think it was important
differences:
PICC_CMD_MF_AUTH_KEY_Bin the second PCD_Authenticate
I didn't see any other differencees that would seem to be significant
See? I don't know why it doesn't work
you said earlier that you purposefully changed that to PICC_CMD_MF_AUTH_KEY_A?
And it was the best authentication at least
It would have to pass the first check for null an that
But not the B one
But not even that
oh, actually
the code you just posted turns 0xC0C1C2C3C4C5 -> 0xFFFFFFFFFFFF & 0xE0E1E2E3E4E5 -> 0xFFFFFFFFFFFF, whereas your code does the opposite?
That's a small detail I just change the passwords because
Testing
If I already changed the base for mine
I can't do it again
So I changed back to default
That's why there's a comment next to declaring the passwords
Show the code to the teacher and test it myself
It works either way
And the card I'm using has the default password I checked lots of times
Anyways I need to go have lunch
aight, i'll read skim the spec rl quik
also, i'll probably be going to sleep in the next hour or two
like, read through something quickly and briefly?
Ohhhhh, one other huge difference, actually
The code that works—it does MIFARE_Read into the buffer before it does MIFARE_Write on the buffer
The for loops only set bytes 0-5 and then 10-15 (which are KEY_A and KEY_B, respectively)
If the MIFARE_Read occurs first, that means that bytes 6-9 will be initialised properly (these are access control bytes, by the way)
However, in the one you wrote, because you removed the MIFARE_Read, bytes 6-9 are just whatever was floating around in the Mega's memory
which means the access control bytes were getting set to (basically) random junk
I'm not entirely clear on what issues you were having with this system but I imagine that could easily cause problems
Also, reading the spec on the access bytes
Remark: With each memory access the internal logic verifies the format of the access conditions. If it detects a format violation the whole sector is irreversibly blocked.
I'm not sure if the library or the RFID card do any validation on writes to the trailer blocks, but if they don't, sector 15 might just be nonoperable at this point
to test this, maybe retry the code that originally worked, but using, say, sector 14 instead of sector 15
I'm not 100% sure what exactly constitutes a format violation, but there's a number of redundancies/duplications in the access control format, so if those copies don't all match that might qualify as a violation, which would be fairly likely if you write random data to those bytes
i will note that i'm still somewhat confused about what exactly the two different keys do, so that may have something to do with something or not
Other notes:
PCD_Authenticate(PICC_CMD_MF_AUTH_KEY_A, &keyB, &(mfrc522.uid)would fail to authenticate if keyA wasn't the same as keyB
- Before you do anything else, change the length of user_password from 6 to 7; that's actually potentially a huge issue; i talked a bit about that in the message this message is replying to
From this (https://www.mouser.com/datasheet/2/302/MF1S503x-89574.pdf) document, page 11, section 8.7.1 Access Conditions
Anyway, it is late and I'm getting off my computer; i'll probably be available sporadically (discord on phone) for possibly up to the next hour
It's confusing but it seems for what I remember that depending the sector each key gives permission for different things like only read, read/write and so
You sure it's necessary? Because it works perfectly fine if get any other password or not exactly that one it says incorrect if I type char by char the password it says correct
For what I read, I need to read the keys with mifare read before I ask for them or smth like that? I don't remember why there was a read there I guess I will just copy it before the null ptr question and after verification
Because of the final '/0'?
Yep
Ok I will change that
What I'm more interested in is that of the mifare read because that could be it
That 0 could be overwriting something important; it's a bit of a long shot but there's a very small possibility that it's causing the whole "stop after chau autenticacion" issue
I don't see why because it is only for the password
And the password passes
After that it isn't relevant
Because it's verifying the passwords on the sector and bla bla
User password and password are just to neglect entry
The issue is that \0 isnt being written to user_password, it's being written to whatever is one byte after it, which could frankly be anything
Again, might be nothing, might be something
But yeah, hopefully that can help you get moving again
mfrc522.MIFARE_Read(bloqueTrailer, buffer, &size);
Maybe by writting this before the null ptr check
As you said it was missing
After PCD_Authenticate, before any modifications to buffer
Also, i would strongly recommend that you do like the original code and put in at least the stuff that dealt with error handling
But when I finish this and I move it to the original project I can't do that error handling with the lcd
It should work by it's own without the debbugin tools
That way, if, say, the read fails, it can detect the error and abort the attempt, rather than write possibly invalid data which would kill the sector
After any try I read the card again to see if anything changed
And it didn't for any reason
Any ways likely that's the error because in the if's I change the information in buffer and after them write it to the sector but I never got the buffer with the information first
I mean, you can just return from the function with an error value and print "Ocurrio un error, oprime 1 para continuar, o 2 para reintentar" to the lcd
That doesn't explain at all why it didn't just write whatever and took what was in the buffer or whatever but
This may solve it or at least take us a step further
What do you mean?
I get that it didn't work because originally I should read from the trailer sector to get the access bits we don't know about and then only re write the passwords and pass it to mifare write
I get that what I don't get
It's why didn't it work, badly but worked
With whatever data buffer had
Maybe because we didn't have the access bytes in the middle
That's why we read it in the first place
We know that passwords but not the access bits
Anyways I need to prepare to go to school when I come back I can try adding the read and see what happens
Yeah, it might even be that sector 15 is still working fine, too, and it's just that the writes have been failing all this time
(Maybe the chip verifies the access bits before actually writing, and's it's just been silently erroring)
Yeah that makes sense
Maybe with just that we solved the first issue I hope so
If we did what's next is the error handling
Basically
If you try to read a card that already has the correct password and doesn't need to change it will say "this card it's already available for use" Or something and go back to the menu
Probably it would be something like try on the read, throw if the password read is the one we are trying to change it to, and catch and print that the card is available and return or whatever
Something like that
I don't know error handling in cpp so I'm just saying
For error handling, I'd go with returning true/false, or if you need more information, returning an integer error code (or an enum value error code)
When i last checked, arduino disabled exception handling by default, i think (exceptions = try/throw/catch), because exceptions involve a lot of hidden code being generated under the hood, which isn't great when you're working in embedded environments with strict resource limits like arduino
What I need is that when you enter master mode to change the base password
If it doesn't have the base password and it has the password that my project accepts
Basically if you pass the card a second time
It detects it and says
This card is already good and goes back if not I would get stuck
But it won't be only true or false