Publicidad

sábado, 17 de junio de 2017

Voltímetro y Amperímetro con LCD Nokia 5110



En el anterior tutorial vimos como hacer un doble voltímetro y amperímetro para una fuente de laboratorio. 

Como recordaréis, la fuente disponía de una tensión positiva y otra negativa, lo que nos obligaba al uso de amplificadores operacionales para adaptar la señal y poder medirla con Arduino.

Para mostrar las tensiones y corrientes empleamos un LCD monocromo de 16 caracteres x 2 filas de texto, que se quedaba un poco justo para mostrar toda la información.

Pues bien, en el siguiente proyecto vamos a simplificar el circuito de medida del voltímetro y vamos a sustituir el LCD de 16x2 caracteres por un display gráfico Nokia 5110.

En una primera parte vamos a hacer el voltímetro y en un segundo circuito añadiremos el amperímetro.




1. Voltímetro con Arduino y LCD Nokia 5110


Esquema

El voltímetro aquí descrito únicamente lo vamos a usar para medir tensiones positivas.

Solo necesitamos un atenuador de señal a la entrada del pin A0 del Arduino. Si no sabes qué es un atenuador de señal y para qué sirve, por favor echa un vistazo al Proyecto 28.2 antes de continuar.





El funcionamiento del sketch es muy sencillo. Simplemente conectamos el pin A0 al divisor de tensión formado por las resistencias R1 y R2. Debido al valor escogido para R1 y R2, el divisor de tensión funciona como un atenuador x6 de la tensión que queremos medir, y como la máxima tensión en los pines del Arduino es de 5V, significa que la máxima tensión que podemos medir es de 30V. Todo esto, está explicado con más detalle en el Proyecto 28.2.

Bien, al tener una atenuación x6, la variación entre 0 y 5V en el pin A0 corresponde con una tensión entre 0 y 30V en la fuente de alimentación.

En la variable RawVCC almacenamos el valor de analogRead(A0). Con la función map(RawVCC, 0, 1023, 0, 3000); convertimos los 0-1023 valores posibles de RawVCC en 0-3000, que se corresponden con la variación entre 0 y 30V de la fuente. Luego sólo hay que dividir entre 100 para obtener el valor real de tensión en la fuente de alimentación.


Sketch


/*********************************************************************
This is an example sketch for our Monochrome Nokia 5110 LCD Displays

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/338

These displays use SPI to communicate, 4 or 5 pins are required to
interface

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

Written by Limor Fried/Ladyada  for Adafruit Industries.
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/

// Easy Voltmeter with Arduino & Nokia 5110 LCD Display 
// https://sites.google.com/site/angmuz/

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

// Software SPI (slower updates, more flexible pin options):
// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);


int RawVCC = 0;
float VCC = 0;
float auxVCC = 0;


void setup()   {
  
  // Iniciamos comunicacion serie 
  Serial.begin(9600);
  
  // Iniciamos comunicacion con la pantalla
  display.begin();
  
  // Establecemos el contraste
  display.setContrast(50);

  // Mostramos la pantalla de inicio durante 2 segundos
  //display.display(); 
  delay(2000);
  display.clearDisplay();   
}



void loop()
{
  
  RawVCC = analogRead(A0);
  auxVCC = map(RawVCC, 0, 1023, 0, 3000);
  VCC = (auxVCC / 100.0);
  
  // text display tests
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0,0);
  display.print("V=");
  display.println(VCC,1);
   
  display.setTextSize(1);
  display.setCursor(0,20);
  display.println("Arduino");
  display.print("Easy Voltmeter");
  display.println("sites@angmuz");
  display.display();
  delay(100);  
  
}




2. Voltímetro y Amperímetro con Arduino y LCD Nokia 5110


Esquema

Al igual que en el Proyecto 28.2, para medir la corriente vamos a usar un sensor ACS712. Se conecta como en el esquema, se alimenta entre +5V y GND y la salida la llevamos al pin A3. Si quieres saber más detalles de este módulo haz clic en enlace anterior.





Partiendo del código del voltímetro, añadimos las líneas correspondientes al amperímetro, como en el tutorial 28.2. 
También la parte correspondiente al cálculo del offset, ya estos módulos tienen un error apreciable. Así conseguimos afinar bastante la medida.


Sketch

// Voltímetro y Amperímetro con Nokia 5110 LCD Display
// https://sites.google.com/site/angmuz/

/*********************************************************************
This is an example sketch for our Monochrome Nokia 5110 LCD Displays

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/338

These displays use SPI to communicate, 4 or 5 pins are required to
interface

Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

Written by Limor Fried/Ladyada  for Adafruit Industries.
BSD license, check license.txt for more information
All text above, and the splash screen must be included in any redistribution
*********************************************************************/

