Clear Filters
Clear Filters

Best practice for using a physical button and Arduino to control a Matlab GUI

18 views (last 30 days)
I'm working on a matlab app that will be used to control an instrument. One of my requirements is to have a physical button to initiate measurements, but I want to be able to change settings and use the GUI in my app while Matlab waits for a button press.
I have an arduino which interfaces with the button and controls other aspects of the instrument. Most examples use a while loop that polls the status of the button. Polling must be reasonably fast (~60 Hz) to ensure that button presses aren't missed, and that's going to eat up a lot of time on a single-threaded program. Seems like a clunky solution.
I've been taught that the best practice is to have an interrupt service routine to handle button presses like this, and that polling is inconsistent if your software has tasks to perform aside from polling. But, I haven't found any interrupt-like capability in Matlab.
So, what is the best practice initiating an action in Matlab using a physical button?
My current thinking is that I could run a button-polling function using parfeval, so it is running in an independent thread, and then set up a listener in my app to detect when the polling thread detects a change, similar to the suggestion in this thread. I'm figuring out how to implement this now, but help would be appreciated!
This is the first time I've used Matlab to control a physical instrument, so let me know if I'm missing something obvious.

Accepted Answer

Atharva
Atharva on 24 May 2023
Hey Theo,
Using a button to initiate an action in MATLAB can be achieved through different approaches. Your idea of using a button-polling function with parfeval and setting up a listener in your app can work well. Here's a general outline of how you can implement this approach:
  1. Connect the physical button to your MATLAB system: Ensure that the physical button is connected to your computer or microcontroller and is recognized as an input device.
  2. Create a polling function: Write a MATLAB function that continuously polls the state of the button. This function should check the state of the button at regular intervals and return the state (pressed or released). You can use the parfeval function to run this polling function asynchronously in an independent thread. Here's an example:
function buttonState = pollButton()
% Code to read the state of the button
% Return the button state (pressed or released)
end
% Run the button polling function asynchronously
f = parfeval(@pollButton, 0);
3.Create an app with a listener: In your MATLAB app, create a listener object that listens for changes in the button state.
The listener should be triggered whenever the button state changes (from pressed to released or vice versa). Inside
the listener callback, you can perform the desired action. Here's an example:
classdef MyApp < matlab.apps.AppBase
properties
ButtonListener
end
methods (Access = protected)
function createComponents(app)
% Create the components of your app
% Create the button listener
app.ButtonListener = event.listener(f, 'ObjectCompleted', @app.buttonStateChanged);
end
function buttonStateChanged(app, ~, ~)
% Callback function triggered when the button state changes
buttonState = f.fetchOutputs(); % Get the button state from the polling function
if buttonState == 'pressed'
% Perform the desired action
end
end
end
end
% Create and run the app
app = MyApp();
app.run();
In this approach, the button polling function runs asynchronously in a separate thread, allowing your app to remain responsive while continuously checking the button state. Whenever the button state changes, the listener callback is triggered, and you can perform the desired action based on the button state.
Note that the implementation details may vary depending on the specific hardware and setup you are using to connect the physical button to MATLAB. Make sure to adapt the code to match your specific requirements and hardware configuration.
Additionally, consider handling any necessary debouncing or noise filtering for the button input to ensure reliable button state detection.
  2 Comments
Joaquín Costa
Joaquín Costa on 13 Jan 2024
Hi!
I tried implementing this solution but didn't manage to make it work. Im trying to make a lamp (called 'READYFORSERVICELamp') change colors when I press a button on my circuit (pressing the button makes the voltage go to over 1.9v which is measured in the A0 pin of my Arduino board). I'm not really sure how the listener function works so I'm not sure what's wrong.
classdef InterfaceControle_V2 < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
(...)
end
properties (Access = private)
a
ButtonListener
end
methods (Access = private)
function state = pollButton(app)
aux = readVoltage(app.a,'A0');
if aux > 1.9
state = 1;
else
state = 0;
end
end
function CreateComponents(app)
app.ButtonListener = event.listener(f, 'ObjectCompleted', @app.buttonStateChanged);
end
function buttonStateChanged(app, ~, ~)
% Callback function triggered when the button state changes
state = f.fetchOutputs(); % Get the button state from the polling function
if state == 1
app.READYFORSERVICELamp.Color = 'g';
else
app.READYFORSERVICELamp.Color = 'r';
end
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function initialize(app)
app.a = arduino('COM8','UNO'); %define the global variable for the arduino card
f = parfeval(@pollButton,0);
end
Thanks!
Theo Husby
Theo Husby on 14 Jan 2024
Hi Joaquin,
I don't have a rigorous solution to your problem, but I think your pollButton function needs to have a loop to check the button status. Something like:
function state = pollButton(app)
aux = readVoltage(app.a,'A0');
while aux < 1.9
aux = readVoltage(app.a,'A0');
end
state = 1;
end
This will run until aux exceeds 1.9. You'll also have to call parfeval again at the end of your buttonStateChanged callback so that it starts polling again after state has changed. In your implementation, parfeval will execute just once and then exit.
side note: readDigitalPin is probably more appropriate if you are using a button. Not sure about the specifics of your circuit though.
After I wrote this question, I decided to solve this problem a different way. If you're comfortable with C, coding the button handling logic (debounce, etc.) in the arduino, and then communicating with Matlab through serial is a more flexible solution. While it's significantly more work to implement than the matlab-only arduino toolbox, it was helpful for my application because I needed my arduino to time things accurately and polling it with parfeval way eats up a lot of time with serial communication from the polling. I set my arduino up to send a byte over serial whenever the button was pressed, and then used a bytesAvailableFcn callback to monitor the serial port. The best approach depends on what you want to do with the arduino.

Sign in to comment.

More Answers (0)

Categories

Find more on MATLAB Support Package for Arduino Hardware in Help Center and File Exchange

Products


Release

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!