Help with writing program for an external keyboard

I am currently working on a calculator project using the Uno which involves interfacing a keyboard using the PS/2Keyboard.h library.
Here's a link to it: PS2Keyboard Library, Connect a keyboard for user input

The example code runs fine. What I need to accomplish now is to have it operate similar to how the serial monitor works, if this makes sense. I want to be able to type in a string of characters in the following format:

ADD 3 4

... and then have the user hit enter to put it into the program. I have the code to analyze the entry and calculate it already working with the Serial monitor. It would just be much cooler to have it working independent of a computer. :grin:

Being fairly new I'm a little lost on what way to approach this. I would appreciate any advice pointing me in the right direction. I will post the code I have so far which is mostly just me playing with the idea of using an array. It's pretty much all I've been able to come up with in trying to google myself an answer.

#include <PS2Keyboard.h>

const int DataPin = 8;
const int IRQpin =  3;

char keystr[30];
char datastr;
byte index = 0;

PS2Keyboard keyboard;

void setup() {
  delay(1000);
  keyboard.begin(DataPin, IRQpin);
  Serial.begin(9600);
}

void loop() {
  if (keyboard.available()) 
  {
    if(index < 9)
    {
      datastr = keyboard.read();
      keystr[index] = datastr;
      index++;
      keystr[index] = '\0';
      Serial.print(keystr);
      
    }
  }
char datastr;

Next, I expect to see stuff like:

int resFloat;
float resInt;

int resArray;

int oneVal[10];

The str in the name implies something that is patently false. Don't go there.

Thanks. Nick, the code you provided proved to be very helpful in taking in characters from the keyboard and storing them but I've got another question. The code I have originally was meant to use Serial.parseFloat and Serial.parseInt to grab the numbers from the string. I am using the arduino String class and haven't been able to find any parsing functions for it.

I also tried converting the String to an array using stream.toCharArray and playing with atoi and atof but didn't get too far primarily because I have never used them before.

Here's the part of the code that I am talking about:

void loop()
{    
  static char input_line[MAX_LIMIT];
  static unsigned int input_pos = 0;
  
  if (keyboard.available()) 
  {
    char dataIn = keyboard.read();
    Serial.print(dataIn);                 //View the input as it's being typed
    
    switch(dataIn)
    {
      
      case PS2_DELETE:
      input_line[input_pos] = 0;
      input_pos = 0;
      break;
      
      case PS2_ENTER:
      Operation = input_line; 
      Operation.trim();
      Serial.println(Operation);         //Check the string
      break;
          
      default:
          if(input_pos < (MAX_LIMIT-1))
          input_line[input_pos++] = dataIn;
          break;
    }
    


 for ( j= 0; j<operations; j++) {
    if (Operation.equalsIgnoreCase(sStack[j])) {        
       break;
    }
  } 
  


 switch (j) 
    {
    case 0:  // Divide: DIV x y 
          a = Serial.parseFloat();
          b = Serial.parseFloat();
          op_result = a / b;
          Serial.print(op_result, decimals);
          break;

    case 1:  // Multiply: MUL x y 
          a = Serial.parseFloat();
          b = Serial.parseFloat();
          op_result = a * b;
          Serial.print(op_result, decimals);
          break;

    case 2:  // Add: ADD x y 
          a = Serial.parseFloat();
          b = Serial.parseFloat();
          op_result = a + b;
          Serial.print(op_result, decimals);
          break;

    case 3:  // Subtract: SUB x y 
          a = Serial.parseFloat();
          b = Serial.parseFloat();
          op_result = a - b;
          Serial.print(op_result, decimals);
          break;

    case 4:    // X^Y: X^Y x y 
            b = Serial.parseFloat();
            a = Serial.parseFloat(); 
            op_result = pow(b, a);
            Serial.print(op_result, decimals);
            break;

    case 5:    // Logarithm: LOG x
            b = Serial.parseFloat();
            op_result = log10(b);
            Serial.print(op_result, decimals);
            break;

    case 6:    // Natural Logarithm: NLG x 
            b = Serial.parseFloat();
            op_result = log(b);
            Serial.print(op_result, decimals);
            break;

    case 7:    // 10^X: 10^X 10 
            b = Serial.parseFloat(); 
            op_result = pow(10.00, b);
            Serial.print(op_result, decimals);
            break;

    case 8:    // Reciprocal of X: 1/X x 
            b = Serial.parseFloat();
            op_result = 1.00 / b;
            Serial.print(op_result, decimals);
            break;

    case 9:    // e^X : e^X x 
            b = Serial.parseFloat();
            op_result = pow(2.718281828459045, b);
            Serial.print(op_result, decimals);
            break;

    case 10:   // Square root: SQR x 
            b = Serial.parseFloat();
            op_result = sqrt(b);
            Serial.print(op_result, decimals);
            break ;

    case 11:    // X^2: X^2 x
            b = Serial.parseFloat();
            op_result = b * b;
            Serial.print(op_result, decimals);
            break;

    case 12:    // SIN: SIN x 
            b = Serial.parseFloat();
            if (Degrees){b = b * Pi / 180.0; }
            op_result = sin(b);
            Serial.print(op_result, decimals);
            break;

    case 13:    // COS: COS x 
            b = Serial.parseFloat();
            if (Degrees){b = b * Pi / 180.0; }
            op_result = cos(b);
            Serial.print(op_result, decimals);
            break;

    case 14:    // TAN: TAN x 
            b = Serial.parseFloat();
            if (Degrees){b = b * Pi / 180.0; }
            op_result = tan(b);
            Serial.print(op_result, decimals);
            break;

    case 15:    // ASN: ASN x 
            b = Serial.parseFloat();
            if (Degrees) {op_result = asin(b) * 180.0 / Pi;
            }  else {op_result = asin(b); }
            Serial.print(op_result, decimals);
            break;

    case 16:    // ACS: ACS x 
            b = Serial.parseFloat();
            if (Degrees) {op_result = acos(b) * 180.0 / Pi;
            }  else {op_result = acos(b); }
            Serial.print(op_result, decimals);
            break;

    case 17:    // ATN: ATN x 
            b = Serial.parseFloat();
            if (Degrees) {op_result = atan(b) * 180.0 / Pi;
            }  else {op_result = atan(b); }
            Serial.print(op_result, decimals);
            break;

    case 18:    // Degree mode: DEG
            Degrees = true;
            Serial.print("Degree mode"); 
            break;

    case 19:    // Radian mode: RAD
            Degrees = false;
            Serial.print ("Radian mode");
            break;

    case 20:    // Set decimal places shown: DEC x 
            b = Serial.parseInt();
            if (b>10) {b = 10; }
            decimals = b;
            break;
          
    case 21:    // Clear the LCD
            clrLCD();
            break;
            
       }
  }
}

Basically, I need help figuring out how to take what's in Operation and parsing it so it can be calculated... I thought it's something I already had down, but apparently only when dealing with the Serial port. I should add that the code does respond to the operations like ADD, DIV, SIN, etc. but of course it only prints 0.00000 for everything.

If you have a bit of program memory to spare you can always get the whole line and throw it at a regular expression:

I used that to parse a line from a GPS, for example.

Then once you have the numbers isolated you can use atoi (or similar) to convert them from strings to numbers.

Personally I never use Serial.parseFloat, Serial.parseInt etc. because I like more control over what I am doing.

I suppose you don't want me to warn you not to use String either? Ah well, here is my boilerplate:


Please note that in versions of the IDE up to and including 1.0.3, the String library has bugs as discussed here and here.

In particular, the dynamic memory allocation used by the String class may fail and cause random crashes.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.), as described here for example.

Alternatively, install the fix described here: Fixing String Crashes

Preferably upgrade your IDE to version 1.0.4 or above at: http://arduino.cc/en/Main/Software