#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>

// Software SPI (slower updates, more flexible pin options):
// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3);

// Variables para el voltímetro
int RawVCC = 0;
float VCC = 0;
float auxVCC = 0;

//Variables para el amperímetro
float ICC = 0;
float offset1 = 0;

boolean ofst = 0;

void setup()   {
  
  
  // Iniciamos comunicacion serie 
  Serial.begin(9600);
  
  // Iniciamos comunicacion con la pantalla
  display.begin();
  
  // Establecemos el contraste
  display.setContrast(50);

  // Mostramos la pantalla de inicio durante 2 segundos
  //display.display(); 
  delay(2000);
  display.clearDisplay();   
}

// Función para calcular el offset de la corriente ICC
float offset1Adj()
{
  
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.println("Calculando");
  display.println("offset");
  display.println("No conectar");
  display.println("ninguna carga");
  display.println("Por favor");
  display.println("espere...");
  display.display();
  delay(2000);  // to allow time for stabilizing offset
  for(int i = 0; i < 1000; i++) {
  offset1 = offset1 + (.0264 * analogRead(A3) -13.51);
  delay(2);
  }
  
  digitalWrite(2, LOW);
  ofst = 1;
  return offset1;
}

void loop()
{
  if (ofst == 0) 
    {
    offset1 = offset1Adj();
    }
    
  float average1 = 0;
  for(int i = 0; i < 1000; i++) {
  average1 = average1 + (.0264 * analogRead(A3) -13.51);
  delay(1);
  }
  
  RawVCC = analogRead(A0);
  auxVCC = map(RawVCC, 0, 1023, 0, 3000);
  VCC = (auxVCC / 100.0);
  
  ICC = (average1 - offset1) ; // offset adjust
   
  // text display tests
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("VCC=");
  display.print(VCC,1);
  display.println("V");
  display.print("ICC=");
  display.print(ICC,0);
  display.println("mA");
  display.print("offset=");
  display.println(offset1,0);
  display.println("");
  display.print("Volt-Amp Meter");
  display.println("sites@angmuz");
  display.display();
  delay(100); 
  
}

Módulo Bluetooth

En este primer ejemplo vamos a encender y apagar un motor y a controlar el sentido de giro. Para ello descargamos en Google Play la app BlueTerm de pydasde.es con la que vamos a introducir los comandos de control.

El módulo bluetooth utilizado es el HC-05, lo podeís encontrar en dealxtreme por unos 6-7 euros. La diferencia con el HC-06 es que el primero es maestro-esclavo, mientras que el HC-06 es esclavo.

En DIYmakers hay un estupendo tutorial acerca de estos módulos con un ejemplo sencillo donde se explica como controlar tres leds desde el móvil con la app BlueTerm.


Esquema

Como veis el circuito es muy sencillo, solo hace falta un L293D y el módulo HC-05.


Sketch

El código está basado en un tutorial de Rui Santos y adaptado al circuito anterior.

Antes de cargar el código en el arduino, desconectad los pines para TX y RX ya que son los terminales de comunicación con el PC y si están en uso por el módulo bluetooth dará error al cargar el sketch. Conectar los pines TX y RX del módulo al arduino una vez finalizada la carga del programa.

