Help Wanted for Big Mouth Billy Bass Alexa Hack

First post here - looking for help with a first-time Arduino Hack to integrate an Amazon Alexa into a Big Mouth Billy Bass for hi-jinks. I'm in the home stretch and while I've confirmed I can drive the motors and pick up analog signal on the analog-in pins, putting a script in that uses both causes the fish to not move at all. Looking in the Serial Monitor, signal gets corrupted when I incorporate the Adafruit Motor Shield library and the Analog In, filling the Monitor with garbage, corrupted text.

It's inspired by this guide but given the age of some of the components there I've made some substitutions. Total parts list and code I've converted below (code had to be converted to V2 Motor Shield to compile and work with newer model). Photos of wiring available on request.

Parts:

  • Elgato Uno R3 Controller Board
  • Adafruit Motor Shield V2
  • Big Mouth Billy Bass "Original" 3-Motor Version
  • Alexa Echo Pop (Given the internal speaker, I opted out of the guide's Amp Board and put a jumper wire on the positive speaker terminal to serve as Analog In)

Here's the AnimateBilly.h

//Created by ONG modified from Cyberomlette website. It is probaly better there but we're hacking it.


#include <Adafruit_MotorShield.h>

Adafruit_MotorShield AFMS = Adafruit_MotorShield();

Adafruit_DCMotor *headMotor = AFMS.getMotor(3);
Adafruit_DCMotor *mouthMotor = AFMS.getMotor(2);
Adafruit_DCMotor *tailMotor = AFMS.getMotor(4);


void runMotorOnOff(Adafruit_DCMotor *motor, int aniDelay = 500){
      motor->run(FORWARD);
      delay(aniDelay);
      motor->run(BACKWARD);
      delay(5);
      motor->run(RELEASE);
      delay(aniDelay);
}

void runTwoMotorsOnOff(int aniDelay = 500){
      headMotor->run(FORWARD);
      mouthMotor->run(FORWARD);
      delay(aniDelay);
      headMotor->run(BACKWARD);
      mouthMotor->run(BACKWARD);
      delay(5);
      headMotor->run(RELEASE);
      mouthMotor->run(RELEASE);
      delay(aniDelay);
}

bool randomDecisionToTurnOn(int oddsOn) {
  int score = random(1,100);
  return score < oddsOn;
}

void releaseMotor(Adafruit_DCMotor motor) {
  motor.run(BACKWARD);
  delay(15);
  motor.run(RELEASE);
}

void tapTail(int duration, int times=5){
  int iterDuration = duration / times;
  for (int i = 0; i < times; i++) {
     runMotorOnOff(tailMotor, iterDuration);
  }
}
void dance(int duration, int times = 1){
  int elapsedTime = 0;
  int iterDuration = duration / times;
  for (int i = 0; i < times; i++) {
    if(randomDecisionToTurnOn(60)){
      runTwoMotorsOnOff(iterDuration);
    } else {
     tapTail(iterDuration/2, times*2);
    }
  }
}

void talk(int duration, int wordCount) {
  int iterDuration = duration / wordCount;
  headMotor->run(FORWARD);
  for (int i = 0; i < wordCount; i++) {
     runMotorOnOff(mouthMotor, iterDuration);
  }
}

void setupFishMotors() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Motor test!");

  headMotor->setSpeed(255);
  mouthMotor->setSpeed(255);
  tailMotor->setSpeed(255);
}

void billySleep(){
  headMotor->run(RELEASE);
  tailMotor->run(RELEASE);
  mouthMotor->run(RELEASE);
}

void moveBilly(int movementCount, int duration){
  if (movementCount > 3 && randomDecisionToTurnOn(50)) {
    billySleep();
    dance(duration);
  } else {
    talk(duration, random(2,6));
  }
}

here's the actual file

//Created by ONG modified from Cyberomlette website. It is probaly better there but we're hacking it.

#include "AnimateBilly.h"

int sensorPin = A3;    // select the input pin for the audio signal
int ledPin = 13;

int sampleSensor(int pin, int samples = 10, int duration = 150) {
  float sensorValue = 0;
  int iterDelay = duration / samples;
  for (int i = 0; i < samples; i++) {
    sensorValue += analogRead(pin);
    delay(iterDelay);
  }
  digitalWrite(ledPin, LOW);
  return (int)(sensorValue / samples);
}

int sampleAverages(int pin, int samples = 3, int duration = 100) {
  int iterDelay = duration / samples;
  int avgValue = 0;
  for (int i = 0; i < samples; i++) {
    avgValue += sampleSensor(pin, samples, iterDelay);
    delay(iterDelay);
  }
  return (int)(avgValue / samples);
}

void setup() {
  setupFishMotors();
  // declare the ledPin as an OUTPUT:
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);      // open the serial port at 9600 bps:    
}

int stillPlaying = 0;
int aniDuration = 500;
int previousValue = 0;
int quietThreshold = 2;

void loop() {
  // read the value from the sensor:
  int sensorValue = sampleSensor(sensorPin);
  float smoothedSensorValue = (sensorValue + previousValue) / 2 ;

  if(smoothedSensorValue > quietThreshold) {
    digitalWrite(ledPin, HIGH);
    stillPlaying = min(stillPlaying++, 4);
    moveBilly(stillPlaying, aniDuration);
  } else if (stillPlaying == 0){
      billySleep();
      digitalWrite(ledPin, LOW);
      stillPlaying = 0;
  } else {
    stillPlaying--;
  }
  previousValue = sensorValue;
}

Please read and use How to get the best out of this forum - Projects / General Guidance - Arduino Forum

Links to datasheets of special components are missing as well as schematics. Adding code not tried only makes the post less attractive to read.

