My current setup consists of an Arduino acting as Slave and a Wemos (ESP8266) acting as master.
Partial Master Code:
#include <Wire.h>
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
////////////////////////////////////////
// Requesting I2C Data from Arduino/////
////////////////////////////////////////
Wire.requestFrom(1, 7); // request 7 bytes from slave device #1
char test[7];
Serial.println(Wire.available());
Wire.readBytes(test, Wire.available());
Serial.println((char*)test);
//------> To MQTT...
Partial Slave Code
#include "kSeries.h"
#include <Wire.h>
double CO2_1;
double CO2_2;
double CO2_3;
// Create K30 instance on pin 6 & 7
kSeries K_30(6, 7);
void setup()
{
Serial.begin(9600);
Wire.begin(Arduino_Address);
Wire.onRequest(requestEvent); // register event
}
double measureCO2() {
// Get CO2 value from sensor
double co2 = K_30.getCO2('p');
// Print the value on Serial
Serial.print("Co2 ppm = ");
Serial.println(co2);
return co2;
}
void requestEvent() {
char Cout[7];
dtostrf(CO2_1, 5, 2, Cout);
Wire.write(Cout);
Serial.println("I sent the below value via I2C!");
Serial.println(Cout);
}
void loop()
{
Serial.println("Measuring CO2:...");
delay(500);
////////////////////////////////////////////////////
//Trying to achieve an accurate CO2 Reading
///////////////////////////////////////////////////
CO2_1 = measureCO2();
delay(2000);
CO2_2 = measureCO2();
delay(2000);
CO2_3 = measureCO2();
delay(2000);
----> To calculations/rest of code...
The sensor has been tested and works great by itself. When I leave my wiring but remove the sensor, I get a constant -200.13. This is relatively convenient as I know exactly what my variable should be arriving to the MASTER Wemos via I2C.
Unfortunately I can't get anything except empty boxes, a bunch of y's with two dots above them, or the occasional completely blank space to show up.
The code that came with the sensor only returns a double variable as the CO2 reading. I'm trying to use the dtostrf() function to convert my value from a double to a character array that I can send over to the Wemos on request. Everything seems to go as planned from the Arduino side. In other words "Cout" variable prints -200.13 without the sensor connected as expected.
But, as I mentioned earlier, I can't get any legible values to show up on the Wemos side. I worked on this for a few hours, and I have to believe it's some simple formatting variables trick, but I really couldn't figure it out.
You requested 7 bytes. How many do you actually want to read? 7? Or those that have actually arrived a few (hundred) nanoseconds after you requested them?
Storing 7 characters in a 7 element array is generally NOT a good idea. You need an 8 element array to hold the 7 characters and the terminating NULL.
PaulS:
Storing 7 characters in a 7 element array is generally NOT a good idea. You need an 8 element array to hold the 7 characters and the terminating NULL.
Good point. I'll change this to 8 and report back.
However, I have confused myself here...
The value that the sensor reports is a double which the Arduino treats as 4 bytes [32bits]. But I am trying to change the double into a character array with the dstorf() function in order to send it over I2C to a WEMOS. The Arduino treats characters as 1 byte.
I have set the parameters in the dstorf() function to return a character array of 5 places before the decimal and 2 places after for a total of 7 characters (I will probably change this to 6 and 2 respectively to allow for the null caracter you mentioned).
However, does the dstorf() function actually convert the 4 byte double into 7, 1 byte characters??? And correctly at that?
I apologize here but I've gotten myself lost in this conversion.
KeithRB:
Are you sure the sensor sends a float that the arduino understands? Are the bytes in the right order? I.e. Endianess issues?
I am absolutely not sure. I'm barely sure I've got pants on right now. I'm so new to all this it's making my head spin. Just piecing things together little by little.
I'm assuming the sensor sends a double because my slave code on the Uno (which is actually taking the reading) works. As in it actually returns a correct reading via Serial.println.
double co2 = K_30.getCO2('p');
Now, obviously the sensor is being read in bits through the fancy software.serial, and then somewhere converted to a double through the company's custom kseries.h library. But once I receive the information, ie once it spits out the co2 variable, it's in double form. All I want to do then, is send this double value to the WEMOS (ESP8266).
I apologize because it feels like I'm trying to piece together a puzzle but don't have the foundation (aka all the puzzle pieces) to make a complete picture. But I don't have much coding background... so I suppose that's just how it is until you learn.
Thanks again for all the responses and I look forward to more of your thoughts!
////////////////////////////////////////
// Requesting I2C Data from Arduino/////
////////////////////////////////////////
Wire.requestFrom(1, 7); // request 7 bytes from slave device #1
char test[7];
Serial.println(Wire.available());
Wire.readBytes(test, Wire.available());
Serial.println((char*)test);
I guess I naively assumed that since we requested 7 bytes in Wire.requestFrom that we would automatically get 8 bytes.
Then I figured placed neatly in the "test" character array because of the arguments passed to Wire.readyBytes().
Then finally, I thought, no need to tell Serial.println() how many characters to print, it's got them all sitting pretty in "test"... just code that and it should spit them all out.
Hint: The end of a string needs to be '\0', which readbytes does not supply.
What I think you're saying, however, is that I need to do something along the lines of...
////////////////////////////////////////
// Requesting I2C Data from Arduino/////
////////////////////////////////////////
Wire.requestFrom(1, 8); // request 7 bytes from slave #1 and 1 additional stop byte
char test[7];
int i;
Serial.println(Wire.available());
Wire.readBytes(test, Wire.available());
for (i=0; i<8; i++)
{
Serial.println(test[i]);
}
else
{
Serial.println("Data Transmission Failed... Bummer...");
...and that last character that will be amended to the sending slave will be '\0'
...and this will allow me to see the separate bits of data?
I guess I naively assumed that since we requested 7 bytes in Wire.requestFrom that we would automatically get 8 bytes.
I can't understand that. Stop by your favorite hamburger joint. Order 8 hamburgers, and then tell the order taker to go to the spot where there will be 7 hamburgers at some point, and take however many are currently there. Go sit down to enjoy your meal.
Do you REALLY expect to find 8 hamburgers in the bag?
If you do, can I interest you in a bridge?
What I think you're saying, however, is that I need to do something along the lines of...
NO! NO! NO!
You want 7 bytes; you request 7 bytes. You need a bucket big enough to hold the 7 bytes. If you are going to treat the 7 bytes AS A STRING, you need to add the NULL to the end yourself, AND you need to allow room in the bucket for the NULL.
char bucket[8]; // Room for 7 hamburgers AND a NULL
Wire.requestFrom(1, 7); // Order 7 hamburgers
for(byte b=0; b<7; b++) // Do this 7 times
{
while(Wire.available() == 0) { // Do NOTHING } // Wait for a hamburger to be ready
bucket[b] = Wire.read(); // Put the hamburger that is now ready in the bucket
}
bucket[7] = '\0'; // NULL terminate the array so we can use it as a string