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

domingo, 16 de diciembre de 2018

Arduino funcion para leer puerto serial

Generalmente los códigos que he visto en internet para leer el puerto serial lo hacían directamente en el void loop(), pero a mi esto no me parece nada práctico, o por lo menos a mi me gusta trabajar separando un poco las cosas...

Parte de este código lo saque de internet hace años y no recuerdo de donde, tal vez en el post anterior sobre el puerto serial lo indeque...



/* 
/* Funciones del puerto Serial
/*
/* *********************************************************************** */

// Leer puerto Serial
String LeerSerial(){
  
  char ch = ' ';       //Variable donde se guarda el char que se recibe por serial.
  String mensaje ="" ; //Variable para guardar el texto pasado por serial.
  
  //Lee serial
  if (Serial.available()) //Si el serial esta libre...
    {
    while( ch != '\n') //leemos hasta el retorno de carro o enter.
      { 
      ch = Serial.read(); //Lee un caracter.
      
      mensaje = mensaje + ch ; //lo anadimos a la variable mensaje.
      
      delay(25); //Esperamos 25ms para evitar colixiones de datos.
      }
      
    //Serial.println( mensaje); //Imprimimos el mensaje
    
    return mensaje; //Pasamos el valor leido
    mensaje = "" ; //Borramos el string
     }
}

Arduino determinar si es un número entre 0 y 255

A la hora de recuperar un número de una eeprom puede darse el caso de que ese contenido que hemos leído no sea un número ya sea por que no la hemos limpiado correctamente o pr que ahun no la hemos escrito. Esta función nos regresa true o false dependiendo si es número  entre 0 y 255...



/* Detectamos si los datos de la Eeprom son un numero entre 0 y 255 */
bool ValidarDatosEprom(){
  
  int valor; //Variable para almacenar el dato ovtenido de la eprom
  int Direccion = 0;//Reseteamos el contador
  
  bool DatosInCorrectos = false; //hasta que no se demuestre los datos de la Eeprom son correctos
  
  while(Direccion < 5){ //Recorremos los 5 registros del Array


    valor = DatosEprom[Direccion]; //Leemos el valor
    
    
    if ((valor >= 0) and (valor <= 255))
      {
        //si los datos leidos son un numero entre 0 y 255 no hace nada
      }
      else
      {
        DatosInCorrectos = true; //Si es diferente indica que hay un error
      }
      
    
    Direccion++;
  }//Fin while
  
  return DatosInCorrectos; //Entregamos si hay errores o no
  
}//Fin validar Datos de la Eprom

viernes, 5 de agosto de 2016

Intercambiar datos entre python y arduino.

Excelente video que enseña como conectar y intercambiar datos entre python y arduino:

 

jueves, 30 de junio de 2016

Arduino Los constructores del objeto String

La instrucción String de Arduino a demás de guardar valores y cadenas de texto, tiene otras muchas posibilidades, como por ejemplo pasar datos de Binario a Decimal o incluso a a  Hexadecimal.

Los constructores del objeto String:

String stringOne = "Hello String";                      // using a constant String
String stringOne =  String('a');                        // converting a constant char into a String
String stringTwo =  String("This is a string");         // converting a constant string into a String object
String stringOne =  String(stringTwo + " with more");   // concatenating two strings
String stringOne =  String(13);                         // using a constant integer
String stringOne =  String(analogRead(0), DEC);         // using an int and a base
String stringOne =  String(45, HEX);                    // using an int and a base (hexadecimal)
String stringOne =  String(255, BIN);                   // using an int and a base (binary)
String stringOne =  String(millis(), DEC);              // using a long and a base
String stringOne =  String(5.698, 3);                   // using a float and the decimal places


Código ejemplo:

/*
   String constructors

 Examples of how  to create strings from other data types

 created 27 July 2010
 modified 30 Aug 2011
 by Tom Igoe

 http://www.arduino.cc/en/Tutorial/StringConstructors

 This example code is in the public domain.
 */

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

  // send an intro:
  Serial.println("\n\nString Constructors:");
  Serial.println();
}

