» »

Arduino, OPT3001 in čudni random rezultati

Arduino, OPT3001 in čudni random rezultati

stalker ::

Imam čuden problem: izdelal sem vezje, ki deluje, vendar občasno (najpogosteje ob nenadnih spremembah) meče ven neke čudne rezultate (pretvorjeno v luxe je to vrednost okoli 4000). I2C komunikacija (analogna pina 4 in 5 ter SCL in SDA dajeta iste rezultate, prav tako 100kHz in 400kHz), na arduino je povezano s kabli (najdaljši ima 10cm), INT pina ne uporabljam, senzor je priključen je na 3,3 V, pullup upori so 10k, kondenzator 100nF.

Main program:
#include <Wire.h>
#include "OPT3001.h"
//#define USE_USCI_B1

opt3001 opt3001;

void setup()
{
	unsigned int readings = 0;
	
	Serial.begin(115200);
	delay(1000);
	
	opt3001.begin();
	Serial.println("OPT3001 Initialized----------------------------------");
	// get manufacturer ID from OPT3001. Default = 0101010001001001
	readings = opt3001.readManufacturerId();
	Serial.print("Manufacturer ID: ");
	Serial.println(readings, BIN);
	// get device ID from OPT3001. Default = 0011000000000001
	readings = opt3001.readDeviceId();
	Serial.print("Device ID: ");
	Serial.println(readings, BIN);
	// read config register from OPT3001. Default = 1100110000010000
	readings = opt3001.readConfigReg();
	Serial.print("Configuration Register: ");
	Serial.println(readings, BIN);
	// read Low Limit register from OPT3001. Default = 0000000000000000
	readings = opt3001.readLowLimitReg();
	Serial.print("Low Limit Register: ");
	Serial.println(readings, BIN);
	// read High Limit register from OPT3001. Default = 1011111111111111
	readings = opt3001.readHighLimitReg();
	Serial.print("High Limit Register: ");
	Serial.println(readings, BIN);
	Serial.println("\nOPT3001 READINGS-------------------------------------");
}

void loop()
{
	// Variables
	uint16_t readings;
	
	// Read OPT3001
	readings = opt3001.readResult();
	
	Serial.print("LUX Readings = ");
	Serial.print(readings);
	Serial.print(" ");	
	Serial.println(readings, BIN);
	
	delay(800);
}


OPT3001.h
/*
  OPT3001.h
  Created by Adrian Fernandez, Dec 2013
  Modified by Dung Dang, Dec 2013
  Released into the public domain.
*/

#ifndef opt3001_h
#define opt3001_h
#define opt3001_h

#include <Arduino.h>
#include <Wire.h>

#define OPT_INTERRUPT_PIN 1  // Configuration based on Educational BoosterPack MK II
class opt3001
{
  public:
	void begin();
	uint32_t readResult();
	uint16_t readManufacturerId();
	uint16_t readDeviceId();
	uint16_t readConfigReg();
	uint16_t readLowLimitReg();
	uint16_t readHighLimitReg();
	uint16_t readRegister(uint8_t registerName);
	uint8_t	 interruptPin();
  private:
  
};

#endif


OPT3001.cpp
/*
  OPT3001.cpp
  Created by Adrian Fernandez & Dung Dang, Dec 2013
  
  Released into the public domain.
*/
#include "opt3001.h"
#define slaveAdr 0x44

#define RESULT_REG 0x00
#define CONFIG_REG 0x01
#define LOWLIMIT_REG 0x02
#define HIGHLIMIT_REG 0x03
#define MANUFACTUREID_REG 0x7E
#define DEVICEID_REG 0x7F

