Arduino Micro keyboard - button

I'm trying to make a keyboard with my Arduino Micro. Circuit is OK but I having some issues with the code and hope you can gimme a hand here. For now I'm just trying with one key in pin 8 that should open a new tab in the web browser when you press the button. Just one key for now to see if it works.
I have this code:
#include <Keyboard.h>
void setup() {
// put your setup code here, to run once:
pinMode(8, INPUT);
Keyboard.begin(); // setup keyboard
}
void loop() {
// check buttons
if (readButton(8)) {
doAction(8);
}
}
boolean readButton(int pin) {
// check and debounce buttons
if (digitalRead(pin) == HIGH) {
delay(10000);
if (digitalRead(pin) == HIGH) {
return true;
}
}
return false;
}
void doAction(int pin) {
// perform tasks
switch (pin) {
case 8:
// CMD + T (new tab, Chrome)
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('t');
delay(10000);
Keyboard.releaseAll();
break;
}
}
But once I upload the code it starts opening new tabs automatically for 10 seconds and then stops for another 10 seconds and starts again. All this without pressing the button, it does it automatically. Any idea what I have wrong?

You're using Keyboard.press() which according to the documentation
When called, Keyboard.press()functions as if a key were pressed and held on your keyboard.
That is, you're pressing and holding the key. And so the Arduino keeps sending the key sequence CMD + T (new tab, Chrome) to your PC and thus Chrome will keep opening new tabs.
You need to release after giving enough delay so that you send only one key press to the application.
To end the key press, use Keyboard.release() or Keyboard.releaseAll().
The 10 second is evident from the delay(10000) you've used.

Related

Is there a way for the arduino to read when a key on the keyboard is pressed? as if it were a button, but without using serial.read

I am trying to implement a function that waits until a key is pressed on the keyboard to start taking readings, so far I do it with serial.read but I would like it to be like reading the state of a button, only with the keyboard, so that it depends more on the software
`void mensage(){
option=Serial.parseInt();
Serial.println(msg1);
while(true)
{
if(Serial.available()>0){
if(Serial.parseInt() == 0){
break;
loop();
}
else if(reset==5){
Serial.end();
//Serial.println(msg1);
Serial.begin(9600);
}
}
}
} `

Turn off analog pins if no serial data for x seconds

