Mostrando entradas con la etiqueta serie. Mostrar todas las entradas
Mostrando entradas con la etiqueta serie. Mostrar todas las entradas

lunes, 12 de diciembre de 2022

Comunicación serie entre PC y Arduino, programación python.

  Página principal

Arduino
Python (PC) -> Arduino
Arduino -> Python (PC)
Comunicación serie

Aunque python no es mi lenguaje favorito, he de reconocer que es fácil realizar programas por la gran multitud de comunidad que está detrás.
El entorno de programación es Linux sobre la distribución Debian 11.

Para hacer uso de la comunicación serie, lo primero es descargar la librería serie de python.
    apt install python3
    apt install python3-pip
    pip3 install pyserial

Para la primera prueba creamos un programa en el IDE del arduino que transmita los datos del LDR al PC.





El programa es simple, al iniciar manda una clave par identificarse en la comunicación serie.
En un bucle continuo se mandan los datos cada minuto, con una secuencia numérica.

En la parte del PC, programación python, se busca entre todos los puertos serie, un dispositivo que mande la clave identificativa.
Una vez encontrado el dispositivo, empieza la lectura del puerto serie.
Cuando encuentra los comando apropiados los almacena.
En el momento que aparece el comando FINAL , se imprime todas las variables acumuladas.
He creado dos interfaces para el terminal, uno en blanco y negro y otro en color.



 También he añadido una barra a modo de gráfica , para mostrar el valor de la LDR.

Como segunda parte del proyecto , creo una comunicación desde el PC hacia el arduino.
En este caso enciendo dos LED colocados en los pins D2 y D3, cuando se pulsan las teclas 2 y 3 respectivamente.
Para este caso mando las ordenes D2on o D2off a través del puerto serie.
Interpretadas por el arduino encienden o apagan el LED colocado en el pin D2.



PROGRAMA1.     .PROGRAMA2

VIDEO DEL FUNCIONAMIENTO

Espero que este montaje os haya parecido interesante.


Saludos.
Juan Galaz



Bibliografía:

https://python-para-impacientes.blogspot.com/2016/09/dar-color-las-salidas-en-la-consola.html

domingo, 29 de marzo de 2020

Transmisión de datos, vía láser mediante arduino.


LASER

Arduino

Transmisión de datos


Hace tiempo que quería realizar esta práctica, pero nunca tenía tiempo y ganas.
Con la reclusión debido al coronavirus, he tenido mucho tiempo, y me he puesto a ello.
Mi intensión en esta práctica era la transmisión de datos entre dos placa de arduino mediante un pequeño láser.
Las premisas eran no tener que utilizar ni driver para el láser, ni circuitería externa, solo utilizar componentes pasivos conectados al arduino.
Está claro que utilizar circuitos externos, incluido utilizar algún tipo de portadora, mejoraría bastante la transmisión, pero no era el caso.

En un primer momento a modo de prueba empecé a utilizar una LDR a modo de receptor.
Enseguida me di cuenta que debía tratar la señal de forma analógica para luego pasarla a digital.
Pero el mayor problema era que el cambio del valor de su resistencia era bastante lento.
A partir de los 25 Hz la señal cuadrada se transformaba en señal de diente de sierra.
La utilización de una LDR a modo de receptor, solo se puede utilizar como corte de luz en procesos lentos.

Como no dispongo de un fototransistor para el montaje, me fui a la caja de despiece de aparatos.
En artículos anteriores he explicado mi afición a reciclar aparatos, de donde saco muchas piezas para mis montajes.
De una de las miles de piezas que dispongo, tenía interruptores de luz que se utilizan en impresoras y vídeos antiguos.
Estos pequeños interruptores esta compuestos de un diodo emisor de luz y un diodo receptor de luz, para este montaje utilizo el diodo receptor de luz.
El láser que utilizo es uno pequeño que compré a China. Son muy baratos, 6 unidades por 3€. También se puede utilizar los punteros láser que se suelen ver como llaveros. Comprobar primero que no tienen condensadores, ni ningún tipo de electrónica añadida.

  Láser utilizado, y fotodiodo.


Colocación del láser y fotodiodo para las pruebas.


  Láserfuncionando.

