Paso 16: Relacionando todos juntos con un Arduino
- Controla el motor paso a paso para rotar el móvil fantasma
- Gira en un patrón sinusoidal para que parezcan más "autónoma"
- Gira por 10 segundos (alineados perfectamente con el audio)
- Convierte códigos IR del mando que vino con el kit remoto de IR en los códigos correctos de IR para el reproductor de CD Kenwood
- Proporciona que un IR Lee función para capturar y mostrar los datos exactos de la código de IR desde el control remoto original
- Contiene una lista de código de botón de prensa los códigos para su uso en la traducción de los pulsadores del botón del control remoto
- Envía el código de IR adecuado basado en la tecla del mando a distancia nuevo
- Envía códigos de "Pausa" y "Omitir" 10 segundos después se pulsa el botón de play
- El código también envía algunos mensajes de depuración a la consola de puerto serie en caso de estar interesado en los detalles debajo de la capilla mientras se está ejecutando.
Originalmente planeaba también controlar iluminación para apagar las luces cuando fue disparado un sensor de movimiento. Lamentablemente rompí el hardware estaba utilizando y no tuvo tiempo para reemplazarlo por lo que el sistema será controlado totalmente por el control remoto.
La siguiente lista asigna los pines de Arduino Mego 2560 junta al componente respectivo:
- LED de estado: PWM Pin 13
- La entrada de datos receptor IR: PWM Pin 11
- Emisor de IR al reproductor de CD: PWM Pin 8
- Señales de Control de Motor paso a paso: PWM Pins 4, 5, 6 y 7
- Motivos a pernos apropiados según sea necesario
Dos piezas existentes de código se utiliza y muy modificadas. Estos incluyen la biblioteca IRremote proporcionado por Ken Shirriff y el código de ejemplo de motor de paso a paso incluido en el SDK de Arduino. Y por último, aquí está el código (apalancado y que trabajos anteriores):
/////////////////////////////////////////////////////////////////////////////////////////
/*
Stepper Motor Control - sinusoidal rotation
This program drives a unipolar or bipolar stepper motor.
The motor is attached to digital pins 4 - 7 of the Arduino.
The motor should revolve one direction
following a sinusoidal rate of rotation.
The program also allows the user to remotely activate and deactivate the
glowing ghost mobile of doom. It sends control signals to the mobile for 10
during which time the audio from the disk in the CD player will play 10
seconds of audio. After 10 seconds the code will send the pause and skip
command to go to the next track.
Created on Nov. 4th, 2012
(Some parts based on Stepper Motor Control program by Tom Igoe
Created 11 Mar. 2007
Modified 30 Nov. 2009)
(Some parts based on IRrecord program by Ken Shirriff
Created September, 2009)
*/
#define PAUSE_PLAY_BUTTON 0x6D92C837
#define REPEAT_BUTTON 0x6D929867
#define SKIP_BUTTON 0x6D92E817
#define POWER 0x00FFA25D
#define BUTTON_MODE 0x00FF629D
#define BUTTON_PAUSE_PLAY 0x00FF22DD
#define BUTTON_SKIP 0x00FFC23D
#define BUTTON_0 0x00FF6897
#define BUTTON_1 0x00FF30CF
#define BUTTON_2 0x00FF18E7
#define BUTTON_3 0x00FF7A85
#define BUTTON_4 0x00FF10EF
#define BUTTON_5 0x00FF38C7
#define BUTTON_6 0x00FF5AA5
#define BUTTON_7 0x00FF42BD
#define BUTTON_8 0x00FF4AB5
#define BUTTON_9 0x00FF52AD
#include <Stepper.h>
#include <IRremote.h>
int RECV_PIN = 11;
int BUTTON_PIN = 12;
int STATUS_PIN = 13;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
int step_enabled = LOW;
const int stepsPerRevolution = 2048; // change this to fit the number of steps per revolution for your motor
const float max_speed = 10; //sets the maximum rotational speed of the motor
const float resolution = 100; //sets the frequency by which the motor speed will change
float rotational_vel = 0; //holds the current rotational velocity scalar
// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 4,5,6,7);
void setup() {
// initialize the serial port:
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
pinMode(BUTTON_PIN, INPUT);
pinMode(STATUS_PIN, OUTPUT);
}
// Storage for the recorded code
int codeType = NEC; // The type of code
unsigned long codeValue = 0x6D92C837; // The code value if not raw
int codeLen = 32; // The length of the code
int toggle = 0; // The RC5/6 toggle state
int buttonState = LOW; //virtual button press
// Stores the code for later playback
// Most of this code is just logging
void storeCode(decode_results *results)
{
codeType = results->decode_type;
int count = results->rawlen;
if (results->value == REPEAT)
{
// Don't record a NEC repeat value as that's useless.
Serial.println("repeat; ignoring.");
buttonState = LOW;
return;
}
Serial.print("storing code: ");
Serial.print(results->value, HEX);
codeValue = results->value;
codeLen = results->bits;
Serial.print("; code length: ");
Serial.println(codeLen);
buttonState = HIGH;
}
void sendCode(int repeat) {
if (repeat)
{
irsend.sendNEC(REPEAT, codeLen);
Serial.println("Sent NEC repeat");
buttonState = LOW; //turn off virtual button after sending code
}
else
{
Serial.println("Sending non-repeat code.");
switch (codeValue) {
case POWER:
irsend.sendNEC(PAUSE_PLAY_BUTTON, 32);
codeValue = PAUSE_PLAY_BUTTON;
Serial.print("Sent pause play code: ");
Serial.println(PAUSE_PLAY_BUTTON, HEX);
buttonState = LOW; //turn off virtual button after sending code
break;
case BUTTON_PAUSE_PLAY:
irsend.sendNEC(PAUSE_PLAY_BUTTON, 32);
Serial.print("Sent pause play code: ");
Serial.println(PAUSE_PLAY_BUTTON, HEX);
buttonState = LOW; //turn off virtual button after sending code
break;
case BUTTON_MODE:
irsend.sendNEC(REPEAT_BUTTON, 32);
Serial.print("Sent repeat code: ");
Serial.println(REPEAT_BUTTON, HEX);
buttonState = LOW; //turn off virtual button after sending code
break;
case BUTTON_SKIP:
irsend.sendNEC(SKIP_BUTTON, 32);
Serial.print("Sent skip code: ");
Serial.println(SKIP_BUTTON, HEX);
buttonState = LOW; //turn off virtual button after sending code
break;
}
}
}
int lastButtonState = LOW;
int i = 1;
void loop() {
if (i > resolution)
{
i = 1;
}
// If button pressed, send the code.
//buttonState = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && buttonState == LOW) {
Serial.println("Released");
lastButtonState = LOW;
irrecv.enableIRIn(); // Re-enable receiver
}
if (buttonState) {
Serial.println("Sending IR code");
digitalWrite(STATUS_PIN, HIGH);
sendCode(lastButtonState == buttonState);
digitalWrite(STATUS_PIN, LOW);
step_enabled = HIGH;
lastButtonState = HIGH;
//delay(50); // Wait a bit between retransmissions
}
else if (irrecv.decode(&results)) {
Serial.println("Reading IR code");
digitalWrite(STATUS_PIN, HIGH);
storeCode(&results);
irrecv.resume(); // resume receiver
digitalWrite(STATUS_PIN, LOW);
}
//Serial.println("rotate the motor");
rotational_vel = abs(max_speed * sin(float(i)*3.14159/10) + 2); //program a sinusoidal velocity for the stepper motor
myStepper.setSpeed(rotational_vel);
if (abs(rotational_vel) > 0.001 && step_enabled == HIGH) //a velocity of 0 will lock up the stepper.h library.
{
Serial.println("valid stepper function entry");
if (i < resolution && step_enabled == HIGH)
{
Serial.print("iteration: ");
Serial.println(i);
Serial.print("Velocity: ");
Serial.println(rotational_vel);
myStepper.step(10 * rotational_vel);
i++;
}
else
{
step_enabled = LOW;
i = 0;
Serial.println("Pausing Playback and Skipping");
digitalWrite(STATUS_PIN, HIGH);
codeValue = BUTTON_PAUSE_PLAY;
sendCode(1 == 2);
delay(100); //Wait between transmissions
codeValue = BUTTON_SKIP;
sendCode(1 == 2);
digitalWrite(STATUS_PIN, LOW);
lastButtonState = HIGH;
}
}
}