Main Content

Results for

Four (of many) new features for Apps in MATLAB R2021a

These four new features are the solutions to many inquiries in the Answers forum that continue to receive hundreds of views per month long after they were asked.

Table of Contents

  • Keyboard Shortcuts for UI Components
  • Programmatically scroll UITables
  • Figure always on top
  • UI hyperlink component
  • Demo app: Keyboard shortcut challenge

Keyboard Shortcuts for UI Components

Keyboard shortcuts can now change the focus and make contiguous and non-contiguous selections in ListBox, Table, DatePicker, and ColorPicker menus created in uifigures. The table below summarizes the shortcuts made available in R2021a ( release notes ).

Reminder: in MATLAB R2020b and later you can change the tab order of objects in an app by changing their stack order in AppDesigner using the Reorder tool in the drop-down menu or by right-clicking the component and selecting Reorder from the menu (see R2020b release notes and a screenshot in the Answers forum ).

Programmatically scroll UITables

The scroll function was added in R2016a but as of R2021a it can be used with uitables to programmatically scroll to the top, bottom, left, or right of a table or to a specific row, column or cell ( release notes ). Combined with a uistyle (R2019b) you can scroll to and highlight any part of the uitable.

Syntax examples:

Figure always on top

Figures created with uifigure now have an additional WindowStyle property: 'alwaysontop' ( release notes ). Figures with this setting will stay on top of other windows but unlike the modal option, other windows are still accessible.

See the WindowStyle property description for tips on setting and changing this property.

To toggle the AlwaysOnTop state of your app using a checkbox, state button, or another UI component, follow this callback function template,

function alwaysOnTopCheckBoxValueChanged(app, event)
    value = app.alwaysOnTopCheckBox.Value;
    if value
        app.UIFigure.WindowStyle = 'alwaysontop';
    else
        app.UIFigure.WindowStyle = 'normal';
    end
end

UI hyperlink component

Use the uihyperlink function or the UI hyperlink component in App Designer or a uifigure to add and configure a clickable link ( release notes ). The hyperlink can be assigned to a figure, panel object, tab object, ButtonGroup, or GridLayout object when created in a uifigure. In addition to setting the text and URL, there are lots of properties to control the text format including the VisitedColor property that controls the color of the text after the link is clicked and an optional user-defined HyperlinkClickedFcn function that is evoked when the link is clicked.

Demo app: Keyboard shortcut challenge

The attached zip file contains an app, keyboardShortcutsDemo_R2021a.mlapp , that demonstrates these 4 features. The app displays the extent of arctic sea ice from 1979 to 2016 during the months when extent typically maximizes and minimizes.

Mouseless challenge: After opening the app, without using your mouse, try the following.

  • Select a month (September or March) and any number of years from the list boxes
  • Navigate through the Date Picker and select a date within the range or your selected years (disabled when only 1 year is selected).
  • Navigate to the always-on-top checkbox to pin the app to the top of other windows.
  • Navigate to the text box and enter a year that appears in the uitable to go to that row in the uitable (disabled when only 1 year is selected).
  • Navigate to the URL and press Enter to open the website containing the raw data.

Download the attached zip file, FourNewAppFeatures_R2021a.zip, for a Live script copy of this thread and an app that demonstrates each feature.

Hello, was hoping to share my Public Sharing page with others without the need for them to log in. In Chrome, it works only if I open a page in Incognito Mode, then I can view without logging in.

Also, from FB Messenger, I can click the link and it will open a page on my Iphone without needing login, but some others, including me in Chrome click the link and it says I need to log in first.

Any ideas how to fix that?

Hi!Yersterday i finally connected my rpi 3B+ with sensehat via Thingspeak.All worked just fine but today when i started the stream(run-prod.sh) number of entries appeared stuck on 0.I created a new channel but the problem still persist.If someone could help much obliged.P.S is a project for faculty.Any help would be helpfull.

Regards, Andrei.

