GithubHelp home page GithubHelp logo

Comments (14)

maarten-pennings avatar maarten-pennings commented on September 26, 2024

Hi, I don't see any obvious mistakes.

Did you connect nWAKE to GND (since you pass -1 in the constructor)?

Did you (can you) run the ccs811basic example? What does it say?

from ccs811.

Creepwood avatar Creepwood commented on September 26, 2024

Hi.
Yes, I connected nWAKE to GND.

When I run the ccs811basic sketch I get following output:
setup: Starting CCS811 basic demo
setup: library version: 8
ccs811: begin: HW_ID read failed
setup: CCS811 begin FAILED
setup: hardware version: FFFFFFFF
setup: bootloader version: FFFFFFFF
setup: application version: FFFFFFFF
CCS811: I2C error

Now I'm going to try with a LOLIN D32... I will be back

from ccs811.

Creepwood avatar Creepwood commented on September 26, 2024

Same problem with LOLIN D32 :(

from ccs811.

Creepwood avatar Creepwood commented on September 26, 2024

Ok...now it works. And I can flash the new firmware :) Very happy!

I changed your function CCS811::i2cread(int reg, int num, uint8_t * buf) an copied in the code to I2Cwrite out of the Ardafruit CCS811 lib :D

Now the function looks like:

bool CCS811::i2cread(int reg, int num, uint8_t * buf)
{
uint8_t value;
uint8_t pos = 0;

//on arduino we need to read in 32 byte chunks
while(pos < num){
	
	uint8_t read_now = min((uint8_t)32, (uint8_t)(num - pos));
	Wire.beginTransmission((uint8_t)_slaveaddr);
	Wire.write((uint8_t)reg + pos);
	Wire.endTransmission();
	Wire.requestFrom((uint8_t)_slaveaddr, read_now);
	
	for(int i=0; i<read_now; i++){
		buf[pos] = Wire.read();
		pos++;
	}
}
return true;

}




sry for the bad markdown styling... I do not got it, how I can insert a code block

from ccs811.

maarten-pennings avatar maarten-pennings commented on September 26, 2024

I don't see why your change solves your problem. The code that you added supports reads of more than 32 bytes, but the driver never does that.
Could you simplify your read function by getting rid of the while loop (it will only be executed once since num is always smaller than 32). I want to know the root cause...

from ccs811.

Creepwood avatar Creepwood commented on September 26, 2024

For sure. I'm also interested :)

I tested this code for you (removed while loop): And it works
bool CCS811::i2cread(int reg, int num, uint8_t * buf)
{
uint8_t value;
uint8_t pos = 0;

//on arduino we need to read in 32 byte chunks
	
uint8_t read_now = min((uint8_t)32, (uint8_t)(num - pos));
Wire.beginTransmission((uint8_t)_slaveaddr);
Wire.write((uint8_t)reg + pos);
Wire.endTransmission();
Wire.requestFrom((uint8_t)_slaveaddr, read_now);

for(int i=0; i<read_now; i++){
	buf[pos] = Wire.read();
	pos++;
}
return true;

}
The Serial output:
setup: Starting CCS811 basic demo
setup: library version: 8
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 2000
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: eco2=400 ppm etvoc=0 ppb raw6=3 uA raw10=497 ADC R=267054 ohm
CCS811: eco2=400 ppm etvoc=0 ppb raw6=3 uA raw10=502 ADC R=269741 ohm
CCS811: eco2=400 ppm etvoc=0 ppb raw6=3 uA raw10=507 ADC R=272428 ohm





After that, I tested your function again, because maybe now with new frimware on ccs811 it will work: But it's the same error...
// Reads 'countbytes from register at addressregaddr, and stores them in buf`. Returns false on I2C problems.
bool CCS811::i2cread(int regaddr, int count, uint8_t * buf) {
Wire.beginTransmission(_slaveaddr); // START, SLAVEADDR
Wire.write(regaddr); // Register address
int wres= Wire.endTransmission(false); // Repeated START
delayMicroseconds(_i2cdelay_us); // Wait
int rres=Wire.requestFrom(_slaveaddr,count); // From CCS811, read bytes, STOP
for( int i=0; i<count; i++ ) buf[i]=Wire.read();
return (wres==0) && (rres==count);
}

