Currently im trying to do is send user inputs from Arduino to Simulink. What my physical project is looking like right now is theres two Megas, ones running arduino code to send a number (Mega Send) and another run to recieve it (Mega Recieve). On Simulink, essentaillty Mega Receive is using the Serial Recieve block connected to a display.
Currently the issue im facing is when i've hardcoded the value like the code below, it works fine and its returning the correct data.
Working Hardcoded Code:
void setup() {
Serial1.begin(9600); // Initialize Serial1 for communication
}
void loop() {
float predefinedNumber = 43.546; // Predefined number to send
// Send the predefined number to Simulink via Serial1
writeToSimulink(predefinedNumber);
delay(100); // Delay for 1 second before sending the number again
}
// Function to send the float number in byte format to Simulink
void writeToSimulink(float number) {
byte *b = (byte *)&number;
Serial1.write(b, 4); // Send the float as 4 bytes
Serial1.write(13); // Carriage return
Serial1.write(10); // Line feed
}
But when I use anything to read the user input, like this, it doesnt work! Im really scratching my head, because i dont understand why it send, despite the converted data type being the same.
Not working user input code:
void setup() {
Serial.begin(9600); // Initialize Serial0 (USB) for communication
Serial1.begin(9600); // Initialize Serial1 for communication
}
void loop() {
// Check if data is available to read from Serial (USB)
if (Serial.available() > 0) {
String inputString = Serial.readStringUntil('\n'); // Read input as string until newline character
// Convert the string to float
float userNumber = inputString.toFloat();
// Send the converted float number to Simulink via Serial1
writeToSimulink(userNumber);
// Optional: Print the number back to the Serial Monitor to verify
Serial.print("Sent number: ");
Serial.println(userNumber);
}
delay(100); // Small delay to allow Serial communication to settle
}
// Function to send the float number in byte format to Simulink
void writeToSimulink(float number) {
byte *b = (byte *)&number;
Serial1.write(b, 4); // Send the float as 4 bytes
Serial1.write(13); // Carriage return
Serial1.write(10); // Line feed
}
Really at my wits ends at this, consdiering I need to get it to a stage where it can take two inputs in one line like [123.45 345.67]. Any help would be greatly appreciated
if (Serial.available() > 0) {
String inputString = Serial.readStringUntil('\n'); // Read input as string until newline character
// Convert the string to float
float userNumber = inputString.toFloat();
The above code should be doing the inverse of this:
void writeToSimulink(float number) {
byte *b = (byte *)&number;
Serial1.write(b, 4); // Send the float as 4 bytes
Serial1.write(13); // Carriage return
Serial1.write(10); // Line feed
}
void setup() {
Serial.begin(9600); // why so slow ?
Serial1.begin(9600); // Initialize Serial1 for communication
}
void loop() {
if (Serial.available() > 0) { // Check if data is available to read from Serial (USB)
float input = Serial.parseFloat(); // Read input as float
while (Serial.available() > 0)Serial.read(); // dumb what is left
writeToSimulink(input );
// Optional: Print the number back to the Serial Monitor to verify
Serial.print("Sent number: ");
Serial.println(input, 4);
delay(100); // Small delay to allow Serial communication to settle
}
}
// Function to send the float number in byte format to Simulink
void writeToSimulink(float number) {
byte *b = (byte *)&number;
Serial1.write(b, 4); // Send the float as 4 bytes
Serial1.write(13); // Carriage return
Serial1.write(10); // Line feed
}
I wouldn’t define your float variable within loop - every time it loops it has to redefine that variable and it can’t be used outside of loop.
Define it before setup , you don’t need to then pass it into your procedure making things simplier .
You might want to look at multiplying up your number so it can be an integer rather than a float . With bit of thinking you can often avoid floats
Say send 20345 instead of 20.345 and convert it back at the receiver .( in my example , you can divide that by 1000, to get 20. Add and decimal point and print the remainder to show 20.345)
Also look at what that number is ? If you are for example reading an analog input , just send it and do the maths at the receiver .
Hey, im having a bit of a hard time trying to understand the logic of this? Itakes from serial, and what ever it doesnt take in as a float it clears?
The same problem still seems to be the case, where its not reading the inputs on SIMULINK, but with the hardcoded constant its fine. Would love to see and hear some of your other suggestions.
Hey unfortunately with your iteration it doesnt work. Even when set as a global variable the float value doesnt actually get read by simulink.
float userNumber; // Define the float variable globally
void setup() {
Serial.begin(9600); // Initialize Serial0 (USB) for communication
Serial1.begin(9600); // Initialize Serial1 for communication
}
void loop() {
// Check if data is available to read from Serial (USB)
if (Serial.available() > 0) {
String inputString = Serial.readStringUntil('\n'); // Read input as string until newline character
// Convert the string to float
userNumber = inputString.toFloat();
// Send the converted float number to Simulink via Serial1
writeToSimulink();
// Optional: Print the number back to the Serial Monitor to verify
Serial.print("Sent number: ");
Serial.println(userNumber);
}
delay(100); // Small delay to allow Serial communication to settle
}
// Function to send the float number in byte format to Simulink
void writeToSimulink() {
byte *b = (byte *)&userNumber;
Serial1.write(b, 4); // Send the float as 4 bytes
Serial1.write(13); // Carriage return
Serial1.write(10); // Line feed
}
The only reason why im sending it as floats is becuase of the double type im reading it as on my simulink set up. I find that other data types are very problematic and doesnt convert well.
Same reason as why I cannot really do maths at the reciever as simulink, whilst possible, isnt very flexible within that department.
This might also give an indication, here im printing the bytes sent back and it honestly looks fine.
void setup() {
Serial.begin(9600); // Initialize Serial for USB communication with the Serial Monitor
Serial1.begin(9600); // Initialize Serial1 for communication
Serial.println("Enter float numbers:");
}
void loop() {
if (Serial.available() > 0) {
String inputString = Serial.readStringUntil('\n'); // Read the input until a newline character
// Debug: Print the received input string to Serial Monitor for verification
Serial.print("Received: ");
Serial.println(inputString);
float number = inputString.toFloat(); // Convert the input string to a float
// Debug: Print the float number to Serial Monitor to verify correct conversion
Serial.print("Converted float: ");
Serial.println(number, 4); // Print with 4 decimal places for precision
// Send the converted float number to Simulink via Serial1
writeToSimulink(number);
}
}
// Function to send the float number in byte format to Simulink
void writeToSimulink(float number) {
byte *b = (byte *)&number;
// Debug: Print the byte array to verify its content before sending
Serial.print("Sending bytes: ");
for (int i = 0; i < 4; i++) {
Serial.print(b[i], HEX);
Serial.print(" ");
}
Serial.println();
Serial1.write(b, 4); // Send the float as 4 bytes
Serial1.write(13); // Carriage return
Serial1.write(10); // Line feed
}