#define DEFAULT_CONFIG 0b1100110000010000 // 800ms
#define DEFAULT_CONFIG_100 0b1100010000010000 // 100ms
/* 	CONFIG REGISTER BITS: RN3 RN2 RN1 RN0 CT M1 M0 OVF CRF FH FL L Pol ME FC1 FC0
	RN3 to RN0 = Range select:
					1100 by default, enables auto-range 
	CT = Conversion time bit
					0 = 100ms conversion time
					1 = 800ms conversion time (default)
	M1 to M0 = Mode bits
					00 = Shutdown mode
					01 = Single shot mode
					10 = Continuous conversion (default)
					11 = Continuous conversion
	OVF (Bit 8)	? 	Overflow flag. When set the conversion result is overflown.
	CRF (Bit 7)	?	Conversion ready flag. Sets at end of conversion. Clears by read or write of the Configuration register.
	FH (Bit 6)	? 	Flag high bit. Read only. Sets when result is higher that TH register. Clears when Config register is 
					read or when Latch bit is ?0? and the result goes bellow TH register.
	FL (Bit 5)	? 	Flag low bit. Read only. Sets when result is lower that TL register. Clears when Config register is read 
					or when Latch bit is ?0? and the result goes above TL register.
	L (Bit 4) 	?	Latch bit. Read/write bit. Default ?1?, Controls Latch/transparent functionality of FH and FL bits. When 
					L = 1 the Alert pin works in window comparator mode with Latched functionality When L = 0 the Alert pin 
					works in transparent mode and the two limit registers provide the hysteresis.
	Pol (Bit 3)	?	Polarity. Read/write bit. Default ?0?, Controls the active state of the Alert pin. Pol = 0 means Alert 
					active low.
	ME (Bit 2)	?	Exponent mask. In fixed range modes masks the exponent bits in the result register to ?0000?.
	FC1 to FC0	-	Fault count bits. Read/write bits. Default ?00? - the first fault will trigger the alert pin.
*/


void opt3001::begin()
{
	uint16_t writeByte = DEFAULT_CONFIG;
	// Initialize Wire

	// Use I2C module 1 (I2C1SDA & I2C1SCL per BoosterPack standard) and begin
	


	Wire.begin();
	

	
    /* Begin Tranmission at address of device on bus */
	Wire.beginTransmission(slaveAdr);
	/* Send Pointer Register Byte */
	
	Wire.write(CONFIG_REG);

	/* Read*/
	Wire.write((unsigned char)(writeByte>>8));
	Wire.write((unsigned char)(writeByte&0x00FF));

	/* Sends Stop */
	Serial.println("before ending transmission");
	Wire.endTransmission();
	Serial.println("return to life");
	return;
}

uint16_t opt3001::readRegister(uint8_t registerName)
{
	int8_t lsb;
	int8_t msb;
	int16_t result;


	// Initialize Wire
	Wire.begin();

	/* Begin Transmission at address of device on bus */
	Wire.beginTransmission(slaveAdr);

	/* Send Pointer to register you want to read */
	Wire.write(registerName);

	/* Sends Stop */
	Wire.endTransmission(true);

	/* Requests 2 bytes from Slave */
	Wire.requestFrom(slaveAdr, 2);

	/* Wait Until 2 Bytes are Ready*/
	while(Wire.available() < 2)	{}

	/* Read*/
	msb = Wire.read();
	lsb = Wire.read();
	result = (msb << 8) | lsb;

	return result;
}


uint16_t opt3001::readManufacturerId()
{

	return readRegister(MANUFACTUREID_REG);
	
}

uint16_t opt3001::readDeviceId()
{
	return readRegister(DEVICEID_REG);
		
}

uint16_t opt3001::readConfigReg()
{
	return readRegister(CONFIG_REG);
}

uint16_t opt3001::readLowLimitReg()
{
	return readRegister(LOWLIMIT_REG);
	
	
}

uint16_t opt3001::readHighLimitReg()
{
	return readRegister(HIGHLIMIT_REG);
}


uint32_t opt3001::readResult()
{
	uint16_t exponent = 0;
	uint32_t result = 0;
	int32_t raw=0;
	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>>6;
			break;
		case 1: //*0.03125
			result = result>>5;
			break;
		case 2: //*0.0625
			result = result>>4;
			break;
		case 3: //*0.125
			result = result>>3;
			break;
		case 4: //*0.25
			result = result>>2;
			break;
		case 5: //*0.5
			result = result>>1;
			break;
		case 6:
			result = result;
			break;
		case 7: //*2
			result = result<<1;
			break;
		case 8: //*4
			result = result<<2;
			break;
		case 9: //*8
			result = result<<3;
			break;
		case 10: //*16
			result = result<<4;
			break;
		case 11: //*32
			result = result<<5;
			break;
	}
	return result;	
}

uint8_t opt3001::interruptPin()
{
	return (digitalRead(OPT_INTERRUPT_PIN)==0?1:0);
}


