Serial Auto-reset arduino With servo motor

Hi,

I am using Arduino Serial communication protocol to send & receive Servo motor data to/from Simulink, the problem is that when I start the simulation in simulink, Servo motors go automatically to their initial positions, same when I stop simulation. this is not very practical specially when I am trying to control a robot.

I tried some tricks like adding a 120ohms resistor between 5v & reset or a 10uf capacitor between reset & Gnd, it actually stops the auto-reset but only in Arduino, when I try to open the serial monitor the arduino doesn't restart, but when I try the same in simulink, The arduino restarts everytime I start or I close the simulation.

Actually it does the same thing everytime I push the Reset Button, the servo motors go randomly to their initial position. I tried different arduino cards Mega, Esp32....etc, but in vain...

I tried also to set an initial position in the setup function but still getting the same result.

Does anyone have idea about how to figure out this problem?

If this "Simulink" thingy is resetting the Arduino in the same way that the IDE does, then your anti-reset measures should work in either situation. So perhaps there is something that "Simulink" is doing differently. Perhaps it sends a reset command to the Arduino? If you had thought to post your code we could have checked for that. Perhaps it sends a longer reset pulse than the IDE, and that is defeating your anti-reset measures.

Don't post your code without code tags.

Hi Paul,
Thank you for the advice, I will add tags in the next posts.
Actually here is my code :


// Create a union to easily convert float to byte
#include <SCServo.h>

#include <Pixy2.h>
int x = 0;                      //positon x axis
int y = 0;                      //position y axis
// This is the main Pixy object 
Pixy2 pixy;


SCSCL sc;
#define RXD2 16
#define TXD2 17

//Read Position Variables
int16_t ReadP3 = 0;
int16_t ReadP2 = 0;


int S1,S2,S3; //Save Servo Angle

typedef union{
  float number;
  uint8_t bytes[4];
} FLOATUNION_t;

// Create the variable you want to send (Position)
FLOATUNION_t myValue1;
FLOATUNION_t myValue2;
FLOATUNION_t myValue3;

FLOATUNION_t send1;
FLOATUNION_t send2;
FLOATUNION_t send3;
FLOATUNION_t send4;
FLOATUNION_t send5;




void setup() {
  // initialize serial, use the same boudrate in the Simulink Config block
  Serial.begin(500000);
  Serial2.begin(1000000, SERIAL_8N1, RXD2, TXD2);
  sc.pSerial = &Serial2;
  sc.WritePos(1,  300, 0);
  sc.WritePos(2,  300, 0);
  sc.WritePos(3,  300, 0);


pixy.init();
  pixy.setLamp(1, 0);

}
void loop(){
   int i; 
   pixy.ccc.getBlocks();
   x=   pixy.ccc.blocks[i].m_x;    //Getting Ball Coordinate X
   y=   pixy.ccc.blocks[i].m_y;     //Getting Ball Coordinate Y

   myValue1.number = getFloat(); // Getting Servo Angle1
   myValue2.number = getFloat(); // Getting Servo Angle2
   myValue3.number = getFloat(); // Getting Servo Angle3

  //Converting Angles values to Analog Values
   myValue1.number = map(myValue1.number, 0, 300, 0, 1023);
   myValue2.number = map(myValue2.number, 0, 300, 0, 1023);
   myValue3.number = map(myValue3.number, 0, 300, 0, 1023);

    //Sending Analog value (Corresponding to servo angles)

    if( myValue1.number && myValue2.number && myValue3.number != 0)
    {
   sc.WritePos(1,  myValue1.number, 0);
   sc.WritePos(2,  myValue2.number, 0);
   sc.WritePos(3,  myValue3.number, 0);
   S1 = myValue1.number;
   S2 = myValue1.number;
   S3 = myValue1.number;
    }
    else 
    {
         sc.WritePos(1,  S1, 0);
         sc.WritePos(2,  S2, 0);
         sc.WritePos(3,  S3, 0);
    }
    //Converting & sending Analog data to Servo Angle
   send3.number = map(sc.ReadPos(1), 0, 1023, 0, 300);
   send4.number = map(sc.ReadPos(2), 0, 1023, 0, 300);
   send5.number = map(sc.ReadPos(3), 0, 1023, 0, 300);

   //Sending Ball's Coordinates
   send1.number =x; //save PosRead value in send1
   send2.number =y; //save PosRead value in send1


Serial.write('A'); 
  
 // Print float data

  for (int i=0; i<4; i++){
    Serial.write(send1.bytes[i]); //Send X
  }
 for (int i=0; i<4; i++){
    Serial.write(send2.bytes[i]);  //Send Y
  }
  for (int i=0; i<4; i++){
    Serial.write(send3.bytes[i]); //Send Servo Angle
  }
    for (int i=0; i<4; i++){
    Serial.write(send4.bytes[i]);   //Send Servo Angle
  }
    for (int i=0; i<4; i++){
    Serial.write(send5.bytes[i]);   //Send Servo Angle
  }
    // Print terminator
  Serial.print('\n');
    
  delay(50);
    }
 

