sábado, 1 de febrero de 2014

Arduino reproductor de voz mediante tarjeta SD - Interface LCD

Página principal

Arduino reproductor de voz mediante tarjeta SD

Interface LCD

wav - 8bits -11KHz

xsetaseta@gmail.com

Continuando con mi anterior montaje  Arduino reproductor de voz mediante SD, ahora realizo un interface mediante 2 botones, un potenciómetro y un LCD.
La elección del potenciómetro para seleccionar las canciones es un motivo práctico, de fácil realización y sencillo.
Mediante el potenciómetro seleccionamos las canciones que deben estar creadas en la SD como números del 0 al 63 y con la extensión wav , ejemplo: 1.wav . Para su reproducción pulsamos el botón PLAY y para parar el botón STOP.
Las canciones tienen que estar en formato wav, mono , resolución 8bits y con una frecuencia de 11KHz.
En este formato cada minuto ocupa 0.65M, con lo cual con una tarjeta de 4G  tendremos 6153 minutos, unas 102 horas.
La tasa de frecuencia de muestreo de 11KHz es suficiente para la reproducción de voz .

Esquema del circuito.


Montaje del circuito.

Vídeo del funcionamiento



Muestra de una señal de 500Hz.


//SETA43
//xsetaseta@gmail.com
//arduvoc  Reproductor de audio con arduino
//01/02/2014


#include <LiquidCrystal.h>

LiquidCrystal lcd(7,6,5,4,3,2);

int sensorValue ;
int oldsensorValue=-1;

#include <SD.h>
File dataFile;

String inputString = ""; 
char fileplay[20] ;
boolean stringComplete = false; 

byte valor;
byte bufer0[100];
byte bufer1[100];
int din=0;
int dout=0;
byte nf=0;
byte vacio=1;
byte fin=1;

byte e1Pin=18;
byte e2Pin=19;

void setup()
{
  lcd.begin(16, 2);
  pinMode(9, OUTPUT); //Salida audio

 // pinMode(4, OUTPUT);    // si utilizamos la salida 4 como CS de la tarjeta SD
 // if(!SD.begin(4)){    // 
   pinMode(10, OUTPUT);    // si utilizamos la salida 4 como CS de la tarjeta SD
  if(!SD.begin(10))
  {
    lcd.print("ERROR Tarjeta ");    // Texto informativo
    return;
  }
  else
  {
    lcd.print("Tarjeta OK ");    // Texto informativo
  }   
  delay(900);
  lcd.clear();
  lcd.print("Arduino VOC");
  delay(500);
  lcd.clear();
   
 cli();//stop interrupts

  //timer1 PWM 31KHz
  TCCR1A = 0x81;
  TCCR1B = 0x01;
  OCR1A = 255;
  TIMSK1=0;

  //set timer2 interrupt at 11kHz
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
  OCR2A = 182;
  TCCR2A =2;
  TCCR2B =2;     
  TIMSK2=2;
 
sei();//allow interrupts
 
}
//end setup


ISR(TIMER2_COMPA_vect)  //timer1 interrupt 11kHz toggles
{
 if(fin==0)
  {
  if(nf==0)
    valor=bufer1[dout];
   else
    valor=bufer0[dout];
   
  dout++;
  if(dout>99)
    {
     vacio=1;
     dout=0;
     if(nf==1)
       nf=0;
      else
       nf=1;      
    } 
  OCR1AH = 0;
  OCR1AL = valor;    
  }
}