void loop() {
  // using a constant String:
  String stringOne = "Hello String";
  Serial.println(stringOne);      // prints "Hello String"

  // converting a constant char into a String:
  stringOne =  String('a');
  Serial.println(stringOne);       // prints "a"

  // converting a constant string into a String object:
  String stringTwo =  String("This is a string");
  Serial.println(stringTwo);      // prints "This is a string"

  // concatenating two strings:
  stringOne =  String(stringTwo + " with more");
  // prints "This is a string with more":
  Serial.println(stringOne);

  // using a constant integer:
  stringOne =  String(13);
  Serial.println(stringOne);      // prints "13"

  // using an int and a base:
  stringOne =  String(analogRead(A0), DEC);
  // prints "453" or whatever the value of analogRead(A0) is
  Serial.println(stringOne);

  // using an int and a base (hexadecimal):
  stringOne =  String(45, HEX);
  // prints "2d", which is the hexadecimal version of decimal 45:
  Serial.println(stringOne);

  // using an int and a base (binary)
  stringOne =  String(255, BIN);
  // prints "11111111" which is the binary value of 255
  Serial.println(stringOne);

  // using a long and a base:
  stringOne =  String(millis(), DEC);
  // prints "123456" or whatever the value of millis() is:
  Serial.println(stringOne);

  //using a float and the right decimal places:
  stringOne = String(5.698, 3);
  Serial.println(stringOne);

  //using a float and less decimal places to use rounding:
  stringOne = String(5.698, 2);
  Serial.println(stringOne);

  // do nothing while true:
  while (true);

}


Arduino manipular el puerto directamente

El otro día preguntando una duda en el foro de arduino me dijeron que mirase el enlace a este articulo, lamentablemente no era lo que necesitababa pero esta foma de manipular el puerto me ha parecido muy interesante.
Port Registers
  • B (digital pin 8 to 13)
  • C (analog input pins)
  • D (digital pins 0 to 7)
Examples
DDRD = B11111110; // sets Arduino pins 1 to 7 as outputs, pin 0 as input
DDRD = DDRD | B11111100; // this is safer as it sets pins 2 to 7 as outputs
// without changing the value of pins 0 & 1, which are RX & TX
Why use port manipulation?
  • The code is much more difficult for you to debug and maintain, and is a lot harder for other people to understand. It only takes a few microseconds for the processor to execute code, but it might take hours for you to figure out why it isn't working right and fix it! Your time is valuable, right? But the computer's time is very cheap, measured in the cost of the electricity you feed it. Usually it is much better to write code the most obvious way.
  • The code is less portable. If you use digitalRead() and digitalWrite(), it is much easier to write code that will run on all of the Atmel microcontrollers, whereas the control and port registers can be different on each kind of microcontroller.
  • It is a lot easier to cause unintentional malfunctions with direct port access. Notice how the line DDRD = B11111110; above mentions that it must leave pin 0 as an input pin. Pin 0 is the receive line (RX) on the serial port. It would be very easy to accidentally cause your serial port to stop working by changing pin 0 into an output pin! Now that would be very confusing when you suddenly are unable to receive serial data, wouldn't it?
  • You may need to be able to turn pins on and off very quickly, meaning within fractions of a microsecond. If you look at the source code in lib/targets/arduino/wiring.c, you will see that digitalRead() and digitalWrite() are each about a dozen or so lines of code, which get compiled into quite a few machine instructions. Each machine instruction requires one clock cycle at 16MHz, which can add up in time-sensitive applications. Direct port access can do the same job in a lot fewer clock cycles.
  • Sometimes you might need to set multiple output pins at exactly the same time. Calling digitalWrite(10,HIGH); followed by digitalWrite(11,HIGH); will cause pin 10 to go HIGH several microseconds before pin 11, which may confuse certain time-sensitive external digital circuits you have hooked up. Alternatively, you could set both pins high at exactly the same moment in time using PORTB |= B1100;
  • If you are running low on program memory, you can use these tricks to make your code smaller. It requires a lot fewer bytes of compiled code to simultaneously write a bunch of hardware pins simultaneously via the port registers than it would using a for loop to set each pin separately. In some cases, this might make the difference between your program fitting in flash memory or not!

