Problems when moving DC motors

2

I have a Raspberry Pi with a web server where there is a joystick. I have programmed a script in python that is responsible for translating the position of the joystick to the speed that the DC motors have to have for the car to turn as indicated by the joystick. This is the script:

#! /usr/bin/python

import cgi, cgitb
import socket
cgitb.enable()

socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
form = cgi.FieldStorage()
x = float(form.getvalue('grados'))
y = float(form.getvalue('distancia'))

if 0 <= x and x <= 90:
        derecha = int(round((y/100)*((2*x/90)-1)*255))
        izquierda = int(round((y/100)*255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6", ('127.0.0.1', 31113))
if 90 < x and x <= 180:
        derecha = int(round((y/100)*255))
        izquierda = int(round(((-2*(x-90)/90)+1)*255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6", ('127.0.0.1', 31113))
if 180 < x and x <= 270:
        derecha = int(round((y/100)*((-2*(x-180)/90)+1)*255))
        izquierda = int(round((y/100)*-255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6", ('127.0.0.1', 31113))
if 270 < x and x <= 270:
        derecha = int(round((y/100)*-255))
        izquierda = int(round((y/100)*((2*(x-270)/90)-1)*255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6", ('127.0.0.1', 31113))

In the script I think there are no failures. It tells me a value between -255 or 255 that indicates speed. The sign is responsible for indicating whether the wheels are forward or backward. Behind this number is added a 5 (right engine) or a 6 (left engine) to differentiate later on the Arduino.

The Arduino code I think is well written because if I send the data by hand everything goes perfectly but if the joystick does not go well. It's this (there are some servo things that I control with the same Arduino but it has nothing to do):

#include<Servo.h>

//Creamos los objetos servo
Servo servo;
Servo servo2;
Servo servo3;
Servo servo4;

int DV = 5;
int DA = 12;
int DR = 8;
int IV = 4;
int IA = 7;
int IR = 3;
int enviado; //Aqui enviamos el numero completo
int num; //Numero del servo
int posicion; //Posicion del servo

void setup()
{
  //Inicializamos los Servos
  servo.attach(9);
  servo2.attach(10);
  servo3.attach(11);
  servo4.attach(6);

  pinMode (DV, OUTPUT);
  pinMode (DA, OUTPUT);
  pinMode (DR, OUTPUT);
  pinMode (IV, OUTPUT);
  pinMode (IA, OUTPUT);
  pinMode (IR, OUTPUT);
  //Inicializamos la comunicacion por Serial
  Serial.begin(9600);
}

void loop()
{
    /*
    1- Leer un numero entero por serial
    2- Calculamos su modulo por 10 (sera el numero del motor)
    3- Dividir el entero inicial por 10
    4- Lo que quede, sera la posicion del motor
    */
    enviado = Serial.parseInt();
    num = enviado%10;
    enviado = enviado/10;
    posicion = enviado;

    //Hora de mover los servos!
    if(num == 1)
    {
      servo.write(posicion);
    }
    else if(num == 2)
    {
      servo2.write(posicion);
    }
    else if(num == 3)
    {
      servo3.write(posicion);
    }
    else if(num == 4)
    {
      servo4.write(posicion);
    }
    else if(num == 5 || num == -5)
    {
      if (posicion > 0)
      {
        digitalWrite(DA, HIGH);
        digitalWrite(DR, LOW);
        analogWrite(DV, posicion);
      }
      if (posicion == 0)
      {
        analogWrite(DV, 0);
      }
      if (posicion < 0)
      {
        digitalWrite(DA, LOW);
        digitalWrite(DR, HIGH);
        analogWrite(DV, abs(posicion));
      }
    }
    else if(num == 6 || num == -6)
    {
      if (posicion > 0)
      {
        digitalWrite(IA, HIGH);
        digitalWrite(IR, LOW);
        analogWrite(IV, posicion);
      }
      if (posicion == 0)
      {
        analogWrite(IV, 0);
      }
      if (posicion < 0)
      {
        digitalWrite(IA, LOW);
        digitalWrite(IR, HIGH);
        analogWrite(IV,abs(posicion));
      }
    }
}

I think the error is in that the engines go with delay when moving then a tail is created and it does not move as it should. What I do not understand is because there is delay when I have not programmed it.

EDIT: I get the motor on the right to move by sending me apart the values, with the script move randomly. The one on the left can not control or send the values by hand or using the script with which it also moves randomly.

EDIT2: I have already solved the engine on the left. I thought that it did not make sense that it was not the one on the left and the one on the right if and the problem is that the exits were wrong.

    
asked by Orizzon 22.10.2017 в 00:20
source

2 answers

1

It is very likely that you are suffering an undesired effect of sending whole data without any separator through the serial port.

Problem in the interpretation of data

As you can see in the documentation of Serial.parseInt :

  

Parsing stops when no characters have been read for a configurable time-out value, or a non-digit is read

Which means:

  

The analysis ends when characters have not been read for a configurable time, or a non-digit character is read

What you are suffering is the effect of continuously sending whole data through the serial port that can not be differentiated from each other, so that only when there is a pause of a second or more is the content of the whole number analyzed or you add a new negative sign, etc.

Example:

If you send the data "543" (movement 54 to engine 3) and "1234" (movement 123 to engine 4) in less than one second, the arduino code will understand that you have sent "5431234" (movement 543123 to engine 4) ).

That would explain why they move you in seemingly random ways. As you see, "the motor 3 has been eaten" and, however, a corrupt movement has arrived at the motor 4.

Proposed solution

In the following code I add a ";" at the end of each number to force the analysis of the string received by the serial port:

#! /usr/bin/python

import cgi, cgitb
import socket
cgitb.enable()

socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
form = cgi.FieldStorage()
x = float(form.getvalue('grados'))
y = float(form.getvalue('distancia'))

if 0 <= x and x <= 90:
        derecha = int(round((y/100)*((2*x/90)-1)*255))
        izquierda = int(round((y/100)*255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5;", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6;", ('127.0.0.1', 31113))
if 90 < x and x <= 180:
        derecha = int(round((y/100)*255))
        izquierda = int(round(((-2*(x-90)/90)+1)*255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5;", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6;", ('127.0.0.1', 31113))
if 180 < x and x <= 270:
        derecha = int(round((y/100)*((-2*(x-180)/90)+1)*255))
        izquierda = int(round((y/100)*-255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5;", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6;", ('127.0.0.1', 31113))
if 270 < x and x <= 270:
        derecha = int(round((y/100)*-255))
        izquierda = int(round((y/100)*((2*(x-270)/90)-1)*255))
        print(derecha, izquierda)
        sent = socket.sendto(str(derecha) + "5;", ('127.0.0.1', 31113))
        sent = socket.sendto(str(izquierda) + "6;", ('127.0.0.1', 31113))
    
answered by 23.10.2017 / 10:12
source
0

Good afternoon, try placing delay (1) for arduino stability.

digitalWrite(DA, HIGH);
delay(1);
digitalWrite(DR, LOW);
delay(1);
analogWrite(DV, posicion);
delay(1);

If you can do a dump of the data received.

    
answered by 22.10.2017 в 01:12