void loop()
{
    if(!digitalRead(e2Pin))
        {
         clearBuffer();        
         lcd.clear();
         lcd.setCursor(0, 0); lcd.print("PLAY WAV "); lcd.print(inputString);
         inputString.toCharArray(fileplay,19);
         dataFile.close();
         dataFile = SD.open(fileplay,FILE_READ);
         //dataFile = SD.open("11.wav",FILE_READ);
         while(!digitalRead(e2Pin));
         if (dataFile)
          {          
           for(din=0;din<200;din++) dataFile.read(); //quita 200 bytes del wav
           fillBuffer(); 
           fin=0;         
          }
          else
          {
           lcd.setCursor(0, 0); lcd.print("NO   WAV ");          
          }                           
        }
       
    if(!digitalRead(e1Pin))
        {           
         clearBuffer();
         dataFile.close(); 
         lcd.setCursor(0, 0); lcd.print("STOP WAV ");  
         while(!digitalRead(e1Pin));        
        }

  sensorValue = analogRead(A0)>>4;
  if(oldsensorValue != sensorValue)
    {
    inputString=String(sensorValue,DEC);
    inputString+=".wav";
    lcd.setCursor(0, 1);
    lcd.print(inputString);
    lcd.print("    ");
    }
  oldsensorValue = sensorValue;
  fillBuffer();
}


//Borrar buffer
void clearBuffer()
{
   fin=1;
   for(din=0;din<100;din++){ bufer0[din]=128;  bufer1[din]=128;} //vacia bufer
}

//llenado de buffer
void fillBuffer()
{  
  if(vacio == 1 && fin == 0)
    {    
     if(nf==0)
       for(din=0;din<100;din++) bufer0[din] = dataFile.read();
      else
       for(din=0;din<100;din++) bufer1[din] = dataFile.read();
      
     vacio=0;
     if(!dataFile.available())
       {
         lcd.setCursor(0, 0); lcd.print("END  WAV ");
         fin=1;
         for(din=0;din<100;din++){ bufer0[din]=128;  bufer1[din]=128;} //vacia bufer        
       }
    }  
}

Código fuente.




Saludos
Juan Galaz



Bibliografía:
http://ravc00cs.blogspot.com.es/2012/07/pwm.html
https://github.com/TMRh20/TMRpcm/wiki
http://apcmag.com/arduino-project-5-digital-audio-player.htm
http://arduino-info.wikispaces.com/Arduino-PWM-Frequency
http://hykrion.com/?q=node/153
http://arduino.cc/es/Tutorial/SecretsOfArduinoPWM



lunes, 27 de enero de 2014

Arduino reproductor audio



Arduino reproductor de voz mediante tarjeta SD

wav - 8bits -11KHz

xsetaseta@gmail.com

El arduino da muchas satisfaciones, la documentación que tiene y sus librerías le hacen totalmente manejable para distintos montajes, es camaleónico. Creo que su secreto es la documentación de su microcontrolador y la facilidad de programación de su entorno. Su entorno de programación basado en java es  un  tanto simple, y quizas sea esa la base de su éxito.
En este montaje realizo un reproductor de voz. En una tarjeta SD almaceno ficheros wav en un formato de 8bits y con  una frecuencia de 11KHz. Mediante la consola serie escribo el nombre del fichero a reproducir, y el arduino lo reproduce si existe.
Una de las pocas cosas que no dispone el arduino es un conversor de D/A de serie, no conozco el motivo, los  micros PIC tampoco lo llevan, debe ser un  problema de fabricación para rebajar costes. Lo mas fácil para hacer un conversor D/A sería mediante una serie de resistencias, esto implica un circuito de 16 resistencia.

Como queremos hacer un circuito lo mas sencillo posible, utilizaremos la técnica de modulación por anchura de pulso PWM (Pulse-Width Modulation) .  Consiste como dice el hombre, modular el ancho del pulso para conseguir un voltage de salida dependiendo de la anchura del pulso. En la salida colocamos un condensador a modo de filtro para conseguir una salida analógica mas real.


Una vez explicada la teoría del conversor D/A por ancho de pulso, vamos a implementarlo mediante el microcontrolador ATMEGA328.
Existen varias librerías que realizan la reproducción de un fichero wav mediante el arduino como por ejemplo TMRpcm. Pero resultó que funcionaba en el arduino mega pero no en el  arduino diecimila, no se el motivo.
 Ante esta situación decidí realizar toda la programación, y de esta forma aprender un poco de PWM.