Port registers allow for lower-level and faster manipulation of the i/o pins of the microcontroller on an Arduino board. The chips used on the Arduino board (the ATmega8 and ATmega168) have three ports:
Each port is controlled by three registers, which are also defined variables in the arduino language. The DDR register, determines whether the pin is an INPUT or OUTPUT. The PORT register controls whether the pin is HIGH or LOW, and the PIN register reads the state of INPUT pins set to input with pinMode(). The maps of the ATmega8 and ATmega168 chips show the ports. The newer Atmega328p chip follows the pinout of the Atmega168 exactly.
DDR and PORT registers may be both written to, and read. PIN registers correspond to the state of inputs and may only be read.
PORTD maps to Arduino digital pins 0 to 7
DDRD - The Port D Data Direction Register - read/write
PORTD - The Port D Data Register - read/write
PIND - The Port D Input Pins Register - read only
PORTB maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable
DDRB - The Port B Data Direction Register - read/write
PORTB - The Port B Data Register - read/write
PINB - The Port B Input Pins Register - read only
PORTC maps to Arduino analog pins 0 to 5. Pins 6 & 7 are only accessible on the Arduino Mini
DDRC - The Port C Data Direction Register - read/write
PORTC - The Port C Data Register - read/write
PINC - The Port C Input Pins Register - read only
Each bit of these registers corresponds to a single pin; e.g. the low bit of DDRB, PORTB, and PINB refers to pin PB0(digital pin 8). For a complete mapping of Arduino pin numbers to ports and bits, see the diagram for your chip:ATmega8ATmega168. (Note that some bits of a port may be used for things other than i/o; be careful not to change the values of the register bits corresponding to them.)
Referring to the pin map above, the PortD registers control Arduino digital pins 0 to 7.
You should note, however, that pins 0 & 1 are used for serial communications for programming and debugging the Arduino, so changing these pins should usually be avoided unless needed for serial input or output functions. Be aware that this can interfere with program download or debugging.
DDRD is the direction register for Port D (Arduino digital pins 0-7). The bits in this register control whether the pins in PORTD are configured as inputs or outputs so, for example:
//See the bitwise operators reference pages and The Bitmath Tutorial in the Playground
PORTD is the register for the state of the outputs. For example;
PORTD = B10101000; // sets digital pins 7,5,3 HIGH
You will only see 5 volts on these pins however if the pins have been set as outputs using the DDRD register or with pinMode().
PIND is the input register variable It will read all of the digital input pins at the same time.
Generally speaking, doing this sort of thing is not a good idea. Why not? Here are a few reasons:
So you might be saying to yourself, great, why would I ever want to use this stuff then? Here are some of the positive aspects of direct port access:

viernes, 17 de junio de 2016

Arduino pasar de Binario a Integer

Anoche me vi en la necesidad de convertir un número binario en un número integer, me puse a buscar en internet y encontre un ejemplo para C que he modificado un poco para utilizarlo con arduino.

Binario a Integer:
unsigned int BinToInt (String Binario){
  
  char bin[9]; //Creamos un array de char

  Binario.toCharArray(bin, 9);  //Pasamos el string al array de char que hemos creado
  
  int i = 0;  //Variable para el contador
  unsigned int n = 0;  //Variable para calcular el resultado

  while ( bin[i] == '0' || bin[i] == '1' ) {
    if ( bin[i] == '0' )
      n <<= 1;
    else {
      n ^= 1;
      n <<= 1;
    }
  ++i;
  }
  
  n >>= 1;
  
  Serial.print("Final: ");
  Serial.println(n);

  return(n);

}

miércoles, 1 de junio de 2016

Arduino interpretar comandos del puerto serie

El otro día me encontre este código el cual lo estoy utilizando como referencia para pasar he interpretar comandos por el puerto serial.

Comandos por serie:
/*Código creado por Castig para Taringa (14-04-2013).*/ 
int numChar = 0; //Numero ASCII del caracter. 
char incomingByte = 0;   // informacion entrante (RX) 
int cantPalabras = 1; //Cantidad de palabras que se ingresan (el espacio separa las palabras)
String palabra1 = ""; //Palabra 1 que se ingresa 
String palabra2 = ""; //Palabra 2 que se ingresa 
String palabra3 = ""; //PUEDEN AGREGAR TODAS LAS PALABRAS QUE QUIERAN. 

boolean datosAnalizados = false; //Indica si se termino de recorrer la palabra entrante.

boolean ledPrendido = false; //Indico si el LED se encuentra prendido. 
int pinLed = 13; //pin del LED. Por lo general el pin 13 es donde está el LED que viene integrado en la placa Arduino.

void setup() { 
    Serial.begin(9600); // Abre el puerto serial a 9600 bps 
    pinMode(pinLed, OUTPUT); //Indico que el pin 13 es un puerto de salida void loop(){ 
    while (Serial.available()>0){ 
        numChar = Serial.read();//codigo numerico ASCII del caracter 
        incomingByte = numChar; //transformo el numero en el caracter ASCII  

        //Uso el caracter 32 (espacio) como delimitador de palabras. 
        if (numChar==32){ 
            cantPalabras++; //Cuando encuentro un espacio, indico que se analizara la próxima palabra.
        } 

        /* El caracter 13 corresponde al retorno de carro. 
           El caracter 10 es el salto de línea. 
           El caracter 32 es el espacio. 
           Por lo general se utilizan los caracteres 13 10 para marcar el fin de línea, y equivalen a la tecla ENTER de Windows.
           Por lo tanto, me fijo que el caracter analizado no sea ni 13, 10 o 32*/
        if (numChar!=13 && numChar!=10 && numChar!=32){ 
             
            /*Me fijo que palabra estoy analizando*/ 
            if(cantPalabras==1){ 
                palabra1 = palabra1+incomingByte; //Voy agregando los caracteres leidos a la palabra1 para formarla.
            } 
            if(cantPalabras==2){ 
                palabra2 = palabra2+incomingByte; //Voy agregando los caracteres leidos a la palabra2 para formarla.
            } 
        } 
        if (numChar==10){ 
            datosAnalizados = true; //Esto indica que se analizaron datos 
        } 
    }     
     
    /*Cuando detecto que ya no hay nada para analizar, 
    pero hay datos analizados, procedo a transmitirlos. 
    */ 
    if (Serial.available() <=0 && datosAnalizados==true) { 
        datosAnalizados = false; //Indico que ya no hay datos analizados, ya que los analizé previamente.

        /*Convierto todas las palabras en mayúscula para facilitar la interpretación, pero esto es opcional.*/
        palabra1.toUpperCase(); 
        palabra2.toUpperCase(); 

        //Llamo a la función 'commandInterpreter' y le paso las palabras. Esta función se encargará de interpretar los comandos.
        commandInterpreter(palabra1,palabra2); 

        //Reestablezco el valor de las variables para que puedan ser utilizadas nuevamente.
        palabra1 = ""; 
        palabra2 = ""; 
        cantPalabras = 1; 
        Serial.flush();//Vacío el buffer del puerto serie para evitar leer valores ya leidos.
    } 
     
    if (ledPrendido == true) 
    { 
        digitalWrite(pinLed, HIGH);   // prendo el LED 
    } 
    else 
    { 
        digitalWrite(pinLed, LOW);    // apago el LED 
    } 
} 