El funcionamiento es muy sencillo. Conectar el móvil con el módulo HC-05, la contraseña es 1234 y al pulsar el comando correspondiente en el teclado de la app, el motor obrará en consecuencia.


/*
 * Control DC motor with Smartphone via bluetooth
 * created by Rui Santos, http://randomnerdtutorials.com
 * Modificado por angmuz, https://sites.google.com/site/angmuz/
*/

int motorPin1 = 10; // pin 2 on L293D IC
int motorPin2 = 9; // pin 7 on L293D IC
int enablePin = 5; // pin 1 on L293D IC
int state;
int flag=0;        //makes sure that the serial only prints once the state
 
void setup() {
    // sets the pins as outputs:
    pinMode(motorPin1, OUTPUT);
    pinMode(motorPin2, OUTPUT);
    pinMode(enablePin, OUTPUT);
    // sets enablePin high so that motor can turn on:
    digitalWrite(enablePin, HIGH);
    // initialize serial communication at 9600 bits per second:
    Serial.begin(9600);
}
 
void loop() {
    //if some date is sent, reads it and saves in state
    if(Serial.available() > 0){     
      state = Serial.read();   
      flag=0;
    }   
    // if the state is '0' the DC motor will turn off
    if (state == '0') {
        digitalWrite(motorPin1, LOW); // set pin 2 on L293D low
        digitalWrite(motorPin2, LOW); // set pin 7 on L293D low
        if(flag == 0){
          Serial.println("Motor: off");
          flag=1;
        }
    }
    // if the state is '1' the motor will turn right
    else if (state == '1') {
        digitalWrite(motorPin1, LOW); // set pin 2 on L293D low
        digitalWrite(motorPin2, HIGH); // set pin 7 on L293D high
        if(flag == 0){
          Serial.println("Motor: right");
          flag=1;
        }
    }
    // if the state is '2' the motor will turn left
    else if (state == '2') {
        digitalWrite(motorPin1, HIGH); // set pin 2 on L293D high
        digitalWrite(motorPin2, LOW); // set pin 7 on L293D low
        if(flag == 0){
          Serial.println("Motor: left");
          flag=1;
        }
    }
}




Proyecto 19b - Control motores CC. Parte 2

En este ejemplo vamos a añadir un segundo motor.


Esquema

Sketch

/*
 * Control DC motor with Smartphone via bluetooth
 * created by Rui Santos, http://randomnerdtutorials.com
 * Modificado por angmuz, https://sites.google.com/site/angmuz/
*/

int motor1Pin1 = 10; // pin 2 on L293D IC
int motor1Pin2 = 9; // pin 7 on L293D IC
int enableM1Pin = 5; // pin 1 on L293D IC
int motor2Pin1 = 4; // pin 10 on L293D IC
int motor2Pin2 = 13; // pin 15 on L293D IC
int enableM2Pin = 6; // pin 9 on L293D IC
int state;
int flag=0;        //makes sure that the serial only prints once the state
 
void setup() {
    // sets the pins as outputs:
    pinMode(motor1Pin1, OUTPUT);
    pinMode(motor1Pin2, OUTPUT);
    pinMode(enableM1Pin, OUTPUT);
    pinMode(motor2Pin1, OUTPUT);
    pinMode(motor2Pin2, OUTPUT);
    pinMode(enableM2Pin, OUTPUT);
    // sets enablePin high so that motor can turn on:
    digitalWrite(enableM1Pin, HIGH);
    digitalWrite(enableM2Pin, HIGH);
    // initialize serial communication at 9600 bits per second:
    Serial.begin(9600);
}
 