Llegado a este punto, debía se utilizar un protocolo de comunicación unidireccional.
Mirando entre mis anteriores montajes, encontré que había utilizado el protocolo VirtualWire en transmisión de datos de sensores de temperatura y humedad. Para estos montaje el modo de transmisión eran dos pequeños módulos de 433MHz.
La biblioteca VirtualWire se diseño en un principio para transmitir datos en equipos de radioaficionado.
Esta biblioteca tiene CCR16,  detección de errores de código, y una señal de pulsos previa a los datos, muy útil en la radiofrecuencia.
De las pruebas realizadas utilizando virtualWire , he observado que funciona bien hasta los 10000 Bps.

Como no estaba conforme con esto, decidí emplear la comunicación serie de toda la vida.
Como los arduinos que tengo, Nano, no disponen de mas de un puerto serie, he utilizado los puerto serie virtuales por software, utilizando la biblioteca SoftwareSerial.

  Circuito realizado.

Esta biblioteca funciona bien para velocidades bajas, y para pocos datos continuados, el buffer es pequeño y rápidamente se llena.
Para las pruebas se utilizan 50 bytes cada 1 segundo.

Señales del láser emisor y fotodiodo, además del protocolo USART.

En las pruebas realizadas he conseguido 28800 Bps , a velocidades superiores empiezan los errores.
En el osciloscopio se pueden ver que los pulsos cuadrados se transforman en pulsos de diente de sierra.
Esto puede ser debido a que modulo el láser directamente con la señal que procede de pin del arduino, además de utilizar unos fotodiodos que no están diseñados para este fin.

PROGRAMA EMISOR
//  Emisor

#include <SoftwareSerial.h>

int contador;
char VARI[100];

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

void setup() 
{

  Serial.begin(9600);
  Serial.println("setup EMISOR");
  mySerial.begin(28800);
}

void loop()
{
  digitalWrite(13, true);
  sprintf(VARI,"PRUEBA DE TRANSMISION  Hola mundo %d  \n",contador);
  mySerial.println(VARI);
  digitalWrite(13, false);
  Serial.print("SEND=");
  Serial.println(contador);
  delay(1000);
  contador++;   
}

PROGRAMA RECEPTOR
// Receptor

#include <SoftwareSerial.h>

int contador;
char VARI[100];

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

void setup() 
{

 Serial.begin(9600);
 Serial.println("setup RECEPTOR");
 
  mySerial.begin(28800);
}

void loop() // run over and over
{
   while (mySerial.available() > 0)
   {
      digitalWrite(13, true);
      char c = mySerial.read();
      Serial.print(c);     
   }
   digitalWrite(13, false);
}


Instantánea de la pantalla en las pruebas.

En las siguientes pruebas de distancia, utilice espejos para mandar la señal láser con rebotes, la casa se me hacía pequeña.
Lo mejor es utilizar  espejos con base que se pueden mover en horizontal y vertical,  es difícil enfocar a 12 metros como hacía yo.
El resultado era muy bueno, salvo cuando pasaba gente que interrumpía la señal.

Este experimento es de lo mas entretenido y práctico, lo recomiendo.

Saludos.
Juan Galaz



Bibliografía:
   

    http://www.bolanosdj.com.ar/TEORIA/SENSORESOPTICOS.PDF

viernes, 18 de mayo de 2018

Pequeño terminal serie , wxwidgets

Página principal

wxwidgets
Pequeño terminal serie


Había realizado varios programas que utilizaban el puerto serie, pero no había realizado un terminal serie.
En este programa realizo un pequeño terminal serie multiplataforma utilizando la librería wxwidgets.
Es sencillo sin muchas complicaciones, solo admite 8 bits.
He realizado la compilación bajo las versiones de las librería 2.8.12 y 3.11 , en formato estatico y con DLL.
Cuando se  compilan en dinamico se necesitan las DLL . wxtemdll.zip




PROGRAMA

Hasta pronto.
JUAN GALAZ



Bibliografía:
wxtutor.html
wxtem.html

miércoles, 11 de abril de 2018

Arduino - Comunicación Serie por Software - Interrupciones

Página principal


Arduino
Comunicación Serie por Software

Interrupciones
xsetaseta@gmail.com

