Is anyone still in this thread? :~
Now that the XBees can communicate as required, I need to send data from the two sensors to the receiver. I have are a temperature sensor (MLX90614) and a hall sensor (A3144)
The way to do this I am thinking is to send the temperature and hall sensor data continuously. Since the temperature sensor samples in periods of time, and the hall sensor sends it based on the number of revolutions, I thought it would be a good idea for the receiver to read a packet every time it gets one from the hall sensor. In that time instant, the receiver will consider the latest temperature data packet. This way the receiver doesn't have to send any pilot signals to the transmitters on when to send data, they can transmit continuously.
So I am going to have three codes - T1 (temperature sensor connected with xbee and board), T2 (hall sensor connected with xbee and board) and R3 (receiver of both data).
I already have the temperature sensor sending data to the receiver and displaying it in the COM port (thanks Sembazuru! But I may need your help again!). I don't think I need to change the T1 code. But I need to have to modify the code of the receiver because it has to wait for the hall sensor data and then display that with the latest temperature data.
I also have to change the code of the hall sensor board (T2) for it to be able to transmit the data to the receiver. At this point the hall snesor works wired, but I want to make it wireless. So what I have now :
At T1 (I think this doesn't need to be changed, right?)
#include <SoftwareSerial.h>
#include <i2cmaster.h>
SoftwareSerial XBeeTX(2, 3); // RX, TX
const byte dev = 0x5A<<1; // This is a constant, so use the const keyword to allow the compiler to decide how best to optimize
const char data_start = '*'; // This is a constant, so use the const keyword to allow the compiler to decide how best to optimize
const char data_format[] = "%c%02X%02X"; // %c is a single character, %02X is a 2 character ASCII encoded hex number representing 1 byte
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;
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();
// sprintf() method of output
sprintf(dataStream, data_format, data_start, data_high, data_low); // 1(data_start) + 2(data_high) + 2(data_low) + 1(NULL) = 6 bytes
XBeeTX.print(dataStream);
Serial.print(dataStream); // for diagnostics
Serial.println(F(" Sent over XBee.")); // also for diagnostics, using the F() macro to avoid wasting SRAM with diagnostic messages
delay(2000); // adjust to what ever delay you want.
}
At T2 (the wired hall sensor code, I need to make this wireless)
volatile byte revolutions;
unsigned int rpm;
unsigned long timeold;
unsigned long k;
void setup()
{
Serial.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;
Serial.print("RPM: ");
Serial.println(rpm,DEC);
}
}
void rpm_fun()
{
revolutions++;
}
At R3 (I need to modify this to receive and display even the hall sensor data)
#include <SoftwareSerial.h>
SoftwareSerial XBeeRX(2, 3); // RX, TX
const char data_start = '*'; // This is a constant, so use the const keyword to allow the compiler to decide how best to optimize
const char data_format[] = "%c%02X%02X"; // for sprintf() %c is a single character and %02X is a 2 character ASCII encoded hex number representing 1 byte
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
boolean newReading = false; // Because we use this before explicitly setting it, just to make sure the default is false we set it here.
byte readPosition;
byte data_low;
byte data_high;
char data_in;
void setup()
{
Serial.begin(9600);
XBeeRX.begin(9600);
}
void loop()
{
if (XBeeRX.available())
{
data_in = XBeeRX.read();
//Serial.println(data_in, HEX); // Show the recieved HEX value immediately as recieved for diagnostics.
switch(readPosition)
{
case 0: // Waiting for the start of data token to be received. Ignore any serial data until data_start is received.
{
if (data_in == data_start)
readPosition++;
break;
}
case 1: // data_start processed. Current character should be ASCII representation of the high nybble of data_high.
{
data_high = HexCharToValue(data_in)<<4;
readPosition++;
break;
}
case 2: // high nybble of data_high processed. Current character should be ASCII representation of the low nybble of data_high.
{
data_high = HexCharToValue(data_in)+data_high;
readPosition++;
break;
}
case 3: // low nybble of data_high processed. Current character should be ASCII representation of the high nybble of data_low.
{
data_low = HexCharToValue(data_in)<<4;
readPosition++;
break;
}
case 4: // high nybble of data_low processed. Current character should be ASCII representation of the low nybble of data_low.
{
data_low = HexCharToValue(data_in)+data_low;
readPosition = 0; // Finished receiving expected data structure. Return readPosition to zero to wait for the next data_start token
newReading = true;
}
}
}
if (newReading == true) // newReading is a boolean type
{
sprintf(dataStream, data_format, data_start, data_high, data_low); // reconvert converted serial input to verify the deconversion process worked
//Serial.print(dataStream); // diagnostics
// This whole section of declarations should properly be at the top of either loop() as local variables, or at the top of the sketch as globals. If globals, tempFactor should be a constant
double tempFactor = 0.02; // double and float are the same datatype. Only use one of the two to avoid confusion unless there is a really good reason not to.
unsigned int tempData; // floating point math is executionally expensive on AVR processors. All we really need here is a 16-bit holding bin, polarity is not important.
float kelvin;
float celsius;
tempData = ((data_high & 0x007F) << 8) + data_low;
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 = 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;
}