#Arduino Help
1 messages ยท Page 7 of 1
We wait for 100 ms to make sure the key is actually not pressed. instead of just a bounce in the switch
Since all methods have this now, shouldn't get key also?
because when you press a mechanical switch the waveform looks like
pub fn get_key(&mut self) -> Option<char> {
for col in 0..self.columns.len() {
for row in 0..self.rows.len() {
if self.check_row_col(row, col) == true {
return Some(self.matrix[row][col]);
}
}
}
None
}
we can now simplify get_char_array
get_key is fine because we just ask for the current state
How?
for index in 0..buffer.len() {
match self.wait_for_Key() {
'a' => { return index; }
key => {
// put key in the buffer
buffer[index] = key;
}
}
}
buffer.len()
Because we get rid of all the asking if there's nothing pressed?
yep, now wait_for_key handles that
And with the for loop I guess we no longer need the if and so..
Ok done
So know we finally write code to main?
Yes unless you think of another cool stuff we could do or need but I don't think so
main is like this now
#![no_std]
#![no_main]
mod Keypad;
use panic_halt as _;
#[arduino_hal::entry]
fn main() -> ! {
let dp = arduino_hal::Peripherals::take().unwrap();
let pins = arduino_hal::pins!(dp);
let serial = arduino_hal::Usart::new(
dp.USART0,
pins.d0,
pins.d1.into_output(),
arduino_hal::usart::Baudrate::new(57600),
);
loop {
}
}
I came back from dinner
How tasty
So we should test the three methods and it would be done
Any ideas?
I guess
First I would need to make a variable that stores the matrix
But about the pins
in the loop wait for a string then when you get one print it to the serial?
How do I do it?
First let me check for the pins.
Which ones were
let rows = [
pins.xx.into_pull_up_input().downgrade(),
pins.xx.into_pull_up_input().downgrade(),
pins.xx.into_pull_up_input().downgrade(),
pins.xx.into_pull_up_input().downgrade(),
];
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};
Here is the code from the Arduino
Oh ok
Can I copy the declaration of the matrix as is? (Changing filas and columnas for 4)
yes, and replace the {} with []
Should we anotate the type alias row?
we don't need to
No just a let keys = ...;
At the end or separating the arrays?
let keys = [
[ '1', '2', '3', 'A' ],
[ '4', '5', '6', 'B' ],
[ '7', '8', '9', 'C' ],
[ '*', '0', '#', 'D' ],
];
Ok now the pins
let rows = [
pins.d26.into_pull_up_input().downgrade(),
pins.d27.into_pull_up_input().downgrade(),
pins.d28.into_pull_up_input().downgrade(),
pins.d29.into_pull_up_input().downgrade(),
];
Why downgrade?
that makes them use Dynamic
so you can put them all in an array together
into_opendrain() it's in the docs
let columns = [
pins.d22.into_opendrain().downgrade(),
pins.d23.into_opendrain().downgrade(),
pins.d24.into_opendrain().downgrade(),
pins.d25.into_opendrain().downgrade(),
];
And we can finally call new
should be able to yeah
run cargo check
Checking keypad v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\keypad)
error[E0425]: cannot find function `new` in module `Keypad`
--> src\main.rs:42:26
|
42 | let keypad = Keypad::new(rows, columns, keys);
| ^^^ not found in `Keypad`
For more information about this error, try `rustc --explain E0425`.
error: could not compile `keypad` due to previous error
impl Keypad {
pub fn new(rows: RowPins, columns: ColumnPins, matrix: Matrix) -> Self {
Self {
rows,
columns,
matrix,
}
}
It doesn't make sense to me
oh, it thinks Keypad is a module
Isn't it?
keypad::Keypad::new()
Wait now that I think about it
I didn't make a use ::crate::Keypad::*
Or idk how it was it
Let's go one by one
Is it not?
Keypad isn't keypad is
Yes
But without let to declare a variable to store it then..?
Couldn't I use this?
Or I mean
Why does this happen
Because it's named the same the struct and module?
you can do that also
though... it has a name conflict then
which is why modules are usually snake case
Yeah but it is one word(?
I could call it Matricial_Keypad
And the use the use statement above
snake case is : this_is_snake_case
no uppercase
use matricial_keypad::*; ?
Yeah ig
Idk why but it moved places
Pls
How do I get the module about main
Above*
vscode orders them alphabetically
Oh that's why
it helps a lot when you have like 20-100 files in one folder
Ok finally
We can move to loop
And test
I guess what I would do
Is create a variable that stores the result from calling get key
And then print it to serial port
Same for the rest basically
If you use the get string one, you can test all 3 at the same time
since they call each other
yep
let buffer = ['X'; 20];
or something
yeah, it has to have something in it
The second one is the size right?
yep
Ok time to get testing
Ok now I just have to remember how to print things I will see the last project
How did I solve this?
you will need to print each char at a time
because it's not a &str
But what about the second that is a usize?
actually you can do
uwriteln!(&mut serial, "{:?}", buffer).void_unwrap();
uwriteln!(&mut serial, "{}", buffer_size).void_unwrap();
I think that works
what does cargo check say for the second error?
It wrote so many stuff..
wow they forgot the char impl 
Checking keypad v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\keypad)
error[E0277]: the trait bound `char: uDebug` is not satisfied
--> src\main.rs:50:9
|
50 | uwriteln!(&mut serial, "{:?}", buffer).void_unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `uDebug` is not implemented for `char`
|
= help: the following other types implement trait `uDebug`:
&T
&mut T
()
(A, B)
(A, B, C)
(A, B, C, D)
(A, B, C, D, E)
(A, B, C, D, E, F)
and 76 others
= note: required because of the requirements on the impl of `uDebug` for `[char; 16]`
= note: this error originates in the macro `proc_macro_call` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: no method named `void_unwrap` found for enum `Result` in the current scope
--> src\main.rs:50:48
|
50 | uwriteln!(&mut serial, "{:?}", buffer).void_unwrap();
| ^^^^^^^^^^^
|
::: C:\Users\fuchi\.cargo\registry\src\github.com-1ecc6299db9ec823\void-1.0.2\src\lib.rs:87:8
|
87 | fn void_unwrap(self) -> T;
| ----------- the method is available for `Result<(), void::Void>` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
4 | use arduino_hal::prelude::*; // trait ResultVoidExt
|
help: there is an associated function with a similar name
|
50 | uwriteln!(&mut serial, "{:?}", buffer).unwrap();
| ~~~~~~
error[E0599]: no method named `void_unwrap` found for enum `Result` in the current scope
--> src\main.rs:52:51
|
52 | uwriteln!(&mut serial, "{}", buffer_size).void_unwrap();
| ^^^^^^^^^^^
|
::: C:\Users\fuchi\.cargo\registry\src\github.com-1ecc6299db9ec823\void-1.0.2\src\lib.rs:87:8
|
87 | fn void_unwrap(self) -> T;
| ----------- the method is available for `Result<(), void::Void>` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
4 | use arduino_hal::prelude::*; // trait ResultVoidExt
|
help: there is an associated function with a similar name
|
52 | uwriteln!(&mut serial, "{}", buffer_size).unwrap();
| ~~~~~~
Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `keypad` due to 3 previous errors
add use arduino_hal::prelude::*; ?
alright we are back to this
you need a use 
That solve it for the second one
^
for c in &buffer {
uwrite!(&mut serial, "{}", c).void_unwrap();
}
Ok seems to be done
Also seems 0 warnings
So time to finally actually test
Mmm..
It finally executed so I pressed
From 1 to 9
Then # which is the one I choose to end
And it seems as nothing happened
Oh
I didn't change your 'a'
In the new version
It still didn't do anything
Now I'm going to press each one just in case
Nothing
I'm gonna execute it again with my change
try pressing them 20+ times so that it triggers the auto stop
Because maybe pressing A gives an 'A' and not an 'a'
Ok now I'm going to press a lot
yeah that is an issue
That's the reason I changed to #
But forgot too when we simplified
I pressed a lot of times and nothing happened
So I'm gonna re run with my change just in case
Ok let's see
No nothing happened
I pressed 0 to 9
And then #
Nothing
And pressing a lot of times also doesn't work
Ok
let key = keypad.get_key();
uwriteln!(&mut serial, "{}", key).void_unwrap();
it's going to not like it
if let Some(key) = keypad.get_key() {
uwriteln!(&mut serial, "{}", key).void_unwrap();
} else {
uwriteln!(&mut serial, "none").void_unwrap();
}
Ok let's see
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Error { kind: InvalidData, message: "Windows stdio in console mode does not support writing non-UTF-8 byte sequences" }', C:\Users\fuchi\.cargo\registry\src\github.com-1ecc6299db9ec823\ravedude-0.1.4\src\console.rs:27:45
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Didn't touch anything
um well then
if let Some(key) = keypad.get_key() {
uwriteln!(&mut serial, "{}", key as u8).void_unwrap();
} else {
uwriteln!(&mut serial, "none").void_unwrap();
}
maybe
Oh I thought the problem was with the function and all
apparently the arduino sent back invalid utf8
That last part I didn't get
as it's writing so fast
Oh
The serial port on windows can only hold so much data
try adding a delay_ms(500); in the loop
Which one because there are 2 for loops
pub fn get_key(&mut self) -> Option<char> {
for col in 0..self.columns.len() {
for row in 0..self.rows.len() {
if self.check_row_col(row, col) == true {
return Some(self.matrix[row][col]);
}
}
}
None
}
in main.rs
Oh
between calls to get_key
because right now it's running at like 1 million attempts per second
just a long list of none?
Wouldn't it tell me if it paniced?
not on the arduino
Well here is get key to see
it just locks up if that happens
add a uwriteln!(&mut serial, "hi").unwrap(); just before you call get key
I finished the program but the rx led is blinking
that means it's getting data
from the computer
tx would be sending to the computer
it is so annoying to go copy this each time cargo run -- --port COM6 -c
you can press the up key
to get your history of commands
is the tx led blinking?
in any case lets simplify even more
loop {
delay_ms(500);
uwriteln!(&mut serial, "hi").unwrap();
}
an comment out the making of the keypad and the pin setup
Wait
Now it printed
Maybe it's because of how slow my computer is? Remember when I said the the lcd took it's time to answer to my commands? Tho not this long
hi
none
hi
none
hi
none
hi
none
hi
none
hi
Goes like this for a while
what happens if you press a key?
Tho I don't see it you know
Keep going
It just appeard out of knowhere
And it's doing nothing again
Let's see
maybe we overloaded the windows serial driver 
I pressed all keys but I didn't see the tx turn on and it didn't do anything
It's likely because it has a million more none's to print
Do we maybe try wait for key?
try doing this ^
Ok
we need to get to a known working state
Mmm..
It doesn't work 
Or again it's going to take like 5 minutes and then a lot appear
I have a suggestion
Mmm ..
I mean
I could call get_key, bind it to a variable and then do a match expression maybe where either result makes a break, a catch all that says I received none and another one for a specific key idk..
Thing is
We are printint to much to the serial port ig
Printing*
Too fast*
I'm gonna try again with a delay like 5000000000
Or smth
To see if it prints one time at least
Well it allows 50000 only more is out of bounds
And it also didn't work
Btw now rx is no longer blinking-
Oh there it is
One hi
Oh ofc
The delay is before
So it waited 50000 miliseconds
And then printed hi
And it did again :o
Weird this time it took like way less
Oh when I sent this
It's now another one
As I thought the problem is just how fast we are printing ig?
Ig last time
Since it printed it once and then entered another loop
It didn't happen
So knowing this and having tested that..
What do we do now?
Even know it really takes it's time
And I can't use a much higher delay anyways
Actually
It haven't printed another one
Is rather inconsistent
Oh
It printed so more and I didn't notice
13 times
Now it printed more
So yeah
It seems to be doing fine
With almost the highest delay I can perform.
So now that we know and tested this.. What now?
You know I think that it may work for what we need it, it likely works but no clue how to test it
Could maybe test driven development do it? Like calling wait_for_key in a asserteq! And compare it to an specific key I know I will press idk
Because it seems like for the non-waiting nature of get_key it seems useless or impossible to test
I think testing wait_for_key which is the one we will indeed use should do and if it works then get key too
Or maybe we could try them in setup so it's just once
Sort of
Noooo ai wasn't heree
Well what do you think of my results yesterday ?
Just a little bit after you left with it working with the highest delay possible
And either the test driven development solution or try it in setup solution
And this conclusion
I still have no idea why the serial doesn't working properly. What about this, go back to a 500 ms delay, program the mega, then open the Arduino ide and open it's console viewer
I was using serial just now
For the normal arduino version of this project
Trying to figure it why some code related to the rfid isn't working, I'm frustrated-
Yeah, so I am wondering if the ravedude console is messed up on windows
Hmm
That's why I said maybe we should try it in setup or smth because maybe we are losing time for something that already works
You can do that also. It's up to you as it's your project. I just want to know why it doesn't work properly
We can do all test you want if you have another idea
^ would be one
What but
Wait*
Would that work I mean
I just open an arduino IDEA
Ide*
With no project
And open the console?
Yep
While the program is running
It works if it has a project?
I don't want to create a new one
The Arduino IDE should auto connect
You can just leave it on the blank one it makes or whatever you have open
If it's just for opening the ide
Ok now I open vs
arduino_hal::delay_ms(500);
uwriteln!(&mut serial, "hi").unwrap();
this one?
Yep
Did you ctrl-c to stop the ravedude console?
Cool, so it's just the ravedude console
And I think I know why
Go back to the rust code and add a \r to the end of hi
Then program it again
Do we test the original with buffer buffer size the for c in buffer and uwriteln?
Om
Ok*
It's still the same
Did it actually program? It can't while the Arduino window is open
I should close my arduino IDE windows?
Just the console window
I did that
And check that the command actually programmed (scroll up)
I mean I looked at it trigger the warnings for unused code and all but then I see this
Ok, so it's not going to be a simple fix 
I mean so we need to?
We will just use the Arduino console
let mut buffer = ['x'; 16];
let buffer_size = keypad.get_char_array(&mut buffer);
for c in &buffer {
uwriteln!(&mut serial, "{}", c).void_unwrap();
}
uwriteln!(&mut serial, "{}", buffer_size).void_unwrap();
this one
Well it didn't work
Ok then let's test
if let Some(key) = keypad.get_key() {
uwriteln!(&mut serial, "{}", key as u8).void_unwrap();
} else {
uwriteln!(&mut serial, "none").void_unwrap();
}
arduino_hal::delay_ms(500);
This one
Don't forget to hold the key for at least 500 Ms for it to read it again
It keeps printing none
No matter how much times I press
Or keep it presses
Pressed*
Yeah because it works in the arsuino version I tested it last Wednesday
And the code worked with that pins
.
.
There you have in any case
Hmm, maybe we test check_row_col
For now I need to leave, eat something and bath after that I continue
And also charge the computer while all of that happens
But could you leave me what we are going to do?
Like
The code to test because
Idk how we could test that function
Btw I have a suggestion
Even tho my c program works and it's good reference to see how to detect and print a key
Maybe we could also go to
The git repository
Of either the keypad.h Library I used for arduino
To see even tho in c++ how he did it
Or the one from the 4x3 one because it should be similar
@coral geyser aaaand I'm finally back, we can continue if you are
Please continue
This
Which is our most primitive function
I mean maybe we could print the result of calling our function which is a boolean and so start pushing first other keys to see if it's always false and then push the one I have to and see if it's true or smth like that
Just for refresh imma send it again
fn check_row_col(&mut self, row: usize, col: usize) -> bool {
for (i, pin) in self.columns.iter_mut().enumerate() {
if i == col {
pin.set_low();
} else {
pin.set_high();
}
}
self.rows[row].is_low()
}
Sounds good
How do you that AP?
Btw I will have to make the function public for now
uwriteln!(&mut serial, "{}", keypad.check_row_col);```
Why is this wrong?
Check_row_col needs it's params
It takes as parameters a position of the array right?
So
0 to 3
I guess
Let's make A the one, so row 1 column 3
Yep
uwriteln!(&mut serial, "{}", keypad.check_row_col(1,3)).void_unwrap();
here it is
Ok let's see
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Error { kind: InvalidData, message: "Windows stdio in console mode does not support writing non-UTF-8 byte sequences" }', C:\Users\fuchi\.cargo\registry\src\github.com-1ecc6299db9ec823\ravedude-0.1.4\src\console.rs:27:45
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Does this mean I don't try the arduino ide?
It's printing to fast
Delay_ms(...) 
:0
Yeah I forgot but
It works
Tho it seems I miss calculates
Calculated*
If I press B, not A
I see true
If nothing false
Let me see if nothing else triggers true
So we can detect buttons 
Ah yeah because A would be 0 bruh
Ok fine
So the problem it's get key
.
Thing is.. What's wrong?
Oh I think I know
The fact that is an optional? It makes sense for it to be, how we print it?
Oh tell me
We didn't take into account the speed of electricity
It's switching the pins to fast
So they haven't finished being set to 0v before it reads the input pin
So if we add a small delay, something like delay_us(100); between the setting low in check_row_col and reading the input it should work
That it changes state really fast and by the time we read it is no longer low..?
The mega runs at 16 MHz which allows it to set the pin low, then read the input pin so fast that the electrical state of the wire hasn't changed yet
I get when talking about of state of the pin but, state of the wire?
The lowness hasn't reached the input pin
The voltage change flows across the wire (to the keypad, button, back to the mega) in some amount of time
Happens that that time is to slow for what we are doing
I really can't understand at all I just get that arduino too fast, keypad not so much?
It's a
Keypad thing
Or
It's a physics thing
Arduino is too fast for us
We can go with that
Yep, though I would put it after the for loop
I think that will behave better
So before the is low question?
Yep
pub fn check_row_col(&mut self, row: usize, col: usize) -> bool {
for (i, pin) in self.columns.iter_mut().enumerate() {
if i == col {
pin.set_low();
} else {
pin.set_high();
}
}
arduino_hal::delay_ms(500);
self.rows[row].is_low()
}
So now we try
This again?
Basically what is happening is we set the column to 0v, but by the time the input is read it's at like 4.2v and dropping
Yep
Oh so..
In check row column
We ask for a column and if it's not we set it to 0
Really fast
The problem being
That then we immediately say
Hey it's 0?
And all that before it could physically be 0
Right?
Well now we now check_row_col works now it's just a matter of get key
(as a side note, this has to do with the capacitance of the wire and the internal parts of the microcontroller, it takes time to drain the small amount of charge the capacitance holds)
Ok so for now is printing none slower than before
And the reason we didn't see it with check_row_col is because then we weren't changing which column was set to 0 so it had time
Any chars 

Let the program speak for it itself
"none"
But we got a lower none printing speed rate(?
Oh, you set it to 500 ms 
?
That slow is that many mili(?
0.1 milli seconds
Because we need enough time for the physics to happen but be fast enough you don't notice the delay
Hmm, but faster none printing?
Yes
Try delay_ms(10);
I'm not sure how this is going to make it work-
If it doesn't I have more ideas for things to check
I would normally measure the time delay we need, but ... I am not there ๐คทโโ๏ธ
Sure I was just curious on the logic behind that being the issue for learning purposws
Still none
God damn
K, now setup a test with 2 check_row_col at different spots
What
Oh
uwriteln!(&mut serial, "{}", keypad.check_row_col(1,3)).void_unwrap();
uwriteln!(&mut serial, "{}", keypad.check_row_col(3,2)).void_unwrap();
Like that?
Now it doesn't work
Or it's too fast for me to see the true
uwriteln!(&mut serial, "{}", keypad.check_row_col(1,3)).void_unwrap();
arduino_hal::delay_ms(500);
uwriteln!(&mut serial, "{}", keypad.check_row_col(3,2)).void_unwrap();
arduino_hal::delay_ms(500);
Hmm
Like that?
Yeah
Wtf doesn't it work now-
It doesn't make sense -
Aha
Mm
I re opened and pressed really fast and saw only one true
Hold the key
I did the same for 8 which should be the other unless I'm wrong again
And it didn't work
Now I'm going to see if what I did to B works again first
I did some tries that didn't work
Now I made it again
If I hold it
I still only see false
Let's see if so that of opening already pressing but holding
It works
I wish we had an oscilloscope
If I hold the button
And enter the console
It says true
But only once
It doesn't make any sense to me-
And also it works with B not 8
Yeah, same here
So it do seems that the problem still is in check row col
Go back to 1 check_row_col
But it's just
With 1 it works, with 2 not, but if I hold press is true only before entering and then never more but with the other it doesn't work
Ok
It works perfectly fine
Holding or not
Mmm
Sometimes I pressed and it didn't
Now I pressed three times
And then it started working fine with each press
But those before didn't work
Now I pressed a lot of times
It's kind of inconsistent to start detecting
That's expected with the delay
But holding seems to he consistent
It only reads it every 0.5 s
It works with one at a time tho isn't that how it normally works anyway?
Set that delay to like delay_ms(100) and you should see more consistent results
Because it will read fast and report more often
Sure but what do we do now
The only thing I can think of is that the file with check_row_col didn't get saved. That's it
Yeah
And also I had the slower none
But like I have done this exact thing many times and never seen this
I'm sending the function again in any case
And I even double checked the rust keypad crate and the Arduino keypad library
pub fn check_row_col(&mut self, row: usize, col: usize) -> bool {
for (i, pin) in self.columns.iter_mut().enumerate() {
if i == col {
pin.set_low();
} else {
pin.set_high();
}
}
arduino_hal::delay_ms(10);
self.rows[row].is_low()
}
I am thinking
If get key gives back wrong the key pressed but that isn't it because even if it did it would show the key just the incorrect one
But I'm gonna express it anyways
pub fn get_key(&mut self) -> Option<char> {
for col in 0..self.columns.len() {
for row in 0..self.rows.len() {
if self.check_row_col(row, col) == true {
return Some(self.matrix[row][col]);
}
}
}
None
}
let keys = [
[ '1', '2', '3', 'A' ],
[ '4', '5', '6', 'B' ],
[ '7', '8', '9', 'C' ],
[ '*', '0', '#', 'D' ],
];
Say I pressed 2
So col would 1 at it's second iteration
And row would be 0 at it's first iteration
So it would give back
Some(self.matrix[0][1])
...
Why when I thought about it
It seemed wrong
But now I see it's fine no way-
Well forget all you just saw
Anyways if you needed it there are the two criminals check and get
I am tempted to pull out my oscilloscope to check this all
It will take me a minute to wire everything up for it
It's not like I'm gonna be using it while chatting on discord and stuff
Sure I wait
Man so many thing I gave for granted with arduino
Btw..should I upload something else to the board? Because idk if it's good to keep communication for so long, seeing that led blinking non stop get's me worried
could you zip up the entire project and send it to me?
How do I?
in windows explorer, right click the folder, then send to, compressed (zip) folder
without the target/ folder preferably
wdym?
I setup my mega with a 4x4 keypad to match yours and it behaves the same way (only false with 2 check row col)
so lucky to meet a real embedded developer with stuff at home(?
yep
in our case always false?
yep
I think I found the issue
Who was the agent of evil?
There is a small difference with mega chips, their pins default to high when you switch them to output
The hal doesn't take this into account so when we use open drain instead of grounding it goes to 5v
wh-
Why the hell
Is that a thing
Why when they were doing the mega they thought
Yeah
Output defaults to 5 volts
Tho I didn't understand the issue at all
So let's see
Normally
this is what we want
A microcontroller would have output a 0v by default unless I do something because it's idk what it makes sense
So open drain
Disconnects them completely
And when low they are nothing when high they are 0
But in this case
this is what we get
Since MEGA is a special boy
He decided that outputs are by default 5volts unless we tell them otherwise
But.
How does this affect open drain?
I told until the part that made sense to me
Or I thought I did understand
how open drain is implemented on the mega is it switches from output to input
output for the ground
input for floating
yeah
so when it sets it up, it makes it a output set to 0v. So then everything worked, but as soon as we set it to high (open) it becomes an input that just floats. But setting back to low makes it an output at 5v. Hence why as soon as we add another check_row_col everything breaks
Wait so..
I get mixed all up
So low instead of disconnecting
Set the output to 0 volt?
Why didn't I get a short circuit? Luck?
Its all right, but now the outputs don't pull the inputs down
everything just stays at 5v
yep
Which if I remember correctly could be whatever because of noise
// bitMap stores ALL the keys that are being pressed.
for (byte c=0; c<sizeKpd.columns; c++) {
pin_mode(columnPins[c],OUTPUT);
pin_write(columnPins[c], LOW); // Begin column pulse output.
for (byte r=0; r<sizeKpd.rows; r++) {
bitWrite(bitMap[r], c, !pin_read(rowPins[r])); // keypress is active low so invert to high.
}
// Set pin to high impedance input. Effectively ends column pulse.
pin_write(columnPins[c],HIGH);
pin_mode(columnPins[c],INPUT);
}
this is the keypad library you are using in the arduino code
see the pin_mod and pin_writes
they do this logic
And when set back to low is again an output of 5 volt because of the strange switch and no longer 0 volt? Because of the input output casting?
yep
because with 1 we never change the output to high
Oh that input remains low
In get key
All get high
And then we are done
And with two well one of them would set to high and there's no going back
Ok I think I understood the logic of our problem
Now the thing is the solution
Being aware to tell it
Hey be an output 0 in each iteration?
Or smth
I think the simplest thing is to clone the hal repo and make the edit to fix it
As long as it works and I understand the code and why it works
Keypad.h?
keypad.cpp
unzip it in the same folder that the keypad project is in
um, the one just below your cursor I think
the one that makes a new folder for it
rename the avr-hal-.... folder to just avr-hal
in cargo.toml edit it to have
[dependencies.arduino-hal]
path = "avr-hal"
features = ["arduino-mega2560"]
then try a cargo check
I delete all the rest?
delete the old [dependencies.arduino-hal] section
oh, no your cargo.toml
Go back to your project
yep there
replace that
this will use your local copy of the crate instead of the one on github
Ok done
cargo check
Error
PS C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\keypad> cargo check
error: failed to get `arduino-hal` as a dependency of package `keypad v0.1.0 (C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\keypad)`
Caused by:
failed to load source for dependency `arduino-hal`
Caused by:
Unable to update C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\keypad\avr-hal
Caused by:
found a virtual manifest at `C:\Users\fuchi\OneDrive\Documentos\Codigos_Rust\keypad\avr-hal\Cargo.toml` instead of a package manifest.
Blocking waiting for file lock on build directory
waiting
Still waiting

Any moment now
Finally god
4 minutes
I see a green finished so
It should be fine
Now that we finally got this
What do we do?
And what does this repo has btw? What do I have know?
the avr-hal contains all the library code for the mega
Oh-
now to fix the bug
That seems quite a lot-
go to avr-hal/avr-hal-generic/src
Done
scroll to line 347
/// Set pin low (pull it to GND, Output to low).
#[inline]
pub fn set_low(&mut self) {
unsafe { self.pin.make_output() }
unsafe { self.pin.out_clear() }
}
is what it should be
So in the end we use unsafe
I don't see that
But almost
yeah add the unsafe { self.pin.out_clear() } line to the function
Done
now go recompile your code and run it
which ever
it should also say it's rebuilding avr-hal-generic
What did we do, I mean ik change the behavior of the function to dealt with I/O bullshit but how did we solve it
we just made it force the pin to be low after it makes it an output
So the behavior is
The same as before
But when it comes back from input floating to output
The clear forces it to always be 0v?
yep
It works better but still not quite
I pressed
0 to 9
Then # to exit
This got printed
0
1
3
5
6
7
8
9
x
x
x
x
x
x
x
x
8
we probably need to change the delay in check_row_col
do be less
I have it at delay_us(1); in my version
Btw I don't get still how it works I mean, to match a key we needed 0v as a high, how does having a floating input that could be whatever because of a noise match?
And didn't we want to disconnect it instead of having 0 volts when low? Because now we have 0 volts when low, why no short circuit?
because the inputs are set to default to 5v
because we only ever force 0v, never both 0v and 5v
So it's the traditional high low now?
no it's still inverted (0v means the button was pressed) (5v is not pressed)
Yeah that I get
That's rows
But columns
High is 5 volts because is a floating pin input
And low 0volt output
^ hence the weird wiggle around 5v
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: ser_send(): write error: sorry no info avail
avrdude: stk500_send(): failed to send command to serial port
avrdude: ser_recv(): read error: Controlador no vรlido.
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer
avrdude done. Thank you.
Error: avrdude failed
That but more times
But I mean a it's supposed to work with columns being low disconnected high 0 volts to match the floating input and to avoid short circuit, now it's low 0volt and high 5 volts so I don't know how that still works
I had
I did 1 through 9 this time
the high isn't actually 5v, in that the arduino isn't providing really any current. The pin drifts high because of how the mega's circuits work
You said that high was a floating input right? Isn't a floating input unstable because of noise? But anyways without taking noise into account, isn't a high floating input 5 volts?
I forgot I also returned the size of the array that explains the 9
a floating input is some voltage, but we don't know what without looking at the circuit it's connected to
sorry about that
Wdym sorry
didn't even think to question the hal library
It was so goddamn hard to figure this out
Because it make so much no sense
It's titanic you solved it
Do you want to make the github issue or should I 
Right I guess it could be whatever
So in our case it's 0?
in our case it will go to 5v, but as soon as it gets connected to 0v it will go to 0v and basically no current will flow
You found it, know more, and know how to use GitHub so, I only created one and never used it to have my vs code linked there
But isn't low also 0?
yep, just a different type
the high one can get dragged around by the input's pullup
Clear makes it nothing like the drain behavior?
the actual low 0v can drag the input's pullup to 0v
clear sets it to a hard 0v
What's the difference between hard 0 volt and the usual 0 volt of our high?
I will make a table one second
Ok
Tho I still don't get why our high is 0 but just thought it would be easier to understand our low
Well I'll be turning off my computer so after understanding how this works we go to sleep (?
| Set Output | Pressed | Input | Real Output |
|------------|---------|-------|----------------------|
| Low | No | High | Low |
| High | No | High | Between Low and High |
| Low | Yes | Low | Low |
| High | Yes | High | High |
Let me see it on the pc because cell phone doesn't make it justice
"Set Output" is what the code sets the output pin to be
Which code, ours now?
"Pressed" is whether the button connecting output to input is pressed
"Input" is the input pin
yeah, thats what your code sets
"Real Output" is what you would measure with an oscilloscope on the output pin
Oh ok so when we set out output to low and there's no button press we have a high input because it turns it into a floating input, that's correct?
Wait
Join
No*
That's when high
Let's start again.
So we set our column pin which is an output to low
And no button is pressed
Why is high when low, weren't we setting it to hard 0?
because the button isn't pressed the output isn't connected to the input pin
like electrically
Yes I get that
and the input defaults to high from being pulled up
Oh
We are seeing
Rows and column behavior
Ok now I may understand
Ok so the input defaults to high because it is pull up
So in the first to cases I know it's high for that and I'm ignoring it
No button pressed yet
When my output it's low it's and absolute 0 that doesn't match with 5 volts so the real output is now
Low*
I get that
Then when we set it to high, there's a high-high match?
I mean..
Input pull up defaults to 5 volts
Now.
When we
Have our column pin high
It turn into a floating input which can have whatever voltage, right?
..
5v, but weakly
Why 5 volts?
high is 5v
Oh for that it's a normal pin
Ok I get that
So
We would have a 5 volts matching with another 5 volts
What happens?
nothing, we happy because the voltages match so no current flow
But since they match isn't it like a key pressed or our code it's like no if it's not two low matches it's not a key?
the code will consider a high as nothing being pressed
Ok
which is good when column is set to high because that's a "disabled" column
But what about that between low and high? Does that matter?
that we aren't checking right now
so now if a low column gets connected to a high column, the low column will force everything to 0v
But the only thing that is giving 5v (the inputs)
can only provide a tiny amount of current
so nothing bad happens
where as if the columns also provided 5v as an output they would provide enough current to be an issue
I was speaking about what it said in the real output but since you mention it
How-?
thats just we dont know the voltage
ah, because the output can pull a lot of current in to ground (0v)
so it overrides the weak 5v pullup in the inputs
(also this "a lot" is like 100mA max)
Our column is low so 0 volts to the 0 volts of the input that it's now low
Why the real output it's low? Isn't this the key pressed scenario?
you would measure 0v if you used an oscilloscope to read the voltage of the output pin
in that case the output pin just floats around
it will be something like 4.5v in reality
not actually 0v or 5v
So when the pin is high which is the case we don't want it to match it's not 0 so it wouldn't match the 0-0 as before so it's fine, and when it's low it would match the 0-0 and well the in our behavies the same way
So.
Now instead of asking for the column
With the pin on high
That was 0 volts, we do it with low our now 0 volts?



