Hi guys,
I have configured three XBees to communicate TX1 <==> RX and TX2 <==> RX. And I even tested them individually, with the point to point temperature sensor code. But I am having troubling with the actual code for point to multipoint now.
I think the problem is with the polling signals. I am using "*" and "(" as my polling signals and also as my start characters for my data from each of the sensors. The first sensor TX1 is sending 2 bytes of temperature data, the second one TX2 is sending 2 bytes (unsigned int) of rpm data.
My intention is this -- The RX broadcasts polling signal for TX1, TX1 sends data, after this is read by RX, RX broadcasts polling signal for TX2, TX2 sends data to RX, after this is read the cycle repeats.
I have three codes : one for the receiver, one for the transmitter of the Hall sensor and one for the transmitter of the Temperature sensor.
I have used '*' and '(' as the data_start signals, and the same for the polling signals. The hall sensor sends data (starting with a '(' character) when polled with '(', and the temperature sensor sends data starting with a '*' when polled with '*'..
I think its the polling signals that I am messing up. Can someone help me with this?
Temperature Sensor code (TX 1)
#include <SoftwareSerial.h>
#include <i2cmaster.h>
SoftwareSerial XBeeTX(2, 3); // RX, TX
const byte dev = 0x5A<<1;
const char data_start = '*';
const char data_format[] = "%c%02X%02X";
char dataStream[6]; // data_format will result in 5 characters plus 1 NULL character automatically applied by the sprintf() function so we need a 6 element array as a buffer
byte data_low;
byte data_high;
byte pec;
char data_in;
void setup()
{
Serial.begin(9600);
XBeeTX.begin(9600);
i2c_init(); //Initialise the i2c bus
PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups
}
void loop()
{
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);
// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();
if (XBeeTX.available())
{
data_in = XBeeTX.read();
if (data_in == data_start)
{
sprintf(dataStream, data_format, data_start, data_high, data_low);
XBeeTX.print(dataStream);
Serial.print(dataStream);
Serial.println(F(" Sent over XBee."));
delay(100); // adjust to what ever delay you want.
}
}
}
Hall sensor code (TX 2)
#include <SoftwareSerial.h>
SoftwareSerial XBeeTX(2, 3); // RX, TX
const char data_start = '(';
const char data_format[] = "%c%04X";
char dataStream[6];
volatile byte revolutions;
unsigned int rpm;
unsigned int rpm_send;
unsigned long timeold;
unsigned long k;
char data_in;
void setup()
{
Serial.begin(9600);
XBeeTX.begin(9600);
attachInterrupt(0, rpm_fun, FALLING);
revolutions = 0;
rpm = 0;
timeold = 0;
k = 0;
}
void loop()
{
if (revolutions >= 10) //** Update RPM every 10 counts**
{
k = millis() - timeold;
rpm = 60000/k*revolutions; // **calculate the revolutions per minute
timeold = millis();
revolutions = 0;
}
if (XBeeTX.available())
{
data_in = XBeeTX.read();
if(data_in == data_start) // if polling signal has arrived
{ // send data
sprintf(dataStream, data_format, data_start, rpm);
XBeeTX.print(dataStream);
Serial.println(F("Sent over XBee"));
delay(100);
}
}
}
void rpm_fun()
{
revolutions++;
}
Receiver code
Okay, here is probably where I messed up in the XBeeRX.print(poll_1) and XBeeRX.print(poll_2), signals.
#include <SoftwareSerial.h>
SoftwareSerial XBeeRX(2, 3); // RX, TX
const char poll_1 = '*'; // This is a constant, so use the const keyword to allow the compiler to decide how best to optimize
const char poll_2 = '(';
const char data_format_1[] = "%c%02X%02X"; // for sprintf() %c is a single character and %02X is a 2 character ASCII encoded hex number representing 1 byte
const char data_format_2[] = "%c%02X%02X";
char dataStream_1[6]; // data_format will result in 5 characters plus 1 NULL character automatically applied by the sprintf() function so we need a 6 element array as a buffer
char dataStream_2[6];
boolean newReading_1 = false; // Because we use this before explicitly setting it, just to make sure the default is false we set it here.
boolean newReading_2 = false;
byte readPosition_1;
byte readPosition_2;
byte data_temp_1;
byte data_temp_2;
byte data_rpm_1;
byte data_rpm_2;
char data_in;
void setup()
{
Serial.begin(9600);
XBeeRX.begin(9600);
}
void loop()
{
XBeeRX.print(poll_2) // it sends polling signal 1 later
delay(1000);
// READING DATA
if (XBeeRX.available())
{
data_in = XBeeRX.read();
switch (readPosition_1)
{
case 0:
{
if (data_in == poll_1)
readPosition_1++;
break;
}
case 1:
{
data_temp_1 = HexCharToValue(data_in)<<4;
readPosition_1++;
break;
}
case 2:
{
data_temp_1 = HexCharToValue(data_in)+data_temp_1;
readPosition_1++;
break;
}
case 3:
{
data_temp_2 = HexCharToValue(data_in)<<4;
readPosition_1++;
break;
}
case 4:
{
data_temp_2 = HexCharToValue(data_in)+data_temp_2;
readPosition_1 = 0;
newReading_1 = true;
}
}
// READING HALL SENSOR DATA
switch(readPosition_2)
{
case 0:
{
if (data_in == poll_2)
readPosition_2++;
break;
}
case 1:
{
data_rpm_1 = HexCharToValue(data_in)<<4;
readPosition_2++;
break;
}
case 2:
{
data_rpm_1 = HexCharToValue(data_in)+data_rpm_1;
readPosition_2++;
break;
}
case 3:
{
data_rpm_2 = HexCharToValue(data_in)<<4;
readPosition_2++;
break;
}
case 4:
{
data_rpm_2 = HexCharToValue(data_in)+data_rpm_2;
readPosition_2 = 0;
newReading_2 = true;
}
}
}
if (newReading_1 == true) // newReading is a boolean type
{
sprintf(dataStream_1, data_format_1, poll_1, data_temp_1, data_temp_2);
//Serial.print(dataStream); // diagnostics
double tempFactor = 0.02;
unsigned int tempData;
float kelvin;
float celsius;
tempData = ((data_temp_1 & 0x007F) << 8) + data_temp_2;
kelvin = (tempData * tempFactor);
celsius = kelvin - 273.15;
Serial.print(F(" Celsius: ")); // Save SRAM by using F() macro for constant text messages
Serial.println(celsius);
newReading_1 = false;
}
if (newReading_2 == true) // newReading is a boolean type
{
sprintf(dataStream_2, data_format_2, poll_2, data_rpm_1, data_rpm_2);
unsigned int rpm;
rpm = ((data_rpm_1 & 0x007F) << 8) + data_rpm_2;
Serial.print(F("RPM: ")); // Save SRAM by using F() macro for constant text messages
Serial.println(rpm);
XBee.print(poll_1); // RX polls TX1 after data 2 has been read
delay(100);
newReading_2 = false;
}
}
byte HexCharToValue (char x)
{
byte value;
char upper; // Should match x, so make this a char. (will save 1 byte of stack space in the process).
byte first_result;
if (isxdigit(x))
{
upper = toupper(x);
first_result = upper - 0x30;
if (first_result < 0x0A)
{
value = first_result;
}
else
{
value = first_result - 0x10;
value = value + 9;
}
}
else
{
value = 0;
}
return value;
}
PS : Moderators, this is a modified version of another in the Arduino forum. I thought it better to post it here under "Programming Questions", because that is what this is actually. You guys could remove the other post, I shifted it here because I wasn't getting any responses in the other one.