Hi, I am currently trying to use my FPGA to retrieve data from my Thingspeak LED status graph. Previously, I tried this with my Mode NCU. As I gave "1" to one of the fields in my LED status channel, my LED will light up. It was successfully done. Now, I want to try with FPGA (To be specific, it is Digilent's Zybo Z720 board).

I have learnt that I need to use Pmod ESP32 to achieve this function. Previously, I used the AT commands to send my data from sensor to Thingspeak channel.

Here is the code: void receiveData(XTime time){ XTime tEnd, tCur; u8 recv_buffer=0; u32 num_received=0;

XTime_GetTime(&tCur); tEnd = tCur + (time * COUNTS_PER_SECOND); do { num_received = ESP32_Recv(&ESP32, &recv_buffer,1); if(num_received >0){ num_received = ESP32_Recv(&ESP32, &recv_buffer,1); xil_printf("%c", recv_buffer); } if(tCur == tCur + COUNTS_PER_SECOND){ countdown = countdown -1; } else XTime_GetTime(&tCur); } while (tCur < tEnd);

}

void setWifiMode(void){ u8 tx[]="AT+CWMODE=3\r\n"; u32 num = strlen((char *) tx); xil_printf((char *) tx); ESP32_SendBuffer(&ESP32, tx, num); usleep(100); receiveData(3); }

void connectWifi(void){ u8 tx[] = "AT+CWJAP=\"________\",\"_____________\"\r\n"; u32 num = strlen((char *) tx); xil_printf((char *) tx); ESP32_SendBuffer(&ESP32, tx, num); usleep(100); receiveData(30); }

void establishConnection(void){ u8 tx[] = "AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80\r\n"; u32 num = strlen((char *) tx); xil_printf((char *) tx); ESP32_SendBuffer(&ESP32, tx, num); receiveData(10); }

void cipsend(float temp, u16 co2, u8 light, float humidity){ u8 command[150]; u8 finalcmd[50]; //field1 Ph field2 Temp field3 co2 field4 humidity field5 light sprintf((char*)command, "GET http://api.thingspeak.com/update?api_key=____________&field1=0&field2=%d.%02d&field3=%d&field4=%d.%02d&field5=%d\r\n" ,(int) temp_degc,((int) (temp_degc * 100)) % 100,co2,(int) hum_perrh,((int) (hum_perrh * 100)) % 100,light); u32 length = strlen((char*)command); sprintf((char*)finalcmd, "AT+CIPSEND=%d\r\n", (int)length); u32 cmdlength =strlen((char*)finalcmd); xil_printf("Length %d\r\n", length); xil_printf((char *)finalcmd); ESP32_SendBuffer(&ESP32, finalcmd, cmdlength); sleep(1); xil_printf((char *)command); ESP32_SendBuffer(&ESP32, command, length); receiveData(4); }

Now, I am a bit confusing with the reverse part (receiving data from Thingspeak). Should I use the same AT command like AT+CIPSEND, or change the AT command. Or should I need to do something like Json Parsing.

I appreciate your favourable response. Thanks Luke

Climate Data Toolbox was developed by Chad Greene, a postdoctoral research fellow at NASA Jet Propulsion Laboratory, and Kelly Kearney, a research scientist at University of Washington. The Climate Data Toolbox is freely downloadable from File Exchange and has been downloaded over 5,000 times since 2019.

The toolbox was inspired by one big idea: There are a common set of tasks related to data processing, analysis and visualization that Geoscience researchers and students working with climate data typically perform. Greene and coauthors make the case in their paper published in Geochemistry, Geophysics, Geosystems that having everyone who is tackling climate analysis separately recoding these same tasks is not a good use of time, for the individual or the collective, as it takes away from other more innovative climate work. Better to have a set of reusable, publicly shared functions for those repetitive tasks.

Recently, Lisa Kempler published an example of how to look at the change in temperature of the Pacific Ocean over time using MATLAB and the Climate Data Toolbox.

Try the example here by loading up MATLAB, installing the Climate Data Toolbox, and following along the tutorial.

Hello, I am a beginner for IoT. I found ThingSpeak is an awesome platform for IoT. I am having a problem in the API write request. Whenever we send API request for writing a channel feed, the URL return 0, if is is failure and return a non zero value for success. Is there any way to capture this data? Also, is there any way to block the return of the value from this API.

Thanks...

Hi, currently I am working on a dashboard that uses Thingspeak and Mendix. I am using a GaugeChart in Mendix and it receives data from Thingspeak. However, I have to refresh the page manually to see the new sensor values. One of my answers I got is that it is the Thingspeak that is not sending the data properly.

Long story short, he said that I have to expose API from Mendix which will produce a URL link (similar to Thingspeak API URL link) and in Thingspeak, I have to put that URL into Thingspeak. I have been looking around in Thingspeak and the closest thing that allows me to put an external URL is at ThingHTTP. However, we did not make use of ThingHTTP when communicating with our hardware and for Mendix, I only use Call rest API to receive data. Please help!

MATLAB EXPO 2021 is May 4-5, 2021!

MATLAB EXPO is open to everyone:

  • It's free.
  • It's online.
  • Register now. [Edit: Registration is closed]

Industry Tracks:

  • AI in Engineering
  • Modeling and Simulation
  • Implementation, Verification, and DevOps
  • Algorithm Development and Deployment
  • 5G and Radar
  • FPGA, ASIC, and SoC Design
  • Autonomous Systems
  • Teaching with MATLAB and Simulink
  • Cloud and IoT
  • Motor and Power Control

Special Event: Women in Tech Ignite Session

Women in Tech Ignite is a networking event where the MATLAB community can meet and be inspired by a diverse group of women engineers and scientists and hear about the innovative ways they use MathWorks products. Attendees of all genders are welcome.

[Edit: Registration is closed]

Hello! I use 3 sensors and send the data via esp8266 to thingspeak. I want to take the data from thingspeak and send it to an html page created by me but I haven't worked with thingspeak so far and I don't know how I should proceed. Is there anyone who can help me? An example code that takes data from thingspeak would help me a lot.

We introduced Difficulty Rating functionality during 2020 Cody Contest. Our Cody players have provided difficulty rating for most of the problems. Now we are displaying the ratings in the Problems list view.

Sorting and Filtering to follow...

I am a student with 2 others in my project. we connected 3 RPi sending temp and pressure to my Project channel using fields 1,2 3,4, and 5,6 we were publishing the data from 3 python scripts i wrote and everything was working great and the charts were update then it just stopped publishing. I thought it might be a license/message problem as i was sending information every 1 sec so I changed it to ever 60 sec. Everything worked fine again for 5 minutes and then it all crashed It will not let me reconnect and i can't see any data updating from the other Rpi's any Do you have a technical help line or how should i proceed.

I find this is possible to do, but how does one read the data back.

Buena tarde, he estado tratando de cambiar toda la configuración, con distintos correos para ver si me lanzaba el aviso de fuera de rango de temperatura, pero no he podido lograrlo. También baje una app Ilo thingspeak, para celular, pero tampoco me activa las alarmas. les agradecería su ayuda. gracias. Mensajes a correo,willfree66@outlook.com

Im not able to upload a csv file which I have created using rpi. The csv file is as follows

datetime field1 field2 field3 2021-04-19-10:59:46 0 0 0 2021-04-19-10:59:47 122 -1 265 2021-04-19-10:59:48 123 -1 265 2021-04-19-10:59:49 115 0 266 2021-04-19-10:59:50 122 -7 265 2021-04-19-10:59:51 117 -5 265 the error I get is invalid csv file or contains duplicate timestamp or missing timestamps. If someone could point out the mistake, it would be helpful.

I am having issues with my two channels

https://thingspeak.com/channels/513058

https://thingspeak.com/channels/971602

when I try to view them without being logged in. The channels are public (and have always been that way). I have those links on my desktop and also have them as favourites in my browser. Using any of these will ead to the following behavior

  1. The public view of the channels starts to load
  2. Widgeds etc start to be filled (see attached file Scrennhunter_309.png)
  3. The display view closes after a few seconds and shows the Mathwork/Thingspeak sign on screen with a message box saying "Signed out successfully" (see attached file ScreenHunter_310.png)

In order to circumvent the issue, I have

  • deleted the cache
  • deleted all mathwork cookies
  • deleted all thingspeak cookies

The issue prevails. I have then

  • deleted the cache
  • deleted all cookies

The issue prevails.

I tried

  • Firefox browser Version 78.9.0esr (32-Bit)
  • Internet explorer, newest Version
  • Microsoft Edge, newest Version

The issue prevails

I tried 3 different PCs, each running Windows 10 pro 20H2 (build 19042.928) with all current updates installed

The issue prevails

I tried my Safari browser on my ipad Pro - no issue there!!, neither on my iPhone.

What am I missing? What can/shoud I do?

With best regards vom Germany

Volker Bandke

Everytime I try to log onto my thingspeak the webpage keeps refreshing. Have to stop loading page and every page I go to keeps refreshing.

Introducing content recommendations, a new feed on the community home page with personalized content just for you. MATLAB Central has hundreds of thousands of posts, including files, blogs, questions, and answers. We’re always looking for opportunities to better serve the community as it continues to grow so that visitors can easily help one another and ultimately find what they're looking for.

MATLAB Central has been around for a long time, 20 years this year - more on this milestone in a separate post later. With so much great content it can be a challenge to find what you're looking for or discover new things. We have search and browsing capabilities across the community but even with these robust features you still might not discover some very interesting or relevant content. In the spirit of trying to make sure you don't miss out, we've just released our first version of our recommended content feed. You can see this new feed on the community home page, visible by default via the 'For You' tab.

Recommendations are pulled from across MATLAB Central based on what we think would be relevant to you. We think we have a good starting point and plan on tweaking the algorithms now that it's live. So, expect the feed to only get more relevant over time.

We hope you will find this feature helpful and as always please reply with any feedback you may have.

Hi,

 Recently, I'm trying to view any Public channel (including my public channel). It opens the channel a second and redirects to the login page. Is there any way to see a public channel without login?

S.

I'm testing use of a 3g dongle which is pay as go (in the UK). I'm sending messages to Thingspeak (via Python on Pi) but the credit allowance decrease indicates several megabytes have been used. Even if one message is 1,000 bytes then after 1,000 messages like this I'd expect to lose 1 megabyte of credit but instead it's 10 MB (I'm sending https://api.thingspeak.com/update?api_key=xxxxxxxxxxxxx&field3=12345 ) Has anyone experience of data logging over a mobile data dongle and how much it should cost ?

New in R2021a, LimitsChangedFcn

LimitsChangedFcn is a callback function that responds to changes to axis limits ( release notes ). The function responds to axis interaction such as panning and zooming, programmatically setting the axis limits, or when axis limits are automatically adjusted by other processes.

LimitsChangedFcn is a property of ruler objects which are properties of axes and can be independently set for each axis. For example,

ax = gca(); 
ax.XAxis.LimitsChangedFcn = ... % Responds to changes to XLim
ax.YAxis.LimitsChangedFcn = ... % Responds to changes to YLim
ax.ZAxis.LimitsChangedFcn = ... % Responds to changes to ZLim

Previously, a listener could be assigned to respond to changes to axis limits. Here are some examples.

However, LimitsChangedFcn responds more reliably than a listener that responds to setting/getting axis limits. For example, after zooming or panning the axes in the demo below, the listener does not respond to the Restore View button in the axis toolbar but LimitsChangedFcn does! After restoring the view, try zooming out which does not result in changes to axis limits yet the listener will respond but the LimitsChangedFcn will not. Adding objects to axes after an axis-limit listener is set will not trigger the listener even if the added object expands the axis limits ( why not? ) but LimitsChangedFcn will!

ax = gca(); 
ax.UserData.Listener = addlistener(ax,'XLim','PostSet',@(~,~)disp('Listener')); 
ax.XAxis.LimitsChangedFcn = @(~,~)disp('LimitsChangedFcn')

How to use LimitsChangedFcn

The LimitsChangedFcn works like any other callback. For review,

The first input to the LimitsChangedFcn callback function is the handle to the axis ruler object that was changed.

The second input is a structure that contains the old and new limits. For example,

    LimitsChanged with properties:
      OldLimits: [0 1]
      NewLimits: [0.25 0.75]
         Source: [1×1 NumericRuler]
      EventName: 'LimitsChanged'

Importantly, since LimitsChangedFcn is a property of the axis rulers rather than the axis object, changes to the axes may clear the LimitsChangedFcn property if the axes aren't held using hold on. For example,

% Axes not held
ax = gca(); 
ax.XAxis.LimitsChangedFcn = @(ruler,~)title(ancestor(ruler,'axes'),'LimitsChangedFcn fired!'); 
plot(ax, 1:5, rand(1,5), 'o')
ax.XAxis.LimitsChangedFcn
ans =
    0×0 empty char array
% Axes held
ax = gca(); 
hold(ax,'on')
ax.XAxis.LimitsChangedFcn = @(ruler,~)title(ancestor(ruler,'axes'),'LimitsChangedFcn fired!'); 
plot(ax, 1:5, rand(1,5), 'o')
ax.XAxis.LimitsChangedFcn
ans =
  function_handle with value:
    @(ruler,~)title(ancestor(ruler,'axes'),'LimitsChangedFcn fired!')

Demo

In this simple app a LimitsChangedFcn callback function is assigned to the x and y axes. The function does two things:

  1. Text boxes showing the current axis limits are updated
  2. The prying eyes that are centered on the axes will move to the new axis center

This demo also uses Name=Value syntax and emoji text objects !

Create app

h.fig = uifigure(Name="LimitsChangedFcn Demo", ...
    Resize="off");
h.fig.Position(3:4) = [500,260];
movegui(h.fig)
h.ax = uiaxes(h.fig,...
    Units="pixels", ...
    Position=[200 26 250 208], ...
    Box="on");
grid(h.ax,"on")
title(h.ax,"I'm following you!")
h.eyeballs = text(h.ax, .5, .5, ...
    char([55357 56385 55357 56385]), ...
    HorizontalAlignment="center", ...
    FontSize=40);
h.label = uilabel(h.fig, ...
    Text="Axis limits", ...
    Position=[25 212 160 15], ...
    FontWeight="bold",...
    HorizontalAlignment="center");
h.xtxt = uitextarea(h.fig, ...
    position=[25 191 160 20], ...
    HorizontalAlignment="center", ...
    WordWrap="off", ...
    Editable="off",...
    FontName=get(groot, 'FixedWidthFontName'));
h.ytxt = uitextarea(h.fig, ...
    position=[25 165 160 20], ...
    HorizontalAlignment="center", ...
    WordWrap="off", ...
    Editable="off", ...
    FontName=get(groot, 'FixedWidthFontName'));
h.label = uilabel(h.fig, ...
    Text=['X',newline,newline,'Y'], ...
    Position=[10 170 15 38], ...
    FontWeight="bold");

Set LimitsChangedFcn of x and y axes

h.ax.XAxis.LimitsChangedFcn = @(hObj,data)limitsChangedCallbackFcn(hObj,data,h,'x');
h.ax.YAxis.LimitsChangedFcn = @(hObj,data)limitsChangedCallbackFcn(hObj,data,h,'y');

Update text fields

xlim(h.ax, [-100,100])
ylim(h.ax, [-100,100])

Define LimitsChangedFcn

function limitsChangedCallbackFcn(rulerHand, limChgData, handles, xy)
% limitsChangedCallbackFcn() responds to changes to x or y axis limits.
% - rulerHand: Ruler handle for x or y axis that was changed (not used in this demo)
% - limChgData: LimitsChanged data structure
% - handles: structure of App handles
% - xy: either 'x' or 'y' identifying rulerHand
switch lower(xy)
    case 'x'
        textHandle = handles.xtxt;
        positionIndex = 1; 
    case 'y'
        textHandle = handles.ytxt;
        positionIndex = 2; 
    otherwise
        error('xy is a character ''x'' or ''y''.')
end
% Update text boxes showing rounded axis limits
textHandle.Value = sprintf('[%.3f, %.3f]',limChgData.NewLimits);
% Move the eyes to the new center position
handles.eyeballs.Position(positionIndex) = limChgData.NewLimits(1)+range(limChgData.NewLimits)/2; % for linear scales only!
drawnow
end

See attached mlx file for a copy of this thread.

Highlight Icon image