//Función que analiza e interpreta los comandos 
void commandInterpreter(String comando1, String comando2){ 
         
        //Me fijo que el comando 1 no esté vacío. 
    if (comando1 != ""){ 
        if (comando1 == "PRENDER") 
        { 
            if(comando2 == "LED") 
            { 
                ledPrendido = true; 
                Serial.println("LED PRENDIDO"); 
            } 
            else 
            { 
                Serial.println("COMANDO 2 INVALIDO"); 
            } 
        } 
         
        if (comando1 == "APAGAR") 
        { 
            if(comando2 == "LED") 
            { 
                ledPrendido = false; 
                Serial.println("LED APAGADO"); 
            } 
            else 
            { 
                Serial.println("COMANDO 2 INVALIDO"); 
            } 
        } 
         
        if (comando1 != "PRENDER" && comando1 != "APAGAR") 
        { 
            Serial.println("COMANDO 1 INVALIDO"); 
        } 
    } 
} 


Fuente: http://www.taringa.net/posts/hazlo-tu-mismo/16609621/Arduino-Comunicacion-Serial-e-interpretar-comandos.html

Declarar DS1820 mediante clases

El otro día Noter en el foro de arduino, me respondió a una duda que tenía, ya que me gustaría declarar un DS1820 de forma dinámica, lamentablemente el código no funciona pero en cuanto tenga tiempo para revisarlo me pongo a estudiar el código y a empaparme como funcionan las clases para poder solucionarlo.

Este código lo publico a pesar de que no funcione por que le puede ser de utilidad a mas de una como referencia para programar algo similar.

Declarar DS1820 mediante clases:
#include "OneWire.h"
#include "DallasTemperature.h" //Lib. Termometro de Dallas DS1820. 
 
class Termo {
public:
 Termo(int nPin):pin(nPin), ds(OneWire(pin)), st(DallasTemperature(&ds)){st.begin();};
 float lectura() {
  st.requestTemperatures();
  st.getTempCByIndex(0);
 }
private:
 int pin;
 OneWire ds;
 DallasTemperature st;
};

//Definimos donde estan conectados los distintos sensores
Termo termo[] = {
 Termo(10),
 Termo(11),
 Termo(12),
 Termo(14)
};
 
void setup(){ 
  Serial.begin(9600); 
} 
 
void loop(){ 
 for (int i=0; i<4; i++) {
  Serial.print ("Temp "); 
  Serial.print (i);
  Serial.print(": ") ;
  Serial.print(termo[i].lectura());
  Serial.println (" C"); 
 }
}


Si alguien lo hecha a andar el código, le agradecería que me indicase como corregir el código.

viernes, 20 de noviembre de 2015

Configurar el CH340 o CH341 en un MAC / Configurar copia china de arduino en un MAC

Hace poco me compre en Deal Extreme una copia china de un Arduino Mega 2560 y cuando intente volcar mi primer programa, me di cuenta de que mi MAC (El Capitan 10.11) no me reconocía la placa, ya que estas copias para ser más económicas en ved de montar un un FTDI  que es más caro, utilizan el CH340.

Como es lógico, tras leer en internet de que este chip es compatible con MAC, me dirigí a la web del fabricante, me descargue los drivers  para MAC, seguí los pasos que me indicaba el fabricante, y nada. Busque en los diferentes foros de internet, seguí los pasaos que ponía en dichos foros y nada.

