stevemarple / SoftWire

Software I2C implementation for Arduino and other Wiring-type environments
GNU Lesser General Public License v2.1
136 stars 31 forks source link

SoftWire and AS7262/3 library #7

Closed vangalvin closed 3 years ago

vangalvin commented 6 years ago

Awesome work on the SoftWire library.

The AS7262 and AS7263 sensors both have the same address making it a little awkward to add both in to the one project. They both use the Wire library and I was hoping to be able to use the SoftWire library instead however not sure how to set it up for this.

In the AS726X library they use the wire lib in the flowing way. I have truncated the bits that are not related to the I2C.

Do you think there is any way to replace the way the code uses Wire with SoftWire?

[AS7261.cpp] `#include "AS7261.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) { _i2cPort = &wirePort; _i2cPort->begin(); Serial.begin(115200); } //Does a soft reset //Give sensor at least 1000ms to reset void AS726X::softReset() { //Read, mask/set, write byte value = virtualReadRegister(AS726x_CONTROL_SETUP); //Read value |= (1 << 7); //Set RST bit virtualWriteRegister(AS726x_CONTROL_SETUP, value); //Write }

//Read a virtual register from the AS726x byte AS726X::virtualReadRegister(byte virtualAddr) { byte status;

//Do a prelim check of the read register status = readRegister(AS72XX_SLAVE_STATUS_REG); if ((status & AS72XX_SLAVE_RX_VALID) != 0) //There is data to be read { //Serial.println("Premptive read"); byte incoming = readRegister(AS72XX_SLAVE_READ_REG); //Read the byte but do nothing with it }

//Wait for WRITE flag to clear while (1) { status = readRegister(AS72XX_SLAVE_STATUS_REG); if ((status & AS72XX_SLAVE_TX_VALID) == 0) break; // If TX bit is clear, it is ok to write delay(POLLING_DELAY); }

// Send the virtual register address (bit 7 should be 0 to indicate we are reading a register). writeRegister(AS72XX_SLAVE_WRITE_REG, virtualAddr);

//Wait for READ flag to be set while (1) { status = readRegister(AS72XX_SLAVE_STATUS_REG); if ((status & AS72XX_SLAVE_RX_VALID) != 0) break; // Read data is ready. delay(POLLING_DELAY); }

byte incoming = readRegister(AS72XX_SLAVE_READ_REG); return (incoming); }

//Write to a virtual register in the AS726x void AS726X::virtualWriteRegister(byte virtualAddr, byte dataToWrite) { byte status;

//Wait for WRITE register to be empty while (1) { status = readRegister(AS72XX_SLAVE_STATUS_REG); if ((status & AS72XX_SLAVE_TX_VALID) == 0) break; // No inbound TX pending at slave. Okay to write now. delay(POLLING_DELAY); }

// Send the virtual register address (setting bit 7 to indicate we are writing to a register). writeRegister(AS72XX_SLAVE_WRITE_REG, (virtualAddr | 0x80));

//Wait for WRITE register to be empty while (1) { status = readRegister(AS72XX_SLAVE_STATUS_REG); if ((status & AS72XX_SLAVE_TX_VALID) == 0) break; // No inbound TX pending at slave. Okay to write now. delay(POLLING_DELAY); }

// Send the data to complete the operation. writeRegister(AS72XX_SLAVE_WRITE_REG, dataToWrite); }

//Reads from a give location from the AS726x byte AS726X::readRegister(byte addr) { _i2cPort->beginTransmission(AS726X_ADDR); _i2cPort->write(addr); _i2cPort->endTransmission();

_i2cPort->requestFrom(AS726X_ADDR, 1); if (_i2cPort->available()) { return (_i2cPort->read()); } else { Serial.println("I2C Error"); return (0xFF); //Error } }

//Write a value to a spot in the AS726x void AS726X::writeRegister(byte addr, byte val) { _i2cPort->beginTransmission(AS726X_ADDR); _i2cPort->write(addr); _i2cPort->write(val); _i2cPort->endTransmission(); } `

[AS7261.h] `#ifndef _AS7261_h

define _AS7261_h

include "Arduino.h"

include "Wire.h"

class AS726X { public: AS726X(); void begin(TwoWire &wirePort = Wire, byte gain = 3, byte measurementMode = 3); private: TwoWire *_i2cPort; };`

stevemarple commented 6 years ago

Earlier this month I made some changes to SoftWire so that it has the same interface as the TwoWire class. This was to enable my HIH61xx library to work with both SoftWire and Wire. The changes you wish to make should be fairly straightforward to do. I suggest you have a look at the HIH61xx_Wire_simple_demo and HIH61xx_SoftWire_simple_demo examples to see the slight differences between using Wire and SoftWire. Note also the requirement to define you own buffers for SoftWire. You can then use the HIH61xx library as an example of how to template the AS726X library so that it works with both Wire and SoftWire. All the class functions should be declared and defined in the header file so that the compiler is able to instantiate the classes you use (the linker will remove duplicates).

Remember that the Arduino IDE likes to make its own function prototypes, and it will get confused if the template class <T> part is not on the same line as the rest of the function declaration or definition.

vangalvin commented 6 years ago

Thanks @stevemarple Im having a look at it and managing to confuse myself quite nicely :) The library I cut and pasted the excerpt from was the sensor library from Sparkfun

I see how the HIH61xx sensor works (i think) and the communications with the ship seem prety simple, the AS726X has a ton of registers that need to be written to for setup as well as interrogated to get the data out.

initially for my project I had hoped to use a single sensor but what I am trying to do is identify asbestos on my worksites, currently we look at it and do a best guess and in order to do that often we have to break a bit off. Not the best method as once you to that the particles can become airborne.

vicber commented 5 years ago

hi @vangalvin, have you figured out your problem of "i2c error"? I kind of the similar issue like you, using the same 3rd party library for AS7262 and got the Serial.print("I2C error") as well. I've tried to make sure that my hardware having 0 connecting issues, and wondering if there is any modification has to be done when using this sparkfun library? Thanks!

vangalvin commented 5 years ago

@vicber not as yet, I have had to put the project on hold for a while as some other work has come up. Hopping to get back to it in the not so distant future. I did however purchase an I2C interface chip that allows multiple devices with the same address to co-exist.

kevinunger commented 5 years ago

Have you solved the problem? I'm getting the same 'I2C Error' and can't figure it out.

chepo92 commented 5 years ago

I have made some changes to AS7262 library so you can use softwire. https://github.com/chepo92/Adafruit_AS726x/tree/Softwire