Using Xbee Transceivers for wireless data transmission

Hi everyone,

I have recently got into Arduino couple of months ago (still a beginner :slight_smile: ) but only now I have thought of wireless transmission with the use of XBees.

The main project that I have in mind is by setting up an AGC Mic Amp microphone module, MAX9814, to read the noise/sound and convert it into 5 different sound levels, 0 to 4.

The sound levels will then determine the kind of output, which are of WS2812B LEDs in an 8x8 matrix that have already been soldered and done up. I have also already tested the microphone module and the LEDs on the same arduino without any wireless communication.

The main goal now is to split the current setup into two parts, one being an Arduino Uno with the microphone on the ground, and the other being an Arduino Mega with the LED matrix placed somewhere else nearby.

I have now with me are 2 XBee S1 Transceivers (I believe) that have already been configured with XCTU, coordinator and end-point both at 9600 baud.

I have also read a couple of tutorials that are online but with different modules such as using a potentiometer to control the LED/servo. I am not sure if it will work but I tried modifying the code for the microphone input instead, and I couldn't get the receiving Arduino to read any data coming from the transmitting Arduino.

Here are the codes for each Arduino:

Transmitter:

//Constants: 
//Variables:
int value ; //Value from pot
const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;

void setup() {

  //Start the serial communication
  Serial.begin(9600); //Baud rate must be the same as is on xBee module

}

void loop() {
//run mic sampling
  unsigned long startMillis = millis(); // Start of sample window
  unsigned int peakToPeak = 0;   // peak-to-peak level

  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;

  // collect data for 50 mS
  while (millis() - startMillis < sampleWindow)
  {
    sample = analogRead(A0);
    if (sample < 1024)  // toss out spurious readings
    {
      if (sample > signalMax)
      {
        signalMax = sample;  // save just the max levels
      }
      else if (sample < signalMin)
      {
        signalMin = sample;  // save just the min levels
      }
    }
  }

  peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
  double volts = (peakToPeak * 3.3) / 1024;  // convert to volts
  Serial.print("input volts = ");//for debugging
  Serial.println(volts);


  float voltBoost = (volts * 100);
  if(voltBoost <= 80) //reject low readings to reduce noise
  {
    voltBoost == 0;
  };

  float VU = map(voltBoost, 15, 150, 0, 6);

  //Serial.print("VU mapped = ");//for debugging
  //Serial.println(VU);

    /*//Read the analog value from pot and store it to "value" variable
    value = analogRead(A0);
    //Map the analog value to pwm value
    value = map (value, 0, 1023, 0, 255);|*/
  //Send the message:
  Serial.print('<');  //Starting symbol
  Serial.print(VU);//Value from 0 to 6
  Serial.println('>');//Ending symbol
}

Receiver:

//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

void setup() {
 //Start the serial communication
 Serial.begin(9600); //Baud rate must be the same as is on xBee module
}

void loop() {
    
  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);
   Serial.println(value); //Only for debugging
   index = 0;
   msg[index] = '\0';
   started = false;
   ended = false;
 }
}

Photos are attached of the modules I am using.

All help, suggestions, critics and improvements are appreciated, many thanks in advance!

You are using the same serial port for the serial monitor and the Xbee. Use Software serial or equivalent to connect the Xbee

Thanks Mark for the quick response!

I have edited the code for the transmitter arduino using SoftwareSerial instead:

#include <SoftwareSerial.h>
#define rxPin 0
#define txPin 1
SoftwareSerial xbee = SoftwareSerial(rxPin, txPin);
 
//Variables:
const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;

void setup() {

  //Start the serial communication
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  xbee.begin(9600); //Baud rate must be the same as is on xBee module

}