Al final hablando con un amigo, me indico que en https://www.mac-usb-serial.com/ se pueden adquirir por 6.17€ drivers para el CH340 y para el PL2303 que funcionan perfectamente. Como me fastidiaba tener que utilizar el PC para andar programando, no me quedo más remedio que pasar por el aro. Después de probar el driver para los CH341 que venden, conecte mi arduino al MAC y me lo reconoció a la primera.




Código:
void setup() {
for(int i=0;i<=54
;i++){ //indicamos los pines de salida
pinMode(i, OUTPUT);
}
}

// the loop function runs over and over again forever
void loop() {
secuencia1();
secuencia2();
}

void secuencia1(){
for (int i=0; i<=54; i++){ //Pin 2 al 9
digitalWrite(i, HIGH); // Prenda pin actual
digitalWrite(i-1,LOW); // Apage el Anterior
delay(50); // retardo entre prender y apagar
}
}

void secuencia2(){
for (int i=54; i>=1; i--){ //Pin 2 al 9
digitalWrite(i, HIGH); // Prenda pin actual
digitalWrite(i+1,LOW); // Apage el Anterior
delay(50); // retardo entre prender y apagar
}
}

martes, 13 de octubre de 2015

PCF8574T - Tarjeta expansion 8 bit de bus I2C para Arduino

Hace unos meses en deal extreme me compre varias tarjetas de expansion de bus de 8 bit I2C. Creo que la que compre es la de este enlace.

Estas tarjetas llevan un PCF8574T y no se si es por eso, pero la intensidad que pueden dar es muy pequeña, y no es capaz de activarme el modulo de reles y eso que van octoacoplados.  Menos mal que tenia el osciloscopio a mano y he podido ver en el que efectivamente en las salidas tenia los 5v que tenia que tener.

Pues esta tontería me ha vuelto loco todo el puente y he perdido muchas horas de programación.

Esta tarde apenas he tenido tiempo para sentarme delante del MAC, pero el poco tiempo que he estado delante de la pantalla lo he aprovechado muy bien, ya que he conseguido mandar y recibir comandos por el puerto serial y he descubierto que el expansor de bus I2C de 8 bit funciona correctamente...

Código:
#include <Wire.h>
const int address = 0x20; //Esta direccion puede variar 

void setup()
  {
  Wire.begin(); //Inicializamos el I2C
  Serial.begin(9600);//Velocidad
  }
  
void loop() 
{

Wire.beginTransmission(address); //Inicializamos el PCF8574
Wire.write(170); //En binario seria 1010 1010 o si ponemos 
                 //255 el resultado de la salida seria 1111 1111 
Wire.endTransmission();
delay(100); 
}


Con  Wire.write(170); ponemos en números decimales el resultado binario que queremos conseguir en la salida del PCF8574.

Tabla de 0 al 255 de Sistema numerico Binario a Decimal
00000000   0     01000000   64     10000000  128     11000000  192

00000001   1     01000001   65     10000001  129     11000001  193

00000010   2     01000010   66     10000010  130     11000010  194

00000011   3     01000011   67     10000011  131     11000011  195

00000100   4     01000100   68     10000100  132     11000100  196

00000101   5     01000101   69     10000101  133     11000101  197

00000110   6     01000110   70     10000110  134     11000110  198

00000111   7     01000111   71     10000111  135     11000111  199

00001000   8     01001000   72     10001000  136     11001000  200

00001001   9     01001001   73     10001001  137     11001001  201

00001010  10     01001010   74     10001010  138     11001010  202

00001011  11     01001011   75     10001011  139     11001011  203

00001100  12     01001100   76     10001100  140     11001100  204

00001101  13     01001101   77     10001101  141     11001101  205

00001110  14     01001110   78     10001110  142     11001110  206

00001111  15     01001111   79     10001111  143     11001111  207

00010000  16     01010000   80     10010000  144     11010000  208

00010001  17     01010001   81     10010001  145     11010001  209

00010010  18     01010010   82     10010010  146     11010010  210

00010011  19     01010011   83     10010011  147     11010011  211

00010100  20     01010100   84     10010100  148     11010100  212

00010101  21     01010101   85     10010101  149     11010101  213

00010110  22     01010110   86     10010110  150     11010110  214

00010111  23     01010111   87     10010111  151     11010111  215

00011000  24     01011000   88     10011000  152     11011000  216

00011001  25     01011001   89     10011001  153     11011001  217

00011010  26     01011010   90     10011010  154     11011010  218

00011011  27     01011011   91     10011011  155     11011011  219

00011100  28     01011100   92     10011100  156     11011100  220

00011101  29     01011101   93     10011101  157     11011101  221

00011110  30     01011110   94     10011110  158     11011110  222

00011111  31     01011111   95     10011111  159     11011111  223

00100000  32     01100000   96     10100000  160     11100000  224