Para la generación de la frecuencia patrón del  PWM he utilizado el timer1 con salida al Pin 9 de arduino.
Se genera una frecuencia de 31KHz por medio del timer1. Viene muy bien explicado en la página web:
http://ravc00cs.blogspot.com.es/2012/07/pwm.html

Página 134 ATmega328
Se colocan los registros del timer1 con los siguientes valores:
TCCR1A = 0x81; // seleccion del contador. PWM, Phase Correct, 8-bit  
TCCR1B = 0x01; // prescaler = 1, clkI/O/1 (No prescaling)

TIMSK1=0;      //habilita cualquier interrupción.
Ahora ya tenemos una señal de 31KHz en la salida 9 del arduino que podemos modificar el ancho del pulso cambiando el valor del registro   OCR1A .

Para poder generar en tiempo real sonido a una tasa de muestras de 11KHz, debemos modificar el registro OCR1A 11000 veces por segundo. Esto lo realizamos generando una interrupción  11000 veces por segundo, esto lo conseguimos mediante el timer2 del ATMEGA328.
Página 158 ATmega328
Se colocan los registros del timer2 con los siguientes valores:
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  OCR2A = 182;// = (16*10^6) / (11000*8) - 1 (must be <256)  11khz 
  TCCR2A |= (1 << WGM21);
// turn on CTC mode 
  TCCR2B |= (1 << CS21); 
// Set CS21 bit for 8 prescaler    
  TIMSK2 |= (1 << OCIE2A);
// enable timer compare interrupt

En el vector de interrupción ISR(TIMER2_COMPA_vect) colocamos el programa que modifica el registro OCR1A, según el valor que nos proporciona en cada instante el fichero wav.

Como la lectura de la SD requiere un tiempo, y los datos para actualizar el registro OCR1A deben ser inmediatos, debemos crear un doble buffer donde almacenar los datos para que su disponibilidad sea inmediata.

//SETA43 21/01/2014
// xsetaseta@gmail.com
// reproductor de wav desde tarjeta SD
// wav 11kHz mono
// Arduino Diecimila

#include <SD.h>
File dataFile;

String inputString = "";  
char fileplay[20] ;
boolean stringComplete = false;  

byte valor;
byte bufer0[100];
byte bufer1[100];
int din=0;
int dout=0;
byte nf=0;
byte vacio=1;
byte fin=1;

void setup()
{
  
  Serial.begin(9600);  
  inputString.reserve(50);
  
  pinMode(9, OUTPUT);
 
 // pinMode(4, OUTPUT);    // si utilizamos la salida 4 como CS de la tarjeta SD
 // if(!SD.begin(4)){    //  
   pinMode(10, OUTPUT);    // si utilizamos la salida 4 como CS de la tarjeta SD
  if(!SD.begin(10))
  {
    Serial.println("Tarjeta erronea o no insertada");    // Texto informativo
    return;
  }
  else
  {
    Serial.println("Tarjeta OK");    // Texto informativo
  }
  
cli();//stop interrupts

TCCR1A = 0x81;
TCCR1B = 0x01;
OCR1A = 255;
TIMSK1=0;

//timer interrupts
//by Amanda Ghassaei
//set timer2 interrupt at 11kHz
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  OCR2A = 182;// = (16*10^6) / (11000*8) - 1 (must be <256)  11khz
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS21 bit for 8 prescaler
  TCCR2B |= (1 << CS21);      
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);
sei();//allow interrupts
}//end setup


ISR(TIMER2_COMPA_vect)
{
  //timer1 interrupt 11kHz toggles
  if(nf==0) valor=bufer1[dout];
  if(nf==1) valor=bufer0[dout];
  dout++;
  if(dout>99)
    {
     vacio=1;
     dout=0;
     if(nf==1)
       nf=0;
      else
       nf=1;       
    }  
  OCR1AH = 0;
  OCR1AL = valor;     
  //PORTC= valor;
}