The Serial output:
setup: Starting CCS811 basic demo
setup: library version: 8
ccs811: begin: HW_ID read failed
setup: CCS811 begin FAILED
setup: hardware version: FFFFFFFF
setup: bootloader version: FFFFFFFF
setup: application version: FFFFFFFF
CCS811: I2C error

from ccs811.

maarten-pennings avatar maarten-pennings commented on September 26, 2024

Your working code looks like this at the moment , right?

bool CCS811::i2cread(int reg, int num, uint8_t * buf)
{
  uint8_t value; 
  uint8_t pos = 0;

  //on arduino we need to read in 32 byte chunks
  uint8_t read_now = min((uint8_t)32, (uint8_t)(num - pos));
  Wire.beginTransmission((uint8_t)_slaveaddr);
  Wire.write((uint8_t)reg + pos);
  Wire.endTransmission();
  Wire.requestFrom((uint8_t)_slaveaddr, read_now);

  for(int i=0; i<read_now; i++){
	buf[pos] = Wire.read();
	pos++;
  }
  return true;
}

Notice that pos is always 0 in the first part of the code.
And that in the second part pos equals i.
Furthermore, num is smaller than 32, and value is not used.
Let's use all this to simplify your code further.
We get this:

bool CCS811::i2cread(int reg, int num, uint8_t * buf)
{
  Wire.beginTransmission((uint8_t)_slaveaddr);
  Wire.write((uint8_t)reg);
  Wire.endTransmission();
  Wire.requestFrom((uint8_t)_slaveaddr, (uint8_t)num);

  for(int i=0; i<read_now; i++){
	buf[i] = Wire.read();
  }
  return true;
}

Could you check if this simplification still works - I guess so (let's hope I made no typos).
It would be great if you could rename reg to regaddr and num to count, then the code is even more equal.

If you compare the above code to my driver code, there is not much of a difference left anymore:

  • your code has typecasts, I think they don't do much.
  • my code has a delayMicroseconds(), but I believe you have set that delay to 0us
  • My code reports errors, yours doesn't.
  • I thing the crucial difference is here Wire.endTransmission(); vs int wres= Wire.endTransmission(false); // Repeated START.

The last bullet is tricky. You have no parameter in Wire.endTransmission().
Then the parameter defaults to true. I have an explicit false.
This means I have a single start-write-read-stop I2C transaction (as is normal for a read from register), you have two I2C transactions start-write-stop then start-read-stop (which is tricky because the chip could loose the register address).

Could you try my code and replace the false in Wire.endTransmission(false) to a true.

You could also run as separate check the third bullet, and change my return (wres==0) && (rres==count); also to a return true;.

Happy debugging :-)

from ccs811.

Creepwood avatar Creepwood commented on September 26, 2024

1. I try this code, like your simplification: And it works
bool CCS811::i2cread(int regaddr, int count, uint8_t * buf)
{
Wire.beginTransmission((uint8_t)_slaveaddr);
Wire.write((uint8_t)regaddr);
Wire.endTransmission();
Wire.requestFrom((uint8_t)_slaveaddr, (uint8_t)count);

for(int i=0; i<count; i++){
buf[i] = Wire.read();
}
return true;
}

I only changed for(int i=0; i<read_now; i++) to for(int i=0; i<count; i++) because read_now is not available any more.

2. I try your code with Wire.endTransmission(true) again: And now it works!
bool CCS811::i2cread(int regaddr, int count, uint8_t * buf) {
Wire.beginTransmission(_slaveaddr); // START, SLAVEADDR
Wire.write(regaddr); // Register address
int wres= Wire.endTransmission(true); // Repeated START
delayMicroseconds(0); // Wait
int rres=Wire.requestFrom(_slaveaddr,count); // From CCS811, read bytes, STOP
for( int i=0; i<count; i++ ) buf[i]=Wire.read();
return (wres==0) && (rres==count);
}

3. Let's try your code with Wire.endTransmission(false) : Boom! Not working! Now the code looks like:
bool CCS811::i2cread(int regaddr, int count, uint8_t * buf) {
Wire.beginTransmission(_slaveaddr); // START, SLAVEADDR
Wire.write(regaddr); // Register address
int wres= Wire.endTransmission(false); // Repeated START
delayMicroseconds(0); // Wait
int rres=Wire.requestFrom(_slaveaddr,count); // From CCS811, read bytes, STOP
for( int i=0; i<count; i++ ) buf[i]=Wire.read();
return (wres==0) && (rres==count);
}

