Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

PiBot: Robot Pianista con Arduino para Interpretación Musical de Precisión

Componentes y materiales

Herramientas necesarias

Aplicaciones y servicios online

Sobre el proyecto

Cómo comenzó

Hace años vi un piano automático de Yamaha en una tienda. Desde entonces quise construir mi propio robot pianista. No hay una razón profunda: simplemente tenía ganas de hacerlo.

Visión general

Controlar 88 solenoides (uno por tecla) con dos Arduino Mega sería costoso. En su lugar, usé un Arduino Uno barato y 11 registros de desplazamiento (74HC595) para expandir las salidas. Cada registro controla 8 solenoides, sumando 88 en total. El PC envía tramas de bits al Arduino (no MIDI directo); el archivo MIDI se convierte previamente a bits mediante un script Python.

Hardware

Los solenoides comprados en China resultaron demasiado débiles para pulsar las teclas desde la posición interior. La solución fue alimentarlos a 24V (siendo de 12V) para obtener la fuerza necesaria. El consumo total es alto, así que usé una batería de coche (12V) como fuente de alimentación.

Cada registro de desplazamiento y sus MOSFETs asociados se montaron en una placa controladora. El esquema sigue el ejemplo 2 de la hoja de datos del 74HC595, reemplazando los LEDs por las puertas de los MOSFETs. No se usaron resistencias pull-down para ahorrar coste y soldadura; los MOSFETs cierran por debajo de 4V (comprobado experimentalmente).

Los solenoides se fijaron sobre una placa de plástico con pegamento caliente, pero el calor derretía el pegamento. Finalmente se usó cinta de doble cara resistente a 150°C.

Software

  1. Obtener un archivo MIDI.
  2. Convertirlo a texto con esta herramienta online.
  3. Procesar el texto con el script Python adjunto para generar 11 grupos de 8 bits con marcas de tiempo.
  4. Enviar los datos al Arduino mediante Processing (puerto serie).

El código Python, Processing y Arduino se incluye en la sección de código.

Solución de problemas

Código

Script Python (traducción MIDI → bits)

output_file = open("translated.txt", "w")
input_file = open("megalocania.txt")
raw_input_data = input_file.read()
work_data = raw_input_data.splitlines()
result = []

def main():
    for a in work_data:
        temp_time = time_finder(a)
        if not result:
            result.append(str(temp_time) + ",")
        if on_off_finder(a):
            result[-1] += set_bit(True, note_finder(a))
        elif not on_off_finder(a):
            result[-1] += set_bit(True, note_finder(a))
        elif time_finder_comm(result[-1]) == temp_time:
            result[-1] = str(temp_time) + "," + set_bit_prev(on_off_finder(a), note_finder(a), -1)
        elif time_finder_comm(result[-1]) != temp_time:
            result.append(str(temp_time) + "," + set_bit_prev(on_off_finder(a), note_finder(a), -1))
    for b in result:
        output_file.write(b)
        output_file.write("\n")
    output_file.close()

def set_bit(On, note):
    # Genera 11 campos de 8 bits según la nota (21-108)
    if 21 <= note <= 28 and On:
        return str(2**(note-21)) + ",0,0,0,0,0,0,0,0,0,0"
    elif 29 <= note <= 36 and On:
        return "0," + str(2**(note-29)) + ",0,0,0,0,0,0,0,0,0"
    # ... (resto de rangos omitidos por brevedad)
    else:
        return "0,0,0,0,0,0,0,0,0,0,0"

def set_bit_prev(On, note, index):
    # Similar a set_bit pero actualiza el campo correspondiente en la línea previa
    # ... (implementación omitida)

def indexTh(in_string, find_this, th):
    # Encuentra la posición de la ocurrencia 'th' de find_this
    order = 1
    last_index = 0
    while True:
        temp = in_string.find(find_this, last_index)
        if temp == -1: return -1
        if order == th: return temp
        order += 1
        last_index = temp + 1

def time_finder(in_string):
    time_end = in_string.index(" ")
    return int(in_string[:time_end])

def time_finder_comm(in_string):
    comma = in_string.index(",")
    return int(in_string[:comma])

def note_finder(in_string):
    num_start = in_string.index("n=") + 2
    num_end = in_string.index("v=") - 1
    return int(in_string[num_start:num_end])

def on_off_finder(in_string):
    start = in_string.index(" ") + 1
    end = in_string.index("ch=") - 1
    return in_string[start:end] == "On"

main()

Processing (envío de datos al Arduino)

import processing.serial.*;
Serial myPort;
String[] inputLines;

void setup() {
  myPort = new Serial(this, "COM3", 9600);
  inputLines = loadStrings("translated.txt");
  run();
}

void run() {
  int lastTime = 0;
  for (int i = 0; i < inputLines.length; i++) {
    String temp = inputLines[i];
    delay((Integer.parseInt(temp.substring(0, temp.indexOf(","))) - lastTime) * 5); // multiplicador de tempo
    lastTime = Integer.parseInt(temp.substring(0, temp.indexOf(",")));
    send(temp.substring(temp.indexOf(",") + 1));
  }
}

void send(String data) {
  // Invierte el orden de los 11 bytes porque el piano físicamente va de derecha a izquierda
  String eleventh = data.substring(0, indexOforder(data, ",", 1));
  String tenth = data.substring(indexOforder(data, ",", 1)+1, indexOforder(data, ",", 2));
  // ... (resto de subcadenas)
  String first = data.substring(indexOforder(data, ",", 10)+1);

  myPort.write("888f");
  myPort.write(first + "f");
  myPort.write(second + "f");
  // ... hasta eleventh
  myPort.write("999f");
}

int indexOforder(String data, String find, int order) {
  int currentOrder = 0, lastLocation = 0;
  while (currentOrder < order) {
    lastLocation = data.indexOf(find, lastLocation + 1);
    currentOrder++;
  }
  return lastLocation;
}

Código Arduino (recepción y control de solenoides)

El sketch lee por puerto serie los 11 bytes precedidos por "888f" y terminados en "999f", y los volca a los registros de desplazamiento para activar los MOSFETs. El código completo está en el repositorio.

Esquemáticos

Diagrama de conexiones (basado en el ejemplo 2 del 74HC595 con MOSFETs):

PiBot: Robot Pianista con Arduino para Interpretación Musical de Precisión

Proceso de manufactura

  1. Construya un robot Raspberry Pi controlado por Bluetooth con retroalimentación de audio
  2. Construya un robot con streaming de vídeo controlado por Internet con Arduino y Raspberry Pi
  3. Construye un Robot Raspberry Pi Controlado por Wi‑Fi con Python – Guía Paso a Paso
  4. Controla LEDs con Alexa mediante Raspberry Pi – Guía paso a paso fácil
  5. Construye un Iron Man animado con Arduino: componentes, sensores y guía paso a paso
  6. Find Me: Localizador Inteligente de Objetos con Arduino y Bluetooth
  7. Controlador de Humidificador DIY con Arduino y Relé: Configuración Segura de Alto Voltaje
  8. Construye un robot controlado por voz con Arduino Nano
  9. MobBob: Robot Arduino Impreso en 3D, Controlado por Smartphone Android
  10. Construye un volante joystick personalizado con Arduino para gaming
  11. Arduino 101: Construye un Podómetro con Sensor DHT11 y Pantalla LCD