void loop()
{
  
  if(vacio == 1 && fin == 0)
    {     
     if(nf==0) for(din=0;din<100;din++) bufer0[din] = dataFile.read();
     if(nf==1) for(din=0;din<100;din++) bufer1[din] = dataFile.read();
     vacio=0;
     if(!dataFile.available())
       {
         Serial.println("Fin de cancion");
         for(din=0;din<100;din++){ bufer0[din]=128;  bufer1[din]=128;} //vacia bufer
         fin=1;
       }
    }
    
  if (stringComplete)
    {
     inputString.toCharArray(fileplay,19);
     fileplay[inputString.length()-1]=0; //clear \n
     if(strcmp(fileplay, "stop")  == 0)
       {
         Serial.println("Stop cancion");
         for(din=0;din<100;din++){ bufer0[din]=128;  bufer1[din]=128;} //vacia bufer
         dataFile.close();
         fin=1;         
       }
       else
       {
        inputString.toCharArray(fileplay,19);
        fileplay[inputString.length()-1]=0;
        dataFile.close();
        dataFile = SD.open(fileplay,FILE_READ);
        if (dataFile)
          {
           Serial.print("OK ");
           for(din=0;din<1000;din++) dataFile.read(); //quita 1000 bytes del wav
           fin=0;
          }
          else
          {
           Serial.print("Error ");
          }
          Serial.println(fileplay);
       }      
    inputString = "";
    stringComplete = false;
   }    
}

void serialEvent()
{
  while (Serial.available())
   {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == '\n')   stringComplete = true;
   }
}

El código fuente no está optimizado ni nada, es un ejercicio de programación rápida que funciona.
El programa no hace ninguna comprobación de tipo de fichero wav, ni de tasa de muestreo  ni de resolución de bits, solo toma el fichero de la SD, quita los 1000 primeros bytes y los vuelca en el conversor D/A a una tasa de muestreo de 11KHz.

En la salida, pin 9 del arduino,  sale la señal de audio que se filtra mediante un condensador.

La tarjeta SD funciona a 3,3V, y como el arduino funciona a 5V debemos hacer adaptar la entradas y salidas. Para no complicar el circuito y no gastarnos dinero en un adaptador, lo realizo con resistencias.
Es fácil y normalmente funciona bien.


Esquema eléctrico.


Circuito eléctrico montado en un adaptador de SD a MicroSD.


Diagrama del filtro de audio.




Circuito montado y funcionando.

Video del funcionamiento



Para la conversión y edición  de ficheros wav, utilizo el programa audacity.


Conversor de audio con audacity.

En el siguiente circuito crearé un interface desde el arduino para manejar los ficheros wav.

Saludos
Juan Galaz



Bibliografía:
http://ravc00cs.blogspot.com.es/2012/07/pwm.html
https://github.com/TMRh20/TMRpcm/wiki
http://apcmag.com/arduino-project-5-digital-audio-player.htm
http://arduino-info.wikispaces.com/Arduino-PWM-Frequency
http://hykrion.com/?q=node/153
http://arduino.cc/es/Tutorial/SecretsOfArduinoPWM






domingo, 15 de diciembre de 2013

Generador de frecuencia con Raspberry - PLL

Generador de frecuencia con Raspberry

PLL

xsetaseta@gmail.com

En este montaje aprovechamos el anterior montaje raspfm y modificamos el código fuente para generar una onda de una frecuencia entre 123KHZ y 125MHZ.
He quitado en el programa PIFM todo lo relativo a la modulación de FM y el código de DMA.
El programa pll3 está realizado en C de donde recibe un parámetro de frecuencia a generar. Si por el contrario queremos parar el generador deberemos figurar como parámetro 0.
SETA43 ->Frecuencia: 0.123000 Mhz  Divisor 16650406
SETA43 ->Frecuencia: 0.555000 Mhz  Divisor 3690090
SETA43 ->Frecuencia: 1.000000 Mhz  Divisor 2048000
SETA43 ->Frecuencia: 5.000000 Mhz  Divisor 409600
SETA43 ->Frecuencia: 10.000000 Mhz  Divisor 204800
SETA43 ->Frecuencia: 15.000000 Mhz  Divisor 136533
SETA43 ->Frecuencia: 12.000000 Mhz  Divisor 170667
SETA43 ->Frecuencia: 10.000000 Mhz  Divisor 204800
SETA43 ->Frecuencia: 20.000000 Mhz  Divisor 102400
SETA43 ->Frecuencia: 30.000000 Mhz  Divisor 68267
SETA43 ->Frecuencia: 40.000000 Mhz  Divisor 51200

