#Arduino Help
1 messages · Page 4 of 1
A new weird family of unreleated errors appeard
Feel like it's messing with me
Ah wait
No
Lcd is mutable
And also in the signature of the function says it's a mutable reference
And why wouldn't that pop up until now anyways
remove those &mut also
in lcd?
Ok unless analyzer it's taking it's time
No more errors
Just warnings
Says serial is unused
Which is fairly true as I stated
This was trying to borrow the borrow
So I will remove it from the signature
aka &mut &mut T
Because we already defined lcd to be a mutable borrow?
yeah
so we don't need to borrow it again in the function
Actually only in last one where I don't call read_char
It calls my attention it says read_char is never used
When it is inside the functions
The other functions yeah they are never used still
So now ima finally
Replace the code in main with this functions
And see if it works
What
Show drinks have nothing else
Btw I tried the &mut on each one also
Bruh
Says it doesn't found it in scope
But
There's the module imported
Oh
Don't tell me
Use create
oh, prepend lcd::
Crate*
or a use lcd::*;
Wouldn't it clash with the other?
Maybe we should just rename the lcd dependency to something else
This is a pain
It did
The use crate worked but it says
In don't use it
Any idea?
did you make show_drinks a pub fn ...

Ok done
step #1 of my Gentoo spring cleaning, sudo has now been replaced by doas
With all
Finally it seems..
Let me run cargo check
Yeaaag
Now I'mma test it
It takes it's time to answer to my commands tho
But it works aside from that
Now finally
Let's talk about that state machine
I'm curious about this good practice
When I should do a state machine, why I could have problems with state, and why is it better? And you know that
A state machine is very useful in embedded systems because the system is usually sitting there waiting/doing something then it gets some input and reacts to it then goes back to the default state.
A state machine allows you to manage the state (data) and transitions between states in a formalized way
It's just for human readability or could states go out of control?
Well as you already have it you have a few loops and a few match statements this would combine them all together into a unified system
What I understood is that my programms has a default state, then by calling a function, receivimg an order it changes state, and then goes back to defaull, tracking what the current state of the program is could be problematic and I could do a state machine to manage which state it's in and what it should do in it and change to another or smth, like make the states apparents
yep
This should help a lot with the RFID stuff also as you can manage the states for that
We will implement it in a new module?
sure
Rfid is gonna be such an adventure..
probably a good idea
sure, sounds good
k, first step is to make a
enum State {
...
}
Actually I got mixed up and I had such a mess in my Arduino rfid code so maybe it's because of that
You should make a variant in the enum for each state you want the micro controller to have right now (try to match the current code)
yep
This enum isn't set in stone, so you can change it later if you need to
Default_state
Drink_selection_state
Intensity_selection_state
Waiting_state
Then back to default
How I defined the variants inside the enum?
Why isn't default there?
I thought if I used snake case for something I should for everything tho I saw cammel case more fitting
You are right I think is fine that way
Rust uses different cases for different things
Now we probably want some data to go with it
struct App {
state: State,
...
selected drink?
selected intensity?
}
Both of these can also be enums
Mmmm? What kind of data?
as you just have 3 options on screen
What to do in that state?
I would make them enums with the same names (or short versions) of that the menus have on them
this data will exist for all states
I don't get what data should follow
And what are the next enums about
Are we making enums for enums?
enum Drink {
OptionA,
OptionB,
OptionC,
}
as example
Oh so the options of the menu when it's in each state
I don't get yet why we want that but sure I'll do so, I guess only for select drink and intensity because dispensing does only waiting and the other is merely waiting for something to happen
enum Drink {
OptionA,
OptionB,
OptionC,
}
enum Intensity {
Strong,
Medium,
Weak,
}
Only these two ig
I would name the drink options the actual names
I would not because their names are just temptative, kinda placeholders because is a bartender but we are kinda gonna test it with water and colorants
so i made this place holders as well
Oh okay
So now
struct App {
state: State,
selected_drink: Option<Drink>,
selected_intensity: Option<Intensity>,
}
You lost me a little bit
So I create a struct
Tha has as fields
The state of my program
So I can set it and change it
And
fields for the drink and intensity that I guess would be stored in my struct as my program goes because is info I need
And it's wrapped in the options enums because it can be null for example at the start of the program
I got it right?
yep
Tho shouldn't we call it something else?
Tho I'm thinking what
Let's see it stores the drink, intensity and state of the program..
I was thinning maybe of barman/bartender because that's what's the code about but I had that name for a function in the original that I want to ofc do here too
Tho Bartender could be this struct's name and barman that name's function
Or don't better likely
So you like Bartened or it isn't enough descriptive ?
Bartender*
That works, you get to pick the names
okay now it's common to have a function like
impl Bartender {
pub fn update(&mut self) {
...
}
}
that we will call in a loop so it can automatically update it's state
Oh
So not a new function but rather and update one?
And how do me generalize that it changes to the next state? Or are we doing and update for each one?
"New"*
We will have a new function also
So a new function and then an update function I see
Now because we have the state we can call helper methods to do each state's "stuff" (like printing to the screen or checking for user input)
pub fn update(&mut self) {
match self.state {
State::Waiting => self.do_waiting(),
...
}
}
fn do_waiting(&mut self) {
...
}
What are considered helper functions?
I usually think of any function/method that is not pub a helper function, but there isn't a solid definition
Oh ok
.
I am unsure what the question is
Like
We have an update function
That changes the current state
To the next
But
How do me make so it updates always to the next, because it would like something generic that could be called it doesn't matter the state
ah
fn do_waiting(&mut self) {
// print to screen
// wait for user input
self.state = State::SelectDrink;
}
after the state is set the update method returns, and then the main will call update again with the new state
I think I more or less get it
So how do I start update , I set it to waiting or ask the state?
This is a basic version of a state machine. there are more complex ways to set them up, but this should do for now
You don't do anything in update except match and run the helper for the state
yep
So I call our functions defined in lcd?
yep, we can add lcd and serial to the Bartender struct so you have them
And if it matchs to waiting I merely update to SelectDrink?
Well that's an interesting question. Is waiting an actual state? Now that I think about it don't you just have the select drink screen as the "default" screen?
Yes, when it starts it goes to that screen
So maybe we remove the Waiting state
that works
when the state is done (whatever that means for each state) you set a new state (or the same one) and return
So
When it matches select drink
I call show_select_drink
And then return state as select_intensify?
yep
Ok I am going to try to do update and show it to you
What this structure lets you do is change/add to the states and the transitions between them without having to redo all your code
I don't know why I would need them?
How do you accept auto completion?
well how else are you going to print stuff to the lcd 
Because here in grey is what I want to write
But I don't know to tell it, yeah that is, write it
usually its Tab then enter
Doesn't calling the functions do the work?
but you need to pass them to the functions
fn do_select_drink(&mut self) {
write!(lcd, "test"); // lcd doesn't exist here
}
So how do I re write the struct?
Btw here is update
impl Bartender {
pub fn update(&mut self) {
match self.state {
State::SelectDrink => {
show_drinks(&mut lcd, &mut serial);
return State::SelectIntensity;
}
State::SelectIntensity => {
show_intensity(&mut lcd, &mut serial);
return State::Waiting;
}
State::Waiting => {
show_waiting_screen(&mut lcd);
return State::SelectDrink;
}
}
}
}
struct Bartender<Serial> {
...
lcd: Display<LcdConnection>,
serial: Serial,
}
I think would be a good start
Ah lifetimes..
I mean I ain't against I should learn how to use them
But also yeah why not give ownership
I don't think they would actually help here
It's update good?
you can do self.show_drinks() now that lcd and serial are inside of the Bartender struct
But don't I have to pass them as parameters still?
if they are methods they can have a &mut self which lets you do self.lcd or self.serial in the method
Wait so now show_drinks became a method of my struct?
So since it's now a function from my struct and also a reference from an owned value of the struct it can do it's stuff?
yep
But it's now a method because is in the impl block right?
Because if inside the impl block I do that it seems like it hasn't been declared a method yet to use it that way in update
Or well idk I got a little bit confused
Any function in a struct's impl becomes a method of the struct
I get that
But
I'm treating as a method before making it such?
Or is it like the both steps are done at the same time?
both done at the same time
impl Bartender {
pub fn update(&mut self) {
match self.state {
State::SelectDrink => {
self.show_drinks();
return State::SelectIntensity;
}
State::SelectIntensity => {
self.show_intensity();
return State::Waiting;
}
State::Waiting => {
self.show_waiting_screen();
return State::SelectDrink;
}
}
}
}
So it's update done now?
instead of returning the state, inside of each method (show_drinks, ...) have it do self.state = State::...;
Oh like
Setting it's new state itself
impl Bartender {
pub fn update(&mut self) {
match self.state {
State::SelectDrink => {
self.show_drinks();
self.State = State::SelectIntensity;
}
State::SelectIntensity => {
self.show_intensity();
self.State = State::Waiting;
}
State::Waiting => {
self.show_waiting_screen();
self.State = State::SelectDrink;
}
}
}
}
Finally (?
I would put the self.state lines in the methods, not in update
I didn't understand that
The state transitions can happen anywhere you want, but it would make sense that the code handling each state would perform the transitions when needed from that state
So you say that
I go to the definitions of show drink and bla bla
And add that last line I added in each arm at the end?
And just that? Will the function understand in it's context defined in other module what's self?
you should put the definitions for those in the file with the Bartender struct
in an impl Bartender {}
So lcd Module will die?
Because all it has is that functions and the read char that they need
well it will have the LcdConnection
That one is in the I2C module
oh, hmm
you could keep them in there, but just the logic to display to the screen. Then move the read char to the methods on the Bartender
Tho I won't kill it I'll leave it for the last function which is planned to be done at the end but what I was saying is if I copy and paste all the module lcd to state with few changes
I don't understand at all
So..
I move read_char to a impl block for Bartender in state module and that's it?
Mm?
// === main.rs
fn main() {
// setup pins
// setup lcd
// setup serial
let mut bartender = Bartender::new(lcd, serial);
loop {
bartender.update();
}
}
// === i2c.rs
pub struct LcdConneciton {
...
}
...
// === lcd.rs
pub fn show_select_drinks(lcd: &mut Display<LcdConnection>) {
write!(lcd, ...);
...
}
pub fn show_select_intensity(lcd: &mut Display<LcdConnection>) {
write!(lcd, ...);
...
}
pub fn show_waiting(lcd: &mut Display<LcdConnection>) {
write!(lcd, ...);
...
}
// === state.rs
enum State {
SelectDrink,
SelectIntensity,
Waiting,
}
enum Drink {
...
}
enum Intensity {
...
}
struct Bartender<Serial> {
state: state,
selected_drink: Option<Drink>,
selected_intensity: Option<Intensity>,
lcd: Display<LcdConneciton>,
serial: Serial,
}
impl<Serial> State<Serial> where Serial: Read<u8> + Write<u8> {
pub fn new(lcd: Display<LcdConnection>, serial: Serial) -> Self {
Self {
state: state::SelectDrink,
selected_drink: None,
selected_intensity: None,
lcd,
serial,
}
}
pub fn update(&mut self) {
match self.state {
State::SelectDrink => self.do_select_drink(),
State::SelectIntensity => self.do_select_intensity(),
State::Waiting => self.do_waiting(),
}
}
fn do_select_drink(&mut self) {
lcd::show_select_drinks(&mut self.lcd);
match read_char(&mut self.serial) {
'1' => { self.selected_drink = Some(Drink::OptionA) },
'2' => { self.selected_drink = Some(Drink::OptionB) },
'3' => { self.selected_drink = Some(Drink::OptionC) },
}
self.state = State::SelectIntensity;
}
fn do_select_intensity(&mut self) {
lcd::show_select_intensity(&mut self.lcd);
match read_char(&mut self.serial) {
'1' => { self.selected_intensity = Some(Intensity::OptionA) },
'2' => { self.selected_intensity = Some(Intensity::OptionB) },
'3' => { self.selected_intensity = Some(Intensity::OptionC) },
}
self.state = State::Waiting;
}
fn do_waiting&mut self) {
lcd::show_waiting(&mut self.lcd);
...
self.state = State::SelectDrink;
}
}
fn read_char(serial: &mut (impl Read<u8> + Write<u8>)) -> char {
...
}
That is the idea for the layout (That was a lot of typing to do from memory 😥 )
This is aren't the exact name of my functions but I suppose you wanted to show that the function definitions I made in lcd module stay in lcd module except read_char
Now with that
yeah, the layout is the important part, the names can be whatever
I struggle to understand the last message for example the first impl block with some many serials and stuff but I think I might slowly get it
Ok so
The <Serial> is a generic so we don't have to name the actual type
You make an impl block for State which takes a generic Serial that implement the traits we saw before , and then creat the new function which takes ownersgip of lcd a serial and returns an instance of self, with state in select drink, selected drink none, intensity none and the ownership of serial and lcs
Lcd*
Tho
I think you meant
An impl for the struct bartender
My brain is starting to turn to mush 🧠
oh yeah I got the struct wrong 🤦♂️
It's normal too much text you much to remember
You don't have the code in front of you
8 hours of python + debugging gentoo is not a good combo 
It would be so nice if you could have the code to see like a vs file or smth
I can do that if you want
ah, yeah. I would do a shared session even
I feel like I should have thought of that before this 
I think I need to sleep now
you too, hope i was helpful 💤
And tomorrow there's only one thing left so finally.. Finally.. Lcd can be done
Also.. I'll try to buy or get an usb
So you know we do all the preparation so I can actually take this to school and test, show, keep programming
That's important
More than helpful you are really nice and hardworking like if you were a paid tutor
I like helping people but I don't know if I would get that far
But I think having met people like you I need to return that kindness for the world.
to the*
I have a hard time explaining things, so I practice by helping on this discord
Anyhow, I hope I can get an usb or I'll have to wait a whole week to show this -
I think you do it pretty alright also teaching something helps learning it better and showing to yourself how much you really know, I think it's so cool
thanks
Now get your deserved sleep I'll try this say whenever I made it or what happened and finally go to sleep too.
I hope I make it
Well I had one problem
How weird
For a weird reason
It doesn't find the module or smth
So display, the functions etc can't be used
I don't understand because I have just the same use statements in the other modules and this didn't happen so it doesn't make any sense
You see some extra uses in that photo that was in case that could work
I tried like in the lcd I had a similar problem with i2c
Just use the use crate statement
Didn't work
As you refer to lcd:: directly in some cases
Use only mod
Also didn't work
Add nothing, also didn't work
It's so frustrating
Why won't importing a module in the same folder work or have problems randomly
It just doesn't make sense and I tried anything that made even the slightest of sense and nothing-
And even if I couldn't import the module functions are public and I called them with lcd::
It's just dumb
Actually in the others I didn't need to import the modules and just use
use crate ::lcd::* for example
But he says unused import
Ok I solved part of it
It kinda overlapped when you did
Lcd::show for example
With me using crate:: lcd and etc
But for any reason you couldn't use lcd:: without importing anything?
It's weird
And it's a shame because not only it looked good and I liked it
But also it made it clear to you where to look for that function
Ok..
In the state crate
I listened to the compiler an added this
use crate ::lcd::*;
use crate::LcdConnection;
use embedded_hal::serial::{Write, Read};
use lcd::Display;
Idk why because in lcd they are but as long as it works
Then
The Match expressions it said they were non exhaustivr
So I made the _ catch all and return and empty touple because I think it will never happen so, only to make the compiler happy
Also you made a slightly mistake
But ofc of memory so it's fine
In the match read char of intensity you used as Variants again option a b and c
And it was strong medium weak
Also for some reason
The compiler told me
Hey serial doesn't have to mutable
And I said well if you say so
And now finally..
No more errors..
Let's test it please work
Well again it's taking it's time to answer to my commands for some reason
The choose a valid number and drink not available in menu 1
Worked perfectly
But I pressed 1
I waited and it didn't change menu
Pressed 1 again and it did
Now here in select intensity
Pressed 3,nothing
Pressed 3 a second time, it worked it changed to waiting and came back
I will test it again to make sure but it seems like it works but for any stupid reason you have to insert two correct inputs but incorrect inputs work fine?
Yes that it's exactly what happens
It doesn't make sense
Maybe it has to do with the empty touple.. I don't think so mm..
Ah I see
You call in do show bla bla
Read char again
That happens it seems?
I'll try by matching to the variable I assign to the function, tecla, maybe it works
It says it doesn't find tecla in that scope tch..
The other solution is to call it in the match expression you do in do show drinks
And there match the variants of not available and so but..
It is really verbose and makes the original function less powerful
Well I really will get nothing of sleep so I better stop hear
I implemented what you showed me, make it so there were no errors nor warnings
Tested it, it mostly works except from one error I discovered exactly what it was
The only thing left is that we come up with a solution tomorrow
Oh no..
I didn't ask how big the pendrive should be
And today I have to buy one -
Damn it
I'm having troubles with getting an usb, we should've talked this more before -
The problem is I only have this subject on Wednesdays that makes it problematic because I have to wait a whole other week if I don't get it this time
@coral geyser quick, what usb so I need(?
I guess the only specific is size right?
Then it would up to how many GB I need at the very minimum
I wouldn't go below 8 Gb. As smaller ones are usually class c chips
Not sure how that translates to price
So whatever usb that has at least 8 GB would do?
Because then I see if I can buy a 16 GB one
Yeah, I don't think the install will be bigger than 8Gb
I'm only going to use for the rust setup and maybe saving codes there instead of sending them to myself via mail
Well then today we would have to do that so tomorrow I could start my rust journey at school and show how the rewriting is going
Is going to take long or is it easy?
It shouldn't be that hard to setup
Nice
Btw have you seen what happened yesterday?
Well I fixed all the errors but
Why they happened not entirely sure
Tho the thing that matters is the last that everything works but we are calling read_char two times, that's the only thing to fix idk why I could just have a inmutable borrow for tecla
Now that I think about it, you said you work with python what do you so?
I thought you worked as an embedded developer maybe
Tho with python ig is either data science(with is portion of machine learning and ai) or web development, unless you did embedded in the raspberry pi pico and choose to use micro python instead of Arduino ide or c++
Which I don't know why would you unless you hated them so much
Simulation systems for satellite control
It has a lot of data science
Finally home
Tho I'm gonna be busy from 21:30 to 23:30 (my hour ofc) because I have my python course
Class about inheritance
Aside from that ofc I'm free since tomorrow I'm presenting the rust alternative I want it to be as developed as possible
I have a borrowed pendrive
Are you available? Well if not just tell me when, if not eating or in the course I'll be
Today we finish the lcd once and for all
If I'm not*
Well eating finished so that's no longer something that could get in the way
But I start my class in. .
40 minutes
@coral geyser are you here for 40 minutes?
38*
yeah, i just got home
I have some plans later, not sure exactly when though
I hope god helps me and it's during those 2 hours (?
So what should we do first
The pendrive stuff so at least I can guarantee I'm taking something tomorrow
I would assume the flash drive as that seems important
Or continue with the little it's left
Ok but
What will we pass?
The paths and files or also the codes?
pass?
Because if the codes then it wouldn't be updated
To the pendrive
Oh we can make it so it just allows you to compile any cargo project
Well we will go through it
then if you update it you would just copy it over
Do I connect the usb?
yeah
go into the flash drive and make a folder called "rust_toolchain"
We will install it in there
in the file explorer
okay now go find the folder "C:/Users/[your user]/.cargo" in another file explorer window
No clue how to
copy the ".cargo" and ".rustup" folders over to the "rust_toolchain" folder you made
Well let's wait a little bit ig
cool, now I need to write a powershell script for you. As i don't think you want to memorize the setup you need to do to use it
Rust needs some stuff setup, like that PATH we originally did
Yeah that whole thing..
but so you don't have to do it every time, I can just make a script for it
Not only for rust but more so for Arduino hal
I have no clue how that works but thank you
Cargo it's at 25% of copying
I'm making the setup for my class in the meantime
Even tho I shouldn't if possible I would try to you know continue working on rust at the same time or smth
Yeah some have vs code and also arduino ide
Tho I wouldn't have my extensions ofc
72%
Takings it's time
Well my class it's about to start but at the very least I'll try to completely pass the folders
98% cargo
And well when those two are done I tell you to see if I can continue even in class
The state problem should be easily solved
Cargo has been passed
Next up rustc
Rustup*
Wow so many elements..
Just how heavy is all this-
It should come to about 0.5Gb to 0.8Gb
1.09 GB said rustup
I didn't see cargo
Just for curiosity
What's next after this?
Because
yeah, it gets bigger the more you use cargo/rustup
I guess this would allow me to code rust in vs code
But Arduino_Hal
It's another story
I am double checking that part on my machine
I will let you know how it goes
Sure
Tho it will be weird only this does because you know that two hour install and all, having rust in nightly
I'm wondering if my internet went really slow merely because it's shit or this transfer is killing itn
62%
Eventually getting there
Well I have a break
Let's see how's doing
Idk why it's taking longer than cargo I thought cargo was more problematic
It's like installing it for the second time tho maybe slower
Well in the mean maybe we could try to solve the match issue ig or smth like that
We could do other stuff too but that would be seem that more reasonable
Aaand
My class is done
You know what also is done
Passing rustup and cargo to the pendrive
Finally
So what now?
Maybe also pass vs code to have my extensions? (Does that make sense?)
Or idk pass the Arduino hal file or idk
copy over the avr-gcc.exe file
Is it in the Arduino hal file?
Well answering to my on question no because I don't see it in there
That one that was in the path we defined?
(I went to environment variables to look for it)
Or the whole bin that contains it?
copy the whole bin folder over
Ok so bin folder from Arduino
Shouldn't I copy something from the Arduino hal like idk the specs or smth?
Done
was in a session of Startcraft 2, sorry for the delay
Np
So now copy over your project folder (the one with src/, Cargo.toml) to the usb drive but not in the rust_toolchain folder
just the main folder
I didn't understand
Because you said
Not in the rust_toolchain folder but
That's the only folder we created for the pendrive
copy it to the folder that the rust_toolchain folder is in
So I create another one?
Let's better go step by step first
Which of the two projects
The lcd one
Or the test one
the one you want for tomorrow
Well the lcd because it's the only one we have, now I can ask
So.
I would move
The current state of the program
And if we
Update it
I will need to erase the one from the pendrive and do it again?
Tho I could also send me via mail the changes and copy paste or smth like that but aside from whatever I do to fight I want to know that
Which also applies to when in school I make it better ofc
You could either copy it and edit the copied version, or edit the version on the usb drive
It will be able to have more than one project on the usb drive at a time
Well for now we have only one project so
You teel me to
Grab my
"rust_lcd" Folder
Which has the src, specs, target,cargo, lock bla bla
And also copy it
But not in in the folder we made
Called rust_toolchain
But rather outside
Right?
yes
So I guess I would need this from every project
Tho there won't be that many
Lcd is almost done and when it is,matricial keyboard will have it's own which will be short, and the next is the base functionality of the project, then one only for the rfid and finally the final version of the project
Is there any more steps to the set up for tomorrow?
I need to get you the script so we can test using the usb drive
Well I was going to ask you if that was all how I you know entered and use it when I'm at the school and all
Well when the copy of the folder is complete I'll tell you
I guess for changes to the programm
I will pass myself the code via mail
And replace the current one
I will have to install the vs code extensions in that PC every Wednesday tho
But well
The script will be the last step?
I think so
Well in the meantime
Let's see or think
How could we solve the problem of logic the program currently has
I still don't know why my original solution didn't work, it made complete sense, and the alternatives I thought of aren't that pleasant
what was the behavior again (you can just link me the message if you want)
.
Here I tested when finally got rid of the errors
Do you have any delay_ms in the code?
Like in which part?
I have all the code copied here in discord (?
If you wanna check any module
In particular
Tho as I said for me it's because we are calling read twice first in the function second in the match
Which part was that in?
In the state module you made it so matching what read returns it changes the state, the problem is you called the function before to show the particular menu and it also uses that function so I needed to correct inputs to break out
I'll show you state.rs
use crate ::lcd::*;
use crate::LcdConnection;
use embedded_hal::serial::{Write, Read};
use lcd::Display;
enum State {
SelectDrink,
SelectIntensity,
Waiting,
}
enum Drink {
OptionA,
OptionB,
OptionC,
}
enum Intensity {
Strong,
Medium,
Weak,
}
pub struct Bartender<Serial> {
state: State,
selected_drink: Option<Drink>,
selected_intensity: Option<Intensity>,
lcd: Display<LcdConnection>,
serial: Serial,
}
impl<Serial> Bartender<Serial> where Serial: Read<u8> + Write<u8> {
pub fn new(lcd: Display<LcdConnection>, serial: Serial) -> Self {
Self {
state: State::SelectDrink,
selected_drink: None,
selected_intensity: None,
lcd,
serial,
}
}
pub fn update(&mut self) {
match self.state {
State::SelectDrink => self.do_show_drinks(),
State::SelectIntensity => self.do_show_intensity(),
State::Waiting => self.do_show_waiting_screen(),
}
}
fn do_show_drinks(&mut self) {
show_drinks(&mut self.lcd, &mut self.serial);
match read_char(&mut self.serial) {
'1' => { self.selected_drink = Some(Drink::OptionA) },
'2' => { self.selected_drink = Some(Drink::OptionB) },
'3' => { self.selected_drink = Some(Drink::OptionC) },
_ => (),
}
self.state = State::SelectIntensity;
}
fn do_show_intensity(&mut self) {
show_intensity(&mut self.lcd, &mut self.serial);
match read_char(&mut self.serial) {
'1' => { self.selected_intensity = Some(Intensity::Strong) },
'2' => { self.selected_intensity = Some(Intensity::Medium) },
'3' => { self.selected_intensity = Some(Intensity::Weak) },
_ => (),
}
self.state = State::Waiting;
}
fn do_show_waiting_screen(&mut self) {
show_waiting_screen(&mut self.lcd);
self.state = State::SelectDrink;
}
}
pub fn read_char(serial: &mut impl Read<u8>) -> char {
loop {
if let Ok(current_char) = nb::block!(serial.read()) {
let current_char = current_char as char;
if current_char != '\n' && current_char != '\r' {
return current_char;
}
}
}
}
why does show_drinks need serial?
Because it needs to see what you pressed to or show, unvalid input, drink not available or either break the loop an end the function
Do you want to see the definition of the function?
yes
use crate::i2c::*;
use crate ::state::*;
use ::lcd::*;
use embedded_hal::serial::{Write, Read};
use core::fmt::Write as _;
pub fn show_drinks(lcd: &mut Display<LcdConnection>, serial: &mut (impl Write<u8> + Read<u8>)) {
loop{
lcd.display(
DisplayMode::DisplayOn,
DisplayCursor::CursorOff,
DisplayBlink::BlinkOff);
lcd.position(3, 0);
write!(lcd,"Elija una bebida").unwrap();
lcd.position(1, 1);
write!(lcd, "1-Fernet con Coca").unwrap();
lcd.position(1, 2);
write!(lcd, "2-Sex on the beach").unwrap();
lcd.position(1, 3);
write!(lcd, "3-Agua").unwrap();
let tecla = read_char(serial);
match tecla as char {
'1' => break,
'2' | '3' => {
lcd.clear();
lcd.position(3, 0);
write!(lcd, "Bebida").unwrap();
lcd.position(3, 1);
write!(lcd, "No disponible").unwrap();
arduino_hal::delay_ms(1000);
},
_ => {
lcd.clear();
lcd.position(3, 0);
write!(lcd,"elija un").unwrap();
lcd.position(3, 1);
write!(lcd,"valor valido").unwrap();
arduino_hal::delay_ms(1000);
},
}
}
}
pub fn show_intensity(lcd: &mut Display<LcdConnection>, serial: &mut (impl Write<u8> + Read<u8>)) {
loop{
lcd.clear();
lcd.position(0, 0);
write!(lcd,"Elija la intensidad").unwrap();
lcd.position(1, 1);
write!(lcd, "1-Suave").unwrap();
lcd.position(1, 2);
write!(lcd, "2-Medio").unwrap();
lcd.position(1, 3);
write!(lcd, "3-Fuerte").unwrap();
let tecla = read_char(serial);
match tecla as char {
'1' | '2' | '3' => break,
_ => {
lcd.clear();
lcd.position(3, 0);
write!(lcd,"elija un").unwrap();
lcd.position(3, 1);
write!(lcd,"valor valido").unwrap();
arduino_hal::delay_ms(1000);
},
}
}
}
pub fn show_waiting_screen(lcd: &mut Display<LcdConnection>) {
loop {
lcd.clear();
lcd.position(3, 1);
write!(lcd,"Preparando...").unwrap();
lcd.display(
DisplayMode::DisplayOn,
DisplayCursor::CursorOn,
DisplayBlink::BlinkOn);
arduino_hal::delay_ms(10000);
break;
}
}
Finally
ah these should be
pub fn show_drinks(lcd: &mut Display<LcdConnection>, serial: &mut (impl Write<u8> + Read<u8>)) {
lcd.display(
DisplayMode::DisplayOn,
DisplayCursor::CursorOff,
DisplayBlink::BlinkOff);
lcd.position(3, 0);
write!(lcd,"Elija una bebida").unwrap();
lcd.position(1, 1);
write!(lcd, "1-Fernet con Coca").unwrap();
lcd.position(1, 2);
write!(lcd, "2-Sex on the beach").unwrap();
lcd.position(1, 3);
write!(lcd, "3-Agua").unwrap();
}
where the
'2' | '3' => {
lcd.clear();
lcd.position(3, 0);
write!(lcd, "Bebida").unwrap();
lcd.position(3, 1);
write!(lcd, "No disponible").unwrap();
},
_ => {
lcd.clear();
lcd.position(3, 0);
write!(lcd,"elija un").unwrap();
lcd.position(3, 1);
write!(lcd,"valor valido").unwrap();
},
(notice I removed the delay_ms from these)
are 2 more functions that the
match read_char(&mut self.serial) {
'1' => { self.selected_drink = Some(Drink::OptionA) },
'2' => { self.selected_drink = Some(Drink::OptionB) },
'3' => { self.selected_drink = Some(Drink::OptionC) },
_ => (),
}
code will run
match read_char(&mut self.serial) {
'1' => { self.selected_drink = Some(Drink::OptionA) },
'2'|'3' => {
show_error();
delay_ms(20000);
},
_ => {
show_invalid_drink_error();
delay_ms(20000);
},
}
Notice on an error we don't change states
I got kind of lost
So first you removed the tecla = read_char(serial) part and begginning of match so I don't end the loop now and I can't match to 2 and 3
Yeah I really got lost
These shouldn't have loops in them
They should just print to the lcd and return
Let's keep on with the pendrive when we are done we finish this or if there's another waiting for it to copy
Oh
Ok I can get that part.
But
But here you match something without a match
And also since it isn't in a loop
Would it come back to ask again or you get it wrong?
After lcd position there's only 2 | 3 no match, no variable that could be that it's like missing a half
If state.rs doesn't change the state on a bad answer then the same state gets repeated again
I was pointing out which part of the code I was talking above
So..
First
I remove the loops from the functions
Because the state will take care of what to do now
fn show_error(lcd ...) {
lcd.clear();
lcd.position(3, 0);
write!(lcd, "Bebida").unwrap();
lcd.position(3, 1);
write!(lcd, "No disponible").unwrap();
}
yes
Then
In both the show drink and selection
I maintain the match statement but
'1' would return no break
But 2 or 3 would stay the same
Right?
Oh no
You pointed that part to be replaced
So..
Show drinks and show intensity
I get rid of the loop
¿And also the match?
yes
It would just be the lcd printing the stuff and the match statement below would take care of answering for the user's input
in state.rs, yes
yes
To the second match expression there
And create a functions to print the error messages, right?
yes
yes
This one and the invalid drink one
And do show intensity and waiting would remain the same?
yes
Ok got it I'll try to change it
show intensity needs a similar thing done where you remove the loop and match from it
Yeah ofc that
On purpose or you forgot?
self.state = State::SelectIntensity;
On purpose
Why?
because we want to show the selection screen again
Oh
Ok I get it know
?
Tho doesn't this seem a function for the lcd module?
I tried put it in the impl block
Neither
I have no clue how to implement this function
run cargo check
Also we need to change the usb
we need to actually copy over the avr folder that bin was inside of
oh, the type is &mut Display<LcdConnection>
I didn't understood
Tried that it also didn't work
First outside or inside the impl block?
not in an impl block, and it should be in lcd.rs
Oh
Please explain again
the bin folder we copied to rust_toolchain wasn't enough for it to work
we need the folder that bin/ was in
this folder
fn show_error(lcd: &mut Display<LcdConnection>) {
lcd.clear();
lcd.position(3, 0);
write!(lcd, "Bebida").unwrap();
lcd.position(3, 1);
write!(lcd, "No disponible").unwrap();
}
fn show_invalid_drink_error(lcd: &mut Display<LcdConnection>) {
lcd.clear();
lcd.position(3, 0);
write!(lcd, "Bebida").unwrap();
lcd.position(3, 1);
write!(lcd, "No disponible").unwrap();
arduino_hal::delay_ms(1000);
}
I erase bin-?
yes
show_invalid_drink_error shouldn't have the delay_ms
Why, it will show it for a fraction of a second if not and you wouldn't be fast enough to read it
you should put it in state.rs
match read_char(&mut self.serial) {
'1' => { self.selected_drink = Some(Drink::OptionA) },
'2'|'3' => {
show_error();
delay_ms(20000);
},
_ => {
show_invalid_drink_error();
delay_ms(20000);
},
}
Oh
I guess don't delete it for now
I copy avr to tool chain anyways?
yes
Well I did the implementation
Corrected some errors
I found along the way or things that needed to be changed
Now I only have warnings
Drink warning I can ignore because in the future maybe I will add so options B and C are valid
But the first one calla my attention a bit
oh, ```rust
'1' => {
self.selected_drink = Some(Drink::OptionA);
self.state = State::SelectIntensity;
},
sort of important to actually switch states on that one 🤦♂️
Ok now it should do
Damn it
More warnings
Well I said the drinks one I can ignore
Ok now I think finally..
GOD SAKE
Ok now I can run cargo check
And then test this works
If so the lcd by it's own it's complete leaving one step referring to finishing the code but two to finish this like it's individual project
Mmm
Small detail
I have a pendrive in my usb port
you can eject it
oh, OH
So now to the usb it's only the script left, right?
yeah, though looks like we will want to run cargo run at least once on it, because it's rebuilding everything (I have a test usb drive)
Well now let's test this
Ok it already doesn't work
I presses 5
It said drink not available
I think you colocated them backwards
Well us technically
yeah probably, I was doing 2 things at once
No
Two also says
Drink not available
Hmmm..
That's.. Weird
Ah I see
This is my error
maybe you made both '2'|'3' and _ call the same function
Both functions are equal in definition
Give me a bit
Also I added this
fn do_show_intensity(&mut self) {
show_intensity(&mut self.lcd);
match read_char(&mut self.serial) {
'1' => { self.selected_intensity = Some(Intensity::Strong) },
'2' => { self.selected_intensity = Some(Intensity::Medium) },
'3' => { self.selected_intensity = Some(Intensity::Weak) },
_ => {show_error(&mut self.lcd)},
}
self.state = State::Waiting;
}
It was important and forgotten
What. .
It still works as bad what..
Man I'm really asleep I
Changed the signature of the wrong function
ah
It finally should know..
So we can finally finish this of the pendrive also
Tho it's a shame not even today we got to finish the lcd, it's really resisting
Maybe because it knows just how easy and short are the two next steps
Because literally see the matricial keyboard
This is the code I made from using the library
Of it by itself
#include <Keypad.h>
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);
void setup() {
Serial.begin(9600);
}
void loop() {
char key = keypad.getKey();
if (key != NO_KEY) {
Serial.println(key);
}
}
It needed the number of columns and row, the matrix, which pins for columns which for rows and instanciate the object with all that and make map key that turns the matrix into string
And then the only thing I did in the code
Was call wait for key
So it will block and return the key
That's it
Also if we were so unlucky that we didn't find a library
I had made a code for it without it, to detect the key pressed
#include <stdio.h>
struct Key {
byte id;
char name[5];
};
const struct Key ONE = {0b10001000, "1"};
const struct Key TWO = {0b10000100, "2"};
const struct Key THREE = {0b10000010, "3"};
const struct Key KEY_A = {0b10000001, "A"};
const struct Key FOUR = {0b01001000, "4"};
const struct Key FIVE = {0b01000100, "5"};
const struct Key SIX = {0b01000010, "6"};
const struct Key KEY_B = {0b01000001, "B"};
const struct Key SEVEN = {0b00101000, "7"};
const struct Key EIGHT = {0b00100100, "8"};
const struct Key NINE = {0b00100010, "9"};
const struct Key KEY_C = {0b00100001, "C"};
const struct Key ASTRK = {0b00011000, "*"};
const struct Key ZERO = {0b00010100, "0"};
const struct Key HASH = {0b00010010, "#"};
const struct Key KEY_D = {0b00010001, "D"};
#define COLUMNAS 4
#define FILAS 4
const struct Key KEYPAD[FILAS][COLUMNAS] = {
{ ONE, TWO, THREE, KEY_A },
{ FOUR, FIVE, SIX, KEY_B },
{ SEVEN, EIGHT, NINE, KEY_C },
{ ASTRK, ZERO, HASH, KEY_D }
};
void setup() {
DDRA = 0x0F;
Serial.begin(9600);
}
void loop() {
PORTA = 0b00001000;
for (byte columna = 0; columna < COLUMNAS; columna++) {
for (byte fila = 0; fila < FILAS; fila++) {
if (PINA == KEYPAD[fila][columna].id) {
char imprimir[25];
sprintf(imprimir, "Se presionó la tecla %s", KEYPAD[fila][columna].name);
Serial.println(imprimir);
delay(200);
}
}
PORTA >>= 1;
}
}
We could solve the matricial keyboard and add it to the lcd code
In no time
And also them the relays and so
It's only
See what intensity was selected
And toggle the pin to each relay on off for a delay
And I would make a function so I ain't calling things too much I pass it the number of the delays for each case and that's it
It's just sending a one to a pin an amount of time no library no nothing
We could easily after lcd make that and the project would have it's base functionality already re written
That's why I thought I could for tomorrow, I underestimated the lcd really (?
Btw it works
Except at the end
Because it changes to waiting regardless
This should have the self.state in the match
to fix this
fn do_show_waiting_screen(&mut self) {
show_waiting_screen(&mut self.lcd);
self.state = State::SelectDrink;
}
I didn't get your proposal
that one you probably want to add a delay_ms so you can see the waiting screen
What I'm saying is
If you choose and unvalid
Intensity
It goes to the waiting regardless
But here I added the show error so I don't understand
fn do_show_intensity(&mut self) {
show_intensity(&mut self.lcd);
match read_char(&mut self.serial) {
'1' => {
self.selected_intensity = Some(Intensity::Strong);
self.state = State::Waiting;
},
'2' => {
self.selected_intensity = Some(Intensity::Medium);
self.state = State::Waiting;
},
'3' => {
self.selected_intensity = Some(Intensity::Weak);
self.state = State::Waiting;
},
_ => {
show_error(&mut self.lcd);
delay_ms(20000);
},
}
}
Ah y see why
This it didn't even show the error
Ok I changed it
This is getting so complicated we should publish it as a library crate so future people do it in 5 minutes -
Well not complicated but
You know long and all covered
Btw it works now so yeah that's done
Ok I plug in the usb again?
yep, looks like my script works
Done
First up you will need to download https://frippery.org/busybox/, as I suspect you won't be allowed to run scripts in powershell there, but this should work
https://frippery.org/files/busybox/busybox.exe is the download link
What a mess all of this -
now do you appreciate the Arduino IDE that does this all by itself
Also running software not actually installed on a computer is always painful
Software sort of just expects to be installed properly
so copy that busybox.exe to the rust_toolchain folder
And this is the script, which also goes in the rust_toolchain folder
That was quick
And after that we can test it
okay so this is what to do: right click in the folder, and select the "Open powershell here" option to open a new powershell window in that folder
The toolchain?
yep
And then run .\busybox.exe ash setup_rust_arduino.sh
And then you should be left with a shell that you can run commands in
yep
What now
so now this is setup to use the cargo on the usb drive
so use cd to move to where the project folder is
cd C:\Users\....
Well we are in the usb so
it works anywhere on the system
Wait in my PC or in the usb?
as long as you run the script first
Because in the usb there are literally only two folders
Rust tool chain and rust lcd
Don't I just CD to rust lcd directly?
is the rust_lcd one the updated copy you just finished testing?
Yeah because the things is it would take time to re copy
Maybe tomorrow I wake up earlier
And try to do so
So it's easier to have the already good one
To fix that before you copy it, delete the target/ folder
Don't I just deleted the rust lcd folder in the main folder of the usb and copy again?
Also when you use this on another computer, I recommend copying the project folder (containing you .rs files) to the computer's hard drive
As running cargo check on files on the USB will cause a lot of read/write which can be slow
now cargo check or cargo run
You won't have access to anything but cargo while in this shell
So..
I have my project folder
Where I would code in the school
But
I would compile and run it
Opening a windows poweshell window and cd'ing into my project first running the script prior?
So the terminal in vs code wouldn't work? But I use this one instead to read the errors, check, and upload it to the Arduino?
You could run the shell inside of vscode also
So I could in the terminal type the script and use it like I normally would?
The script just, takes over the shell while it is running
yeah
Ok so let's go through this one more time.
I go to the school
Pick a computer
Plug in the usb
In vs code enter my rust lcd folder or whatever project I wanna work in
Then when I wanna check for the errors or finally run it/upload I open inside toolchain a terminal, or in the same vs code as always, run the script and use it as always
That's it right?
yep
Only thing I don't get it's this part like how to do it and so
optionally, you would copy the rust lcd folder to the computer first edit in there, then copy it back when you are done for the day
Just to speed it up (it won't have to read/write to the USB all the time while you edit stuff)
Btw I can run for example cargo new so I could start another at school also?
Like I copy my folder rust lcd to the for example desktop or smth?
Well now imma delete the current lcd folder as a whole to re copy it but ofc with the working version
Only that?
If you remove the target/ folder before you copy it to/from the usb it will be much faster to copy
yep, you can leave the rust_toolchain folder alone
So
I delete target before copying it to the desktop?
this folder you don't want to copy to the USB if possible
Tho wouldn't that fuck up the one in my drive?
because it's big
cargo can rebuild it
target/ contains all the temporary stuff cargo/rustc uses while it does its stuff
Tho the computer will just choose to use the one at desktop instead of the one in the pendrive?
cargo will build a new one where ever you run cargo check or cargo run
Oh so.
I understand now
I plug the usb
Copy deleting the target folder
My project folder to the desktop
And open that one
Ok I got it now
Well I also talked to you about what's close to being the next thing to do just because I can't believe it's resisting so much when the next stuff to have the basic functionality I want is so apparently easy -
I'm totally fine with it and it's kinda my thing but aren't we maybe over doing it (?
I'm surprised of how much code we wrote for this
Not as a bad thing (excepting for not getting to the point I wanted to for tomorrow) but I drawed my attention
This has more to do, with me pushing you to use standard design practice instead of just writing code how you normally do 
Which add another thing to learn
When we finish this, because for school projects there's not place for pride
I want you to maybe coach me on how to be more independent maybe
Because honestly sometimes it seems like I couldn't write code alone or smth
Or I'm always to dependant
This is a common thing. There is a trade off between time spent getting something to work vs. time spent getting the project as a whole to work
My school project is merely that important but for all the rest I could do something about it
Its fine, plus we went really fast through all this. So totally expected
I mean it's in general the original version I needed also someone to help and I got stuck because he disappeared-
Tho to be fair
I started programming not so many months ago so
It was a bit too much
Of a first thing for me to do
Not knowing C++ barely having learnt C and kind of programming
Because supposedly we should've seen C++ and coded much more on Arduino but yeah pandemic didn't allow it
You are doing great for a beginner, in programming and embedded software
It's like I can totally understand stuff but not do it my own
Tho I hope rust to help me do stuff myself because of the friendly compiler so maybe errors aren't so the end of the road
So I ain't that afraid
I think you are ready to do the next step of the project on your own
, you have all the pieces now you just need to solidify your knowledge by figuring out how to put it together by yourself
The RFID stuff we can come back to
When this was done I was going to ask you like a..
Step guide or smth to how idk you do stuff
remember that cargo check is your friend 
For example I would go over
Like
Ok what did we do in this project
What problems we faced and how we solved them
How we got what we needed
Etc
Btw do you use rust for something else than embedded? Because I wanna keep using it but components do be expensive and you know I would maybe just leave it there
Tho I'm not in the season I'm thinking in doing projects still, I'll tell you what I want to do
I like rust so it's my go to for basically everything
First I re learned C or basically learn it to some extent to introduce into programming, be prepared for the project when it came (this one) and to recover knowledge I should have had, then I learned a lot about Arduino, serial port, codes I did, bla bla and started the project using the libraries and so, then started the python course so next I would learn python to a good degree I'm still at it
also there is nothing wrong with moving on to other languages/areas. Rust is a tool for you to use where you want to or see need for it
But I'm the meantime I just
Couldn't resist anymore to learn rust
I wanted to learn rust and C++
C++ out of curiosity, probably job, I am going to see it in university so I want you be prepared also have the knowledge I should have received and so
Rust more or less I did, now C++ would be the next if I consider I have nothing else to with rust for now
After python C++ and rust
I wanted to see the world of web development closer and also that could earn me money,html, css and JS
And also I see I need them
I saw a video on how to do an online chat with rust
It used css and JS stuff and
I thought hey this looks cool but I don't know that widely know tools
And then I maybe finally stop be satisfied with my options
Don't feel like I have something I really want to learn and finally
Start actually doing projects
To leave the theory field and start actually being a programmer and being better because its only by doing projects
Tho to be honest I really like programming but I don't know what I want to progtamm
Programm*
I relate to that
I'm lost still and I'm really indecisive