I'm kinda new to Arduino and decided to dive deeper into learning abit more about Arduino; So i decided to grab a Sparkfun VEML6075 UV sensor and try to:

1) Initialise it 2) Take readings from it

Without using the Sparkfun libraries at all. Based on what I read in the datasheets, this seems possible by using the I2C communication protocol provided by communicating directly with the registers of the device itself.

However, I can't seem to be able to even initialise the device properly as the readings I have gotten are weird and do not change (I presume this means the device only took one reading and stops at that)

My code is as below:

#include <Wire.h>

byte address = 0x10; // Slave address of the VEML6075
word UVA_data;
uint16_t UVA_combined;
void setup() {
//    uv.begin();
    Serial.println("Module is detected");

void loop() {
    VEML6075_Fetch_UV(address);   // Fetch UVA data *TEST*
    Serial.print("UVA: ");

// shutdown module and init it; restarting the module 
void VEML6075_init(byte address){
    Wire.beginTransmission(address);  // Shutdown command 

    Wire.write(lowByte(0x12));   // Reset command using conf register
    delay(200); // Wait for module to reset 
    // Done //

 void VEML6075_Fetch_UV(byte address){
    Wire.beginTransmission(address);   // Begin transmission into I2C line with Slave address 
    Wire.write(highByte(0x07));     // Issue command to read UVA data 
    Wire.requestFrom(address, 2);
    while(!Wire.available()); // Needs refining; read twice for 16 bits
    UVA_LSB = Wire.read();
    UVA_MSB = Wire.read();  

    UVA_combined = ((UVA_MSB << 8) | UVA_LSB); // Combine to 16bits

As stated in the datasheet:

The VEML6075 contains a CONF register (00h) used for operation control and parameter setup. Measurement results are stored in four separate registers, one each for UVA, UVB, UVcomp1, and UVcomp2 (07h to 0Bh respectively). All registers are accessible via I2C communication. Fig. 7 shows the basic I2C communication with the VEML6075. Each of the registers in the VEML6075 are 16 bit wide, so 16 bit should be written when a write command is sent, and 16 bit should be read when a read command is sent.

I have allocated 16 bits for receiving the data, and have also used the conf address 0x12 to set the timing to 100ms and activate active-force-mode which i presume is the device taking readings automatically. The readings given are way off the accurate readings given when i upload a example code that uses the Sparkfun library, so I'm quite lost at this point. How am I using the I2C protocol wrongly? Thanks!

  • add Wire.endTransmission(false); to send the written bytes before Wire.requestFrom(address, 2); – Juraj Mar 17 at 11:26
  • after Wire.requestFrom(address, 2); returns, the data are available for read – Juraj Mar 17 at 11:28
  • ... thus the line with while(!Wire.available()) can be removed. The highbyte and lowbyte are used in the wrong way. When a 16-bit variable is for example 0x1234, then the highbyte is 12 and the lowbyte is 34. You use already bytes. – Jot Mar 17 at 11:32
  • Could you explain further about what you mean by I'm using highbytes wrongly and in where? In my intitalisation function I used Wire.write(highByte(0x00)); Wire.write(lowByte(0x12)); to emulate 0x0012 for 16bits conf register. Is that correct? – Mack Mar 17 at 11:47
  • 0x00 is already a byte and 0x12 is already a byte. You can do highByte(0x0012) and lowByte(0x0012). If you already pick the bytes from 0x0012 then you can do Wire.write(0x00); // high byte and Wire.write(0x12); // low byte – Jot Mar 17 at 11:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.