Detect key press while running algoirhtm

I would like to build a midi key like instrument which can detect key press fast enough (<100ms) while executing some algorithm and serial communication.

So far I put the key press detection in the main loop and after calling the algorithm subfunction and serial communication part.

The problem is sometimes the algorithm subfunction takes longer than 500ms to run, which means that the key press is delayed or ignored and cause some problem.

What's the best way to handle the key press detection part?

Initially, I want to use the interrupt, but some experience user reminded me that the interrupt may interrrupt the serial communication and cause serious problem.

External interrupts have higher priority than serial, and should cause no problem, but don't do serial I/O in interrupt context.

500ms is an awful long time...

That is an absolute age. What is it doing that takes so long ?

Please post a complete sketch that illustrates the problem, using code tags when you do. See How to get the best out of this forum

As sketch would help but serial output can block for a long time once the TX buffer fills up.
See my tutorial on Arduino Serial I/O for the Real World on how to add non-blocking Serial prints.
For timing your loop see the loopTimer class in my tutorial on Multi-tasking in Arduino

Put your algorithm in a function and break the algorithm in small pieces; the smaller the pieces, the better. Call the function repeatedly.

Your post was MOVED to it's current location as it is more suitable.

Could you take a few moments to Learn and Use The Forum

[quote]Hello.

Welcome to the Arduino Forum. This guide explains how to get the best out of this forum. Please read and follow the instructions below. Being new here you might think this is having rules for the sake of rules, but that is not the case. If you don’t follow the guidelines all that happens is there is a long exchange of posts while we try to get you to tell us what we need in order to help you, which is frustrating for you and frustrating for us.

[/quote]

It will help you get the best out of the forum in the future.

  • Your OS and version can be valuable information, please include it along with extra security you are using.

  • Always list the version of the IDE you are using and the board version if applicable.

  • Use quote or add error messages as an attachment NOT a picture.

  • How to insert an image into your post. ( Thanks @sterretje )

  • Add your sketch where applicable but please use CODE TAGS ( </> )

  • Add a SCHEMATIC were needed even if it is hand drawn

  • Add working links to any specific hardware as needed (NOT links to similar items)

  • Remember that the people trying to help cannot see your problem so give as much information as you can

COMMON ISSUES

  • Ensure you have FULLY inserted the USB cables.

  • Check you have a COMMON GROUND where required. ( Thanks @Perry)

  • Where possible use USB 2.0 ports or a USB 2.0 POWERED HUB to rule out USB 3.0 issues.

  • Try other computers where possible.

  • Try other USB leads where possible.

  • You may not have the correct driver installed. CH340/341 or CP2102 or FT232 VCP Drivers - FTDI

  • There may be a problem with the board check or remove your wiring first.

  • Remove any items connected to pins 0 and 1.

COMPUTER RELATED

  • Close any other serial programs before opening the IDE.

  • Ensure you turn off any additional security / antivirus just to test.

  • There may be a problem with the PC try RESTARTING it.

  • You may be selecting the wrong COM port.

  • Avoid cloud/network based installations where possible OR ensure your Network/Cloud software is RUNNING.

  • Clear your browsers CACHE.

  • Close the IDE before using any other serial programs.

  • Preferably install IDE’s as ADMINISTRATOR or your OS equivalent

ARDUINO SPECIFIC BOARDS

  • CH340/341 based clones do not report useful information to the “get board info” button.

  • NANO (Old Types) some require you to use the OLD BOOTLOADER option.

  • NANO (ALL Types) See the specific sections lower in the forum.

  • NANO (NEW Types) Install your board CORE’s.

  • Unless using EXTERNAL PROGRAMMERS please leave the IDE selection at default “AVRISP mkII”.

  • Boards using a MICRO usb connector need a cable that is both DATA and CHARGE. Many are CHARGE ONLY.

CREATE editor install locations.

  • On macOs ~/Applications/ArduinoCreateAgent-1.1/ArduinoCreateAgent.app/Contents/MacOS/config.ini

  • On Linux ~/ArduinoCreateAgent-1.1/config.ini

  • On Windows C:\Users[your user]\AppData\Roaming\ArduinoCreateAgent-1.1

Performing the above actions may help resolve your problem without further help.

Language problem ?

Try a language closer to your native language:

Thanks to all those who helped and added to this list.

Can't you just do this?
But don't execute all things related to the keypress. Just set a flag that the key was pressed, then quickly return.
Later check the flag and do all the processing.

It runs some signal processing algorithm, which takes quite a while anyway, even on a PC...

I haven't got the code done yet...

Initially, yes. But two things kind of stopped me:

  1. I worry about the interrupt will cause problem on serial.
  2. I have multiple buttons and planning use adc to read the different voltage due to different resistors, It seems the interrupt of this is a little bit complex to implement.

OK, then don't connect the buttons directly to the pins.
Make a button charge a small capacitor when pressed, then measure capacitor charge instead.
Basically a key buffer.

P.S. to clarify - don't use interrupts with this method, just measure the capacitor whenever.

You will have to make clear what the requirement is. Setting a flag or using a capacitor will still delay the reaction till your algorithm is completed. Question is if that is acceptable or not.

Regarding reading Serial, you will not loose data if properly configured; there is a 64 byte buffer so if you don't send more than that while the algorithm is being executed, you will not risk the loss of data.

As I said earlier, break your algorithm in pieces. Take this extremely simple example of an algorithm; it takes about 1.2 seconds to complete (due to the added NOP) on a Nano.

bool algorithm()
{
  static uint64_t result = 0;

  for (uint32_t xCnt = 0; xCnt < numIterations; xCnt++)
  {
    result += xCnt;
    __asm__("nop\n\t");
  }

  sprintf(buffer, "result: 0x%lx%08lx", (uint32_t)(result >> 32), (uint32_t)(result & 0xFFFFFFFF));
  Serial.println(buffer);

  result = 0;
  return true;
}

You can break it into the individual steps as shown below

bool algorithm2()
{
  static uint64_t result = 0;
  static uint32_t xCnt = 0;

  result += xCnt;
  __asm__("nop\n\t");
  xCnt++;

  if (xCnt == numIterations)
  {
    sprintf(buffer, "result: 0x%lx%08lx", (uint32_t)(result >> 32), (uint32_t)(result & 0xFFFFFFFF));
    Serial.println(buffer);
    xCnt = 0;
    result = 0;
    return true;
  }
  else
  {
    return false;
  }
}

Below is an additional function to similate something that needs to be running in parallel with the algorithm; it simply toggles a LED every 250ms.

void heartBeat()
{
  static uint32_t nextUpdateTime = 0;
  static int ledState = LOW;

  if(millis() > nextUpdateTime)
  {
    nextUpdateTime += 250;
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
    //Serial.print(millis()); Serial.print(" > "); Serial.println(ledState);
  }
}

Using the algorithm and the heart beat in loop()

uint32_t numIterations = 0x2FFFF;

char buffer[64];
const byte ledPin = LED_BUILTIN;

void setup()
{
  Serial.begin(57600);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
}

void loop()
{
  static bool isRunning = false;
  static uint32_t startTime;

  heartBeat();

  if (isRunning == false)
  {
    startTime = micros();
    isRunning = true;
  }
  else
  {
    if (algorithm() == true)
    {
      uint32_t endTime = micros();
      Serial.print("duration: "); Serial.println(endTime - startTime);
      isRunning = false;
    }
  }
}

Using algorithm() in loop(), you will not see the LED flash; using agorithm2() in loop(), it will flash as expected.

Hey, is your code finished yet? I would like to see it so that I might be able to use it for my own project.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.