Registered Custom Arduino Library does not work.
5 views (last 30 days)
Show older comments
Hello, I'm using MATLAB R2020a with Arduino Support Package ver. 20.1.1.
For my term project, I want to implement an LCD to my MATLAB code which controls Arduino. LCD library of Arduino IDE does not come in Support Package by default so I tried to add the library with the help of these sources:
I followed the instructions step by step and created the folders as required.
In the end, I managed to add the library, I know that because {'ExampleLCD/LCDAddon' } library is included when I write "listArduinoLibraries" in command window.
Then I tried to use this library in my code;
clear all
close all
clc
addpath('C:\Users\user\Documents\MATLAB\LCD');
port = 'COM5';
board = 'Uno';
a = arduino(port,board, 'Libraries','ExampleLCD/LCDAddon','ForceBuild',true);
But when I run my code as source 1 suggests,I get this error:
"Cannot program board Uno (COM5). Please make sure the board is supported and the port and board type are correct. For more information, see
"Arduino Hardware Troubleshooting.
which is strange because any other code I use (which doesn't have LCD library) works fine. I'd appreciate any help or any guidance in right direction because I'm really confused about the problem. Thank you so much.
I suspect the problem may be syntax related, so I believe I should elaborate on how I added the library. To add custom add-ons on Support package, you need to use a C++ header and a MATLAB Add-on wrapper. I mainly copy-pasted these codes because I'm not familiar with C++ and the syntax is very confusing for me.
C++ Header I used (mainly copy-pasted from https://www.mathworks.com/help/supportpkg/arduinoio/ug/add-lcd-library.html
#include "LibraryBase.h"
#include "LiquidCrystal.h"
#include "LiquidCrystal.cpp"
const char MSG_pLCD_CREATE_LCD_SHIELD[] PROGMEM = "Arduino::pLCD = new LiquidCrystal(%d, %d, %d, %d, %d, %d);\n";
const char MSG_pLCD_INITIALIZE_LCD_SHIELD[] PROGMEM = "Arduino::pLCD->begin(%d, %d);\n";
const char MSG_pLCD_CLEAR_LCD_SHIELD[] PROGMEM = "Arduino::pLCD->clear();\n";
const char MSG_pLCD_PRINT[] PROGMEM = "Arduino::pLCD->print(%s);\n";
const char MSG_SET_CURSOR_LCD_SHIELD[] PROGMEM = "Arduino::pLCD->setCursor(%d, %d);\n";
const char MSG_pLCD_DELETE_LCD_SHIELD[] PROGMEM = "Arduino::delete pLCD;\n";
#define LCD_CREATE 0x00
#define LCD_INITIALIZE 0x01
#define LCD_CLEAR 0x02
#define LCD_PRINT 0x03
#define LCD_DELETE 0x04
byte cursorRow = 0;
class LCD : public LibraryBase
{
public:
LiquidCrystal *pLCD;
public:
LCD(MWArduinoClass& a)
{
libName = "ExampleShield/LCD";
a.registerLibrary(this);
}
void setup()
{
cursorRow = 0;
}
public:
void commandHandler(byte cmdID, byte* dataIn, unsigned int payloadSize)
{
switch(cmdID)
{
case LCD_CREATE: //createLCD
{
byte* pinNumbers = new byte [6];
for (byte i=0; i<6; i=i+1)
{
pinNumbers[i] = dataIn[i];
}
createLCDObject(pinNumbers[0],pinNumbers[1],pinNumbers[2],pinNumbers[3],pinNumbers[4],pinNumbers[5]);
sendResponseMsg(cmdID, 0, 0);
break;
}
case LCD_INITIALIZE: //initializeLCD
{
unsigned int rows = dataIn[0];
unsigned int cols = dataIn[1];
initializeLCD(rows,cols);
clearLCD();
sendResponseMsg(cmdID, 0, 0);
break;
}
// Clear the LCD screen.
case LCD_CLEAR: //clearLCD
{
clearLCD();
cursorRow = 0;
setCursor(0, cursorRow);
sendResponseMsg(cmdID, 0, 0);
break;
}
// Create a command that takes an input and prints it on the LCD screen.
case LCD_PRINT: //printLCD
{
byte* val = {dataIn};
// last byte is the number of rows initialized
// last 2nd byte is the number of columns initialized
char message[payloadSize-1];
for(byte k=0; k<(payloadSize-2); k=k+1)
{
message[k]=val[k];
}
message[payloadSize-2] = '\0';
byte cols = val[payloadSize-2];
byte rows = val[payloadSize-1];
if(cursorRow+1 > rows){
cursorRow = 0;
clearLCD();
}
setCursor(0,cursorRow);
printLCD(message);
cursorRow++;
sendResponseMsg(cmdID, 0, 0);
break;
}
// Delete the LCD object.
case LCD_DELETE: //delete
{
deleteLCDobject();
//reset the cursor position to the first row on deletion
cursorRow = 0;
sendResponseMsg(cmdID, 0, 0);
break;
}
default:
{
// Do nothing
break;
}
// Wrap the LiquidCrystal methods to add debug messages.
public:
void createLCDObject(unsigned int rs,unsigned int enable,unsigned int d4,unsigned int d5,unsigned int d6,unsigned int d7)
{
pLCD = new LiquidCrystal(rs, enable, d0, d1, d2, d3);
debugPrint(MSG_pLCD_CREATE_LCD_SHIELD,rs,enable,d0,d1,d2,d3);
}
void initializeLCD(unsigned int cols,unsigned int rows)
{
pLCD->begin(cols, rows);
debugPrint(MSG_pLCD_INITIALIZE_LCD_SHIELD, cols, rows);
}
void clearLCD()
{
pLCD->clear();
debugPrint(MSG_pLCD_CLEAR_LCD_SHIELD);
}
void printLCD(char message[])
{
pLCD->print(message);
debugPrint(MSG_pLCD_PRINT, message);
}
void setCursor(byte column, byte row)
{
pLCD->setCursor(column, row);
debugPrint(MSG_SET_CURSOR_LCD_SHIELD,column,row);
}
void deleteLCDobject()
{
delete pLCD;
debugPrint(MSG_pLCD_DELETE_LCD_SHIELD);
}
};
The Add-on wrapped code I used (mainly copy-pasted from https://www.mathworks.com/help/supportpkg/arduinoio/ug/add-lcd-library.html
classdef LCDAddon < matlabshared.addon.LibraryBase
properties(Access = private, Constant = true)
LCD_CREATE = hex2dec('00')
LCD_INITIALIZE = hex2dec('01')
LCD_CLEAR = hex2dec('02')
LCD_PRINT = hex2dec('03')
LCD_DELETE = hex2dec('04')
end
properties(Access = protected, Constant = true)
LibraryName = 'ExampleLCD/LCDAddon'
DependentLibraries = {}
LibraryHeaderFiles = 'LiquidCrystal/LiquidCrystal.h'
CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'src', 'LiquidCrystal.h')
CppClassName = 'LCD'
end
properties(Access = private)
ResourceOwner = 'ExampleLCD/LCDAddon';
Rows
Columns
end
methods(Hidden, Access = public)
% InputPins is user input and contains the pins that connect the LCD Data Pins and the arduino
function obj = LCDAddon(parentObj,varargin)
if(nargin < 7)
matlabshared.hwsdk.internal.localizedError('MATLAB:narginchk:notEnoughInputs');
elseif nargin > 7
matlabshared.hwsdk.internal.localizedError('MATLAB:narginchk:tooManyInputs');
end
try
p = inputParser;
addParameter(p, 'RegisterSelectPin',[]);
addParameter(p, 'EnablePin', []);
addParameter(p, 'DataPins', []);
parse(p, varargin{1:end});
catch e
throwAsCaller(e);
end
obj.Parent = parentObj;
obj.RegisterSelectPin = p.Results.RegisterSelectPin;
obj.EnablePin = p.Results.EnablePin;
obj.DataPins = p.Results.DataPins;
inputPins = [cellstr(obj.RegisterSelectPin) cellstr(obj.EnablePin) obj.DataPins];
obj.Pins = inputPins;
count = getResourceCount(obj.Parent,obj.ResourceOwner);
% Since this example allows implementation of only 1 LCD
% shield, error out if resource count is more than 0
if count > 0
error('You can only have 1 LCD shield');
end
incrementResourceCount(obj.Parent,obj.ResourceOwner);
createLCD(obj,inputPins);
end
function createLCD(obj,inputPins)
try
cmdID = obj.LCD_CREATE;
for iLoop = inputPins
configurePinResource(obj.Parent,iLoop{:},obj.ResourceOwner,'Reserved');
end
terminals = getTerminalsFromPins(obj.Parent,inputPins);
sendCommand(obj, obj.LibraryName, cmdID, terminals);
catch e
throwAsCaller(e);
end
end
end
methods(Access = protected)
function delete(obj)
try
parentObj = obj.Parent;
% Clear the pins that have been configured to the LCD shield
inputPins = [cellstr(obj.RegisterSelectPin) cellstr(obj.EnablePin) obj.DataPins];
for iLoop = inputPins
configurePinResource(parentObj,iLoop{:},obj.ResourceOwner,'Unset');
end
% Decrement the resource count for the LCD
decrementResourceCount(parentObj, obj.ResourceOwner);
cmdID = obj.LCD_DELETE;
inputs = [];
sendCommand(obj, obj.LibraryName, cmdID, inputs);
catch
% Do not throw errors on destroy.
% This may result from an incomplete construction.
end
end
end
methods(Access = public)
function initializeLCD(obj,varargin)
p = inputParser;
p.PartialMatching = true;
addParameter(p, 'Rows', 2);
addParameter(p, 'Columns', 16);
parse(p, varargin{:});
output = p.Results;
obj.Rows = output.Rows;
obj.Columns = output.Columns;
inputs = [output.Columns output.Rows];
cmdID = obj.LCD_INITIALIZE;
sendCommand(obj, obj.LibraryName, cmdID, inputs);
end
% Clear the LCD.
function clearLCD(obj)
cmdID = obj.LCD_CLEAR;
inputs = [];
sendCommand(obj, obj.LibraryName, cmdID, inputs);
end
% Print the message on the LCD. This example uses a 16x2 LCD screen and cannot print more than 16 characters.
function printLCD(obj,message)
cmdID = obj.LCD_PRINT;
if numel(message) > 16
error('Cannot print more than 16 characters')
end
inputs = [double(message) obj.Columns obj.Rows];
sendCommand(obj, obj.LibraryName, cmdID, inputs);
end
end
end
0 Comments
Answers (1)
Siraj
on 22 Apr 2024
Edited: Siraj
on 22 Apr 2024
Hi!
It is my understanding that you want to create an LCD add-on library. You have followed all the instructions mentioned in the following link:
You are sure that the library is included because you see it when you execute
>>listArduinoLibraries
command in the command window.
However, when you try to use the library in your code you get the following error:
"Cannot program board Uno (COM5). Please make sure the board is supported and the port and board type are correct. For more information, see Arduino Hardware Troubleshooting."
Based on my knowledge and after reviewing your code, this issue generally occurs when the name of the header file created at the very beginning does not match what is being included as "CppHeaderFile" in the class "LCDAddon"
If you refer to your following code snippet:
classdef LCDAddon < matlabshared.addon.LibraryBase
properties(Access = private, Constant = true)
LCD_CREATE = hex2dec('00')
LCD_INITIALIZE = hex2dec('01')
LCD_CLEAR = hex2dec('02')
LCD_PRINT = hex2dec('03')
LCD_DELETE = hex2dec('04')
end
properties(Access = protected, Constant = true)
LibraryName = 'ExampleLCD/LCDAddon'
DependentLibraries = {}
LibraryHeaderFiles = 'LiquidCrystal/LiquidCrystal.h'
CppHeaderFile = fullfile(arduinoio.FilePath(mfilename('fullpath')), 'src', 'LiquidCrystal.h')
CppClassName = 'LCD'
end
You have used "LiquidCrystal.h" as the C++ header file. Please ensure this is the exact name of the header file that you created initially. As per the example, this name should be "LCDAddon.h"
In summary, make sure that the correct header file is being included when creating the MATLAB class "LCDAddon"
Hope this helps.
0 Comments
See Also
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!