Forum » Elektrotehnika in elektronika » 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:
OPT3001.h
OPT3001.cpp
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?
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?
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.
ki jo je prav v ta namen nosil s seboj.
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 ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | GPS modul NEO-6M GPS in Arduino NanoOddelek: Elektrotehnika in elektronika | 785 (728) | llc |
» | Kdo se spozna na ESP8266 in Arduino?Oddelek: Pomoč in nasveti | 2374 (1952) | chiiiii |
» | Arduino(slave) + ESP8266(master) preko I2CjaOddelek: Elektrotehnika in elektronika | 1011 (864) | teoo |
» | Pomoč C++Oddelek: Pomoč in nasveti | 1346 (1065) | samo111 |
» | Arduino in luči (strani: 1 2 )Oddelek: Elektrotehnika in elektronika | 12035 (9661) | FX6300B |