Sending variable from Processing to Arduino

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);
}

Sure. You are reading the serial buffer without ever testing to see if there is anything in the buffer.

Paul

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.

https://learn.sparkfun.com/tutorials/connecting-arduino-to-processing

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

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 );
  }
}

I'm not familiar with Processing - hopefully someone who is will come along.

I think it would help if you can get Processing to send in the style that will work with my 3rd example - such as <375>

...R

  myPort.write(avgAmplitudeInt);         //send average amplitude to Arduino

What part of that statement do you (mistakenly) think is adding the carriage return that the Arduino code is looking for as the end of data marker?