Need help, reading serial to set digital pins

Hey guys, first of all, I have little experience with arduino coding. So excuse my code if its ugly. Altho i do have some coding experience, i'm struggling on how to approach my dilemna without frying anything.

So the logic of the end goal is this: Have 2 arduino pro micro soldered together. One of them (i'll call it the receiver) is plugged in pc via usb, and the other is plugged in another device through usb to send keyboad keys (i'll call it the transmitter).

so code wise, here is what i'm trying to do: send keyboard keys to pro micro receiver via the serial monitor, then with that keyboard key info, the receiver finds matching pins in the hexa matrix, then activate those pins to emulate a keypad button press. Then the transmitter reads the pins activated by the receiver (like if a keypad button was pressed) and sends a keyboard key.

This is how I plan the wiring:

PC -> pro micro receiver -> pro micro transmitter -> other device

identical pins on the 2 pro micros are soldered together. So pin 2 of pro micro receiver is linked to pin 2 of pro micro transmitter. The same is true for pins 2,3,4,5,6,7,8,9,10,14,15,16. So both pro micros are powered by the usb cable of their respective device.

So far my code works, i managed to find info by reading online and trial/error. However, when its time to activate pins, i'm scared to do trial and error because actual current is activated on pins and i don't want to fry anything.

so far with the code i managed to read serial input and find the physical pins via the matrix. I'm just not sure on how to do the code that activate the pins and emulates a button press. I think i'm supposed to use digital write?

i did read this: How to Set Up a Keypad on an Arduino - Circuit Basics but i'm not sure if i understand it right. So from what i understand, all columns pins are HIGH by default, and all the row pins are LOW by default. So if u understand correctly, once i have the column and row pins, i have to set that column pin to LOW (which was high) and that row pin to High(which was low)?

I'm only worried about the receiver code for now.

Here is the code, for the receiver so far. Lets assume I send "Y" to the receiver via serial monitor.


#include <Keypad.h>

const byte ROWS = 6; //EIGHT rows
const byte COLS = 6; //EIHT columns
char inChar;
char colChar;
char rowChar;
byte matchCol;
byte matchRow;
byte row;
byte col;

//define the symbols on the buttons of the keypads

char hexaKeys[ROWS][COLS] = {
//    2           3           4          5      6              7          pins
  { 'KEY_0', 'KEY_1', 'KEY_2', 'KEY_3','KEY_4', 'KEY_5'},     // 8
  { 'KEY_6', 'KEY_7', 'KEY_8', 'KEY_9','KEY_Q', 'KEY_W'},    // 9
  { 'KEY_E', 'KEY_R', 'KEY_T', 'KEY_Y','KEY_U', 'KEY_I'},      // 10
  { 'KEY_O', 'KEY_P', 'KEY_A', 'KEY_S','KEY_D', 'KEY_F'},    // 16
  { 'KEY_G', 'KEY_H', 'KEY_J', 'KEY_K','KEY_L', 'KEY_Z'},    // 14
  { 'KEY_X', 'KEY_C', 'KEY_V', 'KEY_B','KEY_N', 'KEY_M'}   // 15
};

//               index 0  1   2    3     4    5
byte rowPins[ROWS] = {8, 9, 10, 16, 14, 15}; //connect to the row pinouts of the keypad
byte colPins[COLS] =    {2, 3,  4,   5,    6,    7}; //connect to the column pinouts of the keypad



//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup(){
  Serial.begin(9600);
}

void GetKeyPins(){

  inChar = Serial.read(); // reads the key "Y"

  for (row = 0; row < 6; row++)
  {
       for (col = 0; col < 6; col++)
      {

         if (hexaKeys[row][col] == inChar) // When it finds "Y" in the matrix it gives the array    index
      {
        matchCol = col; //sets matchCol to 3 which is the column array index
        matchRow = row; // sets matchRow to 2 which is the row array index

      }
    }
  }

}


void SendPins(){

digitalWrite(colPins[matchCol], LOW ); //in our example, colPins[matchCol] would be colPins[3] which represents pin 5. So this sets pin 5 to LOW
digitalWrite(colPins[matchRow], HIGH );//in our example, rowPins[matchRow] would be rowPins[2] which represents pin 10. So this sets pin 10 to HIGH
delay(50);
digitalWrite(colPins[matchCol], HIGH ); //sets the pin back to what it was
digitalWrite(colPins[matchRow], LOW ); //sets the pin back to what it was

// this function should emulate pressing button at pin 5 and pin 10
}

void loop() {


  if (Serial.available() > 0) {

    GetKeyPins(); // gets the array index of column and row of the key i sent via serial monitor, "Y" in our example
    delay(50);
    SendPins(); // uses the arrays indexes found with GetKeyPins to emulate a button press


  }

}

In the code, I commented what I think each function/line of code does. Feel free to correct me if i'm wrong.

So my question is: Is the code above correct? Do i have to declare pins with pinmode or does keypad.h sets columns pins to high and row pins low by default?

Thank you if you read all that, and if something isn't clear ask away. I'll do my best to clarify.

This has 2 erors. 'KEY_0' should have double quotes as it is a string.
The array is in fact 3 dimensional as each string is an array itself. And th 2D array will hold pointers to the string arrays. So declaration should be:

const char* hexaKeys[ROWS][COLS] =
1 Like

sorry for the noob question, but what would that change code behavior wise? The hexakeys are used to recognise keyboard input from the serial monitor and find column/row physical pins of that character. So far that part of the code works so i don't understand whats the error.

And is the double quote specific to the 'KEY_0'? Like 'KEY_0' isn't a string but 'Key_1' is?

Also I don't really understand what a pointer is. I tried reading on it but its still blurry. Like what would be the pointer of 'KEY_Y' in the hexaKeys? is it hexaKeys[3][2]?

All need double quotes.
And no idea why your code works...
I do not see how inchar can be equal to any of your hexKeys...
You might want to go for chars in your matrix:
Delete KEY_ everywhere in your matrix, leave the rest as it is...

1 Like

Because they are ASCII characters i think? like

Keyboard.write(65);         // sends ASCII value 65, or A
Keyboard.write('A');            // same thing as a quoted character
Keyboard.write(0x41);       // same thing in hexadecimal
Keyboard.write(0b01000001); // same thing in binary (weird choice, but it works)

Serial.read gets the byte i send to the monitor and that byte is matched in the matrix i think.

This should not work. It needs double quotes.
const char mystring = "bla";
Under the hood it will be a const char array.
You can print the second char via
Serial.write(mystring[1]);
Or via:
Serial.write((mystring+1)
)
Untested..

Like if you look at the customkeypad example in the arduino IDE, thats how its setup. Thats the skeleton i used to build my code.

/* @file CustomKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates changing the keypad size and key values.
|| #
*/
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'0','1','2','3'},
  {'4','5','6','7'},
  {'8','9','A','B'},
  {'C','D','E','F'}
};
byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char customKey = customKeypad.getKey();
  
  if (customKey){
    Serial.println(customKey);
  }
}

That code gives me error....String and char aren't the same. If i try to compile your code it give me an error.

const char mystring = "bla";


void setup() {
  Serial.begin(9600);

}

void loop() {
Serial.write(mystring[1]);
}

error:

Compilation error: invalid types 'const char[int]' for array subscript

However those compile fine:

const char mystring = 'bla';


void setup() {
  Serial.begin(9600);

}

void loop() {
Serial.write(mystring);
}


const char mystring = "bla";


void setup() {
  Serial.begin(9600);

}

void loop() {
Serial.write(mystring);
}

Sorry for the confusion. The forum software does not show the 'star' operator if it is not inside code quotes...

const char * mystring = "bla";

Do you see the difference from your code?

You cannot compare a string using ==.
In your case you should use chars (single chars like 'e') and then you can use == for comparison.

thats exactly what i do. It's in the GetKeyPins function

void GetKeyPins(){

  inChar = Serial.read(); // reads the key "Y" in our example

  for (row = 0; row < 6; row++)
  {
       for (col = 0; col < 6; col++)
      {

         if (hexaKeys[row][col] == inChar) // Compares the value of serial.read to each row/culumn value until to find a match
      {
        matchCol = col; //sets matchCol to 3 which is the column array index
        matchRow = row; // sets matchRow to 2 which is the row array index

      }
    }
  }

}

I'm not sure why you talk about strings, i dont use strings at all in the code.

Are you implying that the hexkey.h (that you did not share) has defines like
#define KEY_e e
???
That would explain a lot...

I was a bit mad.
But now I can laugh about it.
And I realize that I cannot blame you for this bit of obfuscating code.

Basically you can forget all my posts so far. And then we should somehow try to help you with your problem...
Can you add a schematic of your setup?

If you are afraid to blow pins you can use series resistors of 220 ohm with each pin.
That will save them from blowing, even if you short the resistor to ground while the pin is HIGH.

1 Like

Yes. I arrive at the end of this with what I clipped for possible use

If it is just connections between input pins and output pins, no matter which are which or even if they both be the same, wiring with a resistor resistor will not have any effect but will save your ports any damage.

I was going to suggest 2K2, doesn't make much difference. I just have a bigger bag of those and it happens to be what I use when I invite friends over to play. :expressionless:

a7

1 Like

To be honest, to prevent pin damage it's sufficient to prevent currents in excess of the pin rating, so if one pin is set low, the other is set high, and 20 ma is your chosen limit (that's dependent on what processor we're talking about), 5/0.02 = 250 ohms; given the circumstances, anything 270 ohms or above is sufficient, and far below a value that might cause misinterpretation of a 1 for a 0 or vv, given typical internal pullup values > 10k.
YMMV, all bets are off, think it through for yourself, yadda, yadda.

1 Like

Here is a schematic i made. The green one is the receiver, the blue one is the transmitter. But lets forget the transmitter for now.

Both are arduino pro micro ATmega32U4, 5V 16Mhz.

Basically what i'm trying to do is 'reverse engineer' keypad.h logic. Usually you would solder a button matrix to some pins on the pro micro, then use keypad.h to detect which button is pressed and send keyboard keys if you want that keypad to act as a keyboard.

What im trying to do is have the receiver emulate the keypad that you would solder on the arduino. The way i want them to work at the end is: send key stroke to the transmitter via the serial monitor, the transmitter takes the key stroke it received, find a match in the hexaKeys array, once it finds the match, store the column and row pins. Then activate those pins as if it was pressed on a soldered keypad.

then after that, the transmitter sees the activated pins by the receiver as if a soldered keypad button was pressed, then sends a key stroke.

So far in my code i get to the point where i can read the keystroke and get the corresponding pins in the hexaKey array.

Where i'm stuck is: now that i know the pins, how to i ''activate them'' to emulate a button press that the transmitter will ''see''

Hope it makes sense......If not, i'll try to clarify. Again, thanks for your time.

Also, all i have is a soldering iron, the 2 pro micros and some wires. I don't have any resistors, bread board or other stuff so i'd like to use the built-in resistors if possible/needed.

Compilation error: invalid types 'const char[int]' for array subscript

Treat this as an array of characters...

const char mystring[] = {"bla"};

Your ground connection is missing.

Your code will determine whether you blow up any output pins.

So: share the code...