Utilizar un servo de rotación continua con Arduino

21 Apr 2017

En otro post anterior vimos como controlar un servo de los “normales” con Arduino. Este tipo de servo tienen una limitación y es que sólo permiten girar entre 0 y 180 grados. Hay casos en los que necesitamos tener una libertad de movimiento de 360 grados, y es aquí donde entran en escena los servos de rotación continua. La parte negativa es:

  • Son más caros.
  • No podemos controlar la posición.
  • No dispondremos de un control preciso de la velocidad.

Sin embargo, y dependiendo del uso que le demos, podremos vivir con estos inconvenientes.

He encontrado tutoriales en los que convierten un SG90 en uno de rotación continua, pero corres el peligro de romper el servo. Ademas, el rendimiento no es equiparable al de un servo comercial. Por tanto está la opción de comprar un FS90R que, por poco más de 3 euros en Aliexpress, no ahorra toda esa película. Según la ficha técnica del producto las conexiones con estas:

FS90R Arduino
Naranja PWM
Rojo Vcc (5V)
Marrón GND

La forma de usar un servo de rotación continua es igual a la de un servo normal, por lo que también haremos uso de la librería Servo. Veamos un ejemplo de uso en el que podemos ver que, según el ángulo de rotación podemos cambiar tanto la velocidad de rotación como el sentido de giro.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo 
 
void setup() {
  Serial.begin(9600);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  // Servo 100% CW (angle 0 degrees)
  Serial.println("100% CW");
  myservo.write(0);
  delay(1500); 
  
  // Servo stopped(angle 90 degrees)
  Serial.println("Stop");
  myservo.write(90);
  delay(1500);

  // Servo 100% CCW (angle 180 degrees)
  Serial.println("100% CCW");
  myservo.write(180);
  delay(1500);
}

Y poco más.

Arduino

LCD 16x2 en Raspberry Pi

30 Mar 2017

Recientemente he necesitado usar un display para uno de mis proyectos. Por coste y facilidad de uso me he decantado por un LCD1602 que, como su propio nombre indica, se trata de una pantalla LCD que permite mostrar 2 líneas de 16 caracteres cada una. Además está retroiluminado.

Si lo usamos directamente, necesitaremos un montón de conexiones (unos 11 cables) y es poco práctico. De modo que está la opción que incluye un adaptador I2C lo cual reduce el número de conexiones a cuatro (dos de alimentación y dos de control).

Pero… qué es I2C? Pues se trata de un bus serie que nos permite conectar varios dispositivos a un controlador con sólo dos líneas: CLK (Serial Clock) y SDA (Serial Data). Cada dispositivo tiene una dirección predeterminada que se usa para poderse comunicar con él.

El el artículo RTC DS3231 en Raspberry Pi ya explicamos como configurar el protocolo I2C en la Raspberry, de modo que no vamos a repetir lo mismo. Lo único a tener en cuenta es que, en este caso, el único módulo que tenemos que añadir al fichero /etc/modules es el i2c-dev. Y que si queremos que un determinado usuario pueda usar el dispositivo I2C debe pertenecer al grupo i2c:

$ sudo adduser pi i2c

Ejemplo de uso

Antes de probar el ejemplo tenemos que ver la dirección del módulo con el comando:

$ sudo i2cdetect -y 1

Y esa dirección hexadecimal será la que pongamos en la variable I2C_ADDR. El ejemplo es un poco largo porque accede a display a bajo nivel. Seguramente hay alguna librería que simplifica el código, como la hay para Arduino, pero a unas malas es sencillo hacer una.

#!/usr/bin/python

from datetime import datetime
import smbus
import time

# Define some device parameters
I2C_ADDR = 0x3F  # I2C device address
LCD_WIDTH = 16  # Maximum characters per line

# Define some device constants
LCD_CHR = 1  # Mode - Sending data
LCD_CMD = 0  # Mode - Sending command

