Comunicación serial Arduino y PIC

Hola muchach@s,

Estoy queriendo hacer una interfaz entre un pic y un arduino mega. Para empezar queria comunicarlos via el módulo USART de dichos micros, es decir mandar informacion desde el pic hacia el

arduino, solo con un cable, sin hardware raro (pin 17 del PIC (TX) ---> cable ---> pin 19 del arduino (RX1)).

Desde el pic mando constantemente una 'a' y apago y prendo un led para verificar que al menos el pic esta andando. Del lado del arduino, si recibe la 'a' se pone en alto el pin 30 (se prende un

led) y se pone en bajo el pin 46 (se apaga otro led). Sino recibe eso, el caso por defecto (default), se pone en bajo el pin 30 (se apaga el led) y se pone en alto el pin 46 (se prende el otro led).

Uso un switch porque cuando ande esto, pienso poner mas casos y no solo la 'a'. No puedo ver lo que sale del pic, pero usando el monitor serial del IDE de arduino veo que recibe cualquier

cosa menos una 'a' jajaja. ¿puede alguno iluminarme y decirme en que le estoy errando?

Desde ya, muchas gracias!!!!

PROGRAMA DEL PIC:
================
-MPLAB 8.92
-Compilador: HI-TECH 9.83
-uc: PIC16F876A
-Este micro es el emisor

Código:
#include <htc.h>

#define _XTAL_FREQ 20000000

void Inicializar()
	{
	TRISC3 = 0;
	TRISC6 = 1; 
	TRISC7 = 1;
	
	SSPEN = 0;

	TXSTA = 0b00100110;

	RCSTA = 0b10000000;
	
	SPBRG = 119;                    // 29=38400 baudios; 19=57600; 59=19200; 119=9600  
	SPEN = 1;
	TXEN = 1;
	}

void main()
	{
	Inicializar();

	while(1)
		{
		while(!TRMT);
		TXREG = 'a';

		__delay_ms(100);
		RC3=~RC3;
		} //fin del while
	} //fin del main


PROGRAMA DEL ARDUINO
======================
-Arduino IDE 1.0.5
-Arduino Mega
-Este micro es el receptor


Código:
char opcion = 0;

void setup() {
  Serial.begin(9600);        // establezco BR de 9600 para el puerto serie0
  Serial1.begin(9600);       // establezco BR de 9600 para el puerto serie1
  
  pinMode(30, OUTPUT);      // establece el pin digital número 30 como salida
  pinMode(46, OUTPUT);      // establece el pin digital número 46 como salida
}

void loop() {
  
  if(Serial1.available()>0)
    {
    opcion = (char)Serial1.read();
    Serial.print(opcion);
    }

    switch(opcion)
      {
      case 'a':
          digitalWrite(30, HIGH);
          digitalWrite(46, LOW);  
          delay(100);
          break;
                    
      default:
          motor1.run(RELEASE);   
          motor4.run(RELEASE); 
          digitalWrite(30, LOW);  
          digitalWrite(46, HIGH);   
          break;
      }

}

Desde ya, muchísimas gracias!!!!!

Ídolos!!!
 
Hola al programa del arduino lo que yo le cambiaría es

Código:
unsigned char opcion = 0;

void setup() {
  Serial.begin(9600);        // establezco BR de 9600 para el puerto serie0
  Serial1.begin(9600);       // establezco BR de 9600 para el puerto serie1
  
  pinMode(30, OUTPUT);      // establece el pin digital número 30 como salida
  pinMode(46, OUTPUT);      // establece el pin digital número 46 como salida
}

void loop() {
  
  if(Serial1.available()>0)
    {
    opcion = Serial1.read();
    Serial.println(opcion);

    switch(opcion)
      {
      case 'a':
          digitalWrite(30, HIGH);
          digitalWrite(46, LOW);  
          delay(100);
          break;
                    
      default:
          motor1.run(RELEASE);   
          motor4.run(RELEASE); 
          digitalWrite(30, LOW);  
          digitalWrite(46, HIGH);   
          break;
      }

    }


}

Eso se me ocurre que pueda fallar :LOL:
 
Buenas, gracias por la respuesta!!!

Si no me equivoco te referís a ponerle unsigned char en lugar de char solo a la variable opción, verdad?

Ahora pruebo y te digo!!



Buenas, acá va la comunicación un paso mas adelante

El programa emisor (el del PIC) lo simulé en proteus y parece que anda. Si pongo a 1 RB4 manda una 'a', si pongo a 1 RB5 manda una 'b', si pongo a 1 RB6 manda una 'c' y si pongo a uno RB7 manda una 'd'. Cabe aclarar que a esos botones los tengo con sus correspondientes resistencias de pulldown.

Código:
#include <htc.h>

