30Views5Replies

Author Options:

Audio reactive stepper motor control Answered

Hello,

i'm new to the instructables-comunity and i just started to work with arduino some months ago. I've already made some small projects with a stepper motor and a project with a SD-Card-mp3 player for arduino. For my next project i would like to work with audio reactive stepper motor control. To do that, i already bought the SPARKFUN SPECTRUM SHIELD , an Arduino Uno and a hand full of the wellknown 28BYJ-48 Stepper Motors (5V) and the matching ULN2003APG shields.

In the description of the SPARKFUN SPECTRUM Shield it is mentioned that it can also be used to control motors (audio reactive). Unfortunately I couldn't find a code or a manual for it yet.
The SPARKFUN SPECTRUM Shield divides an audio signal into 7 frequency ranges (bands). I would like to drive 7 stepper motors in combination with the Shield. Each of these motors should move in one direction with constant speed as soon as the respective frequency range reaches a certain sound level.

Does anyone know the SPECTRUM SHIELD and can help me? Or has someone already carried out a similar project and can give me some advices? Maybe an Arduino UNO is not enough powered... and I should rather use a bigger microcontroller? I am grateful for any advice. I'm looking for hints on the coding and the wiring.

I attached a rough scheme of my planned project.

And here is a PDF for the MSGEQ7, of them two are used for the SPECTRUM SHIELD.

Would love to get some help from the community!

Discussions

0
None
_Alex_Rex_

24 days ago

Huray! Today I managed to make a stepper motor move, when a specific
audio frequency in a audiosignal reaches a specific level. //



See a video here: https://www.youtube.com/watch?v=u0zMcRt ... e=youtu.be



I added a stepper motor code into my previous code. I declared two Variables BAND and LEVEL.

With BAND i will tell the stepper shield, which frequency band to read.

With LEVEL i tell the stepper shield, what level in that specific frequency band must be reached, until the loop starts.

If the LEVEL reaches a value under LEVEL, then the stepper will stop.



Find the new code here:
Code: Select all
/****************************************************************************** 
Sketch by Alex Rex, 25.07.2019
based on:
SparkFun Spectrum Shield PWM Demo
Toni Klopfenstein @ SparkFun Electronics
February 2015
https://github.com/sparkfun/Spectrum_Shield

*********************************************************************************/

//Declare Spectrum Shield pin connections
#define STROBE 4 /* #define constantName value */
#define RESET 5 /* #define constantName value */
#define DC_One A0 /* Analog Pin A0 with the name DC_one */
#define DC_Two A1 /* Analog Pin A1 with the name DC_Two */


//Define LED connections on the shield
int LED[] = {3, 6, 7, 9, 10, 11, 12}; /* for the seven LED's */

//Define spectrum variables
int freq_amp; /* variable for the 7 Frequency-Bands of the MSGEQ7 */
int Frequencies_One[7];
int Frequencies_Two[7];
int i;

int level = 125; /*minimum level of sound to trigger LED or STEPPER*/
/* ~110 for piano songs, 175 - 340 for pop-songs (songs with a beat)*/
int band = 3; /*7 frequency bands, choose: 0,1,2,3,4,5,6*/
/*0 = ~63Hz , 1 = ~160Hz , 2 = ~400Hz , 3 = ~1000Hz , 4 = ~2500Hz , 5 = 6250Hz , 6 = 16000Hz */

//Stepper Motor Shield pin connections
#define STEPPER_PIN_1 0 /*IN1*/
#define STEPPER_PIN_2 1 /*IN2*/
#define STEPPER_PIN_3 2 /*IN3*/
#define STEPPER_PIN_4 8 /*IN4*/
int step_number = 0;