void loop() {
    //if some date is sent, reads it and saves in state
    if(Serial.available() > 0){     
      state = Serial.read();   
      flag=0;
    }   
    // if the state is '0' the DC motor will turn off
    if (state == '0') {
        digitalWrite(motor1Pin1, LOW); // set pin 2 on L293D low
        digitalWrite(motor1Pin2, LOW); // set pin 7 on L293D low
        digitalWrite(motor2Pin1, LOW); // set pin 10 on L293D low
        digitalWrite(motor2Pin2, LOW); // set pin 15 on L293D low
        if(flag == 0){
          Serial.println("Motors: off");
          flag=1;
        }
    }
    // if the state is '1' the motors will turn right
    else if (state == '1') {
        digitalWrite(motor1Pin1, LOW); // set pin 2 on L293D low
        digitalWrite(motor1Pin2, HIGH); // set pin 7 on L293D high
        digitalWrite(motor2Pin1, LOW); // set pin 10 on L293D low
        digitalWrite(motor2Pin2, HIGH); // set pin 15 on L293D high
        if(flag == 0){
          Serial.println("Motors: right");
          flag=1;
        }
    }
    // if the state is '2' the motor will turn left
    else if (state == '2') {
        digitalWrite(motor1Pin1, HIGH); // set pin 2 on L293D high
        digitalWrite(motor1Pin2, LOW); // set pin 7 on L293D low
        digitalWrite(motor2Pin1, HIGH); // set pin 10 on L293D low
        digitalWrite(motor2Pin2, LOW); // set pin 15 on L293D high
        if(flag == 0){
          Serial.println("Motors: left");
          flag=1;
        }
    }
}



Proyecto 19c - Control motores CC y Leds

Ahora añadimos Leds al circuito.


Esquema

Sketch

/*
 * Control DC motor with Smartphone via bluetooth
 * created by Rui Santos, http://randomnerdtutorials.com
 * Modificado por angmuz, https://sites.google.com/site/angmuz/
*/

int motor1Pin1 = 10; // pin 2 on L293D IC
int motor1Pin2 = 9; // pin 7 on L293D IC
int enableM1Pin = 5; // pin 1 on L293D IC
int motor2Pin1 = 4; // pin 10 on L293D IC
int motor2Pin2 = 13; // pin 15 on L293D IC
int enableM2Pin = 6; // pin 9 on L293D IC
int ledRojo = 2; // Led rojo al pin 2
int ledVerde = 3; // Led verde al pin 3
int state;
int flag=0;        //makes sure that the serial only prints once the state
 
void setup() {
    // sets the pins as outputs:
    pinMode(motor1Pin1, OUTPUT);
    pinMode(motor1Pin2, OUTPUT);
    pinMode(enableM1Pin, OUTPUT);
    pinMode(motor2Pin1, OUTPUT);
    pinMode(motor2Pin2, OUTPUT);
    pinMode(enableM2Pin, OUTPUT);
    pinMode(ledRojo, OUTPUT);
    pinMode(ledVerde, OUTPUT);
    // sets enablePin high so that motor can turn on:
    digitalWrite(enableM1Pin, HIGH);
    digitalWrite(enableM2Pin, HIGH);
    // initialize serial communication at 9600 bits per second:
    Serial.begin(9600);
}
 