#define _XTAL_FREQ 20000000

int cont = 0;

void Inicializar()
	{
	PORTB = 0x00;
	TRISB = 0xFF;
	
	OPTION_REG = 0b10000000;

	TRISC3 = 0;
	TRISC6 = 0; 
	TRISC7 = 1;
	
	SSPEN = 0;

	TXSTA = 0b00000110;

	RCSTA = 0b00000000;
	
	SPBRG = 129;				// 29=38400 baudios; 19=57600; 59=19200; 119=9600  
	SPEN = 1;
	TXEN = 1;

	}

void main()
	{
	Inicializar();

	while(1)
		{

		while(RB4)
			{
			while(!TXIF);
			TXREG = 'a';
			}

		while(RB5)
			{
			while(!TXIF);
			TXREG = 'b';
			}

		while(RB6)
			{
			while(!TXIF);
			TXREG = 'c';
			}

		while(RB7)
			{
			while(!TXIF);
			TXREG = 'd';
			}

		} //fin del while
	} //fin del main

El problema sigue con el circuito receptor (el arduino mega). En el caso default debería ponerse en HIGH el pin 40, cosa que pasa, pero después cualquiera que sea el botón que apriete, se pone en HIGH el pin 46!!!! Me quiero volver chango!!!!!

Código:
#include <AFMotor.h>

//AF_DCMotor motor1(1, MOTOR12_64KHZ); // creo el motor #1
//AF_DCMotor motor4(4, MOTOR34_64KHZ); // creo el motor #4

unsigned char opcion = 0;

void setup() {
  Serial.begin(9600);        // establezco BR de 9600 para el puerto serie0
  Serial1.begin(9600);       // establezco BR de 9600 para el puerto serie1

  //motor1.setSpeed(255);     // establezco velocidad de 255/255
  //motor4.setSpeed(255);     // establezco velocidad de 255/255
  
  pinMode(30, OUTPUT);      // establece el pin digital número 30 como salida
  pinMode(46, OUTPUT);      // establece el pin digital número 46 como salida
  pinMode(40, OUTPUT);      // establece el pin digital número 46 como salida
}

void loop() {
  
  if(Serial1.available()>0)
    {
    opcion = Serial1.read();
    Serial.println(opcion);
    }

  switch(opcion)
    {
    case 'a':
        //motor1.run(FORWARD);   
        //motor4.run(RELEASE); 
        digitalWrite(30, HIGH);
        digitalWrite(46, HIGH);  
        digitalWrite(40, LOW); 
        break;
        
    case 'b':
        //motor1.run(BACKWARD);   
        //motor4.run(RELEASE); 
        digitalWrite(30, HIGH);
        digitalWrite(46, LOW); 
        digitalWrite(40, LOW); 
        break;
        
    case 'c':
        //motor1.run(RELEASE);   
        //motor4.run(FORWARD); 
        digitalWrite(30, LOW);
        digitalWrite(46, HIGH);
        digitalWrite(40, LOW);  
        break;
        
    case 'd':
        //motor1.run(RELEASE);   
        //motor4.run(BACKWARD); 
        digitalWrite(30, LOW);
        digitalWrite(46, LOW); 
        digitalWrite(40, LOW); 
        break;

    case 0x55:
        //motor1.run(FORWARD);   
        //motor4.run(FORWARD); 
        break;
        
    case 0x66:
        //motor1.run(BACKWARD);   
        //motor4.run(BACKWARD); 
        break;
        
    case 0x77:
        //motor1.run(FORWARD);   
        //motor4.run(BACKWARD); 
        break;
        
    case 0x88:
        //motor1.run(BACKWARD);   
        //motor4.run(FORWARD); 
        break;
        
    default:
        //motor1.run(RELEASE);   
        //motor4.run(RELEASE); 
        digitalWrite(30, LOW);  
        digitalWrite(46, LOW);
        digitalWrite(40, HIGH);  
        break; 
    }
  delay(10);  //espera 10ms antes de hacer otra lectura
  }

Lo de los motores óbvienlo jeje, ¿hay alguna forma de ver en el monitor serial el el carácter? me refiero a ver si recibe una 'a' o 'b', no el número que representa a esos caracteres.

Desde ya muchas gracias!!!! Genios!!!
 
Última edición:
Hola amigos:
Quiero conectar un pic y un Arduino de forma serial.
El Problema : Cuando recibo los datos en el Arduino solo recibo un caracter ý u otro parecido
-En el Pic programe en Mikroc por ejemplo mando UART1_Write_Text("PICARDUINO00000"); y UART1_Init(9600); con un cristal de 12MHz, en la simulación manda bien.
-En el Arduino use este ejemplo en el que puedo visualizar los datos en el PC.
-El arduino y el Pic los conecte directamente es decir pin a pin TX-RX

