#Arduino Help
1 messages · Page 6 of 1
You mean input output ig
Because we could in main declares the pins to be input/output and then send them to the new function or something or we could create another struct/enum inside keypad
And get rid of the columns and rows fields
What's that inside the array?
The Pin structs
I'm a little bit confused
That let you set and read the pin's state
They already exist
API documentation for the Rust Pins struct in crate arduino_hal.
Ok so..
The pins struct contains all the pins of my board
So you suggest
That rows and columns
Are arrays that contains the specific fields needed from the pins struct
Right?
Basically
You can take the pins out of the struct that holds them
Like we did for the i2c
And ig brackets for generics or something because I could connect them almost any where
And the serial
pins.xx.into_output()
do you agree with the idea to have the same key struct from the C code inside the Keypad struct?
Do we need it? Isn't that what matrix will do?
The key struct has a field for the bit combination and another for the ASCII character to represent each key, tho in my C example for readability I made the matrix with all my key const struct instances
To represent each key
Tho ig you could also have the ASCII in matrix and a bit field for any key needed set of bits in the display struct
So I guess the main question is, are we doing the individual pin or PORTA method?
Ig we will do our own struct or whatever to replace it unless it isn't that much of a huge pain
Tho I was really considering to use unsafe..
Because I know is safe we won't mess up and it saves up so much code
Because individual pins don't need bit combinations
But how do you track which key is it
In the loop 
Idk how the condition would be because that would make like 64 conditions
for r, row in rows.enumerate() {
for c, col in cols.enumerate() {
}
}
If pin 1 is this and pin 2 is this and pin 3 is this.. And pin 8 is this
Else
If pin 1 is this..
Loops 
Mm
I just don't get it ig we will see
Let's try do individual pins
If it's so much of a pain we will use unsafe
So we need somewhere to put the pins
Yep
matrix will handle it
Well ok ao
I don't understand this
You have 8 wires going to the keypad right?
Doesn't the pins are already contain in a struct and we are extracting the ones we are using for an array?
Yes
The pins struct in main holds the "handles" to those 8 wires so you can read write to them
handles?
We need to get them from pins and put them in Keypad for later use
Is there anything that isn't a pointer (?
Mmmm
The thing is also to the eventual new function we should send
Hey I will use this pins for this
And inside it should take them
And put them somewhere
In the arrays
Exactly
So you told me
That we get say ownership of the handle or whatever
By calling methods into them like into output
Or you could have 8 individual variables 
Just how many lines you want to write-?
I thought we should avoid that kind of stuff, agroup related data, avoid writing extra lines
For the mega the Pins struct from arduino_hal has 50+ pins in it
each as an individual field
Yes, arrays will make it easier
So what do we do-
Man it hurts so much the absence of a library this should've been the second easiest part
^
in the lcd there was a clear direction of what to do but here it's just from scratch
Yeah I don't get how that works is it for taking generic or something the angle brackets
Do you have the docs open?
Because you should have them open to look stuff like this up
cargo doc --open
Exactly what I mean idk if that's something you made yourself or your know it's the way idk
Actually I don't even have the PC open because I knew I wouldn't be writing code soon -
<T> indicates a generic type
So I may turn it now
Gosh finally
I know generics it's just I don't understand like, anyway we will see+
-*
Avr or Arduino?
Arduino_hal
I have been meaning to ask what do the different characters before ? mean in your messages?
Yep
Yeah
Mmm hard to explain
- is like maybe
Surprise like
When someone says something and stops at the last letter
What sound dry and serious or something
What- sound like you know how I imagine a confused what to sound
Okay, makes sense
It would be easier if I could make the sounds
Tho as the other probably it stuck because of me talking a lot to someone who did something similar or something made it stuck
Now about (?
I think that would be a "What!?" For how I normal type
It's not necessary a question sometimes I just don't want messages to be dry or I don't want them to be taken as seriously or idk, this one is really complicated and either I'm just use to it or it's use would have to be explained by a psychologist at this point (?
Mines like a silent one like another kind of shock, as I said with sound it would be so much easier to explain this one
Maybe it's like a /s tag
Maybe is a shield for insecure statements who knows
Like I mean it but I don't
70 fields-
we need more!!!
https://toneindicators.carrd.co/#masterlist you will see people in this server use tone indicators a lot
See how each field is a Pin<..., ...>?
Btw this project that it's peak has, matricial keyboard 4x4, LCD display with I2C, 2 relay modules, an RFID, 4 ultra sound(? ) sensors and one Infrared (?) Sensor
Could be done in the raspberry pi pico or there's a pin shortage?
100+ pins is the minimum I will accept /j
There are like a lot of nested angle brackets, why?
I need a raspberry Pi pico Mega..
They are generics in generics 
Pin<[mode], [number]>
The first is for input/output the one inside for? And the one in the same brackets
What number?
So my pin has inside information of it's state as input output, it's port and number, right?
The one instead of Input is what type of input it is
That's a no btw?
Yep
I don't remember how many pins the pico has easily accessible
Wdy by type of input? That of pull up or pull down?
But I suspect not enough
Yeah me too :(
It's so sad
I have no clue what I'm going to use the raspberry Pi pico on
It's likely gonna get dusty
I need bigger boards pls raspberry don't do this to me-
Search "mode" in that docs window
I will ask you still to set up all so I could be able to work with it but I don't see use in it
Go to arduino_hal::port::mode
Why embedded need to be so expensive-
So I go back? Because there's no mode here
I only buy the micro because if needed and possible I want to work with it and I have to take my chance while it's still relatively cheap
You haven't even seen FPGAs 
But I'm frustrated that I'm doing nothing on it
Those things can be 1000+ dollars
.
Hmm, that's what the path should be
https://rahix.github.io/avr-hal/arduino_hal/port/mode/index.html is the online one
API documentation for the Rust mode mod in crate arduino_hal.
Click "port" in the path at the top
Got there
Oh right
It could analog or digital
But..
The others..
Do I need to know what this modes are?
Pin<input/output<type of input/output>, port and pin number>
Right?
Yep
There is also a special thing you can have in the port and pin number position called Dynamic
Which let's it be any port and pin (the port and pin are stored inside the Pin struct)
Well that seems kinds convenient for us..
I know right 
Column digital input and rows digital output
What type for each?
What do you mean there?
Or well mode I guess
Input<?> 
Digital?
Why isn't digital a thing
It's literally the default
You use 98% of the time
Because it's Floating or PullUp
What's the difference between the two?
Floating pins are basically completely disconnected from anything
PullUp ones will go to 5v by default
Well there's output at least for rows, that says is configured as digital output
Where would I use each one? Which one do I normally use?
So either empty or they work as Vcc? Or what?
Floating is the default one
And why would I use pull up instead of floating?
Well what happens if you attempt to read a floating pin not connected to anything? We don't know it can report as 1 or 0
Why would I read a pin that has nothing to read 
You can actually change the state by just moving your hand around it sometimes
Are the pins going to the keypad connected to anything when the key isn't pressed?
And by connected I mean to 0v or 5v
Which are inputs
But if it's not pressed...
Mmmm I don't remember ...
Then it isn't connected to the columns
Let's see if I can remember with this
This is when someone remembered me how a matricial keyboard worked
Well not "someone" My teacher
Tho this is in
Negative logic
But replace in your mind 0 and 1(?
By default rows are 0
Until you press it then it's 1
Columns start at 0 but we chose when and how many are 1
But ofc the way we use it
It's only have 1 at a time to have a 1 and then keep passing it to the right
Tho idk
How to answer your question
Because
There are wires connected to the pins
And also
In Arduino I just passed the pins without worrying about if they had or not to be pull up to know
Some ARM code I finally found from an old project 
yeah, I can explain it if you want
If it ain't complicated
So these keypads assuming its one of these
General-Purpose Input/Output
These are a matrix of switches
each switch connects the row wire with a column wire
This(?
yep
Do you have the connection to 5v as shown there?
the resistors to vcc
I don't use resistors I just connect the wires
or are they just connected to other pins
That
So in that case the inputs if they are set to floating don't have 0v or 5v to set that state
if no buttons are pressed
I realized I mixed input with output all this time here
I don't understand why resistors change that
The resistors in the diagram above "pull" the wires towards 5v
And why outputs don't need them?
The resistors are there to allow you to pull them to 0v to override them
Because they are outputs they control their own state
So this has to do with inputs needing to be either 0 or 5 volts and being controlled by whoever press them instead of internationally by code?
Oh because there noise that makes it unstable
yep
So the resistors avoid noise so it could be 0 until it's told to be 5 voy
Volt*
Ok got it
So columns are going to be digital output floating dynamic pins and rows are going to be digital pull up input dynamic pins
4 of each
Not quite
We should fix the whole accidentally shorting pins issue
Accidentally shorting?
I will pull the example from my microelectronics textbook
Oooh
yep
Tho idk why that short circuits
as seen here we can short pins by accident
Let get a more base explanation
What would you define a short circuit to be
And what can cause it and what are the consequences
Say one row (I think this diagram is backwards to how you have done it) is set to output 1 and one is set to output 0
Then we connect these to pins together by pressing the correct set of buttons
Nah it's the same columns are the lower wires(?
connecting 5v to 0v

one one side, maybe it just causes your micro controller to restart, on the other ... dead micro controller
So..
if you connect 5v to 0v directly without any resistance, and infinite amount of current will flow
Ok I get that
which is very bad for electronics
And micro components would heat and be useless?
yep, they can basically explode internally
In what case does this reset the micro instead of killing it?
though luckily the arduino pins are protected somewhat against this
I heard there were internal resistors in the pins
That you could use instead of your own with pull up
That's the thing protecting the chip
Ok so now that we more or less understand what a short circuit it's and what it does continue on why two inputs at a time short circuit this
So how we fix this issue of 0v connecting 5v is just not have 5v being directly connected to the keypad through output pins
You can connect 2 outputs together accidentally
^
I don't see how at all..
Because
So my outputs would normally
Have a 1 constantly moving
And the rest 0
And the then the inputs
Also be all 0
you can connect the 1 output to a 0 output
Until I press something
Ok I get that now
But how would that while thing work?
Like..
They have to be two buttons of the same column
Or whichever
If they are from the same column we have the column with 1 and two rows in the same column with 1
If it's from another the row would be 1 but column 0 at least me I can't see the connection that allows that to happen
I am confused by these two messages
I just can't see why pressing a second key
Connects one column to another
Because I only see the connection between a column and it's four rows
press 2 keys in the same row
that will connect 2 different columns together
This the kind of thing it's impossible to explain without a whiteboard-
i am really bad so let s see..
ok so
do you see me or it is for me to take a screenshot?
are we doing rows or columns as input?
I can see it live
as I learn it columns as outputs i control and rows like inputs
so
say we pressed..
row 3 and the 1 is in column 2
ok so now
we also press r2
so..
it is like the same
two rows in 1 but to the same column
what happens if you now press R3,C3
what is R3's state?
i could see a connection there
by pressing two from different columns
but not from the same
^
so it is not garanteed short circuit but kinda likely and in any case there should not be even the slightless chance of shortcircuit, right
yeah, we don't want it to accidentally happen
So what if instead of using 0 on the output we just made the pin disconnected from the microcontroller
Well that makes sense logically because there wouldn't be any Posible 5v to 0v but rather 5v to nothing
Tho wouldn't resistors technically do it also?
cool, so we do that
But how do we make them disconnected?
it's fine if it's through a big reistor
like the ones inside the microcontroller
So why don't we use those?
That would be the open-drain mode
.
They aren't connected by default when you set it to output
I read the description btw and it says
OpenDrain Pin is configured as a digital output with open drain behaviour
What's open drain behavior and how it works is the thing
Open drain acts to connect to 0v when set to low, and disconnect the pin when set to high
And we can't set them?
What-
only some pins can
But I would disconnect it when I want to use it
Or I would have to
So negative logic?
Do*
but, what if we made the input default to being high
Noooo negative logiiiic 
But I understand
That's why the examples seem to always be with negative logic I see
Its setup this way because transistors that pull to 0v are smaller than transistors that pull to 5v
But 0v would do? Don't we kinda need 5?
because chemistry
we let the inputs pull to 5v by default, aka PullUp inputs
I didn't understand that part honestly
First
Pull up wasn't to use the resistors inside?
A pullup input is configured to connect a high value resistor to the pin and 5v
Second are we specifying two types for one pin?
So it's low is 5 volt as a default state?
Input<PullUp> for inputs, Output<OpenDrain> for outputs
But..
yes, we will consider 5v (high) as a logic false
Let's start with inputs
So
I thought we used pull up on inputs
Because of the noise
that to
but it just happens to also fit perfectly for using OpenDrain
It made it constantly 5 volts
it defaults to 5v but doesn't force it to be 5v
So inputs pull up uses the pin resistor and a default 5 volt state to avoid noise and work with negative logic?
And then the outputs would be open drain so there's never a 5v to 0v connection
But
If the maximum outputs can be is 0 volt
What about passing a one as we did before? Like
yep
Before two 1's needed to match so
I guess when I press it down it would be 0 the row and the column would be either nothing or 0
So I guess two 0's would need to match
you will see a 0 on the input only when the column is set to 0 and the button connecting them is pressed
rows: [Pin<Input<PullUp>, Dynamic>; 4],
columns: [Pin<OpenDrain, Dynamic>; 4],

I had an extra >
I thought it should be like input pull up above
Ok now that we finally had been through all this logic and how it works and we made the struct that holds that matrix of possible ASCII characters with the fixed sizes of 4x4 and the pins for the columns and rows so it could be what ever pin from whatever port but with the fixed size of 4 pins that have the configuration to work as we need them too and avoid short circuits.. What now?
struct Keypad {
rows: [Pin<Input<PullUp>, Dynamic>; 4],
columns: [Pin<OpenDrain, Dynamic>; 4],
matrix: [[char; 4]; 4]
}
shouldn't X and Y be 4 
Oh yeah I could swear I changed that
next step: we need a new function to make these things
So
New would receive
I anotate the types the same way?
We could use an alias maybe for the pin types of rows and columns
Like
yep
type ColumnPin = Pin<OpenDrain, Dynamic>;
Shouldn't we use snake case?
types are camel case
you need to name them rows: ...
Btw maybe I need a more descriptive name for matrix if any suggestions
In the struct use the alias you mean?
also either you need to make the type aliases arrays or put the arrays in the function signature
fn new(rows: RowPins, columns: ColumnPins, matrix: Matrix) -> Self {
...
}
Oh
and that also
I am going to switch to Windows real quick
By change have any better idea for the matrix type alias?
Because matrix is kind of an already existing thing so idk
struct Keypad {
rows: Rowpins,
columns: ColumnPins,
matrix: matrix
}
type ColumnPins = [Pin<OpenDrain, Dynamic>; 4];
type Rowpins = [Pin<Input<PullUp>, Dynamic>; 4];
type matrix = [[char; 4]; 4];
impl Keypad {
fn new(row: Rowpins, column: ColumnPins, matrix: matrix) -> Self {
}
}
and back
seems fine
naming is hard
Ok so
I'm still not used to making new functions
I know how to do constructors but I don't remember new function being the same in syntax
How do I complete new?
Self {
rows,
columns,
matrix,
}
Rowpins should be RowPins
Solved
and matrix should be Matrix
impl Keypad {
fn new(row: RowPins, column: ColumnPins, matrix: Matrix) -> Self {
Self {
rows,
columns,
matrix,
}
}
}
Ok so know we have a keypad struct with a matrix of the possible ASCII characters and the pins with the already correct setup of rows and columns and a new function
Two questions
First
That means when I declare the pins I want to use I won't be calling into_output and stuff?
You will, then you will pass them to the new function
Also I made the struct and new function public this time I ain't forgetting 
But didn't already tell how I wanted the pins to be in the types?
yes, but they start as Input<Floating>
How with this data can we make a function to detect the pressed key and return it?
Tho to be honest
The only thing I really need and use
It's waitForKey
But I think is very basic to have that functionality also ig
So a getKey method and waitForKey method should be enough
At least for the purposes and scope of this project
Tho
There one other use this will have
alright setup their signatures
I will tell you in case maaaaybe
and just put todo!() in the body of them
you did
That is where the current project is stucked but
Because of the rfid
Because I successfully
Obtained the password from the user and compare it to another
Well if there's a function that would help like allowing use to write a string or give back a char array and we pass it as a parameters how many letter we want to write
That could help and sound useful
Or it could be not necessary enough for me it sounds really cool but what do you think?
put all the methods you want
Should we call it..
getCharArray?
Btw it's likely the two above would call getKey to do the dirty job and then add to it
make sure the types make sense
So the actually tricky thing is to do getKey
Wdym?
for the functions, what they take and what the return
Well for what they return that's easy
First two return a char and last one a char array
... Tho..
Since it's of unknown size actually a vector 
pub fn getKey() -> char {
todo!()
}
pub fn waitForKey() -> char {
todo!()
}
pub fn getCharArray() -> Vec<char> {
todo!()
}
And about receiving
do you have Vec without std?
An instance of -
Oh no..
I mean it showed me no error so I ain't sure..
No, that error because of unused serial
Warning*
So since there's no error we are fine with vectors..?
so you didn't make it a module?
if it's not a module you won't get errors for it
Oh
...
It was better when I didn't import as a mod and it didn't have +9 errors(?
error[E0412]: cannot find type `matrix` in this scope
--> src\Keypad.rs:4:13
|
4 | matrix: matrix
| ^^^^^^ help: a type alias with a similar name exists: `Matrix`
...
11 | type Matrix = [[char; 4]; 4];
| ----------------------------- similarly named type alias `Matrix` defined here
error[E0412]: cannot find type `Pin` in this scope
--> src\Keypad.rs:7:20
|
7 | type ColumnPins = [Pin<OpenDrain, Dynamic>; 4];
| ^^^ not found in this scope
|
help: consider importing one of these items
|
1 | use arduino_hal::port::Pin;
|
1 | use core::pin::Pin;
|
error[E0412]: cannot find type `OpenDrain` in this scope
--> src\Keypad.rs:7:24
|
7 | type ColumnPins = [Pin<OpenDrain, Dynamic>; 4];
| ^^^^^^^^^ not found in this scope
|
help: consider importing this struct
|
1 | use arduino_hal::port::mode::OpenDrain;
|
error[E0412]: cannot find type `Dynamic` in this scope
--> src\Keypad.rs:7:35
|
7 | type ColumnPins = [Pin<OpenDrain, Dynamic>; 4];
| - ^^^^^^^ not found in this scope
| |
| help: you might be missing a type parameter: `<Dynamic>`
error[E0412]: cannot find type `Pin` in this scope
--> src\Keypad.rs:9:17
|
9 | type RowPins = [Pin<Input<PullUp>, Dynamic>; 4];
| ^^^ not found in this scope
|
help: consider importing one of these items
|
1 | use arduino_hal::port::Pin;
|
1 | use core::pin::Pin;
|
error[E0412]: cannot find type `Input` in this scope
--> src\Keypad.rs:9:21
|
9 | type RowPins = [Pin<Input<PullUp>, Dynamic>; 4];
| ^^^^^ not found in this scope
|
help: consider importing this struct
|
1 | use arduino_hal::port::mode::Input;
|
error[E0412]: cannot find type `PullUp` in this scope
--> src\Keypad.rs:9:27
|
9 | type RowPins = [Pin<Input<PullUp>, Dynamic>; 4];
| ^^^^^^ not found in this scope
|
help: consider importing this struct
|
1 | use arduino_hal::port::mode::PullUp;
|
error[E0412]: cannot find type `Dynamic` in this scope
--> src\Keypad.rs:9:36
|
9 | type RowPins = [Pin<Input<PullUp>, Dynamic>; 4];
| - ^^^^^^^ not found in this scope
| |
| help: you might be missing a type parameter: `<Dynamic>`
error[E0425]: cannot find value `rows` in this scope
--> src\Keypad.rs:16:13
|
16 | rows,
| ^^^^
| |
| a field by this name exists in `Self`
| help: a local variable with a similar name exists: `row`
error[E0425]: cannot find value `columns` in this scope
--> src\Keypad.rs:17:13
|
17 | columns,
| ^^^^^^^
| |
| a field by this name exists in `Self`
| help: a local variable with a similar name exists: `column`
error[E0412]: cannot find type `Vec` in this scope
--> src\Keypad.rs:30:30
|
30 | pub fn getCharArray() -> Vec<char> {
| ^^^ not found in this scope
Some errors have detailed explanations: E0412, E0425.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `keypad` due to 11 previous errors
Ok the first I forgot the capital
About Matrix, what do we call it then?
Matrix is fine
it says there it already exist one called that
It's trying to be helpful and say what you probably ment
oh
so what about the others
use arduino_hal::port::Pin;
|
1 | use core::pin::Pin;
which of the two i need?
use arduino_hal::port::Pin;
considering that is what we have been looking at the docs for
what do i return in getCharArray? how do i do dibamic size arrays without vec, is malloc here a thing?
do you need it to be dynamic?
I want getCharArray to do the following
I want you to be able to write more than one char at a time and that it return all those characters as a char array , not a string because with a char array I can compare it with another index by index so when I do this password thing is going to be reaaaally useful
And I wanted to take as a parameter an interger to say
Ok I want a char array of size 5 because that how many characters long is the password
So you are available to write as much as you want
what if you set a max length of the password and use an array of that length?
Well that works too
So how do I say I give back a char array? Because about the max that's something of the implementation so I would see that later
how about ```
fn get_chars(&mut self, buffer: &mut [char]) -> usize {
}
usize is for counting things
Because for example that isn't giving me back a char array, and it's asking me a char array and I want to make one not ask for one so I don't understand at all
it's the size of the memory space

its just a number
And that number is the number of bytes of memory needed for a certain variable?
no
Then idk what it is but
Why are you return that and not a char array as the idea was?
Returning*
do you know about u8, u16, u32, u64, u128, i8, i16, i32, i64, i128?
the types of numbers
Eh I guess so, signed and usigned ints that have different ranges of numbers they can cover
usize is u16, u32, or u64 depending on the platform
So why not type just for example u16?
because indexing arr[index] expects a usize
It's weird that they are the same but aren't used for the same-
We are returning the chars, just not as the return value 
A usize for the index?
yeah, because usize::MAX is the max number of things you could possibly have in memory
So it expectes to be have a limit size of for example u32?
How (?
And why are we giving a char array as a parameter if I want the char array to be created there and give it back?
Wdym by stuff?
the caller gives us a slice of chars, we put the chars the user types into it
then return how many the user typed
But why would I want to return how many he typed if that's not data I'm interested in?
so you know how many chars where replaced in buffer
Oh wait so.
My function getCharArray
Would recieve as a parameter a buffer to store what I write when calling it?
And also I was going to say that all functions would need to recieve the instance of my struct that has the relevant data but now that I think about that would be with a mutable reference to self so that's fine I understand that very first part
yep
But again why I would want to know that(?
The only thing I want
Is to write my characters and have all of them in a char array
How many, I don't care ig
what about when the user enters a new password?
So you say to also compare the lengths of the passwords?
well you can but thats not the main point
so you know how long the actual password is
But that's what I want to do
I just care that the password I send and the on that would be compared to are equal, length doesn't matter excepting ofc for the fact that if it's longer or shorter is wron-
Oh
It return the size
So I can compare it to the maximum size I established
Right?
sorry, we went into overtime in my rocket league match, the size is needed because say buffer has length 15 chars. And the user types in 4 chars for the password. You need to know that the password in the buffer is only 4 of the 15 chars
Unless the password never changes
No need to apologize
Say I understand but
Oh
I understand
Since I borrow a mutable reference to buffer
By calling the function the buffer would have what I write to it
Ooh
Well so
We know the signature of this function now for the others
I think the only needed parameter would be an instance to hour struct that has all the important data, aka, a mutable reference to self, do you agree?
sure
Ok now I will send the remaining errors
Checking keypad v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\keypad)
error[E0412]: cannot find type `Dynamic` in this scope
--> src\Keypad.rs:9:35
|
9 | type ColumnPins = [Pin<OpenDrain, Dynamic>; 4];
| - ^^^^^^^ not found in this scope
| |
| help: you might be missing a type parameter: `<Dynamic>`
error[E0412]: cannot find type `Dynamic` in this scope
--> src\Keypad.rs:11:36
|
11 | type RowPins = [Pin<Input<PullUp>, Dynamic>; 4];
| - ^^^^^^^ not found in this scope
| |
| help: you might be missing a type parameter: `<Dynamic>`
error[E0425]: cannot find value `rows` in this scope
--> src\Keypad.rs:18:13
|
18 | rows,
| ^^^^
| |
| a field by this name exists in `Self`
| help: a local variable with a similar name exists: `row`
error[E0425]: cannot find value `columns` in this scope
--> src\Keypad.rs:19:13
|
19 | columns,
| ^^^^^^^
| |
| a field by this name exists in `Self`
| help: a local variable with a similar name exists: `column`
Some errors have detailed explanations: E0412, E0425.
For more information about an error, try `rustc --explain E0412`.
error: could not compile `keypad` due to 4 previous errors
you need to add a use ... for Dynamic
search in the docs for Dynamic
Mmm
It seems it isn't in pins
Neither in modes
Mode*
Ah there you are bastard
So..
use atmega_hal::port::Dynamic
?
yep
And what about the other errors?
the names are just wrong
"
a field by this name exists in Self
| help: a local variable with a similar name exists: row
"
rows: row
?
in the struct you called it rows, in the function you called it row
No it is rows
Because row says no such field
Rows says
Cannot find value in this scope
try use arduino_hal::hal::port::Dynamic;
It worked
error[E0425]: cannot find value `rows` in this scope
--> src\Keypad.rs:19:13
|
19 | rows,
| ^^^^
| |
| a field by this name exists in `Self`
| help: a local variable with a similar name exists: `row`
error[E0425]: cannot find value `columns` in this scope
--> src\Keypad.rs:20:13
|
20 | columns,
| ^^^^^^^
| |
| a field by this name exists in `Self`
| help: a local variable with a similar name exists: `column`
For more information about this error, try `rustc --explain E0425`.
error: could not compile `keypad` due to 2 previous errors
only this left
you put row there not rows
But that'st the name of the function parameter
Anyways now that everything works
We have the last more or less complicated task
Making the getKey function
it didn't match what you had here
We know the logic and there's my C example but my C example do it another way
So we will see how to do that function
Then waitForKey would call getKey inside but do it so it blocks
An getCharArray call it multiple times or smth and store the chars it receives
The point is, this is the last "key" Part
So how do we do it?
how about we add 2 helper functions
What were helper functions?
one to enable one of the columns and one to read a row
actually, doing it as one function will probably work better
Like I did in my C code?
functions that aren't pub
Oh I see
a function that checks one column row pair
fn check_row_col(&mut self, row: usize, col: usize) -> bool {
...
}
because self.rows[row] can work nicely without casts
and what's inside the array rows is usize?
It will return true if the button at row, col is pressed
I thought they were the pins(?
rows is the pins
we index with a number
self.rows[0], self.rows[1], ...
Oh so it is one pair at a time but I guess we will call it in loop to for each iteration call a different row and column and so
yep
I declare this function below the getCharArray one still in the impl block?
yep
also functions are snake case
Oh I did them like in C++ sorry (?
Ok done
What do we write inside the new check function?
so first we need to set one of the output pins low
whichever col is
I thought we wouod start with an iterator or for
and make sure the rest are high
And then inside the for turn that one and then the other in the next iteration
Would"
for (i, pin) in self.columns.iter_mut().enumerate() {
if i == col {
pin.set_low();
} else {
pin.set_high();
}
}
we go through each column pin, and set all to high except for the column we want to check
yep
Self.cols you wanted to say self.columns?
oh yeah
so you can call set_low, set_high
those mutate the pin
Oh
And enumerate if I remember correctly..
Gave back a touple with the index and element at said index?
yep
Which is what you are iterating through so it makes sense
So if the current iteration of the loop is equal to the col sended set it high and the rest set them low
I understand
Ok so now we have set the col sended to high and the rest to low
I guess we will then in getKey
wait we didn't check the row yet
Call this function in a for loop to iterate to each posible row in a column and then the next column and so
Ik
yes we will
How do we check the row?
self.rows[row].is_low()
Remember me
Why row needed to be low
I remember column
If low was disconnected
And if high it was 0
And row..
It had 5v by default..
row is high by default
Oh
it goes low when connected to the column we set to low
So pressing it is low
yep
Tho we are asking there for what pin? All of them?
the pin for index row
we don't need to check the others
Oh yeah
So
I pass a certain col and row
I guarantee only the col I pass is high by setting it in any case
And I ask if the row I send is low for that col, right?
yep
And you said I would only see a 0, low, not when I press it but rather when I press it and also it matches with the col?
yep
because it only goes low if it gets connected to ground
which only the one output set to low can do
And it's ground because it's 0v?
yep
But also the other thing would be 0v
ground by definition is 0v
It's like two ground or smth
So now we go to get key where we would basically do a for loop using this function?
sort of related, https://www.youtube.com/watch?v=Bine_PbyFSQ
Circuit operation of MOSFETs (N channel and P channel) and Bipolar junction transistors (NPN and PNP) explained with 3D animations. My Patreon page is at https://www.patreon.com/EugeneK
That explains why it works even tho the 2 are 0 volts?
its more a general how transistors work
yep
try doing that one by yourself first
Oh I am supposed to know but you know supposed even tho I still use them when I learnt about them it was pandemic
So I couldn't say if I know enough
But my answer is correct(?
Ok then let's see
Since the function waits for a usize
I pass as a parameter the index?
yep
pub fn get_key(&mut self) {
for (col, pin) in self.columns.iter().enumerate() {
for (row, pin) in self.rows.iter().enumerate() {
if self.check_row_col(row, col) == true {
return
}
}
}
}
Two issues
First
Idk how to return
The key pressed
...
Mmm..
wait
I had an idea
Why not in matrix
Instead of 4,4
Do
Rows columns
So
||self.matrix[row][col] || 
I could call the matrix at the current row and col
What I thought but , would that work as it is right now? Shouldn't I change what I said?
why 
not sure what you mean here
If it works as you said forget it(?
it should work as is
add a ; after the return and the continue is wrong
The error is the same
and then at the end of the function you need to return a default char
or .... use Option<char> 
So it could return none if it never finds one
yep
you need to return the None
also the continue is still wrong
Where?
Why?
At the end of the function just put None
because it will only check the first row of each column
for that you just do ... nothing
And when it's done asking the rows then it goes to the next column iteration
Shouldn't it skip in the for it's used "for"?
okay it's not wrong, just not needed
yeah it will, my bad there
if ... {
...
}
behaves the same way
Anyways
You are right
Last issue
Borrow checker
Maybe I would need to use a smart pointer
But lemme run cargo check first
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src\Keypad.rs:28:20
|
26 | for (col, pin) in self.columns.iter().enumerate() {
| -------------------------------
| |
| immutable borrow occurs here
| immutable borrow later used here
27 | for (row, pin) in self.rows.iter().enumerate() {
28 | if self.check_row_col(row, col) == true {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
warning: `keypad` (bin "keypad") generated 4 warnings
error: could not compile `keypad` due to previous error; 4 warnings emitted
ah, we need to use 0..len instead
for col in 0..self.columns.len() {
for row in 0..self.rows.len() {
...
}
}
Can you so len in columns and rows?
Now that I think about it
They are an array
So yeah
Dooone
So next wait_for_key
Can we easily just make something blockable?
we could do that if you want to
Nah if it's not needed
Well finally only one method left
get_char_array
Tho two quick questiona first
Do you know what firmware is? i heard is software that operates ok hardware or modifies hardware or smth like that, like drivers, but you know seemed like embedded development was also that
what you are making can be considered firmware
So my definition is correct?
firmware is usually characterized by being indirectly influenced by a user. In other words, its software that just makes hardware do stuff
And also
its also usually unchangeable or hard to change
What else so you know to make in rust aside from embedded development? Apps with yew? Web dev with tauri, dino or webAssembly?
do you*
You can use Rust for basically anything you want, I have done all the above in some form before
Games is a growing one
Because you know since embedded development is kinda hard to do as hobby, cheap, and stuff it's like I would have nothing else to do with rust , after finishing the original project and this re write the idea was starting my adventure to learn C++ to a decent extent while finishing my python course and Django project, when all of that is settle on wanna finally dive into the web development world and learn HTML, CSS and JS, because they seems base knowledge nowadays, for example when I saw the real time chat app with rust with I thought hey interesting it used them
So I thought well I could in that future use rust as my backend
Be it for webs or apps
I want to use rust and that's the only other idea I have (?
And also..
To be fair I don't know for sure if I would use rust embedded again until it grows an ecosystem good enough ig, or I should see
So well I wanted to know of someone who also knew
Is it easier or harder than this web development?
At least the rust ecosystem there should be a lot bigger
that would be better answered by #net-and-web , i don't do much web right now
Oh ok
Having said that
How so we begin the get_char-
_array function?
I guess we could
Enter a for loop for the len of the buffer
I need to go to bed 💤
And add to the index i so it changes which each iteration the result of calling getKey
Oh ok, guten natch and thanks for the help today
I will do maybe a small prototype or smth (maybe not) and leave it here
pub fn get_char_array(&mut self, buffer: &mut [char]) -> usize {
for i in 0..buffer.len() {
if let Some(key) = self.get_key() {
buffer[i] = key;
}
}
return buffer.len()
}
More or less that
Idk if I have to deal with /0 here
I tried to do
buffer[i] = '/0'
Below for loop but it didn't let me do it so
And also I know I'm not properly giving back the len of the actual used buffer and all that but this is kinda prototype to see how to better this later
Btw it's \0, not /0, although idk the api requires NUL termination or no
Well I'm used to the C way that all strings ends with the end string character therefore char arrays too
So idk if here I have to mark the end of the string with said character or not
Good afternoon @coral geyser are you available?
yep
Ok then today likely we can finish this project
This is what I thought tho there's likely more job to do
But for the time being, is it fine for now?
wont this just instantly fill up the buffer with the same char
because get_key doesn't wait
I didn't understand that at all the idea was for it to start the loop, click get key, if it's the some variant and to the current index them move to the next and you know
And then return buffer.len() just for the compiler not to shout at me
but you need to wait for no key being pressed between checking for the key pressed
Would the be fixed by making the exact same thing but with wait for key without the need for a if let.
*?
otherwise you will just get something like
aaaaaaaaaaaaaaaaaaaaaaa
no, because we need to wait for a key pressed, and no key pressed
So I replace get key with wait for key leaving the if let as it is?
Because
Wait for key return a char not an option char
we need something like
let mut index = 0;
loop {
match self.get_key() {
None => { /* no key pressed just check again */ }
Some('a') => {
// enter key pressed (here I use 'a' for enter)
// we don't write the char to the buffer and return what we have written
return index;
}
Some(key) => {
// put key in the buffer
buffer[index] = key;
// move to the next char in the buffer
index += 1;
// check if we reached the end of the buffer
if index == buffer.len() {
return index;
}
// wait for key to be not pressed
while let Some(_) = self.get_key() {}
}
}
}
because we are waiting for the user to press a specific key to stop
So we will tell him that he can write as much as he wants and then use a key to finish the loop?
yep
though we probably want to stop it before the user writes more than the size of buffer
So we have a mutable variable index to know how long is the array and also
For indexing
for index in 0..buffer.len() {
match self.get_key() {
None => { /* no key pressed just check again */ }
Some(key) => {
// put key in the buffer
buffer[index] = key;
// wait for key to be not pressed
while let Some(_) = self.get_key() {}
}
}
}
would be the version for a fixed input size, aka the user always has to type in the amount buffer expects
yep
So we use a loop so he's not forced to write a set amount nor less neither more?
yeah, though we can do the first version as a for loop also
Now I don't understand the first match so.
for index in 0..buffer.len() {
match self.get_key() {
None => { /* no key pressed just check again */ }
Some('a') => { return index; },
Some(key) => {
// put key in the buffer
buffer[index] = key;
delay_ms(100); // delay to debounce input
// wait for key to be not pressed
while let Some(_) = self.get_key() {}
}
}
}
buffer.len()
We call get for key and match it to the none variant and some variant
With an specific key
So if there's nothing pressed yet
Just keep going and asking
But if the specific key is presses end the loop and return the index so we know how long is the char array
Oh they are from the same match
I get it now
maybe we should add
// wait for key to be not pressed
while let Some(_) = self.get_key() {}
to wait for key
that would simplify this somewhat and help in other spots
And if another key is pressed it would be bind to "key" and stored in the current index of the buffer, then b
Index+1, and of that index is already the length of the buffer we go back
Now I just don't understand the last part of while let
Let me see if I understand
While the Some variant isn't an underscore (none I would suppose) it will keep going, since it's a while it will stay there and it needs a {}
It's that correct?
_ in a pattern means: "something but I don't care about it"
Then I don't understand how that line works
How does that waits until nothing else is pressed
Wait*
what does get_key return when no keys are pressed?
none
Does None match Some(_)?
we could do it as
while !matches!(self.get_key(), None) {}
But I want to be able to understand the one above first
the while loop spins in the {} while the condition is true
Oh so
If whatever key is pressed
It continues
I don't care which key
That's why _
But when none is there it won't match and I know it's not pressed
Excellent
Now..
Explain this (?
matches!() takes a value (self.get_key()) and checks if it matches the pattern (None) if it does match it returns true
So the other ! It's so that when it return true it's false and it breaks the loop
Both of them are cool so idk which one to use..
Which one you think is cooler or you prefer?
I like the while let one
Oh ok
So here it's the function up until now
pub fn get_char_array(&mut self, buffer: &mut [char]) -> usize {
let mut index = 0;
loop {
match self.get_key() {
None => { /* no key pressed just check again */ }
Some('#') => {
// enter key pressed (here I use 'a' for enter)
// we don't write the char to the buffer and return what we have written
return index;
}
Some(key) => {
// put key in the buffer
buffer[index] = key;
// move to the next char in the buffer
index += 1;
// check if we reached the end of the buffer
if index == buffer.len() {
return index;
}
// wait for key to be not pressed
while let Some(_) = self.get_key() {}
}
}
}
}
Is it done?
I think we should move
// wait for key to be not pressed
while let Some(_) = self.get_key() {}
to wait for key
That will make wait for key behave better
pub fn wait_for_Key(&mut self) -> char {
loop {
if let Some(key) = self.get_key() {
return key;
}
}
}
In which part?
Btw, is it?
yeah
.
pub fn wait_for_Key(&mut self) -> char {
loop {
if let Some(key) = self.get_key() {
delay_ms(100); // debounce the key
// wait for key to be not pressed
while let Some(_) = self.get_key() {}
return key;
}
}
}
Is what I am thinking
Tho I don't get why is it needed
this will make wait for key wait for a single press then release
So we aren't only dealing which short circuit but also
"Anti-rebote"idk how you call that in English
How did you actually write the delay?
well delay_ms is in arduino_hal::delay_ms
That
