lettura sensore AS7263

Ciao
Sto litigando con un AS7263 della Sparkfun:

ho letto datasheet, le relative librerie ma ci sono cose che non comprendo.
Nel datasheet si parla di registri virtuali per lettura e scrittura, trovo queste indicazioni nelle librerie, ma non capisco come funzionano.
Nelle librerie vedo che uno stesso indirizzoviene attribuito a due variabili diverse.

Per esempio:

#define AS726x_DEVICE_TYPE 0x00
#define AS726x_HW_VERSION 0x01
#define AS726x_CONTROL_SETUP 0x04
#define AS726x_INT_T 0x05
#define AS726x_DEVICE_TEMP 0x06
#define AS726x_LED_CONTROL 0x07

#define AS72XX_SLAVE_STATUS_REG 0x00
#define AS72XX_SLAVE_WRITE_REG 0x01

Questo lo sketch:

/*
  This is a library written for the AS726X Spectral Sensor (Visible or IR) with I2C firmware
  specially loaded. SparkFun sells these at its website: www.sparkfun.com

  Written by Nathan Seidle & Andrew England @ SparkFun Electronics, July 12th, 2017

  https://github.com/sparkfun/Qwiic_Spectral_Sensor_AS726X

  Do you like this library? Help support SparkFun. Buy a board!

  Development environment specifics:
  Arduino IDE 1.8.1

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "AS726X.h"
AS726X sensor;//Creates the sensor object

byte GAIN = 2;
byte MEASUREMENT_MODE = 0;

void setup() {
  sensor.begin(Wire, GAIN, MEASUREMENT_MODE);
}

void loop() {
  sensor.takeMeasurementsWithBulb();
  sensor.printMeasurements();
}

AS726X.cpp (14.3 KB)

AS726X.h (3.21 KB)

Letto alcuni post su Saprkfun, sembra che ci siano errori nelle librerie.
Ma non è possibile leggere senza passare dalle librerie?

Cerco un esperto nella lettura dei registri di un sensore AS7263 tramite I2C

Scusa ma che problemi hai? Studia il datasheet, guarda dove sono i vari registri (... nel datasheet c'è anche un piccolo esempio in 'C'), al limite guarda anche quello che fanno le librerie Sparkfun e usa la libreria wire per fare quello che ti pare :slight_smile:

Guglielmo

Ciao
Ho letto il datasheet, ho già fatto qualcosa con sensori che usano quel protocollo, mi sono fatto uno sketch apposta per la sola lettura dei registri.

Ammetto che la mia formazione è altra e forse mi sto cimentando con qualcosa che va oltre le mie capacità.

Dalla lettura del datasheet parla di registri virtuali ed è questa la parte che non capisco, vedo anche che uno stesso valore di registro viene attribuito a due variabili diverse

#define I2C_AS72XX_SLAVE_STATUS_REG0x00
#define I2C_AS72XX_SLAVE_WRITE_REG0x01
#define I2C_AS72XX_SLAVE_READ_REG0x02
#define I2C_AS72XX_SLAVE_TX_VALID0x02
#define I2C_AS72XX_SLAVE_RX_VALID0x01

Mi sono studiato anche le librerie ma anche li parla di letture e scritture virtuali, che sto rileggendo per capire

Altro punto, io vorrei leggere e scrivere saltando le librerie, che sono per me talvolta complicate, usando solo il WIRE

I²C Slave Interface
If selected by the I2C_ENB pin setting, interface and control can
be accomplished through an I²C compatible slave interface to
a set of registers that provide access to device control functions
and output data. These registers on the AS7263 are, in reality,
implemented as virtual registers in software. The actual I²C slave
hardware registers number only three and are described in the
table below. The steps necessary to access the virtual registers
defined in the following are explained in pseudocode for external
I²C master writes and reads below.

In quanto allo pseudo codice non lo ho compreso.

Non sapendo più cosa fare cercavo una persona che fosse esperta.

qualcuno mi può dire dove sbaglio?

Arduino:1.8.5 (Windows 10), Scheda:"Arduino/Genuino Uno"

C:\Users\stefano\AppData\Local\Temp\cci1XNMV.ltrans0.ltrans.o: In function `loop':

D:\Arduino sketches\AS7263_BasicReadings/AS7263_BasicReadings.ino:97: undefined reference to `getCalibratedR()'

collect2.exe: error: ld returned 1 exit status

exit status 1
Errore durante la compilazione per la scheda Arduino/Genuino Uno.

Questo report potrebbe essere più ricco di informazioni abilitando l'opzione
"Mostra un output dettagliato durante la compilazione"
in "File -> Impostazioni"

questo è lo sketch:

/*
  This is a library written for the AS726X Spectral Sensor (Visible or IR) with I2C firmware
  specially loaded. SparkFun sells these at its website: www.sparkfun.com

  Written by Nathan Seidle & Andrew England @ SparkFun Electronics, July 12th, 2017

  https://github.com/sparkfun/Qwiic_Spectral_Sensor_AS726X

  Do you like this library? Help support SparkFun. Buy a board!

  Development environment specifics:
  Arduino IDE 1.8.1

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.


  ---AVAILABLE FUNCTIONS---
  AS726X(TwoWire &wirePort = Wire, byte gain = 3, byte measurementMode = 3);
  void takeMeasurements();
  void takeMeasurementsWithBulb();
  void printMeasurements();
  byte getTemperature();
  float getTemperatureF();
  void setMeasurementMode(byte mode);
  boolean dataAvailable();
  void enableIndicator();
  void disableIndicator();
  void setIndicatorCurrent(byte current);
  void enableBulb();
  void disableBulb();
  void setBulbCurrent(byte current);
  void softReset();
  void setGain(byte gain);
  void setIntegrationTime(byte integrationValue);
  void enableInterrupt();
  void disableInterrupt();

  //Get the various color readings
  int getViolet();
  int getBlue();
  int getGreen();
  int getYellow();
  int getOrange();
  int getRed();

  //Get the various NIR readings
  int getR();
  int getS();
  int getT();
  int getU();
  int getV();
  int getW();

  //Returns the various calibration data
  float getCalibratedViolet();
  float getCalibratedBlue();
  float getCalibratedGreen();
  float getCalibratedYellow();
  float getCalibratedOrange();
  float getCalibratedRed();

  float getCalibratedR();
  float getCalibratedS();
  float getCalibratedT();
  float getCalibratedU();
  float getCalibratedV();
  float getCalibratedW();
*/

