Problema de reinicio cada vez que mando datos. (SOLUCIONADO)

Buenos dias, estoy realizando un proyecto con Matlab y Arduino. (Da igual mega que Uno) hace los mismo con los dos.

Basicamente cada vez que le envio un paquete de datos, arduino se reinicia, y luego coge los datos.
Eso si uso el codigo del programa “ajuste” si por el contrario uso el de “medir altura” directamente se pone en modo inicial y ya hemos terminado de trabajar.

os dejo los codigo para que los veis y si alguien tiene alguna idea de la causa estaria genial.

Directamente pongo los archivos para abrir el scada en matlab y el programa en ide.

Saludos.

P.D el la segunda funcion de matlab tiene un fallo que no le el valor de arduino, tengo pendiente repararlo.

#include <Wire.h>
#include <VL6180X.h>
#include  <LiquidCrystal_I2C.h>   //libreria para la pantalla

//defino pantalla
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

//variables
// definir variables----Antiguas variables de uso para el programa
int v_motor, ledPin = 13 ;
byte comando, bytelow, bytehigh;
byte dato1[4];
float f = 3.4;
float dato1float=0;

//definir variables para las entradas-salidas
const int stepPin_M0 = 2;  //necesario pwm
const int reset_M0=24;
const int dirPin_M0 = 22;
const int Enable_M0 = 26; 

const int stepPin_M1 = 3;  //necesario PWM revisar que lo sea en mega
const int reset_M1 = 25;
const int dirPin_M1 = 23;
const int Enable_M1 = 27; 

//comandos para el control de programas
byte Programa;

//variables para la configuracion del motores
float Modo_trab_M0=0;
float Modo_trab_M1=0;
float Vel_M0=900; //valor inicial al minimo de velocidad, valores entre 900 y 2500
float Vel_M1=910; //valor inicial al minimo de velocidad, valores entre 900 y 2500

byte GiroM0[4];
byte GiroM1[4];
byte VelM0[4];
byte VelM1[4];

void setup() {
  Serial.begin(9600);
  Wire.begin();
               
  // Indicar a la libreria que tenemos conectada una pantalla de 16x2
  lcd.begin(16, 2);
  // Mover el cursor a la primera posición de la pantalla (0, 0)
  lcd.home (); //lcd.setCursor(0,0);                          
}

void loop() {
  delay(50);
  if (Serial.available()>0){
      delay(500);
      Programa = Serial.read();

  if (Programa == 100){
      ajuste();
  }
  else if (comando==200) {
           medir_altura();
       }
  }

  //pantalla
  //pantalla
  lcd.setCursor(0,0);
  lcd.print(Modo_trab_M0);  // Uso esta linea para poner comentarios de la variable en la pantalla, el nombre de la variable.

  lcd.setCursor(8,0);
  lcd.print(Vel_M0);  // 

  lcd.setCursor(0,1);
  lcd.print(Modo_trab_M1);  // sin las comillas se usa para llammar a la variable

  lcd.setCursor(8,1);
  lcd.print(Vel_M1 );  // sin las comillas se usa para llammar a la variable
}

//fundiones auxiliares
//desde aqui defino cada una de las funciones y lo que realizara despues.
//funcion de ajuste de datos