Salida del programa pll3

Para crear un interface gráfico he utilizado el lenguaje python con la librería gráfica tkinter.
Tiene dos interfaces gráficos pll1.py  y pll2.py , se puede utilizar el que mas guste.


pll2.py

pll1.py









Como vemos en la imágenes, a frecuencia bajas la onda es cuadrada, y según aumentamos la frecuencia se va haciendo senoidal. Con un filtro paso altos  podríamos llegar a una forma de onda casi perfecta.
Con mi osciloscopio podemos ver la forma de la onda hasta un máximo de unos 20MHZ. Con el frecuencímetro  hecho por mi, podemos medir la frecuencia. Existe una desviación de frecuencia que puede ser debido al propio frecuencímetro  por no estar bien tarado.
En cualquier receptor de radio de AM, OC y FM  podemos sintonizar la frecuencia generada.
Deberemos tener cuidado de no pisar las emisoras comerciales, que aunque la potencia es baja podemos tapar la señal de algún vecino.

Archivos de programa

Ahora voy a intentar explicar en lo que pueda, un poco del programa pll3.c .
El BCM2835 es un integrado que además de contener un procesador ARM dispone de una serie de periféricos auxiliares como:
Timers, Interrupt controller, GPIO, USB, PCM / I2S, DMA controller, I2C master, I2C / SPI slave, SPI0, SPI1, SPI2, PWM, UART0, UART1.
Existe un manual BCM2835 ARM Peripherals que explica mas o menos todas las funciones del integrado. Es muy completo pero muy difícil de comprender.
Para utilizarlo como PLL debemos ir a la página 105 , punto 6.3 General Purpose GPIO Clocks.
Colocamos en la dirección CM_GP0CTL las distintas opciones
 struct GPCTL setupword = {6/*SRC*/, 1, 0, 0, 0, 1,0x5a};
Que significan:
Clock source =PLLD
ENAB=1
KILL=0
BUSY=0
FLIP=0
MASH=1
PASSWD=0x5a

Seleccionamos como fuente de reloj PLLD, y MASH control a 1 (equivalente a no MASH divisores).
Ahora establecemos el divisor para el PLL que se coloca en CM_GP0DIV. Variando el valor de este registro podemos variar la frecuencia generada en tiempo real, este es el metodo empleado para generar FM en el montaje de PIFM. Existe dos programas de PIFM, uno que maneja mediante el procesador la frecuencia y otro que utiliza DMA para no sobrecargar el procesador.
Para calcular el divisor que debemos poner en CM_GP0DIV, que genere una frecuencia concreta en el PLL utilizamos la formula:

centerFreqDivider = (int)((500.0 / centerFreq) * (float)(1<<12) + 0.5);


Como ejemplo para una frecuencia de 40.000000Mhz debemos colocar un divisor 51200.
Podéis ver que la formula se puede optimizar bastante, pero no he querido modificar la original para no despistar mucho. El numero 500 se debe a que el PLL se basa en un reloj de 500MHZ y (1<<12) significa 4096, por lo que una forma más rápida sería:

centerFreqDivider =2048000/centerFreq

Como podemos ver, es un tanto difícil de entender.
Después de ver los manuales del ATMEGA del arduino y ver los manuales del BCM2835, la comparación es abismal en favor de ATMEGA,  hecho de menos todas sus explicaciones y esquemas.

Saludos
Juan Galaz



Bibliografía:
http://www.icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter
https://github.com/Emerica/pifm/blob/master/pifm.c
https://github.com/Guzunty/Pi/blob/master/src/gzlib/src/gz_clk.c
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=72&t=17975

lunes, 25 de noviembre de 2013

