adafruit / Adafruit_VEML6070

Arduino Library for VEML6070 Digital UV sensors
14 stars 19 forks source link

Problem with uv.begin(VEML6070_x_T); #8

Open eryk4pdh opened 5 years ago

eryk4pdh commented 5 years ago

Setting the integration time doesn't seem to make an effect on the output value. changing VEML6070_1_T -> VEML6070_2_T should yield in doubling of the output, but it doesn't in my case.

Tested against a simple code which changes the Integration Time every time it's uploaded...

#include <Wire.h>

#define VEML6070_ADDR_ARA       (0x18 >> 1)
#define VEML6070_ADDR_CMD       (0x70 >> 1)
#define VEML6070_ADDR_DATA_LSB  (0x71 >> 1)
#define VEML6070_ADDR_DATA_MSB  (0x73 >> 1)

// VEML6070 command register bits
#define VEML6070_CMD_WDM        0x02
#define VEML6070_CMD_SD         0x01
#define VEML6070_CMD_IT_0_5T    0x00
#define VEML6070_CMD_IT_1T      0x04
#define VEML6070_CMD_IT_2T      0x08
#define VEML6070_CMD_IT_4T      0x0C
#define VEML6070_CMD_DEFAULT (VEML6070_CMD_WDM | VEML6070_CMD_IT_1T)

byte cmd = VEML6070_CMD_DEFAULT;

void setup()
{

  Serial.begin(9600); 
  while(!Serial);
  Serial.println(cmd,BIN);

  Wire.begin(); 
  Wire.requestFrom(VEML6070_ADDR_ARA,1);

  Wire.beginTransmission(VEML6070_ADDR_CMD);
  Wire.write(cmd);
  Serial.println(Wire.endTransmission());

}

void loop()
{
  uint8_t X0,X1;

  Wire.requestFrom(0x39,1); 
  X0 = Wire.read(); 

  Wire.requestFrom(0x38,1);  
  X1 = Wire.read();   

  Wire.endTransmission();

  Serial.print("X0= ");
  Serial.print(X0);
  Serial.print("   X1= ");
  Serial.println(X1);

  delay(500);
}
eecharlie commented 5 years ago

Hi, I just took a quick glance at your code and wanted to offer the following:

-Why are you using code in which you define all the VEML6070 registers & commands yourself, and in fact don't use the VEML6070 library at all? I'd recommend you create a failing example case using the library. This lets us maximally leverage code that's been validated, instead of re-checking all your definitions. While you may be following the same steps as the library's uv.begin(), everyone looking at your code has to re-confirm that for themselves.

-Do you have a more common board like the Arduino Uno you can test with, in the unlikely case it's actually a processor idiosyncrasy?

-Can you please provide an example that can be run as-is (without changing a compile-time constant and re-running) to reveal the erroneous behavior, and include in comments or in println() what you expect and what the actual output is? For your example, it looks like you'll need to call begin() at least twice to change the integration time.

eryk4pdh commented 5 years ago

Sorry I maybe didn't make it clear:

  1. I made his sample code as it was trying to find the issue with the library (quick and dirty to see it it was a hardware issue or software) -> this allowed me to prove my Hardware is ok and the issue is with the VEML6070 library

  2. I need to have a look for ATMEGA328P based board, but I wanted it to work in the M0 core as I need some if the processing power and memory for the other part of the project I am doing (I need a nice GUI with a screen)

  3. Not sure if I understand the question but originally I tried to use this

velmtest.ino example;


#include "Adafruit_VEML6070.h"

Adafruit_VEML6070 uv = Adafruit_VEML6070();

void setup() {
  Serial.begin(9600);
  Serial.println("VEML6070 Test");
  uv.begin(VEML6070_4_T);  
}