float getFloat(){
    int cont = 0;
    FLOATUNION_t f;
    while (cont < 4 ){
        f.bytes[cont] = Serial.read() ;
        cont = cont +1;
        }
    return f.number;
}

How can I check if Simulink is sending a longer reset than the IDE?
Thank you!

It's a mess and I can see some things that look wrong there. But I cannot see any special "software reset" function there, so we can eliminate that idea.

Can you please perform Tools-->Auto Format next and every time you post code in future?

    if( myValue1.number && myValue2.number && myValue3.number != 0)

Can you explain what condition this 'if' is trying to detect?

Only with an oscilloscope. Do you have access to one and the knowledge to use it?

Unfortunately I do not have an oscilloscope.

This means that if the received values (Values of the 3 servo motor) is not 0 than it can go in the loop, to be sure that the min value is not sent by simulink serial.

I'm still not certain what you mean exactly, but perhaps you should change it like this:

if( myValue1.number != 0 && myValue2.number != 0 && myValue3.number != 0)

Here is another mistake I think:

if( myValue1.number && myValue2.number && myValue3.number != 0)
    {
   sc.WritePos(1,  myValue1.number, 0);
   sc.WritePos(2,  myValue2.number, 0);
   sc.WritePos(3,  myValue3.number, 0);
   S1 = myValue1.number;
   S2 = myValue1.number;
   S3 = myValue1.number;
    }
    else 
    {
         sc.WritePos(1,  S1, 0);
         sc.WritePos(2,  S2, 0);
         sc.WritePos(3,  S3, 0);
    }

Here, the values S1, S2, S3 are assigned only when the condition is true, and only used to update the servos when the condition is false. That seems very odd.

Errors like these, combined with the poor indentation, make me suspect that you have attempted to copy&paste this code together without any real understanding of what each line does or did in its original context. If I'm right, you are out of your depth here and need to spend some time working through some basic C programming tutorials.

Actually, it seems like you did not understand my code, here is a more simple version of it, it uses only one servo motor.

// Create a union to easily convert float to byte
#include <SCServo.h>



typedef union {
  float number;
  uint8_t bytes[4];
} FLOATUNION_t;

// Create the variable you want to send (Position)
FLOATUNION_t myValue1;


FLOATUNION_t send1;

int vel = 0;
void setup() {
  // initialize serial, use the same boudrate in the Simulink Config block
  Serial.begin(500000);
  Serial1.begin(1000000);
  //Serial2.begin(1000000, SERIAL_8N1, RXD2, TXD2);
  sc.pSerial = &Serial1;
}
void loop() {

  if (Serial.available() > 0) {
    myValue1.number = getFloat(); // Getting Servo Angle1

    vel = map(myValue1.number, 0, 300, 0, 1023);
    sc.WritePos(3,  vel, 0);
    //
    //Converting & sending Analog data to Servo Angle
    send1.number = map(sc.ReadPos(3), 0, 1023, 0, 300);
    //
    Serial.write('A');
    //
    // // Print float data
    //
    for (int i = 0; i < 4; i++) {
      Serial.write(send1.bytes[i]); //Send X
    }
    // Print terminator
    Serial.print('\n');
    //
    delay(50);
  }
}


float getFloat() {
  int cont = 0;
  FLOATUNION_t f;
  while (cont < 4 ) {
    f.bytes[cont] = Serial.read() ;
    cont = cont + 1;
  }
  return f.number;
}```
you tell me please which section seems to be odd for you and I will explain it.

You are absolutely correct!

How does it help explain the part of your previous code that I didn't understand? There seems to be no equivalent section in this simpler code corresponding to the part I queried in the other code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.