Hi everyone!
I'm having an issue where I'm using a Pro Micro to send keyboard commands to use as part of a custom video-game controller.
But when I close out of the serial monitor the keyboard commands become erratic.
For example, when I push the button with the serial monitor open it types a "c" normally.
However, as soon as I close it out it will send it 3-4 times.
If anyone sees anything wrong or knows how to fix this, let me know!
if ((digitalRead(cameraChange) == LOW)) {
Keyboard.press('c'); //99 = lower-case "c".
cameraReleased = false;
Serial.println("Camera pressed!");
delay(30);
} else if ((digitalRead(cameraChange) == HIGH)) {
Keyboard.release('c'); // 99 = lower-case c.
if (cameraReleased == false) {
Serial.println("Camera released!");
cameraReleased = true;
}
}
If you close the serial monitor, the code can't get rid of the serial data; note that this is specific for boards with native USB. You can use Serial.availableForWrite() to check if there is still sufficient space in the serial buffer.
if ((digitalRead(cameraChange) == LOW)) {
Keyboard.press('c'); //99 = lower-case "c".
cameraReleased = false;
if(Serial.availableForWrite() > 20)
{
Serial.println("Camera pressed!");
}
delay(30);
} else if ((digitalRead(cameraChange) == HIGH)) {
Keyboard.release('c'); // 99 = lower-case c.
if (cameraReleased == false) {
if(Serial.availableForWrite() > 20)
{
Serial.println("Camera released!");
}
cameraReleased = true;
}
}
The 20 is large enough to hold the message that you want to print plus the <CR><LF> that is added by println.
You must be using a USB-capable processor so I expect you have:
Serial.begin(115200);
while (!Serial) {}
That will hang your sketch until the USB connection is established.
You can change it to:
while (!Serial && millis() < 5000) {}
That will give up waiting for the USB connection if it takes longer than five seconds.
Thank you, I tried this but it seems to be only marginally better. It seems like the whoile board lags after I close the serial monitor.
Show your full code. You will have to implement the Serial.availableForWrite() for every print that you do; and the 20 that I used needs to be sufficient space to fit the full message. If you e.g. print all letters of the alphabet in one go, it would be 26 (plus 2 in case you use println).
Rather than a press many times as long as the button is pressed, try just sending once when it is first pressed. Same for release. Also, check for a USB connection before trying to print.
if (cameraReleased
&& (digitalRead(cameraChange) == LOW)) {
Keyboard.press('c'); //99 = lower-case "c".
cameraReleased = false;
if (Serial) Serial.println("Camera pressed!");
}
if (!cameraReleased
&& (digitalRead(cameraChange) == HIGH)) {
Keyboard.release('c'); // 99 = lower-case c.
cameraReleased = true;
if (Serial) Serial.println("Camera released!");
}
}
[/quote]
Here is the entire code:
/*
//pin outs are as follows:
21 = self centre
14 = steer left.
18 = steer right
9, CAMERA
7, CAMERA GND
*/
#include <Keyboard.h>;
//declare global variables
void checkPrint(String i) {
if ((Serial) == true) {
Serial.println(i);
}
}
//pin variables
int selfCentrePin = 21;
int steerLeft = 14;//14
int steerRight = 18;//18 these are the original values
int cameraChange = 9;
int cameraGND = 7;
//functionality variables
boolean switchActivated = false;
boolean steeringLeft = false;
boolean steeringRight = false;
boolean cameraReleased = true;
void setup() {
// put your setup code here, to run once:
pinMode(steerLeft, INPUT_PULLUP);
pinMode(steerRight, INPUT_PULLUP);
pinMode(selfCentrePin, INPUT_PULLUP);
pinMode(cameraChange, INPUT_PULLUP);
pinMode(cameraGND, OUTPUT);
digitalWrite(cameraGND, LOW);
Keyboard.begin();
Serial.begin(9600);
}
void loop() {
Serial.println(Serial.availableForWrite());
delay(250);
//check to see if the switch has been posititioned to steer the truck.
if (digitalRead(steerLeft) == LOW) {
//make sure you're not sending two commands at once.
if (steeringRight == true) {
Keyboard.release(KEY_F2);
checkPrint("Fixed multiple inputs!");
steeringRight = false;
}
//if it has press the button
Keyboard.press(KEY_F1);
checkPrint("Turning left!");
//make sure the arduino knows that the switch is active.
switchActivated = true;
//again make sure the arduino knows that it is steering left.
steeringLeft = true;
} else if (digitalRead(steerRight) == LOW) {
if (steeringLeft == true) {
Keyboard.release(KEY_F1);
if (Serial.availableForWrite() > 20) {
Serial.println("Fixed multiple inputs!");
}
steeringLeft = false;
}
Keyboard.press(KEY_F2);
if (Serial.availableForWrite() > 20) {
Serial.println("Turning Right!");
}
switchActivated = true;
steeringRight = true;
} else {
if ((switchActivated == true) && (digitalRead(selfCentrePin) == LOW)) {
Keyboard.release(KEY_F1);
Keyboard.release(KEY_F2);
if (Serial.availableForWrite() > 20) {
Serial.println("released!");
}
switchActivated = false;
steeringLeft = false;
steeringRight = false;
}
}
if ((digitalRead(cameraChange) == LOW)) {
if (cameraReleased == true) {
Keyboard.press(99); //99 = lower-case "c".
cameraReleased = false;
if (Serial.availableForWrite() > 20) {
Serial.println("Camera pressed!");
}
delay(50);
/*Keyboard.release(99);
delay(50);*/
}
} else if ((digitalRead(cameraChange) == HIGH)) {
Keyboard.release(99); // 99 = lower-case c.
delay(30);
if (cameraReleased == false) {
if (Serial.availableForWrite() > 20) {
Serial.println("Camera released!");
}
cameraReleased = true;
}
}
}
Update:
Here seems to be the fix.
I have made sure that it now checks to ensure that both the Serial is available and that there is enough buffer space before sending the print command.
If seems to require both of these steps (not entirely sure why) for this patch to work.
I made a function that looks like this:
void checkPrint(String i) {
if ((Serial) == true) {
int lengthOfString = i.length();
lengthOfString += 2;
if (Serial.availableForWrite() > (lengthOfString)) {
Serial.println(i);
}
}
}
I will then replaced every instance of Serial.println("Your Text Here"); with checkPrint("Your Text Here);
Because println adds two characters, it would be better to replace if (Serial.availableForWrite() > (lengthOfString)) by if (Serial.availableForWrite() > lengthOfString + 2).
There already is lengthOfString += 2;
OOPS, missed that for some reason. Thanks.