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 | 946 (889) | llc |
| » | Kdo se spozna na ESP8266 in Arduino?Oddelek: Pomoč in nasveti | 2805 (2383) | chiiiii |
| » | Arduino(slave) + ESP8266(master) preko I2CjaOddelek: Elektrotehnika in elektronika | 1177 (1030) | teoo |
| » | Pomoč C++Oddelek: Pomoč in nasveti | 1500 (1219) | samo111 |
| » | Arduino in luči (strani: 1 2 )Oddelek: Elektrotehnika in elektronika | 13096 (10722) | FX6300B |