Debía realizar un análisis de unas señales que transmitían códigos. Para obtener los datos de estas señales debía decodificar los diferentes impulsos de estas señales. El chip decodificador debía ser un arduino, y como nunca había realizado este trabajo, debía experimentar un patron de señales conocidas, y la mas conocida era la comunicación serie.
El estándar serie  es bien conocido, su decodificación normalmente se hace vía hardware, aunque a baja velocidad también se puede decodificar vía Software. Esta es una práctica de decodificación mediante programa de una señal con el protocolo serie, (USART) universal synchronous and asynchronous receiver-transmitter.

Imagen de una señal serie.


Tiempo de la señal Start a una velocidad de 300bps.


Tiempo de la señal Stop a una velocidad de 300bps.

La señal representada corresponde a una señal serie de 8 bits y 1 bits de parada.

Para decodificar esta señal he utilizado dos métodos diferentes:
El primer método cheque continuamente un Pin del arduino, que debemos determinar en el Setup.
El segundo método solo se interrumpe la ejecución del programa si existe un cambio en el Pin2, el cual genera la interrupción 0.

Modo 1.
Creamos una interrupción que continuamente mira el estado del pin que se designa como entrada.
 
  SRetardoStop = SRetardo * 10;

  SRetardoMax = SRetardo * 14;
  // initialize Timer1
  cli();          // disable global interrupts
  TCCR1A = 0;     // set entire TCCR1A register to 0
  TCCR1B = 0;     // same for TCCR1B
  TCCR1B |= (1 << WGM12); // turn on CTC mode:
  TCCR1B |= (1 << CS10);  //sin prescaler
  OCR1A = Scontador;   //contador
  TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt:
  sei();          // enable global interrupts

Vemos como utilizamos el Timer1, le asignamos un valor al contador, cuando el contador llegue a cero produce una interrupción, carga de nuevo el valor del contador, y se ejecuta la rutina de la interrupción.
La rutina de la interrupción es donde se estudia la señal del pin y se llama:
ISR(TIMER1_COMPA_vect)
{
}

Gráfica del chequeo de señal y la toma de valores de la señal.


