Hi everyone
thanks for reading me.
A while ago now, I gave a try at a billy bass hack (the Donald Bell one, for those who know it ).
My first intention was to make it work using a mp3 player module instead of the bluetooth + amplifiers ones from Bell's project.
I was planning to use a previous project's code in order to time schedule the start of the mp3 file (a simple voice test).
Here's my code :
#include <SoftwareSerial.h>
#include "RedMP3.h"
#define MP3_RX 13
#define MP3_TX 11
MP3 mp3(MP3_RX, MP3_TX);
int8_t index = 0x01;//the first song in the TF card
int8_t volume = 0x1e;//0~0x1e (30 adjustable level)
#include <MX1508.h>
MX1508 bodyMotor(6, 9); // Sets up an MX1508 controlled motor on PWM pins 6 and 9
MX1508 mouthMotor(5, 3); // Sets up an MX1508 controlled motor on PWM pins 5 and 3
int soundPin = A0; // Sound input
int silence = 18 ; // Threshold for "silence". Anything below this level is ignored.
int bodySpeed = 0; // body motor speed initialized to 0
int soundVolume = 0; // variable to hold the analog audio value
int fishState = 0; // variable to indicate the state Billy is in
bool talking = false; //indicates whether the fish should be talking or not
//these variables are for storing the current time, scheduling times for actions to end, and when the action took place
long currentTime;
long mouthActionTime;
long bodyActionTime;
long lastActionTime;
unsigned long startMillis;
unsigned long currentMillis;
struct Evenement
{
uint32_t temps;
float mp3;
};
int mouvement = 0;
Evenement evenements[] = {
//temps mp3
{0000, 0},
{5000, 1},
{6000, 0},
{24000, 2},
{25000, 0}
};
void setup() {
bodyMotor.setSpeed(0);
mouthMotor.setSpeed(0);
//input mode for sound pin
pinMode(soundPin, INPUT);
Serial.begin(9600); //start Serial in case we need to print debugging info
startMillis = millis();
}
void loop() {
if ((millis() - startMillis >= evenements[mouvement].temps) && (mouvement < 5))
{
{
if (evenements[mouvement].mp3 == 1 )
{
delay(500);
mp3.playWithVolume(index,volume);
}
if (evenements[mouvement].mp3 == 2 )
{
mp3.stopPlay();
}
if (evenements[mouvement].temps == 25000)
{
mouvement = 0; // On repart au début des mouvements
startMillis=millis(); // Remet le chornomètre à 0
}
mouvement++; // on a traité ce mouvement, on passe au suivant
}
}
currentTime = millis(); //updates the time each time the loop is run
updateSoundInput(); //updates the volume level detected
SMBillyBass(); //this is the switch/case statement to control the state of the fish
}
void SMBillyBass() {
switch (fishState) {
case 0: //START & WAITING
if (soundVolume > silence) { //if we detect audio input above the threshold
if (currentTime > mouthActionTime) { //and if we haven't yet scheduled a mouth movement
talking = true; // set talking to true and schedule the mouth movement action
mouthActionTime = currentTime + 100;
fishState = 1; // jump to a talking state
}
} else if (currentTime > mouthActionTime + 100) { //if we're beyond the scheduled talking time, halt the motors
bodyMotor.halt();
mouthMotor.halt();
}
if (currentTime - lastActionTime > 1500) { //if Billy hasn't done anything in a while, we need to show he's bored
lastActionTime = currentTime + floor(random(30, 60)) * 1000L; //you can adjust the numbers here to change how often he flaps
fishState = 2; //jump to a flapping state!
}
break;
case 1: //TALKING
if (currentTime < mouthActionTime) { //if we have a scheduled mouthActionTime in the future....
if (talking) { // and if we think we should be talking
openMouth(); // then open the mouth and articulate the body
lastActionTime = currentTime;
articulateBody(true);
}
}
else { // otherwise, close the mouth, don't articulate the body, and set talking to false
closeMouth();
articulateBody(false);
talking = false;
fishState = 0; //jump back to waiting state
}
break;
case 2: //GOTTA FLAP!
//Serial.println("I'm bored. Gotta flap.");
flap();
fishState = 0;
break;
}
}
int updateSoundInput() {
soundVolume = analogRead(soundPin);
}
void openMouth() {
mouthMotor.halt(); //stop the mouth motor
mouthMotor.setSpeed(220); //set the mouth motor speed
mouthMotor.forward(); //open the mouth
}
void closeMouth() {
mouthMotor.halt(); //stop the mouth motor
mouthMotor.setSpeed(180); //set the mouth motor speed
mouthMotor.backward(); // close the mouth
}
void articulateBody(bool talking) { //function for articulating the body
if (talking) { //if Billy is talking
if (currentTime > bodyActionTime) { // and if we don't have a scheduled body movement
int r = floor(random(0, 8)); // create a random number between 0 and 7)
if (r < 1) {
bodySpeed = 0; // don't move the body
bodyActionTime = currentTime + floor(random(500, 1000)); //schedule body action for .5 to 1 seconds from current time
bodyMotor.forward(); //move the body motor to raise the head
} else if (r < 3) {
bodySpeed = 150; //move the body slowly
bodyActionTime = currentTime + floor(random(500, 1000)); //schedule body action for .5 to 1 seconds from current time
bodyMotor.forward(); //move the body motor to raise the head
} else if (r == 4) {
bodySpeed = 200; // move the body medium speed
bodyActionTime = currentTime + floor(random(500, 1000)); //schedule body action for .5 to 1 seconds from current time
bodyMotor.forward(); //move the body motor to raise the head
} else if ( r == 5 ) {
bodySpeed = 0; //set body motor speed to 0
bodyMotor.halt(); //stop the body motor (to keep from violent sudden direction changes)
bodyMotor.setSpeed(255); //set the body motor to full speed
bodyMotor.backward(); //move the body motor to raise the tail
bodyActionTime = currentTime + floor(random(900, 1200)); //schedule body action for .9 to 1.2 seconds from current time
}
else {
bodySpeed = 255; // move the body full speed
bodyMotor.forward(); //move the body motor to raise the head
bodyActionTime = currentTime + floor(random(1500, 3000)); //schedule action time for 1.5 to 3.0 seconds from current time
}
}
bodyMotor.setSpeed(bodySpeed); //set the body motor speed
} else {
if (currentTime > bodyActionTime) { //if we're beyond the scheduled body action time
bodyMotor.halt(); //stop the body motor
bodyActionTime = currentTime + floor(random(20, 50)); //set the next scheduled body action to current time plus .02 to .05 seconds
}
}
}
void flap() {
bodyMotor.setSpeed(180); //set the body motor to full speed
bodyMotor.backward(); //move the body motor to raise the tail
delay(500); //wait a bit, for dramatic effect
bodyMotor.halt(); //halt the motor
}
My wiring so far looks like this :
I'm using an 1000 uF capacitor with the usb breakout.
the potentiometer is logarithmic 5K.
So far i feel i'm getting close but that's not quite a success.
The mp3 file plays but the fish moves really randomly and not in sinc with the voices.
For anyone could help me, that would be a relief.
thanks