00100001  33     01100001   97     10100001  161     11100001  225

00100010  34     01100010   98     10100010  162     11100010  226

00100011  35     01100011   99     10100011  163     11100011  227

00100100  36     01100100  100     10100100  164     11100100  228

00100101  37     01100101  101     10100101  165     11100101  229

00100110  38     01100110  102     10100110  166     11100110  230

00100111  39     01100111  103     10100111  167     11100111  231

00101000  40     01101000  104     10101000  168     11101000  232

00101001  41     01101001  105     10101001  169     11101001  233

00101010  42     01101010  106     10101010  170     11101010  234

00101011  43     01101011  107     10101011  171     11101011  235

00101100  44     01101100  108     10101100  172     11101100  236

00101101  45     01101101  109     10101101  173     11101101  237

00101110  46     01101110  110     10101110  174     11101110  238

00111111  47     01101111  111     10101111  175     11101111  239

00110000  48     01110000  112     10110000  176     11110000  240

00110001  49     01110001  113     10110001  177     11110001  241

00110010  50     01110010  114     10110010  178     11110010  242

00110011  51     01110011  115     10110011  179     11110011  243

00110100  52     01110100  116     10110100  180     11110100  244

00110101  53     01110101  117     10110101  181     11110101  245

00110110  54     01110110  118     10110110  182     11110110  246

00110111  55     01110111  119     10110111  183     11110111  247

00111000  56     01111000  120     10111000  184     11111000  248

00111001  57     01111001  121     10111001  185     11111001  249

00111010  58     01111010  122     10111010  186     11111010  250

00111011  59     01111011  123     10111011  187     11111011  251

00111100  60     01111100  124     10111100  188     11111100  252

00111101  61     01111101  125     10111101  189     11111101  253

00111110  62     01111110  126     10111110  190     11111110  254

00111111  63     01111111  127     10111111  191     11111111  255



Las 8 direcciones posibles.
| 0 | 0 | 0 | = 0x20
| 0 | 0 | 1 | = 0x21
| 0 | 1 | 0 | = 0x22
| 0 | 1 | 1 | = 0x23
| 1 | 0 | 0 | = 0x24
| 1 | 0 | 1 | = 0x25
| 1 | 1 | 0 | = 0x26
| 1 | 1 | 1 | = 0x27
PCF8574

No se si me explicado bien, pero por lo menos lo he intentado...

Guardar en un string los datos que se han pasado desde el PC o MAC al ARDUINO

A continuación aquí añado un pequeño código para guardar en un string los datos que se han pasado desde el PC o MAC al ARDUINO.

Código:
/*
* SerialReceive sketch
* Guardar en un string el contenido de un dato
* pasado por serial desde el PC o MAC a ARDUINO
*/

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

void loop ()
  { 
  char ch = ' '; //Variable donde se guarda el char que se recibe por serial.
  String mensaje ="" ; //Variable para guardar el texto pasado por serial.

  if (Serial.available()) //Si el serial esta libre...
    {
    while( ch != '\n') //leemos hasta el retorno de carro o enter.
      { 
      ch = Serial.read(); //Lee un caracter.
      Serial.println(ch); //Imprime el caracter "ch" recivido por serial. 
      mensaje = mensaje + ch ; //lo anadimos a la variable mensaje.
      delay(25); //Esperamos 25ms para evitar colixiones de datos.
      }
    Serial.println( mensaje); //Imprimimos el mensaje
    mensaje = "" ; //Borramos el string
     }
  }


Luego los datos de la variable mensaje los podremos utilizar como mejor nos convenga.

domingo, 5 de enero de 2014

Arduino cast o truncar un número foat para Convertit float a int, convertir int a byte...

Según el manual de referencia de Arduino, el operador cast (convertidor de tipos) traduce de un tipo de variable a otra y fuerza que los cálculos se realicen según en el nuevo tipo de variable.

Ejemplo
int i;
float f;
f = 3.6;
i = (int) f; // ahora i es 3

Nota
Cuando hacemos un casting de un float a un int (coma flotante a entero) el valor es truncado, no redondeado. Así que por ejemplo, tanto (int) 3.2 como (int) 3.7 acaban siendo 3.

Fuente: http://arduino.cc/es/Reference/Cast

Una ved llegados a este punto podemos pensar que cast no muy útil puesto que al utilizarlo perdemos los decimales. Pero existe un truco para pasar un valor foat a int sin perder las decimales. Imaginemos que estamos trabajando con un termometro que nos mide la temperatura en grados, y el valor entregado lo tenemos almacenado en una variable float, y nosotros queremos pasarlos a una variable tipo int con dos decimales de precisión. Para solventar este problema, tenemos que trabajar en fracciones de la unidad (décimas, centésimas, milésimas) y escoger la unidad que mejor se ajuste a nuestras necesidades.