void loop() {
//run mic sampling
  unsigned long startMillis = millis(); // Start of sample window
  unsigned int peakToPeak = 0;   // peak-to-peak level

  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;

  // collect data for 50 mS
  while (millis() - startMillis < sampleWindow)
  {
    sample = analogRead(A0);
    if (sample < 1024)  // toss out spurious readings
    {
      if (sample > signalMax)
      {
        signalMax = sample;  // save just the max levels
      }
      else if (sample < signalMin)
      {
        signalMin = sample;  // save just the min levels
      }
    }
  }

  peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
  double volts = (peakToPeak * 3.3) / 1024;  // convert to volts
  Serial.print("input volts = ");//for debugging
  Serial.println(volts);


  float voltBoost = (volts * 100);
  if(voltBoost <= 80) //reject low readings to reduce noise
  {
    voltBoost == 0;
  };

  float VU = map(voltBoost, 15, 150, 0, 6);//maps sound range on to 9 levels which are then used in if statements below to call matrix array functions

  //Serial.print("VU mapped = ");//for debugging
  //Serial.println(VU);
  
  //Send the message:
  xbee.println(VU);
  delay(100);
}

As well as the receiver arduino:

#include <SoftwareSerial.h>
#define rxPin 0
#define txPin 1
SoftwareSerial xbee =  SoftwareSerial(rxPin, txPin);

void setup(){
 pinMode(rxPin, INPUT);
 pinMode(txPin, OUTPUT);
 xbee.begin(9600);
 Serial.begin(9600);
 Serial.println("Starting XBee Comunication");
}


void loop()
{
 float VU = xbee.read();
 Serial.println(VU);
 delay(100);

 if (VU == 2) //read xbee communication data for volume level 3
 {
  digitalWrite(10, HIGH);
  delay(1000);
  digitalWrite(10, LOW);
 }
}

The serial monitor at the receiver arduino keeps reading a value of -1 despite the XBee being connected/disconnected.
Is there a way to tell if the transmitter XBee and receiver XBee are communicating with each other? I am still unsure if they are even transmitting any data.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

...R

Thank you Robin for the reply!

I will check it out and definitely try it and post my results again soon!

Pins 1 & 0 are the pins for the serial port for communicating with the USB/Serial Monitor. You still have a conflict and you need to select another 2 pins

Thanks Mark again for pointing my silly mistakes out, my apologies if I seem slow to catch on.

Here's the updated code again:

Transmitter:

#include <SoftwareSerial.h>
SoftwareSerial XBee(2, 3);
 
//Variables:
const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;

void setup() 
{
  //Start the serial communication
  Serial.begin(9600); //serial / USB port
  Serial.println("Starting XBee Comunication");
  pinMode(2, INPUT);
  pinMode(3, OUTPUT);
  XBee.begin(9600); 
}

void loop() 
{
  //run mic sampling
  unsigned long startMillis = millis(); // Start of sample window
  unsigned int peakToPeak = 0;   // peak-to-peak level

  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;

  // collect data for 50 mS
  while (millis() - startMillis < sampleWindow)
  {
    sample = analogRead(A0);
    if (sample < 1024)  // toss out spurious readings
    {
      if (sample > signalMax)
      {
        signalMax = sample;  // save just the max levels
      }
      else if (sample < signalMin)
      {
        signalMin = sample;  // save just the min levels
      }
    }
  }

  peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
  double volts = (peakToPeak * 3.3) / 1024;  // convert to volts
  //Serial.print("input volts = ");//for debugging
  //Serial.println(volts);

  float voltBoost = (volts * 100);
  if(voltBoost <= 80) //reject low readings to reduce noise
  {
    voltBoost == 0;
  };

  float VU = map(voltBoost, 15, 150, 0, 6);//maps sound range on to 9 levels which are then used in if statements below to call matrix array functions

  Serial.print("VU mapped = ");//for debugging
  Serial.println(VU);

  
  //Send the message:
  XBee.write(VU);
  delay(100);
}

Receiver:

#include <SoftwareSerial.h>
SoftwareSerial XBee(10, 11);

void setup() 
{
  //Start the serial communication
  Serial.begin(9600); //serial / USB port
  Serial.println("Starting XBee Communication");
  pinMode(10, INPUT);
  pinMode(11, OUTPUT);
  XBee.begin(9600);   //software serial port
}


void loop()
{
  while (XBee.available() > 1)
  {
    int newVU = XBee.read();
    Serial.println(newVU);
  }
}

Edited to change some lines.

Hi all, I finally got it to work!

It was mainly due to problems with the initial setup of the XBee's and some connections that are swapped by accident.

However, I have learnt more about the XBee's as well as serial communication (which I had zero clue about) between the 2 arduinos in such a short timeframe.

And again, thank you all for your help and expertise in guiding me! :slight_smile: