0

I'm new to serial communication. I tried to make Arduino talk to MATLAB, but certain values are allowed to be received like 100 and 101. I tried other values but didn't work. The problem is with ASCII code but I tried to subtract what is read by 48 but failed.

This is the Arduino code that I found on Google and edited it for my servo motor problem:

#include <Servo.h>
const int servoPin = 3;
int recValue; // received value from MATLAB
Servo Servo1;

void setup()
{
  Serial.begin(9600);
  Servo1.attach(servoPin);
}

void loop()
{
  if (Serial.available() > 0)
  {
    recValue = Serial.read();
    if  (recValue == 100)
    {
      Servo1.write(0);
      delay(1000);
    }
    if (recValue == 101)
    {
      Servo1.write(90);
      delay(1000);
    }
  }
}

So how can I read the correct angles that I received from the MATLAB via serial communication? Thanks.

  • What exaclty are you getting from Matlab over serial? – chrisl Jun 30 '18 at 15:13
  • When using recValue as 100, the motor rotates to the 0 position and if 101, the motor rotates to 90 degrees. When I change recValue to any number, I get nothing from MATLAB and the motor does not rotate to any position in the two cases. – ezzeddin Jun 30 '18 at 15:20
  • I don't understand, what exactly you want to achieve. Your comment states the exact functionality, that is provided by your code. When you want to control the sensors angle from Matlab, send an actual value to the Arduino and use it in Servo1.write() – chrisl Jun 30 '18 at 15:25
  • Sorry for not being clear. For example, I want to make the motor rotate 45 degrees. I should write 45 in MATLAB and then it can convert the value to 45 so that I can use Servo1.write(45) afterwards. I will edit the code but I want to know how to convert the value that I receive from MATLAB in order to be the exact 45 value. – ezzeddin Jun 30 '18 at 15:35
  • Serial.parseInt()? – Juraj Jul 1 '18 at 17:00
0

chrisl is quite right. You need to understand how MATLAB is talking to your Arduino. I suspect it is sending a sequence of characters for each servo angle instead of a single character. In your code you are waiting for 100 and 101, which are the ASCII 'd' and 'e' characters, and then acting immediately you have read one character. See if the servo will turn if you send 'd' or 'e'. If that works then what you need to do is read a whole line of ASCII characters e.g. '9' (which is 57) and '0' (which is 48) followed by a delimiter e.g. newline (13) At the beginning of line you can set int angle = 0 and each time you read a character multiply your angle by 10 and add in the new value by subtracting 48 from it. When you reach the delimiter you can then send the angle to the servo. Oh - and make sure MATLAB is talking at the right baud rate.

| improve this answer | |
  • Thanks a lot. I tried to send 'd' and 'e' and the motor really turned. But I still don't understand how the last few sentences. How can I delimit '9' and '0' to become 90? – ezzeddin Jun 30 '18 at 22:39
  • I now understand that we're making a map between 0-9 values to 0-90 degrees but how can I do that in Arduino? Is this done for the recValue variable in Arduino? or servalue in MATLAB? – ezzeddin Jun 30 '18 at 22:41
  • If you want to send 90 to the Arduino it will be sent as the character 9 (which is 57) and then character 0. You will only get a single character at a time in each iteration of your loop. The first time Serial.available() is true Serial.read() will return value 57. Subtract 48 from that to get 9 and store in a variable declared as int angle. The next time Serial.available() is true (which may be a few loops() later) you will read 48. So then angle = angle * 10 + (value - 48) gives you the angle to send to your servo. You can send to the server when you get a non-digit character from MATLAB – jksemple Jun 30 '18 at 22:48
  • Yes, but what is the value Serial.read()? Is this what we get from MATLAB via serial communication between it and arduino? – ezzeddin Jun 30 '18 at 23:04
  • Serial.read() will collect the next available ASCII character sent from MATLAB to the Arduino. It only returns one character at a time so if you had sent the number 125 from MATLAB you would need to call Serial.read() three times to get the '1', '2' and '5' characters. You then need to recombine them as I said above to get a single integer of 125 to send to the servo – jksemple Jun 30 '18 at 23:08
1

I'm assuming, that you are sending the angle value as a 1-byte value, so no ASCII encoded numbers. This is how the code in your question works, so it should be right.

You don't have to convert anything here. The Serial.read() function already returns an integer value and you are saving it to an integer variable. But in your code you only care for 2 different states (100 and 101), instead of the actual angle value. Now you only have to replace your if-statements and write this value directly to the servo:

Servo1.write(recValue);

EDIT:

You doesn't seem as you know how serial communication (to be exactly USART) functions. So I will explain further:

The data, that is send over serial is just a stream of bytes. All content, that get transmitted are converted to a stream of bytes. Every byte has a numerical value. For example a byte with the bit-content 00100000 has a numerical value of 32. But at some point in history it was necessary to send text with a byte stream. So someone invented ASCII, which assigns a character or control command to every numerical value from 0 to 127. So if you send a byte with the numerical value of 32, you could mean the actual numerical value 32, or you could mean the ASCII equivalent to 32, which is the space character. This is just an interpretation of the byte data, that flows through the serial interface.

So you have to investigate, in which kind you are encoding the angle value. If you use fwrite() in your Matlab code, you are most likely sending the byte value, which you can simply use as described above. If you use fprintf(), you are sending the angle value as an ASCII encoded string. The value 32 from above would then occupy 2 bytes with the characters 3 and 2, which correspond to the byte values of 51 and 50. In this case you should add a delimiter character at the end in fprintf() (for example the newline character "\n") and use Serial.parseInt() to get the angle value from the string.

You can read more of this in many tutorials about Serial communication that you can find in the internet. Also refer to the example, that come with the Arduino IDE.

| improve this answer | |
  • What do you mean by 1-byte value? Because I tried many ranges from 0 to 180 degrees and the motor still does not rotate. – ezzeddin Jun 30 '18 at 15:59
  • I have also added delay(1000) after Servo1.write(recValue) – ezzeddin Jun 30 '18 at 16:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.