1 Like

Good morning Railroader,

 Thank you for the good guidance on forum use - helped me not use the Fritzing Diagram I was planning to make. I have a drawn schematic ready, forgive my poor penmanship.

 I must add three things: first, it's an Elegoo Uno R3 Control Board - got the brand name mixed up, and the Alexa is a 2023 Gen 1 Release. I will also add that I have tried this code; it does compile and upload fine, but the fish motors simply does not move at all when Analog Signal flows from the Alexa.

And, as you requested, datasheets for the special components are in this reply. I can't find them for the Alexa or the original Big Mouth Billy Bass, but the Elegoo board and Adafruit Motor Shield have them. I must link them however, new users cannot upload PDF attachments. I will link their text plainly for clarity, though.

A data sheet for the Elegoo

https://epow0.org/~amki/car_kit/Datasheet/ELEGOO%20UNO%20R3%20Board.pdf

It is Elegoo's own version of the Arduino Uno R3, added here to compare differences I may be unaware of

https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf

I am having trouble finding Adafruit's exact specs for the Motor Shield V2 but I found the Overview Guide

https://cdn-learn.adafruit.com/downloads/pdf/adafruit-motor-shield-v2-for-arduino.pdf

Slight revision - the A3 Analog Input Pin is connected to the Adafruit Motor Shield's own A3 Input Through-Hole, but due to the soldering of the Shield's pins it should still run into the Elegoo's own A3 Input.

Image showing MotorShield Terminal Pins on a R3

You need a GND. Only the wire to A3 is not enough. The little current into A3 must have a return path.

Hello Railroader,

Good thinking - would I need to initialize that in code like I do with setting up A3, or would that be done with a physical connection on the Elegoo to a designated GND Terminal Slot? And I assume I'd then take the other end and put it on the Alexa Speaker's Negative Terminal?

The "Echo pop" minus to board GND. The shield is for sure having the controller GND as common.

Hello Railroader,

I added in a Ground to the system by connecting the Negative Alexa Speaker line to one of the Shield's 5v GND Terminal Pins. I'm still not getting any motion from the fish but that is certainly something we would need for the Analog Input. No adjustments to the code have been made.

I also have reached out to the hack script's original creator via email. Between all of us we should be able to figure this out...

Is the "USB power" powering the motors? If so, that would likely be a mistake.

Please post the datasheet for the motors.

Hello Railroader,

Got more time to work on this today; the motors do not run on the USB Power. They operate on the 5-12V Power Terminal on the Shield.

Exact datasheet information for these Billy Bass motors isn't clear (I can't find spec info for the 1990s model I have), but I have heard them described as "cheap 5v DC Toy motors".

I'll add that they work fine when using this Motor Diagnostic Code from project website (that I modified for use with the V2 Motor Shield). This code is a simple looping movement of the motors just to make sure you wired them up right, and has no Analog Input functionality to modify the movement. Given that this code and another Audio Diagnostic code INO work when uploaded desperately to the Elegoo R3, and the combined functionality offered by the first-posted Billy code INO doesn't, using both the Arduino Motorshield V2 library and the Analog In pins is causing problems. This is a hunch though and I have no knowledge as to why/why not these two features of the board would conflict with one another. It's not discussed as an issue in the original project guide I'm following.

//Created by ONG modified from Motor Diagnostic from Cyberomlette website. It is probably better there but we're hacking it.

#include <Adafruit_MotorShield.h>

Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
#define NUM_MOT/home/ophio/Downloads/OmletteCombinedSketch/Billy.inoORS 3

Adafruit_DCMotor *headMotor = AFMS.getMotor(3);
Adafruit_DCMotor *mouthMotor = AFMS.getMotor(2);
Adafruit_DCMotor *tailMotor = AFMS.getMotor(4);

void setup() {

  Serial.begin(9600); //setting up serial for this test so the console yells at you
  Serial.println("Test motors...");

  AFMS.begin(); //call the shield object made earlier

}


void loop() {
  headMotor->setSpeed(150); //set all motor speeds. Could probably put this into an for loop in setup after assigning each one an array value
  mouthMotor->setSpeed(150);
  tailMotor->setSpeed(150);

  mouthMotor->run(FORWARD);
  delay(1000);
  mouthMotor->run(BACKWARD);
  delay(1000);
  mouthMotor->run(RELEASE);

  tailMotor->run(FORWARD);
  delay(2000);
  //tailMotor->run(BACKWARD);
  //delay(2000);
  tailMotor->run(RELEASE);


  headMotor->run(FORWARD);
  delay(1500);
  headMotor->run(RELEASE);
}

The speaker negative is not ground. You need to locate Alexa ground on the board. It will be the negative lead of the 12V supply.

Since the motor diagnostic works but your code does not, it most likely is due to the A3 signal not being wired correctly. Did you try the audio diagnostic sketch the original author provided? It will tell you if you are getting a signal or not?

Make sure to adjust to from A0 to A3 to suit your wiring.

Good morning,

Apologies for the delay on this - I went out and got an Arduino Uno R3 and replaced the Elegoo variant. They should function identically (and indeed reproduce the same issues), but I wanted to try and see if this was a factor.

I have indeed tested the Audio Diagnostic Sketch, and can detect audio in the Serial Window from the speaker. When I first wired and tested this Sketch, I was getting 686-1023 from dead quiet to max volume on the Serial Read of the Pin, but once I connected the Shield's Ground to the Alexa Speaker Ground as suggested earlier in this thread from my schematic, I got a more reasonable 0-436.

Still, I should try to connect the Shield Negative to the Alexa 12V Power Negative somewhere on the board...I'll have to work on it this weekend.