En este ejemplo que me puso noter en el foro de arduino se ve claramente a que me refiero:

Código:
float grados=27.56;
int centGrados= grados*100.0; // centGrados=2756
Serial.print(centGrados/100); // Imprime 27
Serial.print(",");
Serial.print(centGrados%100);// Imprime 56 

Fuente: http://forum.arduino.cc/index.php?topic=208565.0

Gracias a ehrja y noter por enseñarme este truco.

sábado, 4 de enero de 2014

Arduino Histeresis, retardo o tolerancia de una medida

Normalmente se le llama histeresis a una tolerancia o retardo que tiene un material. Imaginemos que nuestro arduino esta midiendo la temperatura de un liquido que tiene que empezar a fluir a los 30ºC y tiene una tolerancia de 2ºC pues nuestro liquido fluiría entre los 28 y los 32ºC.

De esta forma nosotros podríamos calentar el liquido hasta alcanzar los 33ºC y dejar de calentarlo hasta que la temperatura leída sea menor que 30ºC pero pero superior a 28ºC....

Con esta función calculamos la histeresis de un número:

Código:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); // 0x27 es la direccion del LCD 16x2

int tolerancia = 5;

void setup() 
  {
  lcd.init();
  lcd.backlight(); //enciende la iluminacion 
  }

void loop() 
  {
    Histeresis (random(-10, 10), random(-10, 10), tolerancia );
    delay(2000);
  }
// x = Es un valor fijo, por ejemplo el que hemos programado o estipulado.
// y = Puede ser el valor obtenido por una sonda.
// t = La tolerancia o magen que hemos estipulado, la histeresis.

void Histeresis (int x, int y, int t)
  {
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("X: ");
    lcd.print(x);
    lcd.print(" Y: ");
    lcd.print(y);
    lcd.setCursor(0, 0);
    lcd.print("Tol: ");
    lcd.print(t);
    lcd.setCursor(6, 0);

    int superior, inferior = 0;
    superior = x + t; //valor fijo + tolerancia
    inferior = x - t; //valor fijo + tolerancia
    if ((y >= inferior) && (y <= superior))
      {
      lcd.print(" Si");
      }
      else
      {
      lcd.print(" No");
      }
  }



viernes, 3 de enero de 2014

Arduino Obtener el taño de un aray 2D con sizeof();

Hacia tiempo que estaba atascado con un programa, necesitaba recorrer un array multidimensional o array 2D del cual desconocía el tamaño o número de filas.

Código:
int ProgTemporizador [][7] = 
  {
  //Fecha, Mes, Año, Hora, Minutos, Salida, Estado  
  {2014, 1, 2, 10, 12, 0, 1},
  {2014, 1, 2, 10, 13, 0, 0},
  {2014, 1, 2, 10, 13, 1, 1},
  {2014, 1, 2, 10, 14, 1, 0}
  };



Después de preguntar en el foro de arduino, noter me dio la solución. Cuando hacia sizeof(ProgTemporizador); el resultado que obtenía era 56 y yo me pensaba que estaba haciendo algo mal. Pero no es así, ya que sizeof(); no el número de filas de un array, si no que nos devuelve tamaño en bytes del array. Para obtener el número de filas de un array en nuestro caso tenemos que dividir el resultado por 14:

Si hacemos un sizeof(ProgTemporizador); obtenemos  56 (4*7*2), que es el resultado de la mutiplicación del número de filas del array por El número de columnas del array por 2 ya que un INT ocupa 2 bytes.

Código:
int ProgTemporizador [][7] = 
  {
  //Fecha, Mes, Año, Hora, Minutos, Salida, Estado  
  {2014, 1, 2, 10, 12, 0, 1},
  {2014, 1, 2, 10, 13, 0, 0},
  {2014, 1, 2, 10, 13, 1, 1},
  {2014, 1, 2, 10, 14, 1, 0}
  };

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

void loop()
  {
  int x = sizeof(ProgTemporizador);   
  x = (x / 7) / 2;
  //x = x / 14; Mas facil seria dividirlo por 14...
  Serial.print ("Numero X = ");
  Serial.println (x);
  for (int i=0; i < x; i++)
    {
      for (int n=0; n < 7; n++)
        {
          Serial.print(ProgTemporizador [i][n]);
          Serial.print("   ");
        }
    Serial.println();    
    }
  Serial.println ("-----------------------------------------------------");  
  delay(5000);
  }

Fuente: http://forum.arduino.cc/index.php?topic=208323.0

Arduino Funcion para obtener la fecha en modo texto

Hace un rato me he encontrado con esta funcion que ha publicado jalfonsosuarez en el foro de arduino, y me ha parecido muy interesante, ya que con ella se puede pasar una fecha obtenida del relog en tiempo real (RTC) a modo texto muy facilmente y con poco codigo:

Código:
/*
FUNCION PARA OBTENER LA FECHA EN MODO TEXTO
Devuelve: DD-MM-AAAA HH:MM:SS
*/
String dimeFecha()
  {
  char fecha[20];
  DateTime now = RTC.now(); //Obtener fecha y hora actual.
        
  int dia = now.day();
  int mes = now.month();
  int anio = now.year();
  int hora = now.hour();
  int minuto = now.minute();
  int segundo = now.second();
        
  sprintf( fecha, "%.2d.%.2d.%.4d %.2d:%.2d:%.2d", dia, mes, anio, hora, minuto, segundo);
  return String( fecha );
  }

Fuente:
http://forum.arduino.cc/index.php?topic=207403.0 

lunes, 30 de diciembre de 2013

Arduino mostrar temperatura con un DS1820 en un LCD 16x2 I2C

Tras varios días de desesperación ya he conseguiguido echar a andar el DS1820 conectado a un display, este es el codigo que he utilizado:



Código:
/*
Autor: Aitor Martin
Fecha: 28-12-2013
Titulo: Sensor de temperatura DS1820
Placa: Arduino uno
Post: http://aitormartin-apuntes.blogspot.com.es/2013/12/arduino-mostrar-temperatura-con-un.html

Código de dominio publico. Se puede distribuir y modificar  libremente, 
siempre y cuando se mencione al autor y se proporcione un enlace a su web.
*/

#include <OneWire.h> //Configurar bus onewhire de Dallas
#include <DallasTemperature.h>//El ternometro de Dallas DS1820
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); // 0x27 es la direccion del LCD 16x2

//Pata por la que van a entrar los datos al Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

void setup() 
  {
  lcd.init();
  lcd.backlight(); //enciende la iluminacion
  sensors.begin(); //Iniciamos la libreria del DS1820
  }

void loop() 
{

  sensors.requestTemperatures(); //leemmos la temperatura del sensor.
  lcd.setCursor(0, 0);
  lcd.print(sensors.getTempCByIndex(0)); 
  lcd.print(" *C");
  delay(3000);
  }



Nota:
A mi a la hora de compilar, las librerias del DS1820 me dierón problemas. Si este es tu caso mira este enlace:

http://aitormartin-apuntes.blogspot.com.es/2013/12/arduino-sensores-ds-1820-y-el-error.html

Arduino sensores DS 1820 y el error WConstants.h

Hace cosa de un par de días que me puse a hacer pruebas con los DS 1820 y no conseguia que me funcionase nada me daba un error el :

Error (TCL 3.7.1 Beta):
Documents/Arduino/libraries/DallasTemperature_371Beta/DallasTemperature.cpp:9:26: 
error: WConstants.h: No such file or directory

De internet me descargue muchas librerias diferentes, pero nada si no era un error, era el otro. Me fui a la que creo que es la web oficial y me descarge la versión TCL 3.7.1 Beta, pero me daba el error que aparace en el recuadro de arriba. A si que me decidi descargarme una versión mas vieja de la libreria. Me baje la libreria TCL 3.5.0 me me dio otro error muy diferente:

Error (TCL 3.5.0):
Documents/Arduino/libraries/DallasTemperature/DallasTemperature.cpp:9:26: error: WConstants.h: No such file or directory
Fuente: http://www.todomarino.com/forum/showthread.php?84914-Informativo-DS18B20-y-arduino-v-1-0

Esta ved me decia que no encontraba WConstants.h, a si que buscando por internet me encontre con una web en la que David Dicha Perez nos da la solución a este problema:

Solucion:
Si alguien se le ha dado por bajarse la ultima versión que han sacado los de arduino (la v 1.0) y usa los sensores de temperatura del tipo ds1820 o otros de dallas os va a fallar. A parte de bajar las ultimas versiones de las librerías onewire y dallastemperature hay que editar a mano la de dallastemperature y cambiar los sitios donde pueda poner WConstants.h o wiring.h por Arduino.h.

No se si ya lo sabíais pero me acabo de volver mico para encontrar esa referencia...

por si alguien quiere ver el resto de cambios echadle un ojo a los de la 1.0:

http://arduino.cc/en/Main/ReleaseNotes

A si que con el editor de textos abri el fichero DallasTemperature.cpp y cambie el texto que ponia WConstants.h por Arduino.h tal y como comentava David, compile y me funciono a la primera.

Antes:
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

#include "DallasTemperature.h"

extern "C" {
  #include "WConstants.h"
}

Despues:
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

#include "DallasTemperature.h"

extern "C" {
  #include "Arduino.h"
}

Si no quereis complicaros, en la sección de descargas suelo tener una copia de seguridad de mis librerias compartida con todo el mundo.