LCD_LINE_1 = 0x80  # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0  # LCD RAM address for the 2nd line
LCD_LINE_3 = 0x94  # LCD RAM address for the 3rd line
LCD_LINE_4 = 0xD4  # LCD RAM address for the 4th line

LCD_BACKLIGHT = 0x08  # On
# LCD_BACKLIGHT = 0x00  # Off

ENABLE = 0b00000100  # Enable bit

# Timing constants
E_PULSE = 0.0005
E_DELAY = 0.0005

# Open I2C interface
# bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
bus = smbus.SMBus(1)  # Rev 2 Pi uses 1


def lcd_init():
    # Initialise display
    lcd_byte(0x33, LCD_CMD)  # 110011 Initialise
    lcd_byte(0x32, LCD_CMD)  # 110010 Initialise
    lcd_byte(0x06, LCD_CMD)  # 000110 Cursor move direction
    lcd_byte(0x0C, LCD_CMD)  # 001100 Display On,Cursor Off, Blink Off
    lcd_byte(0x28, LCD_CMD)  # 101000 Data length, number of lines, font size
    lcd_byte(0x01, LCD_CMD)  # 000001 Clear display
    time.sleep(E_DELAY)


def lcd_byte(bits, mode):
    # Send byte to data pins
    # bits = the data
    # mode = 1 for data
    #        0 for command

    bits_high = mode | (bits & 0xF0) | LCD_BACKLIGHT
    bits_low = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT

    # High bits
    bus.write_byte(I2C_ADDR, bits_high)
    lcd_toggle_enable(bits_high)

    # Low bits
    bus.write_byte(I2C_ADDR, bits_low)
    lcd_toggle_enable(bits_low)


def lcd_toggle_enable(bits):
    # Toggle enable
    time.sleep(E_DELAY)
    bus.write_byte(I2C_ADDR, (bits | ENABLE))
    time.sleep(E_PULSE)
    bus.write_byte(I2C_ADDR, (bits & ~ENABLE))
    time.sleep(E_DELAY)


def lcd_string(message, line):
    # Send string to display
    message = message.ljust(LCD_WIDTH, " ")
    lcd_byte(line, LCD_CMD)

    for i in range(LCD_WIDTH):
        lcd_byte(ord(message[i]), LCD_CHR)


def main():
    # Initialise display
    lcd_init()

    while True:
        # Send current time
        str_time = datetime.now().strftime("%H:%M:%S")
        lcd_string(str_time, LCD_LINE_1)
        lcd_string("", LCD_LINE_2)

        time.sleep(1)


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        pass
    finally:
        lcd_byte(0x01, LCD_CMD)

Raspberry Pi

Utilizar un servo con Arduino

29 Mar 2017

Vamos a ver cómo usar el servo SG90 con Arduino. Lo primero que debemos saber es para qué sirve cada uno de los tres cables que tiene este componente. Según la ficha técnica del producto ésta es la función de cada uno de ellos:

SG90 Arduino
Naranja PWM
Rojo Vcc (5V)
Marrón GND

La forma de usar el servo en Arduino es muy simple gracias a la librería Servo. Y nada mejor que verlo en funcionamiento con un ejemplo. Este código lo que hacer es mover el servo de 0 a 180 grados, esperar 15 milisegundos y volver de estos 180 grados a los 0 iniciales. Y vuelta a empezar. Para que funcione tienes que conectar el cable naranja al pin 9 de tu Arduino.

#include <Servo.h>
 
Servo myservo;
int pos = 0;
 
void setup() {
  myservo.attach(9);  // attach servo on pin 9
}

void loop() {
  for(pos = 0; pos < 180; pos += 5) {
    myservo.write(pos);
    delay(15);
  }
  
  for(pos = 180; pos >=1 ; pos -= 5) {
    myservo.write(pos);
    delay(15);
  }
}

Sencillo, ¿verdad?

Arduino