void loop() {
    //if some date is sent, reads it and saves in state
    if(Serial.available() > 0){     
      state = Serial.read();   
      flag=0;
    }   
    // if the state is '0' the DC motor will turn off
    if (state == '0') {
        digitalWrite(motor1Pin1, LOW); // set pin 2 on L293D low
        digitalWrite(motor1Pin2, LOW); // set pin 7 on L293D low
        digitalWrite(motor2Pin1, LOW); // set pin 10 on L293D low
        digitalWrite(motor2Pin2, LOW); // set pin 15 on L293D low
        if(flag == 0){
          Serial.println("Motors: off");
          flag=1;
        }
    }
    // if the state is '1' the motors will turn right
    else if (state == '1') {
        digitalWrite(motor1Pin1, LOW); // set pin 2 on L293D low
        digitalWrite(motor1Pin2, HIGH); // set pin 7 on L293D high
        digitalWrite(motor2Pin1, LOW); // set pin 10 on L293D low
        digitalWrite(motor2Pin2, HIGH); // set pin 15 on L293D high
        if(flag == 0){
          Serial.println("Motors: right");
          flag=1;
        }
    }
    // if the state is '2' the motor will turn left
    else if (state == '2') {
        digitalWrite(motor1Pin1, HIGH); // set pin 2 on L293D high
        digitalWrite(motor1Pin2, LOW); // set pin 7 on L293D low
        digitalWrite(motor2Pin1, HIGH); // set pin 10 on L293D low
        digitalWrite(motor2Pin2, LOW); // set pin 15 on L293D high
        if(flag == 0){
          Serial.println("Motors: left");
          flag=1;
        }
    }
    // if the state is '3' the leds will turn ON
    else if (state == '3') {
        digitalWrite(ledRojo, HIGH); // set Red led ON
        digitalWrite(ledVerde, HIGH); // set Green led ON
        if(flag == 0){
          Serial.println("Leds ON");
          flag=1;
        }
    }
    // if the state is '4' the leds will turn OFF
    else if (state == '4') {
        digitalWrite(ledRojo, LOW); // set Red led OFF
        digitalWrite(ledVerde, LOW); // set Green led OFF
        if(flag == 0){
          Serial.println("Leds OFF");
          flag=1;
        }
    }
}

Coche RC Laser

Coche radiocontrol con Servo-Láser


En este proyecto vamos a añadir a nuestro coche de control remoto un láser apuntado por dos servos.
Uno de los servos mueve el láser en el eje X, el otro en el eje Y, de esa forma apuntamos el láser dónde queramos.

Y para añadir más complejidad al proyecto, en este coche los motores serán paso a paso. A cambio ganamos en precisión de movimientos.

El láser tiene una construcción modular, por lo que se puede instalar en cualquier tipo de vehículo que se os ocurra. Es un láser de 5mW, pero con uno de potencia suficiente podríamos quemar objetivos.

El coche está construido totalmente a mano, partiendo de una lámina de metacrilato a modo de chasis y el soporte de los motores es un perfil en U sacado de una canaleta para cables como las empleadas por los electricistas.

Detalle de los servos.




Esquema
El shield para motores de Adafruit es perfecto para ese proyecto, ya que permite controlar dos servos y dos motores paso a paso en la misma tarjeta.

Conectamos el receptor de infrarrojos en el pin D2 ya que es el único que no se usa. Y para que el diodo láser no esté permanentemente encendido, en lugar de conectarlo a 5V directamente, lo vamos a conectar al pin A0 y lo encenderemos a voluntad con el mando a distancia.

Los pines analógicos de arduino también se pueden utilizar como entradas/salidas digitales con tan solo configurarlo así en el setup.





Sketch

#include <AccelStepper.h>
#include <AFMotor.h>
#include <IRremote.h>
#include <Servo.h>

// two stepper motors one on each port
AF_Stepper motor1(64, 1);
AF_Stepper motor2(64, 2);

int receiverpin = 2; 
IRrecv irrecv(receiverpin); 
decode_results results;

Servo servoH;  // create servoH object to control a servo 
Servo servoV;  // create servoV object to control a servo                
 
int posH=80;
int posV=80;
boolean laser=0;

// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {  
  motor1.onestep(FORWARD, DOUBLE);
}
void backwardstep1() {  
  motor1.onestep(BACKWARD, DOUBLE);
}
// wrappers for the second motor!
void forwardstep2() {  
  motor2.onestep(FORWARD, DOUBLE);
}
void backwardstep2() {  
  motor2.onestep(BACKWARD, DOUBLE);
}

// Motor shield has two motor ports, now we'll wrap them in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);

//Funciones para los motores

void goForward()
{
  stepper1.move(4000);
  stepper2.move(-4000);  
}

void goBackward()
{
  stepper1.move(-4000);
  stepper2.move(4000);    
}
void turnRight()
{
  stepper1.move(-1100);
  stepper2.move(-1100);    
}
void turnLeft()
{
  stepper1.move(1100);
  stepper2.move(1100);    
}
void turnRight45()
{
  stepper1.move(-550);
  stepper2.move(-550);    
}
void turnLeft45()
{
  stepper1.move(550);
  stepper2.move(550);    
}


void setup()
{  
  Serial.begin(9600); 
  irrecv.enableIRIn();
  
  stepper1.setMaxSpeed(600);
  stepper1.setAcceleration(300);
  stepper2.setMaxSpeed(600);
  stepper2.setAcceleration(300);
  
  servoH.attach(10); 
  servoV.attach(9); 
  
  pinMode(A0, OUTPUT);
}

//Funciones para los servos 
//Funcion 1
void servoH_dcha()
{
  if (posH >= 15)
  {
    posH--;
    servoH.write(posH);
    delay(500);
  }
  if (posH < 15)
  {
    posH=posH+5;
    servoH.write(posH);
    delay(500);
  }
}
//Funcion 2
void servoH_izqda()
{
  if (posH <= 165)
  {
    posH++;
    servoH.write(posH);
    delay(500);
  }
  if (posH > 165)
  {
    posH=posH-5;
    servoH.write(posH);
    delay(500);
  }
}
//Funcion 3
void servoV_arriba()
{
  if (posV <= 165)
  {
    posV++;
    servoV.write(posV);
    delay(500);
  }
  if (posV > 165)
  {
    posV=posV-5;
    servoV.write(posV);
    delay(500);
  }
}
//Funcion 4
void servoV_abajo()
{
  if (posV >= 15)
  {
    posV--;
    servoV.write(posV);
    delay(500);
  }
  if (posV < 15)
  {
    posV=posV+5;
    servoV.write(posV);
    delay(500);
  }
}
//Funcion 5 Home
void Home()
{
  servoH.write(80);
  servoV.write(80);
  delay(500);
}

//Funcion LaserONOFF

void laserONOFF()
{
  if (laser==0){
    digitalWrite(A0, HIGH);
  }
  if (laser==1){
    digitalWrite(A0, LOW);
  }
  laser=!laser;
  delay(500);
}


void translateIR()
{
  switch(results.value)
  
  {
    case 0xD05: laserONOFF(); break;  // Laser ON/OFF 
    case 0x505: laserONOFF(); break;  // Laser ON/OFF 
        
    case 0xD02: goForward(); break;  // Go Forward 
    case 0x502: goForward(); break;  // Go Forward 
        
    case 0xD08: goBackward(); break; // Go Backward 
    case 0x508: goBackward(); break; // Go Backward 
        
    case 0xD06: turnRight(); break;  // turn Right 90º
    case 0x506: turnRight(); break;  // turn Right 90º
        
    case 0xD09: turnRight45(); break;  // turn Right 45º
    case 0x509: turnRight45(); break;  // turn Right 45º
        
    case 0xD04: turnLeft(); break;   // turn Left 90º
    case 0x504: turnLeft(); break;   // turn Left 90º    
    
    case 0xD07: turnLeft45(); break;   // turn Left 45º
    case 0x507: turnLeft45(); break;   // turn Left 45º
        
    case 0xD35: servoH_dcha(); break;  //PLAY
    case 0x535: servoH_dcha(); break;  //PLAY    
    
    case 0xD36: servoH_izqda(); break; //STOP
    case 0x536: servoH_izqda(); break; //STOP

    case 0xD00: servoV_arriba(); break;  //CERO
    case 0x500: servoV_arriba(); break;  //CERO    
    
    case 0xD30: servoV_abajo(); break;   //PAUSE
    case 0x530: servoV_abajo(); break;   //PAUSE    
    
    case 0xD1C: Home(); break; //RANDOM
    case 0x51C: Home(); break; //RANDOM
    
    
  }
}


void loop()
{
   if (irrecv.decode(&results))
  {
    translateIR();
    irrecv.resume(); // receive the next value
    //Serial.println(results.value, HEX); 
    //Serial.println(laser);  
  }
 
  stepper1.run();
  stepper2.run();
}

Publicidad