/********************Setup Loop*************************/
void setup() {

//Set LED pin configurations
for(i=0; i<7; i++)
{
pinMode(LED[i], OUTPUT);
digitalWrite(LED[i], LOW);
}

//Set Spectrum Shield pin configurations
pinMode(STROBE, OUTPUT);
pinMode(RESET, OUTPUT);
pinMode(DC_One, INPUT); /* Input from MSGEQ7 to arduino */
pinMode(DC_Two, INPUT); /* Input from MSGEQ7 to arduino */
digitalWrite(STROBE, HIGH);
digitalWrite(RESET, HIGH);

//Initialize Spectrum Analyzers
digitalWrite(STROBE, LOW);
delay(1);
digitalWrite(RESET, HIGH);
delay(1);
digitalWrite(STROBE, HIGH);
delay(1);
digitalWrite(STROBE, LOW);
delay(1);
digitalWrite(RESET, LOW);

//Set Stepper Shield pin configurations
pinMode(STEPPER_PIN_1, OUTPUT);
pinMode(STEPPER_PIN_2, OUTPUT);
pinMode(STEPPER_PIN_3, OUTPUT);
pinMode(STEPPER_PIN_4, OUTPUT);
}


/**************************Main Function Loop*****************************/
void loop() {

Read_Frequencies();
Graph_Frequencies();
delay(25);

OneStep(false);
delay(2);

}


/*******************Pull frequencies from Spectrum Shield********************/
void Read_Frequencies(){ /* Read volume value for each band */
for (freq_amp = 0; freq_amp<7; freq_amp++)
{
Frequencies_One[freq_amp] = analogRead(DC_One);
Frequencies_Two[freq_amp] = analogRead(DC_Two);
digitalWrite(STROBE, HIGH);
digitalWrite(STROBE, LOW);
}
}

/*******************Light LEDs based on Frequencies Output Value*************/
void Graph_Frequencies(){
for( i= 0; i<7; i++)
{
if(Frequencies_One[i] >= level)
{
digitalWrite(LED[i], HIGH);

}
else{
digitalWrite(LED[i], LOW);
}
}
}

/**************Stepper Motor Moving to Level Value of one Band from EQ*************/
void OneStep(bool dir){
if(Frequencies_One[band] >= level){
switch(step_number){
case 0:
digitalWrite(STEPPER_PIN_1, HIGH);
digitalWrite(STEPPER_PIN_2, LOW);
digitalWrite(STEPPER_PIN_3, LOW);
digitalWrite(STEPPER_PIN_4, LOW);
break;
case 1:
digitalWrite(STEPPER_PIN_1, LOW);
digitalWrite(STEPPER_PIN_2, HIGH);
digitalWrite(STEPPER_PIN_3, LOW);
digitalWrite(STEPPER_PIN_4, LOW);
break;
case 2:
digitalWrite(STEPPER_PIN_1, LOW);
digitalWrite(STEPPER_PIN_2, LOW);
digitalWrite(STEPPER_PIN_3, HIGH);
digitalWrite(STEPPER_PIN_4, LOW);
break;
case 3:
digitalWrite(STEPPER_PIN_1, LOW);
digitalWrite(STEPPER_PIN_2, LOW);
digitalWrite(STEPPER_PIN_3, LOW);
digitalWrite(STEPPER_PIN_4, HIGH);
break;
}
}else{
switch(step_number){
case 0:
digitalWrite(STEPPER_PIN_1, LOW);
digitalWrite(STEPPER_PIN_2, LOW);
digitalWrite(STEPPER_PIN_3, LOW);
digitalWrite(STEPPER_PIN_4, LOW); /*HIGH*/
break;
case 1:
digitalWrite(STEPPER_PIN_1, LOW);
digitalWrite(STEPPER_PIN_2, LOW);
digitalWrite(STEPPER_PIN_3, LOW); /*HIGH*/
digitalWrite(STEPPER_PIN_4, LOW);
break;
case 2:
digitalWrite(STEPPER_PIN_1, LOW);
digitalWrite(STEPPER_PIN_2, LOW); /*HIGH*/
digitalWrite(STEPPER_PIN_3, LOW);
digitalWrite(STEPPER_PIN_4, LOW);
break;
case 3:
digitalWrite(STEPPER_PIN_1, LOW); /*HIGH*/
digitalWrite(STEPPER_PIN_2, LOW);
digitalWrite(STEPPER_PIN_3, LOW);
digitalWrite(STEPPER_PIN_4, LOW);


}
}
step_number++;
if(step_number > 3){
step_number = 0;
}
}







