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

Proceso Terrario Control V.0.3

De ved en cuando suelo recibir e-mails preguntándome como va el proceso del Terrario Control, si esta abandonado el proyecto o sigue en marcha. La verdad es que últimamente no tengo mucho tiempo para dedicarle al Terrario Control, pero si sigue en marcha, pero tardara un poco.

El Terrario Control V.0.1 esta totalmente funcional, pero los parámetros de la configuración se tenían que introducir en el momento de la programación. Pero el sofwar esta preparado para que se puedan introducir estos datos por el serial, pero no llegue a terminar esta parte ya que no dominaba correctamente la comunicación serial.

El terrario Control V.0.2 su funcionamiento es similar al V.0.1 pero con la diferencia de que los parámetros de configuración los carga desde una tarjeta SD. Al igual que en el V.0.1 me falta implementarle la comunicación serial. Hay algunos algoritmos que se tienen que mejorar para que sea más eficiente, pero por lo demás funciona bastante bien.

Actualmente, tanto la versión V.0.1 como la V.0.2 están paradas, puesto que actualmente estoy trabajando en la versión V.0.3.

La versión V.0.3 la estoy haciendo desde cero, reciclando algunas partes de código, pero lamentablemente debido a sus nuevas características, no he podido reutilizar tanto código como me gustaría.

La principal diferencia entre las versiones anteriores y el Terrario Control V0.3 es que este esta diseñado para poder trabajar de forma independiente o conectado inalambricamente a una red de hasta 6000 nodos, e interactuar entre ellos.

Actualmente el Terrario Control  puede realizar las siguiente punciones:

- Encender y apagar hasta 6 salidas.
- Leer 6 termometros.
- Leer los datos de 2 sensores de Humedad y Temperatura.
- Recibir y trasmitir comandos a trabes del puerto serial.

Actualmente estoy trabajando en el interprete de comandos, que espero terminar esta tarde.

Debido al interés que hay por ciertas personas en el Terrario Control V.0.3, seguiré posteando por este blog las últimas novedades y el estado del proyecto.

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.