#include "AS726X.h"
AS726X sensor; 
 
  float getCalibratedR();
  float getCalibratedS();
  float getCalibratedT();
  float getCalibratedU();
  float getCalibratedV();
  float getCalibratedW();
  
byte GAIN = 3;
byte MEASUREMENT_MODE = 3;

void setup() {
  sensor.begin(Wire, GAIN, MEASUREMENT_MODE);
}

void loop() {
  sensor.takeMeasurements();
  sensor.printMeasurements();
 
 Serial.println(getCalibratedR(),2); 
}

ho aggiunto solo i FLOAT e il SERIAL

keywords.txt (2.67 KB)

perchè scrivi i prototipi delle funzioni della libreria qui?
mi sa che così le sovrascrivi

dai un occhiata al primo esempio della libreria...

#include "AS726X.h"
AS726X sensor;
 
  float getCalibratedR();
  float getCalibratedS();
  float getCalibratedT();
  float getCalibratedU();
  float getCalibratedV();
  float getCalibratedW();

ho eliminato i FLOAT ma non passa la verifica:

Arduino:1.8.5 (Windows 10), Scheda:"Arduino/Genuino Uno"

D:\Arduino sketches\AS7263_BasicReadings\AS7263_BasicReadings.ino: In function 'void loop()':

AS7263_BasicReadings:90: error: 'getCalibratedR' was not declared in this scope

  Serial.println(getCalibratedR()); 

                                ^

exit status 1
'getCalibratedR' was not declared in this scope

Questo report potrebbe essere più ricco di informazioni abilitando l'opzione
"Mostra un output dettagliato durante la compilazione"
in "File -> Impostazioni"

ok ho provato a compilarlo e in effetti non compila in quanto mi da il tuo errore :smiley:
poi l'ho guardato...

void loop() {
  sensor.takeMeasurements();
  sensor.printMeasurements();
 
 Serial.println(getCalibratedR(),2);
}

e mi sono chiesto....
ma se takeMeasurements() è una funzione/metodo di sensor
e se printMeasurements() anche è un metodo di sensor...

perchè getCalibratedR() deve essere figlio di nessuno? :wink:

p.s.
spero che tu abbia eliminato tutte le righe non solo la parola float :slight_smile:

ok capito
che ignorante.
Grazie

