07-14-2023 12:53 AM
Hi everyone, I am currently having a problem. I have some buttons, potentioknobs etc which are connected to arduino Mega which in turn is connected to mcp2515 module. Another such panel is created using the same setup. The arduino Megas are acting as transmitters. Both the Arduino's are connected to another mcp2515 module which in turn is connected to receiver arduino uno. The receiver is connected to laptop on which the states of the buttons is displayed on the serial monitor. The receiver is interfaced with labview to process the data and display the states as a mockup of the actual cockpit panel.
On the serial monitor i am getting the states as two strings with different CAN ID's (arduino code and serial monitor snippet attached).
First problem i am having is that on the serial monitor i am getting the states of both the panels (on separate lines) continuously but on labview i am only getting the second string. For both the VI's (BCP and FCS), the read buffer shows the 2nd string not the first.
The second problem is i have 2 panels. The states of the first panel are in the first string and the states of the second panel are in the second string and i need to separately input the strings to the panels (VI's attached). I can merge the VI's into one VI.
The arduino receiver code is:
#include <mcp2515.h>
#include <SPI.h>
MCP2515 mcp2515(10);
byte buttonStates[2] = {0, 0}; // Initial button states for two transmitters
void setup() {
Serial.begin(9600);
SPI.begin();
mcp2515.reset();
mcp2515.setBitrate(CAN_250KBPS, MCP_8MHZ);
mcp2515.setNormalMode();
}
void loop() {
struct can_frame canMsg;
if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
if (canMsg.can_id == 0x0F3) {
int buttonIndex = canMsg.data[0];
byte buttonState = canMsg.data[1];
if (buttonIndex >= 1 && buttonIndex <= 4) {
if (buttonState == 0) {
buttonStates[0] &= ~(1 << (buttonIndex - 1)); // Clear the corresponding bit
} else {
buttonStates[0] |= (1 << (buttonIndex - 1)); // Set the corresponding bit
}
}
} else if (canMsg.can_id == 0x0F6) {
int buttonIndex = canMsg.data[0];
byte buttonState = canMsg.data[1];
if (buttonIndex >= 1 && buttonIndex <= 9) {
if (buttonState == 0) {
buttonStates[1] &= ~(1 << (buttonIndex - 1)); // Clear the corresponding bit
} else {
buttonStates[1] |= (1 << (buttonIndex - 1)); // Set the corresponding bit
}
}
}
}
// Print the button states for both transmitters
Serial.print("F3 ");
for (int i = 0; i < 4; i++) {
Serial.print((buttonStates[0] >> i) & 0x01);
}
Serial.println();
Serial.print("F6 ");
for (int i = 0; i < 9; i++) {
Serial.print((buttonStates[1] >> i) & 0x01);
}
Serial.println();
delay(250); // Adjust delay as needed
}
Solved! Go to Solution.
07-14-2023 02:37 AM
Are you familiar with the debugging tools? Run your VI with highlight execution to see if you only get the second string.
Your Arduino program writes two lines in quick succession and then waits. Since your LabVIEW indicator only displays the last received line, it will appear as if it only receives the second line.
It would be easiest to merge your LabVIEW VIs. From the string you receive, split off the first three characters and handle the "F3 " and "F6 " cases separately.
07-14-2023 04:42 AM
Hello, Abdullah.
in a previous Post, you attached your code (RCP.vi) that you created with LabVIEW 2021. You appear to have updated your version of LabVIEW to LabVIEW 2023, but many of us long-time LabVIEW users (such as myself) do not upgrade every year (to allow our code to remain compatible with our co-workers). The problem you are posing sounds simple to me to answer, but I cannot open your VI to understand what you are currently trying to do, and how you might be able to fix your code yourself.
If, indeed, you are receiving a string as shown in your ArduinoOutput.png, and you are reading it using the principles of "Reading from VISA" (which @crossrulz and others have posted many times on the Forum), your "Reading VISA" sub-VI will be able to return a String which starts with either F3 or F6. Send all the strings with F3 to a sub-VI called "Process F3 Strings", and those with F6 to "Process F6 Strings". The F3 routine lights up the F3 Indicators based on the String contents, and the F6 routine does similar processing for the F6 routines. As the data come in (at 9600 baud, they'll be staggered by a few milliseconds), you should see the signals from the two Megas showing up on the set of Indicators you have designed on your (invisible-to-me) VIs destined to display them.
Note that the previous paragraph assumes you've already solved the problem of merging the two serial streams from the two Megas into a single string that alternates (or at least identifies the sources) between the two Mega (which I'm assuming are called F3 and F6). Boy, it sure would be nice to see your LabVIEW code (Save for Previous Version, LabVIEW 2019 or LabVIEW 2021 would work for me ...).
Bob Schor
07-14-2023 12:45 PM - edited 07-14-2023 12:54 PM
I apologize as I have 3 Labview versions 19, 21, and 23. I am currently working on some 35 panels for my Bachelors project and all the VI's have kind of gotten mixed up. I have attached 2021 version of both the VI's. I am receiving both the strings which i have checked using the highlight execution but the strings are received in quick succession. The first string is barely visible for a millisecond which is followed by the second string after which there is a delay. So the read buffer only shows the second string.
I have not yet merged the VI's together. I am currently looking at the idea where i can run both the VI's in parallel. The BCP receiving both the strings but only processing the string starting with F3 while the FCS only processing the string starting with F6.
Update: I have run both the VI's in parallel and i don't know how but the i am getting the result that i want. The BCP.vi is processing the F3 string whereas the FSC.vi is processing the F6 string (picture attached). I have not made any modifications to the code or anything.
07-14-2023 12:49 PM
Hi @cordm. I have used the highlight execution tool and i am indeed getting both the strings. But they are being received in a quick succession. The first string is displayed for maybe a millisecond followed by the second string after which there is a delay. So only the second string remains in the buffer.
07-14-2023 02:15 PM
It probably works because the VIs are alternating reading from the port. Maybe because you started them in the order that messages are sent? That is not a very robust solution.
To merge your VIs, do this:
- read from port
- split string at third character
- wire the first part to a case structure selector
- in the "F6 " case, process the rest of the string as in FSC
- in the "F3 " case, process the rest of the string as in BCP
- in the default case, do nothing or add an indicator for unexpected message
07-14-2023 03:45 PM - edited 07-14-2023 03:49 PM
When i use Search/Split string function. Only the second string is split. The problem still remains that the first string is so quickly followed by the second that it doesnt remain in buffer for long. The read buffer is only showing the second string. I tried using the newline delimiter but still not working cause the fucntion is only reading the second string.
07-15-2023 07:37 AM
Wow! I finally figured out (more or less) what your BCP and FCS routines are doing!
Stop! Think about what you want to do, and forget, for the moment, about how you are going to do it!
Situation: You are getting (single) strings of data from a target and are (correctly!) reading it using VISA. Call this routine "VISA Read" (or something like that -- it is neither BCP nor FCS, it is the VISA Read, and is going to send its output to either BCP or FCS. How do you tell?
It appears that valid messages start with F3 or F6, with F3 being processed by BCP and F6 being processed by FCS. So how do you tell? The format of all the messages is ["F3<space><more stuff>" or "F6<space><more stuff>". So you need to parse this string, splitting out the "F?<space>" part from the <more stuff>.
Welcome to the "Scan from String" function, which does exactly this (and has an Error In/Error Out, to boot!). Bring your String into "Scan from String". What are you looking for? "F<number><space>". So write-click the function (after wiring the Read Buffer output into the Input String input) and choose "Edit Scan String". You want to "Match Exact String" (i.e. "F"), and "Scan Decimal Integer" (the 3 or 6, followed by a space which "ends the integer"). When you run this, you will find that it splits, say, "F3 1110\r\n" into "Output 1" (the I32 value 3, in this case) and "remaining string", " 1101\r\n".
Great! You now "know" that this wants to go to the BCP function to parse the string " 1101\r\n" because Output 1 is the value "3". If it had been the value 6, you would send the String to FCS to finish the parsing.
I'm not going to post a VI here, as I've tried to "talk you through" the process to enable you to "do it yourself" and get some practice with String Processing in LabVIEW. It is also important to take a step back and look at the problem in "logical pieces", the first of which is "Get a VISA Message and decide whether to parse it as an F3 message for BCP or an F6 message for RCS". Also, what if it was "something else"? What if the first character is not an F, or the second character is not a number? You might want to think how you'd handle those cases, as well.
Bob Schor
07-15-2023 12:39 PM
Thank you @Bob_Schor. I'll try your solution but currently i have some 20 other panels to work on. Thanks again.