Modo 2.
Para este caso no existe ninguna temporización, el programa utiliza la interrupción externa Int0 que se encuentra en el Pin 2 del arduino.
El programa solo se interrumpe cuando detecta un cambio de señal en el Pin 2 del arduino.
bool SetupSerie2(unsigned int  baud)
{
  pinMode(2, INPUT);
  digitalWrite(2, HIGH); // Enable pull-up resistor
  cli();                 // Enable global interrupts
  EIMSK |= (1 << INT0);  // Enable external interrupt INT0
  EICRA |= (1 << ISC00); // Trigger INT0 on Change
  sei();
......

La rutina de la interrupción es donde se estudia los tiempos del cambio de señal del Pin 2 del arduino y se llama:
ISR(INT0_vect)
{

}


En los dos casos cuando se ha completado la lectura de un byte,  se pone la variable SDatoEstado = 1; .
En el bucle del programa principal que chequea continuamente el SDatoEstado = 1; , mediante la rutina  SerialAvailable() ,cuando detecta un carácter válido, se obtiene el byte  mediante la rutina SerialGet().
Para esta práctica no he querido crear un buffer que sería lo normal, pues si se entretiene mucho el programa principal pudiera sobrescribirse los datos.
En ambos casos a velocidades superiores a 4800 bps, me producían errores, se mezclaban las interrupciones, no he querido profundizar en su posible solución.

Para entender la interrupciones en el arduino, estuve buscando en internet un tutorial, encontrando este:
https://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/
en plan atrevido, realicé una traducción, espero que no sea muy mala. TRADUCCION

Las gráficas de la señales están realizadas mediante Osciloscopio Hantek6022BL y PulseView bajo Linux (Debian8_32bits).

PROGRAMAS

Hasta pronto.
JUAN GALAZ

Bibliografía:

https://aprendiendoarduino.wordpress.com/2016/11/13/interrupciones/
https://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/
http://www.engblaze.com/we-interrupt-this-program-to-bring-you-a-tutorial-on-arduino-interrupts/


jueves, 5 de mayo de 2016

ANDROID - ARDUINO - Programación JAVA - MAX7219 - Bluetooth - HC05 Conexión serie.


Android

ANDROID - ARDUINO
Anunciador con matriz de led controlado por android
Programación JAVA
MAX7219
Bluetooth  HC05
Conexión serie

En un montaje de electrónica, había realizado un marcador con el chip MAX7219. En este montaje el control lo había hecho utilizado un interprete de basic  en su modo trial  BASIC4Android. Me quedó las ganas de realizarlo en java, pero no había programado nunca en java. Ahora que tengo un poco de idea lo he realizado, quitándome la espina.
He de decir que ha sido difícil la programación, buscando por aquí y por allí encontré algún que otro ejemplo que me ayudo bastante. He de decir que al estar muy extendido android, existen infinidad de páginas y tutoriales que te ayuda a la programación.
El programa hace uso del bluetooth para manda los textos que se representan en la matriz de led. Utiliza la comunicación serie para transmitir la información, en el otro lado se encuentra el módulo HC05 que es un convertidor de bluetooth a serie.
En el terminal android debemos tener activado el bluetooth y emparejados los dispositivos.
Escribimos lo que queramos y lo mandamos a la matriz de caracteres.

Mediante eclipse diseñamos el interface gráfico.


activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <EditText
        android:id="@+id/Aentrada"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/textView1"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="22dp"
        android:ems="10"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:inputType="text"
        android:text="@string/entrada"
        android:textSize="@dimen/abc_action_bar_subtitle_text_size" />

    <EditText
        android:id="@+id/Asalida"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/Aentrada"
        android:layout_below="@+id/Aentrada"
        android:layout_marginTop="26dp"
        android:ems="10"
        android:inputType="text"
        android:text="@string/salida"
        android:textSize="@dimen/abc_action_bar_title_text_size" >

    </EditText>

    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/Asalida"
        android:layout_marginTop="60dp"
        android:gravity="center" >

        <Button
            android:id="@+id/Aboton1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="FunSend1"
            android:text="@string/boton1" />

        <Button
            android:id="@+id/Aboton2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="FunSend2"
            android:text="@string/boton2" />

        <Button
            android:id="@+id/Aboton3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="FunSend3"
            android:text="@string/boton3" />
    </LinearLayout>

    <Button
         android:id="@+id/Asalir"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/linearLayout1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="34dp"
        android:onClick="FunSalir"
        android:text="@string/salir" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/Aentrada"
        android:layout_alignParentTop="true"
        android:text="@string/hello_world" />

</RelativeLayout>

También hay que modificar el ficheros AndroidManifest.xml para poder utilizar el bluetooth.
Además impedimos que rote la pantalla.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.seta43blue"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />


    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>



La totalidad de los fichero los he comprimido y los he colocado en el enlace que se ve al final de página.
El programa en java es largo y solo explicare algún trozo.
El programa empieza con la función onCreate donde se mira si el dispositivo android tiene bluetooth, y si lo tiene activado.
Después lanzamos una función FunConectar2 donde se realiza la conexión al dispositivo.
 protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        Wentrada=(EditText)findViewById(R.id.Aentrada);
        Wsalida=(EditText)findViewById(R.id.Asalida);  
        Miblue = BluetoothAdapter.getDefaultAdapter();
                 
        if (Miblue == null)
        {
              AlertDialog.Builder dialog = new AlertDialog.Builder(this);
              dialog.setMessage("Sin soporte bluetooth");
              dialog.setCancelable(false);
              dialog.setPositiveButton("OK", new DialogInterface.OnClickListener()
                  {
                  public void onClick(DialogInterface dialog, int which)   { finish(); }                                            
                });
                dialog.show();
        }
       
        if (!Miblue.isEnabled())
        {
              AlertDialog.Builder dialog = new AlertDialog.Builder(this);
              dialog.setMessage("Activar bluetooth");
              dialog.setCancelable(false);
              dialog.setPositiveButton("OK", new DialogInterface.OnClickListener()
                  {
                  public void onClick(DialogInterface dialog, int which)   { finish(); }                                            
                });
                dialog.show();
        }
       
        AlertDialog.Builder dialog0 = new AlertDialog.Builder(this);
        dialog0.setMessage("Programa para conectar android y arduino.\nManda frases a la matriz de led.\nSETA43");
        dialog0.setCancelable(false);
        dialog0.setPositiveButton("OK", new DialogInterface.OnClickListener()
              {
              public void onClick(DialogInterface dialog, int which)   { FunConectar2(); }                                            
            });
        dialog0.show();
              
    }