I have a program on my computer that sends serial data to my Arduino that dictates the analog write on the Arduino. How can I check if no new serial data has been sent for x seconds and if there isn't do something. E.G:
if (newDataInLastSeconds(10) {
// Do Something...
}```
For this problem you can use a state machine that tracks the state of the serial link, and setup actions that trigger on state transitions. If you also want to setup actions that happen every loop() depending on the state of the link, that's even easier to set up (not shown).
You're likely already checking Serial.available() to see if there are any bytes received on the serial line, correct? All you need to do is create a very simple two-state state machine:
Determine the timeout you want
Keep track of what state the data timeout is in (bool serial_fresh -- you've either received data recently or not)
Keep a record of the last time you received any data
If the serial line is fresh, compare the current time to the previous time. If greater than your timeout, then set fresh to false (this is a state transition) and do the action you want to do
If the serial line is not fresh, and you just received data, then set fresh to true (another state transition) and do the action you want to do on that transition
// start in the unfresh state, we won't transition to fresh until
// we receive the first byte - if this doesn't match what you want change to fit
bool g_serial_fresh = false;
const unsigned long SERIAL_TIMEOUT_MS = 5000; // or however many milliseconds
unsigned long g_last_serial_rx_ms = 0;
void transitionToFresh() {
g_serial_fresh = true;
/* do what you want to do when the link comes back up - turn on ADC */
}
void transitionToStale() {
g_serial_fresh = false;
/* do what you want to do when the link times out - shutdown ADC */
}
bool serialTimedOut() {
return (millis() - g_last_serial_rx_ms) > SERIAL_TIMEOUT_MS;
}
void doStateMachine() {
bool received_data_this_loop = false;
if (Serial.available() > 0) { // assumes you read all available bytes later
g_last_serial_rx_ms = millis();
received_data_this_loop = true;
}
if (!g_serial_fresh && received_data_this_loop) {
transitionToFresh();
}
else if (g_serial_fresh && serialTimedOut()) {
transitionToStale();
}
}
void loop() {
doStateMachine();
/* do regular programmy things here */
}
You can make a function with a while loop that checks for new data during a specific amount of time by using the Serial.available function:
boolean newDataInInterval(long waitInterval){
long startTime = millis();
while (millis() <= (startTime+waitInterval)) {
if (Serial.available() > 0) {
return true;
}
}
return false;
}
Note that waitInterval should be given in milliseconds.

want to change the program coded for push button to a normal switchbutton

So basically, i am working on a Feedback system for Home automation ,which updates the state of the physical button connected to your board onto the Blynk app, so that you can control your lights from both - manually and through the app.I am using an ESP32 board.The state of the physical button connected to the board is taken and is sent to the virtual button on the blynk app,using the native logic of blynk i.e param.asInt().hence i cannot use the logic of the normal switch like:
if (digitalRead(PUSH_BUTTON_1) == LOW) {
digitalWrite(RELAY_PIN_1, HIGH);
// Update Button Widget
Blynk.virtualWrite(VPIN_BUTTON_1, HIGH);}
as i have to use relay1State which is given as param.asInt(); to update the blynk app.Also if i use this type of code i am incurring sequential toggles in the blynk app:
void checkPhysicalButton()
{
if (digitalRead(PUSH_BUTTON_1) == HIGH) {
relay1State =!relay1State;
digitalWrite(RELAY_PIN_1, relay1State);
Blynk.virtualWrite(VPIN_BUTTON_1, relay1State);
}
else {
digitalWrite(RELAY_PIN_1, relay1State);
Blynk.virtualWrite(VPIN_BUTTON_1, relay1State);
}}
so hence i have to use my the pushbutton state logic to remove the sequential toggles .But i am unable to use it as a "Press for on, release for off" switch.
it works as a Toggle switch- "press once to turn and press again to turn it off."
i want to change this logic to Press for on, release for off.Please help me.Thank you!
BLYNK_WRITE(VPIN_BUTTON_1) {
relay1State = param.asInt();
digitalWrite(RELAY_PIN_1, relay1State);
}
void checkPhysicalButton()
{
if (digitalRead(PUSH_BUTTON_1) == LOW) {
// pushButton1State is used to avoid sequential toggles
if (pushButton1State != LOW) {
// Toggle Relay state
relay1State = !relay1State;
digitalWrite(RELAY_PIN_1, relay1State);
// Update Button Widget
Blynk.virtualWrite(VPIN_BUTTON_1, relay1State);
}
pushButton1State = LOW;
} else {
pushButton1State = HIGH;
}

arduino keyboard does not release cause freeze

When I upload this script, my normal keyboard is not usable anymore and I think the right alt key is stuck in, even if I unplug the arduino the problem is still there.
The goal of this is to have a push to talk pedal for teamspeak. I was able to get around the problem using another script that passes itself as a controller but this causes other issues with games since they think I am using a controller all of a sudden.
From what I understand, this code should loop, while the pin is active, it should simulate the right alt key being pressed. When it is done it should release all key pressed by the script. It is hard to debug this since whenever I upload it I have to spend 10 minutes to be able to use my keyboard again.
Any help would be appreciated. Extra info, I am using the arduino leonardo.
#include <Keyboard.h>
void setup() {
// Initialize Button Pins
Keyboard.begin();
pinMode(9, INPUT_PULLUP);
}
void loop() {
Keyboard.releaseAll();
while (digitalRead(9) == HIGH) {
Keyboard.press(KEY_RIGHT_ALT);
delay(500);
}
delay(500);
Keyboard.releaseAll();
// wait for new window to open:
}
Note: without the actual hardware at my disposal for some tests, it is hard to know what is going wrong, so I'll try to review your code looking for possible point of failures.
According to the docs, press() functions as if a key were pressed and held down on the keyboard.
According to these other docs, INPUT_PULLUP effectively inverts the behavior of the INPUT mode, where HIGH means the sensor is off, and LOW means the sensor is on.
Therefore, a simple modification would be:
#include <Keyboard.h>
void setup() {
// Initialize Button Pins
Keyboard.begin();
pinMode(9, INPUT_PULLUP);
}
void loop() {
static bool pressed = false;
// does the pedal close the circuit with GND?
if (digitalRead(9) == HIGH) { // no
if (pressed) {
Keyboard.release(KEY_RIGHT_ALT);
pressed = false;
}
} else { // yes
if (!pressed) {
Keyboard.press(KEY_RIGHT_ALT);
pressed = true;
}
}
delay(500); // waste time
}
Does this code display the same issues?

Arduino Loop and alarm

I'm working on my first physical computing project with an arduino, well actually a seeduino stalker 2.1. I'm building a device to record water collection rates over time.
Getting the project set up and running hasn't been all that hard, until today that is. Inside the main loop I have a call to the a method that handles the logging. I also now an alarm delay to handle a timer repeat I need in order to summarize data and send it via SMS to a recipient number.
The issue is that when the alarm.repeat() is active it preempts the logging of the data. The question is: why is the logging method inside the loop not working when the alarm.delay is there?
void setup() {
Serial.begin(9600);
Wire.begin();
setTime(1,17,0,1,1,13); // set time
Alarm.timerRepeat(60, Repeats); //set repeater
}
void loop(){
logging(); //call logging
Alarm.delay(1300); //for repeater
}
void Repeats(){
Serial.println("the repeater fired"); // just to see it working
}
void logging(){
val = digitalRead(Sensor_Pin); // read Sensor_Pin
if (val == HIGH) {
// If Sensor N.C. (no with magnet) -> HIGH : Switch is open / LOW : Switch is closed
// If Sensor N.0. (nc with magnet) -> HIGH : Switch is closed / LOW : Switch is open
digitalWrite(Led_Pin, LOW); //Set Led low
//Serial.print("status -->");
//Serial.println("low");
//delay(500);
} else {
digitalWrite(Led_Pin, HIGH); //Set Led high
logdata();
}
}
void logdata(){
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File myFile = SD.open("datalog.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
//DateTime now = RTC.now();
//String myString = readTimestamp(now);
time_t t = now();
String aDate = String(year(t))+"/"+String(month(t))+"/"+String(day(t))+" "+String(hour(t))+":"+String(minute(t))+":"+String(second(t));
myFile.println(aDate);
// close the file:
myFile.close();
Serial.println(aDate);
delay(500); } else {
// if the file didn't open, print an error:
// Serial.println("error opening DATALOG.TXT");
}
}
Q: Why must I use Alarm.delay() instead of delay()? A: Task scheduling
is handled in the Alarm.delay function. Tasks are monitored and
triggered from within the Alarm.delay call so Alarm.delay should be
called whenever a delay is required in your sketch. If your sketch
waits on an external event (for example, a sensor change), make sure
you repeatedly call Alarm.delay while checking the sensor.
From the FAQ of the Alarm library. So it looks like Alarm.Delay is just like the standard delay but can be interrupted by scheduled events. Your logging call isn't scheduled, it just happens at the start of the loop. ..is your logging not happening at all? It looks like it should be called at the start of each loop, then a 1300 delay with your repeater firing during the delay.
On your logdata() function you're calling delay(50) instead of Alarm.delay(50).
As caude pointed, you have to use Alarm.delay when a delay is needed, otherwise the delay will mess up with the alarms.
I think you could have done in other way using timer library. If you say the data has to be logged every second,it easier to done by timer.Example code
#include <SimpleTimer.h>
// the timer object
SimpleTimer timer;
// a function to be executed periodically
void repeatMe() {
Serial.print("Uptime (s): ");
Serial.println(millis() / 1000);
}
void setup() {
Serial.begin(9600);
timer.setInterval(1000, repeatMe);
}
void loop() {
timer.run();
}

Resources