Las dudas son las siguientes: Tengo que utilizar un MAX232 en ambos lados ? cambiar algo en el PIC?

Código:
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.println("Goodnight moon!");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.println("Hello, world?");
}

void loop() // run over and over
{
  if (mySerial.available()){
      Serial.write(mySerial.read());
      //Serial.println("ARDUINOPC12340");
      Serial.println("");
  }
  
  if (Serial.available())
    mySerial.write(Serial.read());
    
    delay(500);
}
 
Última edición por un moderador:
Tienes que conectar RX de PIC con TX de Arduino, y viceversa. Es decir, el pin de envío del PIC (TX) lo unes con el de recepción de Arduino (RX). Además, ambos tienen que tener la misma masa (importante si cada uno lo alimentas con fuentes diferentes).

Yo hice algo parecido hace poco, y tuve problemas con corrupción de datos, es decir, que algunos caracteres no llegaban bien. Miré con el osciloscopio y vi que Arduino tenía un error en la velocidad de los bits de +3.5%, mientras que en el PIC lo tenía del -3.6%. En total, un 7% de error que puede afectar (el estándar dice que se puede tolerar hasta un 5%).
Pero esto solo sucedía a la máxima velocidad (115200 baudios, soy un poco exagerado, jeje). Con velocidades más bajas ya no tenía problemas porque los errores eran mucho menores.

Así que a 9600 no deberías tener ningún problema. Si lo estás teniendo, probablemente haya algo mal en el código del PIC. Asegúrate de que la función UART1_Init() sabe que estás usando un cristal a 12kHz. Nunca he usado Mikroc, así que no sé cómo hacer eso.

Por supuesto, los microcontroladores trabajan a niveles TTL, así que no hace falta el MAX232 por ninguna parte, los conectas directamente y ya está.

Por otra parte, el código del Arduino lo puedes simplificar a algo como esto
Código:
#include <SoftwareSerial.h> //puerto serie software

//PINES
#define RXpin 10
#define TXpin 11
#define baudRate 9600

SoftwareSerial device(RXpin, TXpin);

void setup()
{
  Serial.begin(baudRate);
  device.begin(baudRate);
}

void loop()
{
  if (device.available())
    Serial.write(device.read());
  if (Serial.available())
    device.write(Serial.read());
}

Pruebas estas cosas, y nos cuentas cómo te ha ido ;)

Saludos.
 
En el proyecto que estoy haciendo necesito realizar una comunicación entre PIC y arduino mediante el protocolo RS232.
Si bien en proteus simulado si vale, ya cuando intento implementar en físico, no hay comunicación.
Pienso que el problema quizás sea que el PIC está trabajando con el oscilador interno y no está utilizando un cristal para la frecuencia de reloj o quizá el problema sea que se interfieran la comunicación serial de USB del arduino con la comunicación serial al PIC.

Dejo el código de PIC y arduino.
Gracias a quien me sepa dar una mano.
Código arduino:
PHP:
[b]int val;
int f=0;
void setup() {
Serial.begin(9600);                   
pinMode(13,OUTPUT);
}
void loop() {
if(Serial.available()>0)
  {
  val = Serial.read();          
  if(f==0)
  {
    digitalWrite(13,HIGH);
    f=1;
  }
  else
  {
    digitalWrite(13,LOW);
  f=0;  
  }
  }
}
Código pic:

PHP:
#include <16F628A.h>
#FUSES NOWDT                      //No Watch Dog Timer
#FUSES INTRC                      //Internal RC Osc
#FUSES NOPUT                      //No Power Up Timer
#FUSES NOPROTECT                  //Code not protected from reading
#FUSES NOBROWNOUT                 //No brownout reset
#FUSES NOMCLR                       //Master Clear pin enabled
#FUSES NOLVP                      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                      //No EE protection
#FUSES RESERVED                   //Used to set the reserved FUSE bits
#use delay(clock=4000000)
#use RS232(BAUD=9600, XMIT=PIN_B1, RCV=PIN_B2, BITS=8, PARITY=N)

long count=100;
short f=0;
#int_EXT
void  EXT_isr(void) 
{
while(input(PIN_B0)){}
putc(count);
                           //Envio por al comparador
   if(f==0)
   {
   output_high(PIN_B3);
   f=1;
   }
   else
   {
   output_low(PIN_B3);
   f=0;
   }
   delay_ms(10);
}

void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_EXT);
   enable_interrupts(GLOBAL);
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
output_low(PIN_B3);
   // TODO: USER CODE!!
while(1){
output_high(PIN_B6);
delay_ms(1000);
output_low(PIN_B6);
delay_ms(1000);
}
}
PD: El códigó está hecho en lenguaje C.
 