Control de 17 salidas Raspberry - Domótica

Control de 17 salidas Raspberry

Domótica

xsetaseta@gmail.com

Esta es la continuación de mi artículo sobre el control de 17 salidas con la raspberry.
Aquí vamos a dar una utilidad práctica al montaje, para encender y apagar luces de un piso.
Mediante la pulsación sobre las diferentes partes del plano, se encienden o apagan las diferentes salidas de la raspberry. Aquí pondríamos los relés, que encenderían o apagarían las luces.
Para encender vía internet, solo lo podríamos realizar mediante un programa de acceso vía vnc, próximamente se hará mediante un navegador.
Programa funcionando




Vídeo de demostración

ARCHIVO PROGRAMA.
Crea un directorio y descomprime todos los ficheros en el directorio creado.
Se ejecuta con permisos de superusuario. sudo ./raspif

ARCHIVO LIBRERÍAS.
Si no tienes la librería instalada, deberás descomprimir el fichero librerias.tar.gz en /usr/local/lib .
Si quieres además compilar, he añadido el fichero include.tar.gz para que lo descomprimas en /usr/local/include los ficheros de cabeceras.
Recomiendo que visites https://projects.drogon.net/raspberry-pi/wiringpi/ y sigas la instrucciones para compilar e instalar las librerías.


Saludos
Juan Galaz



Bibliografía:

https://projects.drogon.net/raspberry-pi/wiringpi/

martes, 19 de noviembre de 2013

Control de 17 salidas Raspberry

Control de 17  salidas Raspberry

Librería WiringPi - SDL

 Raspberry Pi

xsetaseta@gmail.com

En el anterior montaje Control de 3 salidas Raspberry Pi había realizado la programación en lenguaje Python. En este montaje realizo el control de las 17 salidas de la raspberry en lenguaje C, utilizando la librería wiringPi, y el interface gráfico lo he realizado con la librería SDL.
A cada uno le gusta el lenguaje donde mas ha programado, y en mi caso es C. Este es el motivo de que haya buscado una librería en C para manejar las salidas de la raspberry, y encontré wiringPi. La librería wiringPi la ha realizado Gordons y se encuentra en su página https://projects.drogon.net/raspberry-pi/wiringpi/.
Para manejar las salidas de la raspberry ha simulado el manejo de entradas y salidas de arduino.

void pinMode (int pin, int mode);
para indicar si el pin es de entrada o salida (INPUT, OUTPUT)

void digitalWrite (int pin, int value); escribe un valor alto o bajo (HIGH or LOW)

En el programa lo primero que se hace es  inicializar la librería con  wiringPiSetup (); , y colocar todos los pin del GPIO como salida.

//___________Todos lo GPIO como salidas_____

    wiringPiSetup () ;
    for(z=0;z<17;z++)    pinMode (z, OUTPUT) ;

//________________




Correspondencia entre GPIO y pin.



Para que lea una especie de botones, utilizo una función que detecta zonas de imagen, que una vez activada mediante el ratón, se cambia la imagen del botón.


Imagen del programa funcionando.


Montaje eléctrico. Como prueba solo utilizo 3 pin.


FICHERO FUENTE


Saludos
Juan Galaz



Bibliografía:

https://projects.drogon.net/raspberry-pi/wiringpi/


lunes, 18 de noviembre de 2013

Control de salidas Arduino con Raspberry o PC

Control de salidas Arduino

con Raspberry o PC

 C - SDL

xsetaseta@gmail.com

En este montaje, realizó una comunicación entre la raspberry y el arduino mediante el cable USB.
Además de realizar la comunicación a través del cable usb, el arduino se alimenta de él.
Se basa en un anterior montaje aserie.html que activaba o desactivaba todas las salidas del arduino mediante un interface gráfica realizada en C y con la librería SDL.
Ahora he modificado un poco la programación de mi montaje para que funcione tanto en un PC con Linux como en la Raspberry. Este es mi primer programa para Raspberry que utiliza las librerías SDL.
Para que lea una especie de botones, utilizo una función que detecta zonas de imagen, que una vez activada mediante el ratón se cambia la imagen del botón. Es un sistema muy sencillo que como luego veremos en montajes posteriores, se puede utilizar para activar o desactivar partes de una imagen para encender un dispositivo.


