Go Down

Topic: Using XBee RSSI values to control Mozzi synths (Read 1 time) previous topic - next topic

Funkturm

Hello. I hope someone can help.

My Arduino knowledge is currently pretty basic, but I am trying to use XBee RSSI values to control Mozzi synths, so that various envelopes or filters change when 3D objects are further apart of closer together. There are 4 objects, each with an XBee inside.

I am trying to use

rssiDur = pulseIn(digitalPin, LOW, 200);

as mentioned here - http://log.liminastudio.com/itp/physical-computing/measuring-xbee-signal-strength-from-the-rssi-pin, but don't know how to use / adapt this to control synths.

I have some code that I had a lot of help with that seems to read the fact that there RSSI data there, but it doesn't seem to change the sound when the distance changes, just when it detects another XBee transmitting.

Code: [Select]

#include <MozziGuts.h>
#include <Oscil.h> // oscillator
#include <tables/cos2048_int8.h> // table for Oscils to play
#include <AutoMap.h> // maps unpredictable inputs to a range
 
// desired carrier frequency max and min, for AutoMap
const int MIN_CARRIER_FREQ = 22;
const int MAX_CARRIER_FREQ = 440;

// desired intensity max and min, for AutoMap, note they're inverted for reverse dynamics
const int MIN_INTENSITY = 700;
const int MAX_INTENSITY = 10;

AutoMap kMapCarrierFreq(0,1023,MIN_CARRIER_FREQ,MAX_CARRIER_FREQ);
AutoMap kMapIntensity(0,1023,MIN_INTENSITY,MAX_INTENSITY);

const int KNOB_PIN = 0; // set the input for the knob to analog pin 0
const int LDR_PIN = 1; // set the input for the LDR to analog pin 1

Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aCarrier(COS2048_DATA);
Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aModulator(COS2048_DATA);

int mod_ratio = 3; // harmonics
long fm_intensity; // carries control info from updateControl() to updateAudio()

//Constants
const int ledPin = 3; //Led to Arduino pin 3 (PWM)

//Variables
bool started= false;//True: Message is strated
bool ended  = false;//True: Message is finished
char incomingByte ; //Variable to store the incoming byte
char msg[3];    //Message - array from 0 to 2 (3 values - PWM - e.g. 240)
byte index;     //Index of array

int rssiDur = 0;
int rssiMapped =0;
bool calib = false;
bool calib_top = false;
int base_value= 0;
int top_value=0;

void setup() {
  //Start the serial communication
  Serial.begin(9600); //Baud rate must be the same as is on xBee module
  pinMode(ledPin, OUTPUT);
  pinMode(6, OUTPUT);
  calib = true;
  calib_top = true;
  startMozzi(); // :))
}
void updateControl(){
  // read the knob
  //int knob_value = mozziAnalogRead(KNOB_PIN); // value is 0-1023
  rssiDur = pulseIn(5, LOW, 200);
  rssiMapped = map(rssiDur, 10, 40, 0, 1023);
 
 
  Serial.print("raw RSSI : ");
  Serial.println(rssiDur);
  Serial.print("RSSI mapped : ");
  Serial.println(rssiMapped);
 
   //delay(100);
 
  // map the knob to carrier frequency
  int carrier_freq = kMapCarrierFreq(rssiMapped);
 
  //calculate the modulation frequency to stay in ratio
  int mod_freq = carrier_freq * mod_ratio;
 
  // set the FM oscillator frequencies to the calculated values
  aCarrier.setFreq(carrier_freq);
  aModulator.setFreq(mod_freq);
 
  // read the light dependent resistor on the Analog input pin
  int light_level= mozziAnalogRead(LDR_PIN); // value is 0-1023

  fm_intensity = kMapIntensity(light_level);

}

 int updateAudio(){
  long modulation = fm_intensity * aModulator.next();
  return aCarrier.phMod(modulation); // phMod does the FM
}