Última edición por un moderador:
Pues para saber que pasa comunica uno con un PC y lo verificas, y luego el otro con el PC. Después lo s dejas solos a ver.
De todos modos para depurar este tipo de cosas viene bien que uno de ellos tenga dos puertos serie.
 
no se que hagas con

f en el arduino si la pregunta es con f para que lees val ?

y en el pic

putc(); sirve para escribir 1 caracter y no un entero largo asi que no te va aservir
me va a servir perfectamente esto:

char letra

putc(letra);


pero no va a funcionar esto

int16 letra

putc(letra);

tampoco

int32 letra; // tampoco long letra;
putc(letra);

y sobre todo para que atoras tanto el micro

digamos envias y atoras con un delay
 
Mi proyecto trata de un control de temperatura con un LM35, en el cual estoy usando un pic y arduino.

Bueno, el pic está programado para que envíe tres señales H, L, P; ahora en el pic está conectado a un LCD el cual sale VALOR DEL SET POINT y TEMPERATURA ACTUAL; el cual mediante un teclado configuras el SET POINT Y así obtener la temperatura deseada y si es ALTO, BAJO o CONSTANTE enviará esas señales de H, L y P.

Lo que quiero es ver estas señales en mi computadora; por esa razón estoy usando el arduino, el cual mediante comunicación serial pueda recibir ya sea la H , L o P y así poder ver esas señales en mi computadora ya sea H , L o P.
Pero a la hora de conectar el pic al arduino con tx y rx de manera crossover, la pantalla de mi lcd, el que dice temperatura actual, deja de parpadear.

¿Me podrían ayudar a qué se debe ese problema, por favor?

A continuación les daré el programa del pic y del arduino:

PIC16F877A:
PHP:
movlw    .64
call    RS232_EnviaDato
movlw    .64
call    RS232_EnviaDato
borralcd    ;se borra todo lo q contiene la pantalla    
mensaje 1    ;aparece mensaje  en la fila 1
milisegundo .500
milisegundo .500

borralcd    ;se borra todo lo q contiene la pantalla    
mensaje 2    ;aparece mensaje 2
milisegundo .500
milisegundo .500
ARDUINO UNO
PHP:
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup()
{
  Serial.begin(9600); // abre el puerto serie,y le asigna la velocidad de 9600 bps
  mySerial.begin(9600);
}
void loop()
{
// envía datos sólo si los recibe:
  if (mySerial.available() > 0)
  {
    char incomingByte = mySerial.read();
    Serial.print("He recibido: ");
    Serial.println(incomingByte);
    delay(250);
  }
}
 

Adjuntos

  • comunicacion serial.png
    comunicacion serial.png
    21.4 KB · Visitas: 20
  • proyecto final.txt
    14.5 KB · Visitas: 15
  • ñam.png
    ñam.png
    6.5 KB · Visitas: 19
Última edición por un moderador:
Me imagino que usas el arduino para recibir los datos del PIC, porque tu PC no tiene puerto serial.
Pero puedes usar un conversor de RS-232 a USB, y así sería más sencillo.

Como no adjuntaste las librerías que se requieren para el programa en ensamblador, no se podrá compilar para determinar si es en ese programa donde se encuentra el problema. (Supongo que sí)

PD:
Me parece que ese proyecto tiene una mezcla poco usual, en cuanto a lenguajes de programación y entornos. :rolleyes:
 
En el mensaje he mandado el programa completo del PIC, que lo he guardado en un bloc de notas y esta con el nombre de proyecto final.txt y si podría descargarlo y mirar cual es el error muchas gracias, es urgente este proyecto lo tengo que presentar el martes, nesecito su gran ayuda por favor.

Si el arduino lo uso para recibir solo tres señales del pic el cual es H( cuando la temperatura esta alta) , L ( cuando la temperatura esta baja) y P ( cuando es igual ala temperatura del SET POINT).
 
Última edición:
En ese archivo del programa en ensamblador, se hace referencia a las siguientes librerías:

include<electronicpic16f877.asm>
include<teclado.asm>
include<mensaje.asm>;libreria mensaje
include<lcd.asm>;libreria lcd
include<conversion.asm>
include<adc.asm>
include<rs232_16f877.asm> ;incluir rutina rs232.asm

Por eso los proyectos deben subirse completos dentro de un archivo comprimido. (Incluyendo todo lo referente al mismo.)
 
Las que te mencioné anteriormente.

electronicpic16f877.asm
teclado.asm
mensaje.asm
lcd.asm
conversion.asm
adc.asm
rs232_16f877.asm

Sin esas librerías no se puede compilar el programa principal y esas librerías únicamente las tienes tú.
Búscalas en tu PC y súbelas dentro de un archivo comprimido, por favor.
 
Atrás
Arriba