no, è una svista che può succedere soprattutto se ti sei concentrato su altro :slight_smile:

la mia comunque non voleva essere una presa in giro :slight_smile:

Ciao

la mia comunque non voleva essere una presa in giro :)

mai pensato credimi
Grazie ancora
Sei pratico con I2C?

si, no, dipende :slight_smile: tu chiedi e se non lo so io, qualcun'altro si farà sicuramente avanti :wink:

Grazie
Ho modificato lo sketch in questo modo:

#include <AS726X.h>
AS726X sensor;

byte SetBulbCurrent(0);
/*
   Sets the current limit on the indicator LED and optional bulb (They are connected in parallel) The default is current = 0 or 12.5 mA.
  0: 12.5 mA
  1: 25 mA
  2: 50 mA
  3: 100 mA
*/

byte MEASUREMENT_MODE = 3;
/*
  0: Continuous reading of VBGY (Visible) / STUV (IR)
  1: Continuous reading of GYOR (Visible) / RTUX (IR)
  2: Continuous reading of all channels
  3: One-shot reading of all channels (power-on default)
*/

byte GAIN = 0;
/*
  Pass in a 0, 1, 2 or 3 to change the gain.
  0: 1x
  1: 3.7x
  2: 16x
  3: 64x (power-on default)
*/

byte I_Time = 50; //50*2.8ms < 255, 90 max I_Time value
/*
  This sets the time over which samples are taken.
  Takes a value between 0 and 255.
  Integration time will be 2.8 ms * integrationValue
*/


void setup() {
  sensor.begin(Wire, GAIN, MEASUREMENT_MODE, SetBulbCurrent, I_Time);
}

void loop() {
  sensor.takeMeasurementsWithBulb();
  //  sensor.printMeasurements();

  Serial.print(sensor.getCalibratedR());
  Serial.print(",");
  Serial.print(sensor.getCalibratedS());
  Serial.print(",");
  Serial.print(sensor.getCalibratedT());
  Serial.print(",");
  Serial.print(sensor.getCalibratedU());
  Serial.print(",");
  Serial.print(sensor.getCalibratedV());
  Serial.print(",");
  Serial.println(sensor.getCalibratedW());
}

e le librerie di conseguenza:
.cpp

#include "AS726X.h"
#include "Arduino.h"
//Sets up the sensor for constant read
//Returns the sensor version (AS7262 or AS7263)

AS726X::AS726X()
{
 
}