void ajuste(){
  GiroM0[0]=Serial.read();  GiroM0[1]=Serial.read(); GiroM0[2]=Serial.read();  GiroM0[3]=Serial.read();   //modo de trabajo, Recivo un decimal 1,8;0,9;0,225;0,1125
  VelM0[0]=Serial.read();   VelM0[1]=Serial.read();  VelM0[2]=Serial.read();  VelM0[3]=Serial.read();      //velocidad de trabajo, para el motor de giro
  GiroM1[0]=Serial.read();  GiroM1[1]=Serial.read(); GiroM1[2]=Serial.read();  GiroM1[3]=Serial.read();   //modo de trabajo, Recivo un decimal 1,8;0,9;0,225;0,1125
  VelM1[0]=Serial.read();   VelM1[1]=Serial.read();  VelM1[2]=Serial.read();  VelM1[3]=Serial.read();      //velocidad de trabajo, para el motor de giro

  Modo_trab_M0 = *(float*)GiroM0; // No usamos '&' porque no queremos el puntero de un puntero
  Vel_M0 = *(float*)VelM0;        // No usamos '&' porque no queremos el puntero de un puntero
  Modo_trab_M1 = *(float*)GiroM1; // No usamos '&' porque no queremos el puntero de un puntero
  Vel_M1 = *(float*)VelM1;        // No usamos '&' porque no queremos el puntero de un puntero

  //confirmamos valores escribidos para saber si realmente tenemos los que queremos
  //Vel_M0 = map(Vel_M0,10,100,900,2500);  // adaptamos el valor leido a un retardo
  //Vel_M1 = map(Vel_M1,10,100,900,2500);  // adaptamos el valor leido a un retardo

  Serial.println(Modo_trab_M0);
  Serial.println(Vel_M0);
  Serial.println(Modo_trab_M1);
  Serial.println(Vel_M1);
  Serial.println(float(Programa));

  Programa=0;
}

void medir_altura(){
  //hacemos girar el motor una vuelta a diferente velocidades
  Serial.println(float(Programa));

  Programa = 0;                                
}

P_base.ino (4.23 KB)

Desktop.zip (14.8 KB)

Error enorme que veo en el código es esto