void loop() {
 
 
  //delay(100);
 

  if(rssiDur != 0){
      digitalWrite(6, HIGH);
    }else{
      digitalWrite(6,LOW);
    }

    audioHook();
 
while (Serial.available()>0){
    //Read the incoming byte
    incomingByte = Serial.read();
    //Start the message when the '<' symbol is received
    if(incomingByte == '<')
    {
     started = true;
     index = 0;
     msg[index] = '\0'; // Throw away any incomplete packet
   }
   //End the message when the '>' symbol is received
   else if(incomingByte == '>')
   {
     ended = true;
     break; // Done reading - exit from while loop!
   }
   //Read the message!
   else
   {
     if(index < 4) // Make sure there is room
     {
       msg[index] = incomingByte; // Add char to array
       index++;
       msg[index] = '\0'; // Add NULL to end
     }
   }
 }
 
 if(started && ended)
 {
   int value = atoi(msg);
   
   //analogWrite(ledPin, value);
   Serial.println(value); //Only for debugging
   if(calib_top){
   if(value == 0){
    top_value = rssiMapped;
    Serial.println(top_value);
    calib_top = false;
   }
   }
   
   index = 0;
   msg[index] = '\0';
   started = false;
   ended = false;
 }
}



Any help at all would be appreciated, bearing in mind my basic level of knowledge. I did the Mozzi introductory tutorials, so I get how to wire stuff together, but am not so clear on how to adapt the code.

Thank you in advance. 

Grumpy_Mike

Quote
read the fact that there RSSI data there, but it doesn't seem to change the sound when the distance changes,
Are you expecting the signal strength to change when the distance changes? It will not. Just print out the values and see what they say. You will find that they do not change linearly with distance but keep roughly the same and then drop off very quickly as you loose the signal.

jremington

RSSI depends on a lot of things and generally can't be used to estimate distance.

MarkT

RSSI is principally going to be sensitive to polarization and multipath interference, as a distance indicator its
pretty rough.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Funkturm

Thanks for the replies. I am not trying to get an EXACT distance measurement, but to get the sound to change with the RSSI values, which I have seen change as one XBee gets further away from the other.


Any idea how I can capture these values and use them to change the sound, exact or otherwise?

jremington

#5
Aug 28, 2018, 02:11 am Last Edit: Aug 29, 2018, 12:22 am by jremington
To read the XBEE RSSI pin as described on that web page, in addition to connecting the output pin to an Arduino input pin, you will also have to connect the XBEE ground and the Arduino ground.

Then, follow the instruction given on the web page:

Quote
Since this function gives you a duration, it's up to you to map that to a value relevant to your program.
Use the Arduino map() function for that. Let us know how well it all works.

Funkturm

Thanks. I am using a shield for the Arduino (Nano) and XBee, so the ground is already connected. It's the mapping part I am struggling with, but will look further into that now. 

Funkturm

I tried the mapping, and now get a repeating click when the two XBees are powered / connected, and no sound at all when either is disconnected. Changing the frequency in the code doesn't change anything with the sound. Any ideas?

Code: [Select]


#include <MozziGuts.h>
#include <Oscil.h> // oscillator template
#include <tables/sin2048_int8.h> // sine table for oscillator

// use: Oscil <table_size, update_rate> oscilName (wavetable), look in .h file of table #included above
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aSin(SIN2048_DATA);

// use #define for CONTROL_RATE, not a constant
#define CONTROL_RATE 64 // Hz

int rssiDur = 0;
int rssiMapped = 0;
bool calib = false;
bool calib_top = false;
int base_value= 0;
int top_value=0;

void setup(){
    //Start the serial communication
  Serial.begin(9600); //Baud rate must be the same as is on xBee module
  pinMode(6, OUTPUT);
  calib = true;
  calib_top = true;
  startMozzi(CONTROL_RATE); // :)
  aSin.setFreq(660); // set the frequency
}


void updateControl(){
  // put changing controls in here
  rssiDur = pulseIn(5, LOW, 200);

  rssiMapped = map(rssiDur, 10, 40, 0, 1023);
 
 
  Serial.print("raw RSSI : ");
  Serial.println(rssiDur);
  Serial.print("RSSI mapped : ");
  Serial.println(rssiMapped);
 
  aSin.setFreq(rssiDur);
}


int updateAudio(){
  return aSin.next(); // return an int signal centred around 0
}


void loop(){
  audioHook(); // required here
}

Grumpy_Mike

#8
Aug 28, 2018, 11:01 pm Last Edit: Aug 28, 2018, 11:01 pm by Grumpy_Mike
You seem to be using the serial port on the Arduino to talk to the XBees and the port monitor, you can't do both at the same time.

Funkturm

Thanks Mike

Newbie question, but how do I change that (so it hopefully works?).

Grumpy_Mike

You could talk to the XBee using software serial.

Funkturm

How would that work (basic question, I know, but am a bit stuck here)?

Grumpy_Mike

You look up software serial and use two other pins to talk to the XBee.

Go Up