void loop() {
  Serial.print("UV light level: "); Serial.println(uv.readUV());

  delay(1000);
}```

I also just tried to use uv.begin(xxx) twice in this code and it didn't seem to have an effect.
eryk4pdh commented 5 years ago

When running uv.begin(VEML6070_2_T); i see this on I2C:

Screenshot 2019-05-13 at 09 38 18

When I run my example I see this:

Screenshot 2019-05-13 at 09 38 46

It seems like the uv.begin() doesn't actually send the 2T value 0x0A to the configuration register?

eecharlie commented 5 years ago

It looks like an Adafruit developer has been assigned to this so I will probably step back.

I didn't completely follow your last two comments. The I2C bus capture is really helpful though - what tool is that? I agree that something seems wrong if the library appears to setup a write to the command register but then doesn't write. From the source code, it's clear that's not what it should be doing. I'm also confident that in my use of the library, this basic feature has worked. In your I2C capture, what's the significance of "Setup Write to [0xNN]" versus "Write [0xNN]"?

Do the unit tests included with the library work for you?

You might consider writing another unit test that passes in a dummy i2c bus object (must be defined by you) you can then use to capture and check the i2c bus activity, and then you can compare exactly what the library sends to the bus compared to what you expect, and what is sent in your example code.

eryk4pdh commented 5 years ago

Hey I use a logic analyser and software from here: http://saleae.com

I stand to be corrected but I think the difference is that setup write usually points to the register to were you want to write / read, almost like setting a pointer to a specific i2c device, and then you need to write the data to that register.

However the VEML607x family seem to work in slightly different way (this is my understanding of the data sheet, might be wrong) they expose the registers as device address... try doing an I2C bus scan and you will see the registers sitting on the bus the device with a dedicated address which is a bit odd. So I skip the setup write and just dump data with a write

I didn't try anything else so far

eecharlie commented 5 years ago

I think you are correct. Most I2C devices follow a process where you address the device, then specify the address of a register on the device, then do a read or write operation. The VEML6070 simplifies this by using multiple device addresses instead of internal register addresses, and I think this is technically a simpler derivative protocol than full I2C. The difference may be in start/stop signaling. I'm not immediately finding a reference on this. However, I asked because shouldn't your bus analyzer label the transactions the same way in both cases?

What I would do in your shoes is start with a complete known working configuration (code+hardware) from the unit tests or example code, and then make the most marginal modifications possible one at a time, until you find out exactly what smallest change breaks expected behavior. This should include running the code on an ATMega platform to start with if at all possible. When you get to the simplest small change to a familiar example that breaks it, post the complete working example & steps to cause failure.

I do not have time right now to do this myself to help you troubleshoot. I highly recommend starting from the unit tests included with the library. I notice you still haven't answered my question about whether the unit tests pass for you. Please run /examples/unittests/unittests.ino and see what you get.

jorisvervuurt commented 3 years ago

I know this is an old (but still open) issue, but I’m running into the same issue. Looking at the code, I see that the writeCommand always writes the value of _commandRegister.reg. There is a struct (_commandRegister.bit) in which values are set, but they are never used when writing to the I2C device. The value of reg is set to 0x02 in the constructor but never updated anywhere, so this is the only value that gets written to the device.

Note that I’m not really a C developer, so if I’m overlooking something please let me know...

Looking through the code, it seems it isn’t a finished piece (e.g. the shutdown feature won’t work either). @ladyada is there any chance of this getting finished properly? Thanks! :-)

ladyada commented 3 years ago

if someone can submit a PR that would be ideal, we can review it!

jorisvervuurt commented 3 years ago

if someone can submit a PR that would be ideal, we can review it!

Unfortunately I think I’m not the right person for that task, perhaps you or a colleague at Adafruit can look at it, @ladyada? Thanks and happy holidays! ;-)

ladyada commented 3 years ago

we'll add to our list but there's no ETA... this chip got discontinued :(

jorisvervuurt commented 3 years ago

we'll add to our list but there's no ETA... this chip got discontinued :(

Hmm, I didn’t notice that. Do you know of any alternative for UVA measurement?

ladyada commented 3 years ago

we think the LTR-390 is the last i2c UV chip, we're working on the breakout right now! very frustrating, UV chips are constantly being discontinued

jorisvervuurt commented 3 years ago

@ladyada Okay, thanks. Unfortunately, the LTR-390 is not usable in our project due to the different sensitivity of the sensor. The VEML6070 is ideal though... :-(

eecharlie commented 3 years ago

If you’d like to tell me more about your application I can see if I have source code or documented solutions to unreliable device behavior. I put this sensor (or the 6075, I forget) in a commercial product a few years ago. Please direct message or email.

jorisvervuurt commented 3 years ago

If you’d like to tell me more about your application I can see if I have source code or documented solutions to unreliable device behavior. I put this sensor (or the 6075, I forget) in a commercial product a few years ago. Please direct message or email.

Thanks for the offer, but that's not needed. I'm currently writing my own implementation in Node.js (using the i2c-bus package). Will release it once it's finished.

jorisvervuurt commented 3 years ago

@ladyada @eecharlie Just published my own implementation as a Node.js package to npm: https://www.npmjs.com/package/jvsveml6070

It implements everything per the datasheet and Application Note and works with any breakout (including the Adafruit one) or custom VEML6070 implementation. Even supports different RSET resistor values. ;-)

Happy 2021!