void loop() {
  delay(50);
  if (Serial.available()>0){
      delay(500);      // <== ELIMINAR

llevas razon, eso no tenia que estar en ese sitio, pero aun asi continua haciendo lo mismo.

Es decir, le envio un dato desde matlab y en la pantalla por “un segundo” aparecen los valores iniciales.

Se esto ya que

lcd.setCursor(0,0);
lcd.print(Modo_trab_M0);  // Uso esta linea para poner comentarios de la variable en la pantalla, el nombre de la variable.

lcd.setCursor(8,0);
lcd.print(Vel_M0);  // 

lcd.setCursor(0,1);
lcd.print(Modo_trab_M1);  // sin las comillas se usa para llammar a la variable

lcd.setCursor(8,1);
lcd.print(Vel_M1 );  // sin las comillas se usa para llammar a la variable

Veo por pantalla estos valores y dos de ellos estan inicializados a 0 y los otros dos 900 y 910

despues se actualiza y aparecen los datos que he enviado.

Asi cada vez que envio algo nuevo.

vamos avanzando, arduino se reinica cada vez que uso fopen en matlab...

Y donde usas fopen en VL6180X.h?

Buenas noches, lo del VL6180X.h es porque luego quiero usar unas cosas y puse la libreria.

fopen lo uso en Matlab como comando para abrir el puerto serie y cada vez que realizo esto es cuando Arduino se reinicia.

Estoy investigando mas. Se aceptan toda clase de sugerencia.

Las sugerencias debes darlas tu porque tu usas MATLAB y no muchos de nosotros lo usamos.

Arduino no puede reiniciarse al recibir comandos seriales, eso te lo garantizo.
Asi que prueba de otro modo.

Tu programa falla cuano usas la parte de punteros

 Modo_trab_M0 = *(float*)GiroM0; // No usamos '&' porque no queremos el puntero de un puntero
  Vel_M0 = *(float*)VelM0;        // No usamos '&' porque no queremos el puntero de un puntero
  Modo_trab_M1 = *(float*)GiroM1; // No usamos '&' porque no queremos el puntero de un puntero
  Vel_M1 = *(float*)VelM1;        // No usamos '&' porque no queremos el puntero de un puntero

La idea es pasar de 4 bytes a float? No es mas facil usando una estructura union?

Aisla esa parte.

Hola, vamos por partes:

La funcion que indicas la uso ya que en otra pregunta me explicaron como hacerlo asi y la verdad es que va muy bien

y en este otro enlace he puesto un video para ve pudas ver lo que me refiero con reinicios, cada vez que le mando unos valores los toma pero siempre pasando por los valores iniciales. es como si apagara arduino y lo encendiera cada vez.

Creo que el error está aquí: if (Serial.available()>0) .Está condición se cumple cuando hay un byte en el buffer, pero estas leyendo 3 caracteres, más un final de línea ( supongo que el matlab envía uno). Es decir, este if se cumple durante cuatro ciclos del loop, pero los if que están anidados dentro de este no, hasta que hay 4 caracteres dentro del buffer. Una posible solución es leer 4 caracteres con if (Serial.available()>=4 y luego hacer un serial.flush().
Saludos

He probado y continua sin funcionar, voy a dar un paso para atras y veamos que sucede, empezare por enviar otro tipo de datos desde matlab mas simple, encender y apagar un led

Josko85:
Buenas noches, lo del VL6180X.h es porque luego quiero usar unas cosas y puse la libreria.

fopen lo uso en Matlab como comando para abrir el puerto serie y cada vez que realizo esto es cuando Arduino se reinicia.

Estoy investigando mas. Se aceptan toda clase de sugerencia.

Cuando se abre el puerto serie del arduino, si el sistema operativo pone RTS activo produce un reinicio del arduino.
Puedes mirar el esquema del arduino, la linea RTS está conectada, normalmente con un condensador al reset del micro.
Esta pensado para poner el micro en el estado de reinicio y que se pueda hacer el upload.

Mira a ver si el mathlab puede abrir el puerto sin cambiar el estado de RTS...

https://es.mathworks.com/help/instrument/requesttosend.html

saludos.

Porque no pruebas algo simple, algun ejemplo y luego que te asegures que todo funcione bien avanzamos con este código?

Buenos dias y feliz año.

Harkonnen he estado investigando y supuestamente tengo la posibilidad de configurar mi puerto serie para que evite esto, pero aun haciendo esto continua ocurriendo. He visto en otros enlaces que para evitar esto tenian que cortar un elemento fisico de la placa. Voy a continuar investigando.

Surbyte he probrado haciendo algo muy simple, encender y apagar un led, si lo hago con la libreria de matlab no tengo problema pero esta solo puede activar y desactivar salidas y alguna cosa mas pero lo de enviar por puerto serie solo va bien si abres el puerto, lo dejas abierto y por ejemplo recibes desde arduino.

Voy a probar a usar bluetooth en lugar de puerto serie para ver si el resultado es el mismo.

Estas seguro que se reinicia y no es un error de programa? Coloca en el setup un mensaje con un delay para estar seguro.

Bueno vamos avanzando. Os cuento como va el tema.

Despues de leer mucho he visto que no soy el único con este problema durante la historia, os dejo los principales link que he visto.

http://playground.arduino.cc/Main/DisablingAutoResetOnSerialConnection

Ninguna solucion me ha parecido bien.

Asique ahora the pensado otra cosa, si Mega tiene mas puertos serie pues vamos a usar otro.

Y efectivamente usando Rx1 y Tx1 ha funcionado bien. Pra comunicarme he usado un stm-8522 que tenia por casa.

Ya porfin llegan los datos y no se reinicia. Pero siempre tenemos un pero. ahora mando un 1 y en ocasiones llega un 33 o un 97 en decimal.

Me queda cuadrar tipos de datos para que sea lo que tiene que ser.

pero bueno poco a poco vamos para adelante.

Te ha funcionado porque el monitor serie esta sobre Rx0 y Tx0 y no sobre los demás.

Lo que yo no había entendido que se reteaba cuando conectabas MATLAB sino que interpreté que ya estaba conectado y cuando enviabas datos lo hacía.

Me alegro que vayas por buen camino.

Ahora no entiendo como te conectas con Serial1?

Buenas tardes te voy comentando

Te ha funcionado porque el monitor serie esta sobre Rx0 y Tx0 y no sobre los demás.

Yo hacia todo directamente al puerto que conectaba el usb para cargar el programa de arduino.

Esto me probocaba fallos y por tanto pase a usar los puertos Rx1 y Tx1 con un adaptador.

Asi tendo separado el cargar el programa con el comunicar desde matlab.

Lo que yo no había entendido que se reteaba cuando conectabas MATLAB sino que interpreté que ya estaba conectado y cuando enviabas datos lo hacía.

Desde matlab sufria rinicios cada vez que abria el puerto del usb o enviaba algo ya que era lo mismo que hacer cambios en el programa de matlab.

Ahora con Serial1 he tenido problemas de datos erroneos asique he decidido usar Tx0 y Rx0 y ole va muy bien ahora ya puedo enviar datos sin error ninguno a mi programa todo va perfectamente bien. envio y modifico sin problemas.

Ahora no entiendo como te conectas con Serial1?

Para conectarme con Serial1 (TX1 y Rx1) que ahora cambiado a Tx0 y Rx0 uso un adaptador , concretamente el STM-8522 y otro puerto usb distinto del ordenador.

Pero como todo no es oro, ahora tengo problemas con el envio de Matlab a arduino. Me envia lo que le da la gana. y solo veo tonterias..... Tengo que seguir investigando esto.

Tal vez la cantidad de datos del MATLAB sea demasiada y se pierda información.

Eso habría que establecerlo.
Verifica que no le envie las ordenes demasiado seguido.

Hola, he probado con un dato y me lleva loco, el enviar ya esta controlado, llega todo pero el volver… me envia lo que le da la gana, no se si tengo roto el dispositivo conversor. Comprare otro y vamos a ver que pasa. Me quedo sin ideas.

Incluso he probado con un Usb a Rs232 directamente y sacar los cables del DB9 pero nada de nada.

Como digo comprare uno especifico de arduino. pero no entido que el enviar si y el volver no…

Bueno pues ya esta solucionado el problema.

Vamos por partes.

Primero he puesto un modulo Pl2303 (ojo version que acepta w-10, esta otra antigua) y con esto se ha terminado mis problemas de comunicacion.

Gnd unidas, modulo y mega.

Mega Tx1 a Rx del modulo
Mega RX1 a Tx del modulo

aqui os dejo los codigo de arduino y de matlab para cualquiera que lo quiera probar.

//variables para la configuracion del motores
float Modo_trab_M0=0;
float Modo_trab_M1=0;
float Vel_M0=900; //valor inicial al minimo de velocidad, valores entre 900 y 2500
float Vel_M1=910; //valor inicial al minimo de velocidad, valores entre 900 y 2500

byte GiroM0[4];
byte GiroM1[4];
byte VelM0[4];
byte VelM1[4];



void setup()
{
  Serial.begin(9600);
         
}

void loop()
{
  delay(50);
  
  if (Serial1.available()>0){
    Programa=Serial1.read();
    
    if (Programa==100){
      Pro_1();
    }
    if(Programa==200){
     Pro_3();
    }
    if(Programa==300){
     Pro_3();

  }
 }

//fundiones auxiliares
//desde aqui defino cada una de las funciones y lo que realizara despues.

void  Pro_1(void){
                   GiroM0[0]=Serial1.read();  GiroM0[1]=Serial1.read(); GiroM0[2]=Serial1.read();  GiroM0[3]=Serial1.read();   //modo de trabajo, Recivo un decimal 1,8;0,9;0,225;0,1125
                   VelM0[0]=Serial1.read();  VelM0[1]=Serial1.read();  VelM0[2]=Serial1.read();  VelM0[3]=Serial1.read();      //velocidad de trabajo, para el motor de giro
                   GiroM1[0]=Serial1.read();  GiroM1[1]=Serial1.read(); GiroM1[2]=Serial1.read();  GiroM1[3]=Serial1.read();   //modo de trabajo, Recivo un decimal 1,8;0,9;0,225;0,1125
                   VelM1[0]=Serial1.read();  VelM1[1]=Serial1.read();  VelM1[2]=Serial1.read();  VelM1[3]=Serial1.read();      //velocidad de trabajo, para el motor de giro

                    Modo_trab_M0 = *(float*)GiroM0; // No usamos '&' porque no queremos el puntero de un puntero
                    Vel_M0 = *(float*)VelM0;        // No usamos '&' porque no queremos el puntero de un puntero
                    Modo_trab_M1 = *(float*)GiroM1; // No usamos '&' porque no queremos el puntero de un puntero
                    Vel_M1 = *(float*)VelM1;        // No usamos '&' porque no queremos el puntero de un puntero

Serial1.print(Modo_trab_M0);     
Serial1.print(",");
Serial1.print(Vel_M0);           
Serial1.print(",");
Serial1.print(Modo_trab_M1);     
Serial1.print(",");
Serial1.print(Vel_M1);          
Serial1.print(",");
Serial1.println(float(Programa));
//si uso println cada valor que mando a matlab lo pone en una nueva variable
//si uso print todos los valores los mete en la misma variable creando un vector columna.

  Programa=0;
  }


void Pro_2(void){
                     
  }

  void Prog_3(void){  
  
  float fin = 999;

  for (int i=0; i <= 10; i++){
      Serial1.print(temp);  // al poner print sin ln lo que hago es que matlab lo recibe en una unica variable
      temp=temp+1;
      Serial1.print(","); //envio una coma para despues poder separar números en matlab      
      }
      Serial1.println(fin); // determino donde acabara mi envio                      

 //haciendo esto con una unica variable en matlab me sirve para guardar todo sin nisiquiera tener que definir la 
 //longitud de la variable.
    }

En matlab tenemos que hacer una apertura del puerto que corresponda y luego con solo ejecutar la parte que corresponde a cada sub programa todo a funcionar.

Cuando acabamaos cerramos el puerto y listo.

%%%%%%%%%%zona apertuda puerto%%%%%%%%55

s = serial('COM6','BaudRate',9600);
warning('off','MATLAB:serial:fscanf:unsuccessfulRead');
%abrir puerto
fopen(s);
%PAUSAMOS EL PROGRAMA DURANTE 3 S
pause(3);

%%%%%%%%%%%fin apertura puerto%%%%%%%%

%%%%%%%%%%%zona prog_1%%%%%%%%%%%%%
%CREAMOS LAS VARIABLE
Programa=100;
Step_motor0=typecast(single(3.1),'uint8'); 
Vel_motor0=typecast(single(3.2),'uint8');
Step_motor1=typecast(single(3.3),'uint8'); 
Vel_motor1=typecast(single(3.4),'uint8');

%ENVIAMOS LA VARIABLE COMANDO QUE ES UN BYTE DIRECTAMENTE
fwrite(s,Programa,'uint8');
% 
for i=1:4
fwrite(s,Step_motor0(i),'uint8');
end
for i=1:4
fwrite(s,Vel_motor0(i),'uint8');
end
for i=1:4
fwrite(s,Step_motor1(i),'uint8');
end
for i=1:4
fwrite(s,Vel_motor1(i),'uint8');
end

a=fscanf(s,'%s')%%%  %s lo recibo como cararter
%  a=fscanf(s,'%f')%%%% %f si lo quiero como float, pero tendre que poner uno 
%por cada valor que envie.1º valor ->a, 2º valor ->b,....
%%%%%%fin prog_1%%%%%%

%%%%%%zona prog_2%%%%%%
Programa=200;
%%libre para que cada uno haga lo que quiera.
%%%%%%fin prog_2%%%%%%


%%%%%%zona prog_3%%%%%%

Programa=300;
fwrite(s,Programa,'uint8');
%tomo las variables directamente
Medidas=fscanf(s,'%s')%%%  %s lo recibo como cararter

%%%%%%fin prog_3%%%%%%

%%zona cierre puerto
 fclose(s);
 delete(s);
 clear s;
 %%fin zona cierre puerto%%

Con esto queda solucionado el problema.

Aunque mi conversor ponia ttl se ve que no funcionaba bien.
Saludos.