void AS726X::begin(TwoWire &wirePort, byte gain, byte measurementMode, byte SetBulbCurrent, byte I_Time)
{
 _i2cPort = &wirePort;
 _i2cPort->begin();
 Serial.begin(115200);
 _sensorVersion = virtualReadRegister(AS726x_HW_VERSION);
 if (_sensorVersion != 0x3E && _sensorVersion != 0x3F) //HW version for AS7262 and AS7263
 {
 Serial.print("ID (should be 0x3E or 0x3F): 0x");
 Serial.println(_sensorVersion, HEX);
 }

 setBulbCurrent(SetBulbCurrent); //Set to 0b00 12.5mA (minimum)
 disableBulb(); //Turn off to avoid heating the sensor

 setIndicatorCurrent(0b11); //Set to 8mA (maximum)
 disableIndicator(); //Turn off lights to save power

 setIntegrationTime(I_Time); //I_Time * 2.8ms, 50 * 2 .8ms = 140ms. 0 to 255 is valid.
 //If you use Mode 2 or 3 (all the colors) then integration time is double. 140*2 = 280ms between readings.

 setGain(gain); //Set gain to 64x

 setMeasurementMode(measurementMode); //One-shot reading of VBGYOR
...

.h

/*
 Name: AS726X.h
 Created: 7/11/2017 12:06:22 PM
 Author: andrew.england
 Editor: http://www.visualmicro.com
*/

#ifndef _AS726X_h
#define _AS726X_h
#include "Arduino.h"
#include "Wire.h"
class AS726X {
public:
 AS726X();
 //void begin(TwoWire &wirePort = Wire, byte gain = 3, //byte measurementMode = 3);
void begin(TwoWire &wirePort = Wire, byte gain = 3, byte measurementMode = 3, byte SetBulbCurrent = 0, byte I_Time = 50);
...

ma ho un dubbio, ho dovuto impostare dei valori nella .h, questi li posso cambiare a piacere dallo sketch per come lo ho modificato, oppure la .cpp prende sempre questi e di conseguenza lo sketch?

non ho capito nulla :slight_smile:

cioè non ho capito perchè hai dovuto modificare la libreria e quali modifiche hai fatto?

in ogni caso se ti funziona ... ok

però se modifichi la libreria probabilmente se in futuro verrà aggiornata perderai le tue modifiche

detto questo...
nella begin standard del cpp la setbulbcurrent viene impostata a 12,5 mA cioè il minimo
ma tu puoi richiamare la funzione setBulbCurrent() con il tuo valore che vuoi, ed è una funzione che gia esiste

void AS726X::setBulbCurrent(byte current)
{
	if (current > 0b11) current = 0b11; //Limit to two bits

										//Read, mask/set, write
	byte value = virtualReadRegister(AS726x_LED_CONTROL); //Read
	value &= 0b11001111; //Clear ICL_DRV bits
	value |= (current << 4); //Set ICL_DRV bits with user's choice
	virtualWriteRegister(AS726x_LED_CONTROL, value); //Write
}

idem per setIntegrationTime()

//Sets the integration value
//Give this function a byte from 0 to 255.
//Time will be 2.8ms * [integration value]
void AS726X::setIntegrationTime(byte integrationValue)
{
	virtualWriteRegister(AS726x_INT_T, integrationValue); //Write
}

quindi non vedo la necessità di fare queste modifiche per mettere i valori fissi nella begin...

Ciao
Sono partito da questo esempio fornito con le librerie:

#include "AS726X.h"
AS726X sensor;//Creates the sensor object
byte GAIN = 0;
byte MEASUREMENT_MODE = 0;

void setup() {
  sensor.begin(Wire, GAIN, MEASUREMENT_MODE);//Initializes the sensor with non default values
}

void loop() {
  sensor.takeMeasurements();
  sensor.printMeasurements();
}

dove si passano i valori di:

 GAIN e MEASUREMENT_MODE //Initializes the sensor with non default values

ho voluto aggiungere anche

setBulbCurrent(SetBulbCurrent)
e
IntegrationTime(I_Time)

prima erano di default nella libreria.
La mia domanda è se i valori che ho dovuto attribuire nella libreria .h (altrimenti non compilava) in questa posizione:

void begin(TwoWire &wirePort = Wire, byte gain = 3, byte measurementMode = 3, byte SetBulbCurrent = 0, byte I_Time = 50);

vengono sovrascritti da quelli che arrivano dallo sketch

ho fatto prove e sembra che i valori vengono aggiornati con quelli che passa lo sketch

mi ripeto :slight_smile:
i valori erano di default nella libreria per quanto riguarda il metodo begin!

cioè quando tu inizializzi il sensore il begin assegna dei valori predefiniti a setBulbCurrent che è 12,5mA e a IntegrationTime, che non mi ricordo quanto era.

in ogni caso

una volta fatto il begin

Tu puoi modificare sempre e in qualsiasi momento il valore di entrambi

come? ? ??

chiamando i metodi:

setBulbCurrent(byte current)
setIntegrationTime(byte integrationValue)

nel tuo caso:
sensor.setBulbCurrent(NuovoValoreDiCorrente) // valore tra 0 e 255

e chiamando il metodo:
sempre nel tuo caso
sensor.setIntegrationTime(NuovoValoreDiIntegrationTime) // valore tra 0 e 255

questi 2 comandi li puoi usare dove vuoi e quante volte vuoi all'interno del tuo programma

quindi, per questo motivo....

non ti serve modificare la libreria!

:grin: :grin:

Ciao
Grazie per le risposte
Provo a spiegare in modo differente per essere sicuro di avere capito.
Nella libreria originale ho questo:

void begin(TwoWire &wirePort = Wire, byte gain = 3, byte measurementMode = 3);

e questo nella .cpp sempre prima delle modifiche:

setBulbCurrent( 0b00); //Set to 0b00 12.5mA (minimum)
setIntegrationTime(50); //50 * 2 .8ms = 140ms. 0 to 255 is valid

Due domande
mi confermi che se anche non sono nel void begin... li posso cambiare?
Se si perchè ho gain e measurementMode nel void begin?

nel void Setup() dello sketch posso quindi fare questo:

sensor.setGain(byte gain);
sensor.setBulbCurrent(byte current);
sensor.setMeasurementMode(byte mode);
sensor.setIntegrationTime(byte integrationValue);