I am attempting to send the variable avgAmplitudeInt() from Processing to an Arduino Uno in order to adjust the brightness of the onboard Arduino LED on pin 13 using"manual" PWM.
For some reason the variable does not seem to be updating in the Arduino sketch as the LED on pin 13 does not change. It remains constantly on. Any pointers?
Processing Code:
/**
* This sketch demonstrates how to use an FFT to analyze
* the audio being received via an Audio input.
* <p>
* FFT stands for Fast Fourier Transform, which is a
* method of analyzing audio that allows you to visualize
* the frequency content of a signal. You've seen
* visualizations like this before in music players
* and car stereos.
* <p>
* For more information about Minim and additional features,
* visit http://code.compartmental.net/minim/
*/
import processing.serial.*; // Serial Communication Library (via USB cable to Arduinio)
import ddf.minim.analysis.*;
import ddf.minim.*; // Audio Library
Serial myPort; // Create object from Serial class
Minim minim;
AudioInput in;
FFT fft;
float avgAmplitude; // store avg volume globally
int avgAmplitudeInt = int(avgAmplitude);
void setup()
{
size(512, 200, P3D);
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
minim = new Minim(this);
// specify that we want the audio buffers of the AudioPlayer
// to be 1024 samples long because our FFT needs to have
// a power-of-two buffer size and this is a good size.
// use the getLineIn method of the Minim object to get an AudioInput
in = minim.getLineIn();
// create an FFT object that has a time-domain buffer
// the same size as the audio input sample buffer
// note that this needs to be a power of two
// and that it means the size of the spectrum will be half as large.
fft = new FFT( in.bufferSize(), in.sampleRate() );
}
float maxAmp = 0;
void detectAmplitude()
{
avgAmplitude = fft.calcAvg(20,20000); // fft.calcAvg(minFreq, maxFreq)
// maxAmp doesn't decrease, but will ensure values don't
// exceed 255
if (avgAmplitude > maxAmp) { maxAmp = avgAmplitude; }
avgAmplitudeInt = int(avgAmplitude * 255 / maxAmp);
myPort.write(avgAmplitudeInt); //send average amplitude to Arduino
println(avgAmplitudeInt);
}
void draw()
{
background(0);
stroke(255);
// perform a forward FFT on the samples in LineIn's mix buffer,
// which contains the mix of both the left and right channels of the file
fft.forward( in.mix );
detectAmplitude();
for(int i = 0; i < fft.specSize(); i++)
{
// draw the line for frequency band i, scaling it up a bit so we can see it
line( i, height, i, height - fft.getBand(i)*8 );
}
}
Arduino Code:
char avgAmplitudeInt; // Data received from the serial port
int ledPin = 13; // Set the pin to digital I/O 13
void setup()
{
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop()
{
avgAmplitudeInt = Serial.read(); // read it and store it in val
//Serial.println(avgAmplitudeInt);
digitalWrite(ledPin, HIGH);
delayMicroseconds(avgAmplitudeInt); // 100 is Approximately 10% duty cycle @ 1KHz
digitalWrite(ledPin, LOW);
delayMicroseconds(1000 - 100);
}
Paul_KD7HB:
Sure. You are reading the serial buffer without ever testing to see if there is anything in the buffer.
Paul
Ooo, how do we test if there is anything in the serial buffer? What might be a good example?
Also this needs to happen as quickly as possible since it is sampling audio in real-time, I am not sure if there is any thing that would cause a hang-up. I am unable to use serial monitor with Arduino because Processing is communicating to the serial port so wasn't sure how to test this.
Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.
Robin2:
Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.
...R
This was certainly very helpful! I am now able to enter a number in Arduino serial monitor and the LED on pin 13 will correctly vary it's brightness depending on the number.
I am however still until able get the Processing sketch to somehow communicate the variable to the Arduino.
The RX light flickers when the Processing sketch is active, indicating that it is receiving data over Serial but I am stumped how to troubleshoot this further.
Here is my updated code:
Arduino
int ledPin = 13; // Set the pin to digital I/O 13
const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
int avgAmplitudeInt = 0; // new for this version
boolean newData = false;
void setup()
{
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
Serial.println("<Arduino is ready>");
}
void loop()
{
recvWithEndMarker();
showNewNumber();
digitalWrite(ledPin, HIGH);
delayMicroseconds(avgAmplitudeInt); // 100 is Approximately 10% duty cycle @ 1KHz
digitalWrite(ledPin, LOW);
delayMicroseconds(1000 - 100);
}
void recvWithEndMarker() {
static byte ndx = 0;
char endMarker = '\n';
char rc;
if (Serial.available() > 0) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}
void showNewNumber() {
if (newData == true) {
avgAmplitudeInt = 0; // new for this version
avgAmplitudeInt = atoi(receivedChars); // new for this version
Serial.print("This just in ... ");
Serial.println(receivedChars);
Serial.print("Data as Number ... "); // new for this version
Serial.println(avgAmplitudeInt); // new for this version
newData = false;
}
}
Processing
/**
* This sketch demonstrates how to use an FFT to analyze
* the audio being received via an Audio input.
* <p>
* FFT stands for Fast Fourier Transform, which is a
* method of analyzing audio that allows you to visualize
* the frequency content of a signal. You've seen
* visualizations like this before in music players
* and car stereos.
* <p>
* For more information about Minim and additional features,
* visit http://code.compartmental.net/minim/
*/
import processing.serial.*; // Serial Communication Library (via USB cable to Arduinio)
import ddf.minim.analysis.*;
import ddf.minim.*; // Audio Library
Serial myPort; // Create object from Serial class
Minim minim;
AudioInput in;
FFT fft;
float avgAmplitude; // store avg volume globally
int avgAmplitudeInt = int(avgAmplitude);
void setup()
{
size(512, 200, P3D);
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
minim = new Minim(this);
// specify that we want the audio buffers of the AudioPlayer
// to be 1024 samples long because our FFT needs to have
// a power-of-two buffer size and this is a good size.
// use the getLineIn method of the Minim object to get an AudioInput
in = minim.getLineIn();
// create an FFT object that has a time-domain buffer
// the same size as the audio input sample buffer
// note that this needs to be a power of two
// and that it means the size of the spectrum will be half as large.
fft = new FFT( in.bufferSize(), in.sampleRate() );
}
float maxAmp = 0;
void detectAmplitude()
{
avgAmplitude = fft.calcAvg(20,20000); // fft.calcAvg(minFreq, maxFreq)
// maxAmp doesn't decrease, but will ensure values don't
// exceed 255
if (avgAmplitude > maxAmp) { maxAmp = avgAmplitude; }
avgAmplitudeInt = int(avgAmplitude * 255 / maxAmp);
myPort.write(avgAmplitudeInt); //send average amplitude to Arduino
println(avgAmplitudeInt);
}
void draw()
{
background(0);
stroke(255);
// perform a forward FFT on the samples in LineIn's mix buffer,
// which contains the mix of both the left and right channels of the file
fft.forward( in.mix );
detectAmplitude();
for(int i = 0; i < fft.specSize(); i++)
{
// draw the line for frequency band i, scaling it up a bit so we can see it
line( i, height, i, height - fft.getBand(i)*8 );
}
}