And the Serial output is again:
setup: Starting CCS811 basic demo
setup: library version: 8
ccs811: begin: HW_ID read failed
setup: CCS811 begin FAILED
setup: hardware version: FFFFFFFF
setup: bootloader version: FFFFFFFF
setup: application version: FFFFFFFF
CCS811: I2C error


So the problem is the Wire.endTransmission(false)... with Wire.endTransmission(true) it's working :)
Why is that? :D Do you want to update your repro like that? I can also try to flash another CCS811 firmware with this code for you.


And I'm really excited if the CCS811 is now better working with the new firmware. Currently I log the values in an MySQL database and compare it with an iAQ-Core P sensor from AMS. I run two iAQ-Core P sensors since 3 years... and I really like it. They are installed in two different rooms, that are connected with a opened door. And both values are pretty good!

iaq_corep

But compared with the CCS811.... the CCS811 values ​​are totally different :(
airquality

from ccs811.

maarten-pennings avatar maarten-pennings commented on September 26, 2024

Thanks for all the testing!
I already suspected the STOP condition.

We could change the codem however, from a transaction perspective my code (without the STOP) is better than the new code (with the STOP).

You are running this on an ESP32, right?
Could you try if the ESP8266 workaround works for ESP32 as well?

int wres= Wire.endTransmission(false); // Repeated START
delayMicroseconds(50); // <== extra wait here

Do you happen to have a logic analyser/scope?
I'm really interested to see what happens when this executes.

from ccs811.

Creepwood avatar Creepwood commented on September 26, 2024

No problem ;) Yes I am using a ESP32.
It seem, that the ESP8266 workaround is not working.

1. try with Wire.endTransmission(false): not working
bool CCS811::i2cread(int regaddr, int count, uint8_t * buf) {
Wire.beginTransmission(_slaveaddr); // START, SLAVEADDR
Wire.write(regaddr); // Register address
int wres= Wire.endTransmission(false); // Repeated START
delayMicroseconds(50); // Wait
int rres=Wire.requestFrom(_slaveaddr,count); // From CCS811, read bytes, STOP
for( int i=0; i<count; i++ ) buf[i]=Wire.read();
return (wres==0) && (rres==count);
}
20190113_170140

2. try with Wire.endTransmission(true): working
bool CCS811::i2cread(int regaddr, int count, uint8_t * buf) {
Wire.beginTransmission(_slaveaddr); // START, SLAVEADDR
Wire.write(regaddr); // Register address
int wres= Wire.endTransmission(true); // Repeated START
delayMicroseconds(50); // Wait
int rres=Wire.requestFrom(_slaveaddr,count); // From CCS811, read bytes, STOP
for( int i=0; i<count; i++ ) buf[i]=Wire.read();
return (wres==0) && (rres==count);
}
20190113_170042


I checked the whole scope buffer... but don't see any differents

from ccs811.

maarten-pennings avatar maarten-pennings commented on September 26, 2024

Sorry was a busy week - did not yet have time to look at this ...

from ccs811.

maarten-pennings avatar maarten-pennings commented on September 26, 2024

I think I solved your problem.
See the new section I added for ESP32.
Basically, there is a bug in the ESP32 I2C lib (for repeated start conditions).
So, do not use ESP32 Arduino core lib version 1.0.0, but use 1.0.1.

I hooked an ESP32 to a CCS811, and this library change did it for me.
(Using library 1.0.0, I do see the correct I2C transaction on the logic analyser, but the bytes reported by the CCS811 are not picked up by the ESP32 lib).

from ccs811.

maarten-pennings avatar maarten-pennings commented on September 26, 2024

Can I close the Issue?

from ccs811.

Creepwood avatar Creepwood commented on September 26, 2024

Sorry for waiting... this time it was a busy week for me :D

I think we can close the issue.

I'm going play around with your library, but I think the next few weeks will be to busy for me.
And when I come across a problem again, I will contact you by a new issue ;)

Thanks bro.

from ccs811.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.