Montaje eléctrico


Control desde el programa en la Raspberry

En el fichero adjunto veremos el programa para el PC y para la Raspberry. El programa en la Raspberry deberá funcionar sin problema en la distribución Raspbian, pero la versión para PC está compilada para Debian 7, para los que tengan otra versión de Linux, deberán compilar los códigos fuentes.

FICHERO FUENTE


Un Saludo
Juan Galaz

jueves, 17 de octubre de 2013

Control de salidas Raspberry - Arduino -Python

Control de salidas

Raspberry - Arduino -Python

 Raspberry Pi

xsetaseta@gmail.com

En este montaje realizó una comunicación entre la raspberry y el arduino mediante el cable USB.
Además de realizar la comunicación a través del cable usb, el arduino se alimenta de él.
Se basa en un anterior montaje aserie.html que activaba o desactivaba todas las salidas del arduino mediante un interface gráfica realizada en C y con la librería SDL.
En este caso hacemos lo mismo pero programando en python y con la librería tk.
Como realmente la raspberry es un ordenador con linux como sistema operativo, la realización se efectúa en el PC con debian por cuestión de velocidad, y luego se pasa a la raspberry donde funciona perfectamente.
El programa de arduino consiste en que se lee constantemente el puerto serie. Cuando se recibe una orden "1Dig13" el arduino interpreta que tiene que poner a 5V la salida de arduino Digital13. Si recibe la orden "0Dig13" el arduino pone la salida Digital13 a 0V.
Para mandar las ordenes al arduino se puede utilizar la consola del programador de arduino o cualquier otro programa de comunicaciones como por ejemplo CuteCom o minicom en  Linux.
void WriteComand()
{
  
   
    if(!strcmp(entrada,"0An0"))
      {
       digitalWrite(14, LOW);
       goto salir1;
      }
    if(!strcmp(entrada,"1An0"))
      {
      digitalWrite(14, HIGH);
       goto salir1;
      }
    
    if(!strcmp(entrada,"0An1"))
      {
      digitalWrite(15, LOW);
       goto salir1;
      }
    if(!strcmp(entrada,"1An1"))
      {
      digitalWrite(15, HIGH);
       goto salir1;
      }
................
Ejemplo de como interpreta el arduino las ordenes a través del interface serie.


def fAn0():
                global An0
                if An0  ==  0:
                        An0=1
                        ser.write('1An0\n')
                else:
                        An0=0
                        ser.write('0An0\n')
                print  "An0",An0                
                return

def fAn0():
                global An0
                if An0  ==  0:
                        An0=1
                        ser.write('1An0\n')
                else:
                        An0=0
                        ser.write('0An0\n')
                print  "An0",An0                
                return
Ejemplo de como manda la raspberry las ordenes a través de interface serie.


El programa funcionando en la rapberry.


Circuito montado y funcionando.

Nos puede surgir algun problema como este:

Traceback (most recent call last):

  File "./raArPy.py", line 5, in <module>
    import serial
ImportError: No module named serial

Significa que no tenemos instalado el modulo serie, se instala con la orden:

sudo apt-get install python-serial

Otro problema que puede surgir es que no tengamos permisos para escribir el los puertos serie, /dev/ttyACMx/dev/ttyUSBx , depende del modelo de arduino que tengamos . Para solucionarlo, debemos dar permisos al usuario que ejecuta el programa con la orden :

adduser usuario dialout

Arreglado estos problemas, ya solo nos queda ejecutar el programa ./raArPy.py .

Archivos del montaje

Un saludo
Juan Galaz

Bibliografía:

http://www.safecreative.org/work/1207302042960-curso-python-para-principiantes
http://docs.python.org/2/contents.html
http://gmendezm.blogspot.com.es/2012/12/tutorial-tkinter-python-gui.html