LED-STEPPER-Sound-reactive-alex-rex.jpg (79.88 KiB) Not viewed yet

Thats pretty cool!
But now i wanna use one stepper motor for each frequency band (7 Bands = 7 Motors).
I thougt about to use some I²C - Motor Shields. Someone can recomand anything, that will work?
The LED's will disappear in the final project.

WHY ALL THAT?
In the End of the project i would like to visualize Audio in material form. (Not as LED's, Beamer or Displays!)

The Motors (Rotors, or Actuators) should move some structure (or similar
objects), that will interpret the Audio into moving material. I'm still
in the beginning with that project. As for now.
0
None
_Alex_Rex_

24 days ago

I've made some progress with my project.


I wrote my first small code!

With this code i can light up LED's to the 7 Frequency-Bands, when the volume level of each freq-band reaches a specific value.

Find a small video here:

https://www.youtube.com/watch?v=al5oVSO ... e=youtu.be



here is the small code: (mostly i changed the last few lines of code from the original demo)
Code:
Sketch by Alex Rex, 24.07.2019
based on:
SparkFun Spectrum Shield PWM Demo
Toni Klopfenstein @ SparkFun Electronics
February 2015

https://github.com/sparkfun/Spectrum_Shield


*********************************************************************************/

//Declare Spectrum Shield pin connections
#define STROBE 4 /* #define constantName value */
#define RESET 5 /* #define constantName value */
#define DC_One A0 /* Analog Pin A0 with the name DC_one */
#define DC_Two A1 /* Analog Pin A1 with the name DC_Two */
//Define LED connections on the shield
int LED[] = {3, 6, 7, 9, 10, 11, 12}; /* for the seven LED's */

//Define spectrum variables
int freq_amp; /* variable for the 7 Frequency-Bands of the MSGEQ7 */
int Frequencies_One[7];
int Frequencies_Two[7];
int i;

/********************Setup Loop*************************/
void setup() {

//Set LED pin configurations
for(i=0; i<7; i++)
{
pinMode(LED[i], OUTPUT);
digitalWrite(LED[i], LOW);
}

//Set Spectrum Shield pin configurations
pinMode(STROBE, OUTPUT);
pinMode(RESET, OUTPUT);
pinMode(DC_One, INPUT); /* Input from MSGEQ7 to arduino */
pinMode(DC_Two, INPUT); /* Input from MSGEQ7 to arduino */
digitalWrite(STROBE, HIGH);
digitalWrite(RESET, HIGH);

//Initialize Spectrum Analyzers
digitalWrite(STROBE, LOW);
delay(1);
digitalWrite(RESET, HIGH);
delay(1);
digitalWrite(STROBE, HIGH);
delay(1);
digitalWrite(STROBE, LOW);
delay(1);
digitalWrite(RESET, LOW);
}
/**************************Main Function Loop*****************************/
void loop() {

Read_Frequencies();
Graph_Frequencies();
delay(25);

}
/*******************Pull frequencies from Spectrum Shield********************/
void Read_Frequencies(){ /* Read volume value for each band */
for (freq_amp = 0; freq_amp<7; freq_amp++)
{
Frequencies_One[freq_amp] = analogRead(DC_One);
Frequencies_Two[freq_amp] = analogRead(DC_Two);
digitalWrite(STROBE, HIGH);
digitalWrite(STROBE, LOW);
}
}

/*******************Light LEDs based on Frequencies Output Value*************/
void Graph_Frequencies(){
for( i= 0; i<7; i++)
{
if(Frequencies_One[i] >= 220) /* ~110 for piano songs, 175 - 340 for pop-songs (songs with a beat)*/
{
digitalWrite(LED[i], HIGH);

}
else{
digitalWrite(LED[i], LOW);
}
}
}




What's next for my project?:

Now I would like 7 stepper motors to be switched on/off instead of the 7
LEDs. I think it would be best if the >digitalOut< of the
Spectrum-shield go to a programmable Stepper-Shield and start /
interrupt a loop program there.



Can someone give me a hint which stepper shields can do this? Does
anyone have a hint for the right code for the Spectrum Analyzer Shield
to do something like this?



The exact movement of the motors has not yet been determined. I would
just say: turn clockwise at constant speed. Maybe I would extend the
movement of the motor later: e.g. gently starting and gently stopping of
the motor ... or something similar. But i will come to this later on ..




I would be very happy about an answer / thoughts / hints.
cheers, Alex
Alex-Rex-LED-Spectrum-Analyzer.jpg
0
None
_Alex_Rex_

4 weeks ago

thanks for your fast respond and your thoughts. i will think about it for few days.
i also thougth about, to use programmable motor shields (like: grove I2C motor driver), so that the number of the ports of the SPECTRUM SHIELD and the ARDUINO will just do fine. The SPECTRUM SHIELD just tells each MOTOR SHIELD to start the program, or to stop it.
... but i will think about that and come back with a more accurate idea.
thanks!

0
None
Downunder35m_Alex_Rex_

Reply 27 days ago

There might be your main prolem: The spectrum needs to start the code for all motors all the time.
I don't know how the library actually works but with a bit of luck you should be able use this call to address loops in your code.
Like having a loop for each motor.
It then would be no problem to try out how quick the spectrum and UNO can handle the updates and reactions.
I played a bit with a stepper and changing speeds quickly is no problem, reversing though is.
For your case I think a good aproach might be to have the spectrum just set the variables for motor loops, or one motor loop for all to save processing time.
Means you sort what comes from the spectrum in one loop that moves the values to the variables for the motor control.
Another loop or called function then uses the variables to replace those in the motor code from the previous round.
Won't be as quick and responsive as dimming light to sound the traditional way but should be possible on just an UNO.
You can also try two UNO's.
One handles the spectrum and prepares the data, the other gets the data through a serial connection.
Could solve the problem of making the motors accellerate and slow down properly as you then can use quite complex code on the motor UNO.

0
None
Downunder35m

4 weeks ago

First problem is the CPU.
Running a 3D printer with just 3 motors at decent speeds is hard enough, doing it with 7 most certainly would require a 32bit CPU.
Second problem is what you actually want to do with the motors.
The shield only gives a signal per channel that you can read and use with the Arduino.
That means you need to convert the signal or signal ranges in question into motion.
It is pretty straight forward to assign one motor to one output from the shield.
Making two or more motors work at the same time requires the use of interupts.
Combine both problems and you will get stuck quite quickly :(

I suggest to have a look at the motor driving libraries and code for common, Arduino based 3D printer and milling machines, like Marlin or GRBL for example.
You should be able to find the corresponding infos either right on the Github pages or on the author's project page(s).
Right now and with just an UNO I can only think of abusing the enitre system a little bit or to cheat.
Cheating I would try somehow like this:
Get the 7 motors running without the audio shield.
Preferably so that they are off with no signal and then use 2 or 3 different values for low to full speed.
Then try to either create a clean loop or use interupts to have all 7 motors running at the same time.
Use another loop with corresponding variables to set the speeds from the individual motrs in a simple pattern.
Like:
1: all off
2: motor 1 on
3: motor one and two on
.....
... motor one and two on while motor three changes the speed from low to high and back
....
all motors randomly changing speeds

The key is find out when the UNO is about to give up with the motor handling or speed of the motors.
If in doubt and no good without than you have no other choice and must use interupts.
Once the motor movement is sorted you "simply" replace you variables with the results of the mapped readouts from the shield.