Jump to content
Sign in to follow this  
Marc

OPT3001 and MSP430

Recommended Posts

One thing I think I'll try is a non-Energia I2C direct approach to see if Energia timing issues are playing a role. I'll be adapting the F5529 sample code to read the device and then send it to a USB display. My reason for a non-serial display approach is based on the USB's ability to handle conversations on a millisecond time frame. And, a good learning experience.

Share this post


Link to post
Share on other sites

I know how you feel @@NurseBob, wow nursing instructor at day, developer at night?

 

Thanks @@Rei Vilo, I downloaded the SensorsWeather_Library and hooked up my sensor to the CC3200 launchpad. It works without glitches now!

There is still a NAK at the end of the wire transmission, but the CC3200 seems to have no problem getting the correct value.

I am more convinced that it is some timing issue with the energia wire implementation.

Share this post


Link to post
Share on other sites

I think I have found the issue:

 

In the energia opt3001.cpp code (line 77) the implementation for the register read readRegister(uint8_t registerName) declared the lsb, msb and result variables as int8_t.

 

(line 79, OPT3001.cpp)

int8_t lsb;
int8_t msb;
int16_t result;
 
I changed this to unsigned, as they are supposed to be:
uint8_t lsb;
uint8_t msb;
uint16_t result;
 
The code now works. Thank you for sharing your library @@Rei Vilo, I was able to realize this by doing a side by side comparison with your code. I hope this will prevent any issues you may have with your project @@NurseBob!

Share this post


Link to post
Share on other sites

 

I think I have found the issue:

 

In the energia opt3001.cpp code (line 77) the implementation for the register read readRegister(uint8_t registerName) declared the lsb, msb and result variables as int8_t.

 

(line 79, OPT3001.cpp)

int8_t lsb;
int8_t msb;
int16_t result;
 
I changed this to unsigned, as they are supposed to be:
uint8_t lsb;
uint8_t msb;
uint16_t result;
 
The code now works. Thank you for sharing your library @@Rei Vilo, I was able to realize this by doing a side by side comparison with your code. I hope this will prevent any issues you may have with your project @@NurseBob!

 

Ahh!!!  A bit of magic. :)

Great catch.

Share this post


Link to post
Share on other sites

I suspect there is a math error in the OPT301.cpp file.  Shining a bright source on the sensor I see the sketch reporting a value of 131040 lux.  The maximum value the sensor can report is 83806 lux. After looking more closely at a pair of logic traces, I am wondering about the handling of the I2C transactions on the Energia side. I see ACK with the EVM, and NAK with the Energia code, though the magnatude of the values are close (0xBFFF for the Energia code, and 0xCC10 for the EVM)

Share this post


Link to post
Share on other sites

I believe there is still a problem in OPT3001.cpp.  The device has a max Lux value of 83886, but the readResult() method returns 131040 after a left shift of the raw result.
(forgive the double post; I thought the previous had not been sent...)

Share this post


Link to post
Share on other sites

Yes, another issue with the OPT3001.cpp (or is it?) is that instead of using the calculation methods of the datasheet, they use a shortcut using bit shifting to approximate the exponent multiplication constant. This is probably to keep the data as a uint32_t instead of a float.

 

To get the exact data as the OPT3001EVM, I replaced the opt3001::readResult() function on 146 of OPT3001.cpp (and the prototype in OPT3001.h to a float) to:

 

float opt3001::readResult()
{
uint16_t exponent = 0;
float result = 0;
int16_t raw;
raw = readRegister(RESULT_REG);
 
/*Convert to LUX*/
//extract result & exponent data from raw readings
result = raw&0x0FFF;
exponent = (raw>>12)&0x000F;
 
//convert raw readings to LUX
switch(exponent){
case 0: //*0.015625
result = result*0.01;
break;
case 1: //*0.03125
result = result*0.02;
break;
case 2: //*0.0625
result = result*0.04;
break;
case 3: //*0.125
result = result*0.08;
break;
case 4: //*0.25
result = result*0.16;
break;
case 5: //*0.5
result = result*0.32;
break;
case 6:
result = result*0.64;
break;
case 7: //*2
result = result*1.28;
break;
case 8: //*4
result = result*2.56;
break;
case 9: //*8
result = result*5.12;
break;
case 10: //*16
result = result*10.24;
break;
case 11: //*32
result = result*20.48;
break;
default:
result = 0;
}
 
return result;
 
}

Share this post


Link to post
Share on other sites

Thanks for the clarification. I had also come to the realization that the bit shift was a shortcut that simplified coding, and in many cases wouldn't cause a problem with a board designed to show principles.

Share this post


Link to post
Share on other sites

I see I may need to further edit the algorthim for readResult(), since I want to see the decimal portion - my application is working in low light levels (between 0.05 and 0.5 lux).  So an integral result of 0 is a problem.  Ultimately, I won't really need the conversion as the intent is to set a range for the interrupts and change the state of my app based on the high/low interrupts.  But for now, I the serial output is handy for debugging.  So, back to the docs on page 20 calculating Lux.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×