La función FunConectar2 es la que realiza la conexión al dispositivo ya emparejado.
Crea un lista de dispositivos emparejados.
ArrayList <String> list = new ArrayList<String>();

Prueba a crear un createBluetoothSocket al dispositivo emparejado. Esto me creó una confusión debido a que no daba error aunque no existiese ese dispositivo, pero lo que creo que comprueba si dispone de conexión serie.
btSocket = createBluetoothSocket(device);

Prueba a crear un  btSocket.connect();  ,y si se se puede indica en pantalla ok->dirección desl dispositivo.
btSocket.connect();
Log.d(TAG, "....Conexion ok...");
Wentrada.setText("ok->" + address);

Para terminar creamos una clase donde se realiza la escritura y la lectura desde el bluetooth. ConnectedThread.
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();                          

La clase ConnectedThread tiene varias funciones: la própia de creación ConnectedThread  que se inicia con start, la run que no la usamos para nuestro ejemplo, y la write utilizada para mandar la cadena.
 private class ConnectedThread extends Thread
     {
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
 
        public ConnectedThread(BluetoothSocket socket)
         {
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
            try
                {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
                }
            catch (IOException e) { }
            mmInStream = tmpIn;
            mmOutStream = tmpOut;
         }
 
        public void run() {
           byte[] buffer = new byte[256]; 
           int bytes; 
            // Keep listening to the InputStream until an exception occurs
            while (true)
             {
                try {
                         bytes = mmInStream.read(buffer);
                         bytes=bytes+1; //No sirve para nada es para quitar aviso
                    //h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();     // Send to message queue Handler
                    }
                catch (IOException e) { break; }
             }
        }
 
        /* Call this from the main activity to send data to the remote device */
        public void write(String message) {
            Log.d(TAG, "...Data to send: " + message + "...");
            byte[] msgBuffer = message.getBytes();
            try
                {  mmOutStream.write(msgBuffer);  }
            catch (IOException e)
                {  Log.d(TAG, "...Error data send: " + e.getMessage() + "...");  }
        }

    }

Para termina creamos las funciones que mandan la cadena mediante la pulsación de los botones.
public void FunSend1(View view)
    {
        mConnectedThread.write(Wsalida.getText()+ "        " + "\n");
    }
public void FunSend2(View view)
    {
        mConnectedThread.write("/" + Wsalida.getText() + "\n");
    }  
public void FunSend3(View view)
    { 
        mConnectedThread.write("&"+ Wsalida.getText() + "\n");       
    }  

Perdonar si no explico muy bien los programa, estoy aprendiendo java y android.

Captura de pantalla del dispositivo físico.


PROGRAMA


Notas
Para depurar los programas  utilizamos la consola de eclipse.
  private static final String TAG = "bluetooth2";
 
Log.d(TAG, "...Conectando...");

Con el comando Log.d(TAG, "...Conectando..."); mandamos la cadena bluetooth2  ...Conectando...   a la consola android.
Para poder filtra todos los mensaje, que son muchos, configuramos de la siguiente forma:

Observamos  en la pantalla LogCat todos los mensajes que lleven la cadena bluetooth2.

Saludos
Juan Galaz


Bibliografía:
http://code.tutsplus.com/es/tutorials/create-a-bluetooth-scanner-with-androids-bluetooth-api--cms-24084
http://developer.android.com/intl/es/guide/topics/connectivity/bluetooth.html
http://www.tutorialspoint.com/android/android_bluetooth.htm
http://solderer.tv/data-transfer-between-android-and-arduino-via-bluetooth/
http://www.intorobotics.com/how-to-develop-simple-bluetooth-android-application-to-control-a-robot-remote/
http://www.instructables.com/id/Android-Bluetooth-Control-LED-Part-2/
https://examples.javacodegeeks.com/category/android/core/bluetooth/