S konverzijo v luxe ni nič narobe, ker so že nekateri rezultati, izpisani direkt iz registra, čudni.
Kaj bi lahko bilo narobe? Komunikacija? Pokvarjen čip?

 od 17 do 40 je normalno, ne vem od kje pobere 4k?

od 17 do 40 je normalno, ne vem od kje pobere 4k?


 42 je ok, ostalo wtf?

42 je ok, ostalo wtf?

TESKAn ::

Hm, videt je, kot da te eksponent heca? Izpisi si celoten rezultat (vseh 16 bitov), bos hitro videl, ce te tam kaj heca.
Uf! Uf! Je rekel Vinetou in se skril za skalo,
ki jo je prav v ta namen nosil s seboj.

mihaelf3 ::

V loop() imas
uint16_t readings;

opt3001::readResult() pa vrne uint32_t.
torch it

stalker ::

Mislim, da sem pogruntal, kje je napaka. MSB in LSB sta bila napačno deklarirana, int8_t sem spremenil v int16_t. Prej je občasno LSB vrgel ven 32 bitno število, sedaj pa ne več. Program sem posplošil in zgleda, da bo ok.
#include <Wire.h>

void setup()
{
  Serial.begin(9600);
  delay(1000);
  
  Wire.begin();
  Wire.beginTransmission(0x44);
  Wire.write(0x01);
  Wire.endTransmission();
}

void loop()
{
  //int raw=0;
  int16_t lsb;
  int16_t msb;
  int16_t result;
  
  Wire.begin();
  Wire.beginTransmission(0x44);
  Wire.write(0x00);
  Wire.endTransmission(true);
  
  Wire.requestFrom(0x44, 2);
  while(Wire.available() < 2)	{}
  msb = Wire.read();
  lsb = Wire.read();
  result = (msb << 8) | lsb;
  Serial.print("msb ");
  Serial.println(msb, BIN);
  Serial.print("lsb ");
  Serial.println(lsb, BIN);
  Serial.print("RESULT ");
  Serial.println(result,BIN);
  delay(1000);
}

stalker ::

Zdaj dela pravilno. Napaka je bila, ker sem uporabljal predznačene spremenljivke. Prilagam še program, če ga bo kdo kdaj potreboval.
#include <Wire.h>

void setup()
{
  Serial.begin(9600);
  delay(1000);
  
  Wire.begin();
  Wire.beginTransmission(0x44);
  Wire.write(0x01);
  Wire.write(0xC410);
  Wire.endTransmission();
}

void loop()
{
  uint16_t lsb;
  uint16_t msb;
  uint16_t result;
  uint16_t register_result;
  int eksponent;
  
  double lux;
  
  Wire.begin();
  Wire.beginTransmission(0x44);
  Wire.write(0x00);  
  Wire.endTransmission(true);
  
  Wire.requestFrom(0x44, 2);
  while(Wire.available() < 2)	{}
  msb = Wire.read();
  lsb = Wire.read();
  result = (msb << 8) | lsb;
  
  register_result=result;
  
  eksponent=result>>12;
  result=result&0x0FFF;
  
  lux=0.01*pow(2,eksponent)*result;
  
  Serial.print("msb ");
  Serial.println(msb, BIN);
  Serial.print("lsb ");
  Serial.println(lsb, BIN);
  Serial.print("REGISTER ");
  Serial.println(register_result,BIN);
  Serial.print("RESULT ");
  Serial.println(result,BIN);  
  Serial.print("eksponent ");
  Serial.println(eksponent,BIN);  
  Serial.print("LUX ");
  Serial.println(lux,DEC);
  Serial.println(" ");
  delay(1000);
}


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

GPS modul NEO-6M GPS in Arduino Nano

Oddelek: Elektrotehnika in elektronika
7695 (638) llc
»

Kdo se spozna na ESP8266 in Arduino?

Oddelek: Pomoč in nasveti
182106 (1684) chiiiii
»

Arduino(slave) + ESP8266(master) preko I2Cja

Oddelek: Elektrotehnika in elektronika
10929 (782) teoo
»

Pomoč C++

Oddelek: Pomoč in nasveti
71266 (985) samo111
»

Arduino in luči (strani: 1 2 )

Oddelek: Elektrotehnika in elektronika
9811396 (9022) FX6300B

Več podobnih tem