stevemarple / softwire Goto Github PK
View Code? Open in Web Editor NEWSoftware I2C implementation for Arduino and other Wiring-type environments
License: GNU Lesser General Public License v2.1
Software I2C implementation for Arduino and other Wiring-type environments
License: GNU Lesser General Public License v2.1
I suppose this is a find-replace issue? or are the double 'set' words intentional?
There is a small bug in the example for DS1307 while getting the hour.
Here is the fix: tenHour = (registers[2] & 0x30) >> 4;
I'm trying to use this SoftWire with stm32duino link. The library compiles fine and the example ListDevices.ino is working. However, the read() function seems to be broken on stm32 as it returns incorrect values. Any ideas how to get this library to work with stm32duino?
Hi Steve,
I'm using a MLX90614 connected to ESP32-C3 super micro board with Arduino-IDE 2.3.2. So I tried your example "SoftWire_MLX90614", but no success. I found following problems in your example :
While I had the problems above, I saw that you created a library for the MLX90614. So I installed it and tried example MLX90614_demo. But I got compilation error :
".....src\ MLX90614.cpp: In member function 'bool MLX90614::read(uint8_t, uint16_t&) const':
d:\Program Files (x86)\Arduino\neue_Libraries\libraries\MLX90614\src\MLX90614.cpp:154:24: error: passing 'const SoftWire' as 'this' argument discards qualifiers [-fpermissive]
i2c.write(command) || // Command sent"
I didn't check further for that because I'm using SoftWire with the problem solutions above.
I hope my comments can help others with the same problems.
Thank you Steve for SoftWire, it runs really fine in my project now.
Hi, thank you for the great work. I was trying to read the data with a restart condition like this.
uint8_t readByte(uint8_t address, uint8_t subAddress, SoftWire& wire) {
wire.beginTransmission(address);
wire.write(subAddress);
wire.endTransmission(false);
wire.requestFrom(address, (size_t)1);
uint8_t data = 0;
if (wire.available()) data = wire.read();
return data;
}
A correct transaction with the Wire
library looks like this.
But it seems that a restart condition is not issued with SoftWire
. The hardware setup and code are exactly the same except for the use of SoftWire
instead of Wire
.
I've forced to use repeatedStart
instead of start
in Line 449 of SoftWire.h
. Then I could issue a restart condition but the data was not correct.
Do you have any idea to work around this issue?
Hi
Couple of question if I may. 1.Is there any tested working softwire or softi2c lib for esp32 to control 16x2 liquid crystal lcd?
2.If it runs , will the original two i2c channels still work with other devices? (i already using twowire library to control 2 sensors, and normal i2c to control another 2sensors. I don't want any signal to mingle with the lcd so I look for alternative).
Thanks for any attention. Rich J.
I don't have the source code anymore sadly, and I am kind of scared to repreduce the results on another board.
The code was very simple, though. It was something like that:
#include "SoftWire.h"
SoftWire Wire2(4, 5);
void setup()
{
Wire2.begin();
Wire2.setClock(0);
}
void loop()
{}
I'm not sure if I called setClock(0)
before or after the begin()
call.
I'm pretty sure that's what broke it because the parameter 0
in the setClock(0)
function is the only value I changed before and after compiling and uploading.
If it's not only my hardware that's at risk, maybe it would be a good idea to prevent users from setting the clock to 0Hz, or to negative numbers (assuming that's even possible).
Hello,
¿Why does the library have a lower bound to the I2C frequency? It seems that the lowest frequency allowed by setClock is 1961 Hz. ¿Whats the reasoning behind this?
Nice library btw.
Hi Steve, sorry posted this in the wrong place... please ignore.
Problem:
I use mpu6050 sensor and raspberry pie Pico development board. I can make sure the wiring is correct. However, the same code can run on Arduino uno and esp32, and can correctly read mpu6050 data. After the raspberry pie Pico runs, it cannot correctly read data.(Raspberry pie enables Pico to read normally using hardware IIC.)
arduino for rp2040:
https://github.com/earlephilhower/arduino-pico
Picture:
Raspberry pie Pico failed to read with software IIC:
Arduino uno successfully read with software IIC:
Code:
#include <SoftWire.h>
SoftWire Wire(12, 13); // Raspberry pie Pico(SDA=12,SCL=13) ,ARDUINO UNO(SDA=2,SCL=3)
const int MPU6050_addr = 0x68;
int16_t AccX, AccY, AccZ, Temp, GyroX, GyroY, GyroZ;
uint8_t swTxBuffer[32];
uint8_t swRxBuffer[32];
void setup() {
Wire.setTxBuffer(swTxBuffer, sizeof(swTxBuffer));
Wire.setRxBuffer(swRxBuffer, sizeof(swRxBuffer));
Wire.begin();
Wire.beginTransmission(MPU6050_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
Serial.begin(9600);
}
void loop() {
Wire.beginTransmission(MPU6050_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU6050_addr, 14, true);
AccX = Wire.read() << 8 | Wire.read();
AccY = Wire.read() << 8 | Wire.read();
AccZ = Wire.read() << 8 | Wire.read();
Temp = Wire.read() << 8 | Wire.read();
GyroX = Wire.read() << 8 | Wire.read();
GyroY = Wire.read() << 8 | Wire.read();
GyroZ = Wire.read() << 8 | Wire.read();
Serial.print("AccX = ");
Serial.print(AccX);
Serial.print(" || AccY = ");
Serial.print(AccY);
Serial.print(" || AccZ = ");
Serial.print(AccZ);
Serial.print(" || GyroX = ");
Serial.print(GyroX);
Serial.print(" || GyroY = ");
Serial.print(GyroY);
Serial.print(" || GyroZ = ");
Serial.print(GyroZ);
Serial.print(" || Temp = ");
Serial.println(Temp / 340.00 + 36.53);
delay(500);
}
Hi, does this library support the onRequest function from the Arduino Wire library?
https://www.arduino.cc/reference/en/language/functions/communication/wire/onrequest/
There is a Wiring library that is referenced for a specific board (Adafruit PCA 9685) I am trying to use, http://wiring.org.co/reference/libraries/Wire/index.html
Will SoftWire act as a replacement for that library? That is, assuming I change a few minor lines within that library, such as Wire.h --> SoftWire.h. That library is a pain because it does not easily import into the Arduino native environment, instead the "library" actually implements its own IDE on top of the Arduino IDE.
Where does this particular library come from?
#include <DisableJTAG.h>
Hi,
I'm tring to use SoftWire to connect to BME280 on a heltec wifi kit32.
If I use soft SDA SCL (GPIO_4,GPIO_15) respectivley it works fine. (note the I2C OLED diplay is connected to 4,15
When I move the BME280 to two other GPIO's (21,21) it work fine until i call the SDD1306 lib display.init() command.
This appaers to set the SoftWire pins back to (4,15)
Does this mean I cant use SDD1306 and SoftWire on differnet pins?
Nice library btw ..
Thanks
Hello.
The class cannot be used as software I2C by other libraries, like Adafruit's because it does not implement the TwoWire interface.
Please add it, as your class already implements the needed methods.
Thanks!
I have implemented a I2C master on a STM32F103 and it works correctly.
However, while performing tests, I did an experiment: I shorted the scl line to ground, to see whether this was correctly handled. My application then crashed. After a long examination, I found that in such a case there is an infinite indirect recursion, thus the crash.
The problem lies in the function sclHighAndStretch
. In case of a timeout, it calls the function stop
which itself calls sclHighAndStretch
. We need a way to break this recursion. I see two ways:
sclHighAndStretch
to hold it from calling stop
again.stop2
code for this instance, that does not call sclHighAndStretch
again.PS : advice : in the description of the library, it would be useful to specify that the user needs to supply a read and a write buffer at initialisation time. I had a hard time figuring out what was wrong until I discovered this. I used to use a library from Roger Clark's package that was very close, but that did not require buffers to be supplied, so I was not aware of the need of buffers.
In the llStartWait() function, the stop() call for case nack should include either a break; or a return immediately after it.
Currently my compiler is giving "warning: this statement may fall through".
It looks like it currently will call stop() twice, then return timedOut, but not sure what the actual intent is here.
SoftWire::result_t SoftWire::llStartWait(uint8_t rawAddr) const
{
AsyncDelay timeout(_timeout_ms, AsyncDelay::MILLIS);
while (!timeout.isExpired()) {
// Force SDA low
_sdaLow(this);
delayMicroseconds(_delay_us);
switch (llWrite(rawAddr)) {
case ack:
return ack;
case nack:
stop();
default:
// timeout, and anything else we don't know about
stop();
return timedOut;
}
}
return timedOut;
}
Line 72 is referencing a non-existent method (rawWrite):
errors += i2c.rawWrite(command);
Changing it to:
errors += i2c.write(command);
seems to have solved the issue.
Hi stevemarple,
i want to use softWire for 3 pressure sensors with same address (because i dont have multiplexer) so i try to use ur library.
As u said high-level functions provide almost direct compatibility with the Wire library.
I dont know how to set up buffer, con figure SoftWire to use beginTransmission(), endTransmission(), read(), write() and requestFrom () and other high-level functions.
this is my code
softwire.txt
could you help me to it. Thank you so much
Hi
this:
void exitPWM(void)
{
// Make SMBus request to force SMBus output instead of PWM
SoftWire::setSclLow(&i2c);
delay(3); // Must be > 1.44ms
SoftWire::setSclHigh(&i2c);
delay(2);
}
should be:
void exitPWM(void)
{
// Make SMBus request to force SMBus output instead of PWM
SoftWire::sclLow(&i2c);
delay(3); // Must be > 1.44ms
SoftWire::sclHigh(&i2c);
delay(2);
}
Wire.read() always returns 255
With Wire library example works correctly
`#include <SoftWire.h>
#include <AsyncDelay.h>
SoftWire Wire(SDA, SCL);
#define disk1 0x50 //Address of 24C32 eeprom chip
void setup(void)
{
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Wire");
Wire.begin();
unsigned int address = 0;
Serial.println("writeEEPROM");
writeEEPROM(disk1, address, 123);
Serial.println("readEEPROM");
Serial.println(readEEPROM(disk1, address), DEC);
Serial.println("end");
}
void loop(){}
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data )
{
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.write(data);
Wire.endTransmission();
delay(5);
}
byte readEEPROM(int deviceaddress, unsigned int eeaddress )
{
byte rdata = 0xFF;
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8)); // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
Wire.endTransmission();
Wire.requestFrom(deviceaddress,1);
if (Wire.available()) rdata = Wire.read();
return rdata;
}`
Recompiled a slightly-modified, but working, program which used AS3935 and SoftWire to speak to an AS3935 in a MOD-1016 card. Wouldn't work. Backed out of changes. Still won't work. Tried demo. Wouldn't work. Hardware not changed.
Signal analyzer sees writes to 0x06 (AS3935 address is 0x03, so this is right) and 0x07, reads 0x24 always. It looks like SoftWire llwrite function buffers bytes to be sent, but nobody seems to call endTransmissionInner, which looks like it would be the thing to actually transmit what's in the buffer!
Here's the sequence I see:
SW: llWrite: 0x6
SW: llWrite: 0x6
SW: llWrite: 0x6
sPU=>sI1
SW: llWrite: 0x6
SW: llWrite: 0x6
SW: llWrite: 0x7
SW: llRead: got 0x24
SW: llWrite: 0x6
sI1=>sI2
SW: llWrite: 0x6
SW: llWrite: 0x7
SW: llRead: got 0x24
SW: llWrite: 0x6
SW: llWrite: 0x6
SW: llWrite: 0x7
SW: llRead: got 0x24
sI2=>sL
SW: llWrite: 0x6
SW: llWrite: 0x7
SW: llRead: got 0x24
SW: llWrite: 0x6
SW: llWrite: 0x6
SW: llWrite: 0x7
SW: llRead: got 0x24
Problem - noise floor was set to 0 but didn't set ==> 2
Did this get broken with the update to SoftWire? Or am I missing something else?
Here's my Arduino code:
#define PROGNAME "MOD-1016_AS3935_lightning_sensor.ino"
#define VERSION "0.3.4"
#define VERDATE "2018-08-04"
/*
Side notes: that program uses SoftWire, which initializes pin 14 (A0) for SDA
and pin 17 (A3) for SCL.
Many "Something else happened!" events
Two kinds of calls - process and getTriggered. What events lead to each?
getTriggered returns the value of _triggered
process turns _triggered off if state is WaitR
Does calling getInterruptFlags and getState clear these? No.
When should they be called?
Add a real-time clock to this setup, then hard-wire it; move it to an ESP so can
query a timeserver?
v0.3.0 removed dumping registers unless VERBOSE or actual lightning detected
*/
#include <AsyncDelay.h>
#include <SoftWire.h>
#include <AS3935.h>
#ifdef JTD
#include <DisableJTAG.h>
#endif
//************************
//************************
#define VERBOSE 4
const unsigned long BAUDRATE = 115200;
const int tabColumn = 40;
//************************
//************************
/*************************** hardware incl GPIO *******************************/
/*
connections:
A0 SDA for sensor (yellow)
A3 SCL for sensor (white)
D2 IRQ line from sensor (blue)
D13 LED
*/
const int piSensor = 2; // IRQ pin from sensor
const int intSensor = 0; // Arduino pin 2 is INT0; pin 3 (not used here) is INT1
const int pdThrobber = 13;
const uint8_t i2cAddr = 0x03;
const byte antennaTuningValue = 0x02;
/******************************* Global Vars **********************************/
int distanceEstimate = 0;
uint8_t count = 0;
bool ledState = true;
AS3935 as3935;
AsyncDelay throbberTimeout, textThrobberTimeout;
char states [ ] [ 6 ] = { "Off", "PwrUp", "Init1", "Init2", "Listn", "WaitR", "Cal" };
/************************** Function Prototypes *******************************/
void ISR_lightning_sensor (void);
void displayRegs ();
/******************************************************************************/
void setup () {
const int dly = 5;
#ifdef JTD
disableJTAG();
#endif
Serial.begin ( BAUDRATE );
while ( !Serial && millis() < 2000 );
// sda, scl, address, tunCap, indoor, timestamp
as3935.initialise ( 14, 17, i2cAddr, antennaTuningValue, true, NULL );
// no delays necessary - internal to as3935 code
// delay ( dly );
// as3935.reset();
// delay ( dly );
// as3935.clearStats();
// delay ( dly );
as3935.start();
// start implicitly calls calibrate
// delay ( dly );
// wait until it's in Listen state
while ( as3935.getState() != AS3935::stateListening ) as3935.process();
// process steps through initilization states
// delay ( dly );
if ( ! as3935.setNoiseFloor ( 0 ) ) {
Serial.println ( "Failed to set noise floor!" );
while ( 1 );
}
delay ( dly );
if ( 1 ) {
uint8_t val = 0xff;
if ( ! as3935.readRegister ( AS3935::regNoiseFloor , val ) ) {
Serial.println ( "Failed to read noise floor register!" );
while ( 1 );
}
val = ( val >> 4 ) & 0x07;
if ( val != 0 ) {
Serial.print ( "Problem - noise floor was set to 0 but didn't set ==> " );
Serial.println ( val );
}
while ( 1 );
}
// as3935.calibrate();
// delay ( 20 );
// set bit 5 of interrupt mask register to ignore disturbance events
as3935.setRegisterBit ( 0x03, 5, 1 );
delay ( 20 );
// set threshold number of strikes within 1 minute
// 0x00 -> 1; 0x01 -> 5; 0x02 -> 9; 0x03 -> 16 in bits 5-4 of register 2
as3935.setRegisterBit ( 0x02, 5, 0 );
delay ( 20 );
as3935.setRegisterBit ( 0x02, 4, 1 );
delay ( 20 );
// as3935.setMinimumLightnings ( 1 );
pinMode ( pdThrobber, OUTPUT );
digitalWrite ( pdThrobber, ledState );
pinMode ( piSensor, INPUT );
attachInterrupt ( intSensor, ISR_lightning_sensor, RISING );
throbberTimeout.start ( 1000, AsyncDelay::MILLIS );
if ( VERBOSE >= 2 ) {
textThrobberTimeout.start ( 10UL * 60UL * 1000UL, AsyncDelay::MILLIS );
}
#if VERBOSE >= 2
Serial.print ( "\n\nLightning Sensor [" );
Serial.print ( PROGNAME );
Serial.print ( "] v");
Serial.print ( VERSION );
Serial.print ( " (" );
Serial.print ( VERDATE );
Serial.print ( ")\n\n" );
displayRegs ();
#endif
}
void loop () {
int interruptFlags = -1;
int distanceEstimate = -1;
static int oldState = -1;
/*
AS3935 software state
stateOff = 0,
statePoweringUp = 1, // first 2ms wait after power applied
stateInitialising1 = 2,
stateInitialising2 = 3,
stateListening = 4,
stateWaitingForResult = 5,
stateCalibrate = 6,
*/
int state = as3935.getState();
if ( state != oldState ) {
for ( int i = 0; i < tabColumn; i++ ) Serial.print ( " " );
Serial.print ( "===> new state: " );
Serial.println ( states [ as3935.getState() ] );
oldState = state;
}
if ( as3935.process() ) {
interruptFlags = as3935.getInterruptFlags();
distanceEstimate = as3935.getDistance();
Serial.println ( "\n------ process -------" );
Serial.print ( "Interrupt flags: 0x" );
if ( interruptFlags < 0x10 ) Serial.print ( "0" );
Serial.print ( interruptFlags, HEX );
if ( distanceEstimate != 63 ) {
Serial.print ( "; ( Distance: " );
Serial.print ( distanceEstimate );
Serial.print ( " km )" );
}
Serial.println ();
}
if (as3935.getBusError()) Serial.println ( "\nBus error!" );
if ( as3935.getTriggered() ) {
Serial.print ( "\n\n---------- triggered ----------\n" );
interruptFlags = as3935.getInterruptFlags ();
switch ( interruptFlags ) {
case 0x01:
if ( VERBOSE >= 10 ) displayRegs ( );
Serial.print ( "Noise" );
break;
case 0x04:
if ( VERBOSE >= 10 ) displayRegs ( );
Serial.print ( "Disturber" );
break;
case 0x08:
displayRegs ( );
distanceEstimate = as3935.getDistance();
Serial.print ( "Lightning at distance " );
Serial.print ( distanceEstimate );
Serial.print ( " km" );
break;
case -1:
break;
default:
if ( VERBOSE >= 20 ) displayRegs ( );
Serial.print ( "Something else" );
break;
}
if ( interruptFlags >= 0 ) {
Serial.println ( " happened!" );
Serial.println("----------------------\n\n");
}
}
if (throbberTimeout.isExpired()) {
ledState = ! ledState;
digitalWrite ( pdThrobber, ledState );
if (++count > 5) {
count = 0;
// displayRegs ();
}
throbberTimeout.start(1000, AsyncDelay::MILLIS);
}
if ( VERBOSE >= 2 ) {
if (textThrobberTimeout.isExpired()) {
Serial.println ( "Still alive..." );
textThrobberTimeout.start ( 10UL * 60UL * 1000UL, AsyncDelay::MILLIS );
}
}
}
/**/
/ lightning sensor /
//
void ISR_lightning_sensor (void) {
as3935.interruptHandler();
}
void displayRegs () {
static bool firstTimeP = true;
Serial.print ( "\nAS3936 Registers as of " );
Serial.print ( millis() );
Serial.println ( " ms" );
/*
AS3935 registers
0x00 5-1 AFE_GB 0 PWD
AFE Gain Boost (norm 0x12 = 18)
Power-down (norm 0)
0x01 6-4 NF_LEV 3-0 WDTH
Noise Floor Level (norm 0)
Watchdog threshold (norm 2)
0x02 6 CL_STAT 5-4 MIN_NUM_LIGH 3-0 SREJ
Reg is usually 0xc2 (using a reserved bit!)
Clear statistics (norm 1)
Minimum number of lightning (norm 0)
Spike rejection (norm 2)
0x03 7-6 LCO_FDIV 5 MASK_DIST 3-0 INT
Frequency division ratio for antenna tuning (norm 0)
Mask Disturber (norm 0)
Interrupt (norm 0)
0x04 S_LIG_L
Energy of the single lightning LSByte
0x05 S_LIG_M
... MSByte
0x06 4-0 S_LIG_MM
... MMSByte
0x07 5-0 DISTANCE
Distance estimate (kilometers; norm 0x3f)
0x08 7 DISP_LCO 6 DISP_SRCO 5 DISP_TRCO 3-0 TUN_CAP
Display LCO on IRQ pin (norm 0)
Display SRCO on IRQ pin (norm 0)
Display TRCO on IRQ pin (norm 0)
Internal tuning capacitors 0-120pF steps of 8pF (2)
*/
uint8_t val;
as3935.readRegister ( 0 , val );
Serial.print ( " AFE gain boost ( 0x12 ): " ); Serial.println ( ( val >> 1 ) & 0x1f, HEX );
Serial.print ( " Power-down ( 0 ): " ); Serial.println ( ( val >> 0 ) & 0x01, HEX );
as3935.readRegister ( 1 , val );
Serial.print ( " Noise Floor Level ( 0 ): " ); Serial.println ( ( val >> 4 ) & 0x03, HEX );
Serial.print ( " Watchdog threshold ( 2 ): " ); Serial.println ( ( val >> 0 ) & 0x0f, HEX );
as3935.readRegister ( 2 , val );
Serial.print ( " Clear statistics ( 1 ): " ); Serial.println ( ( val >> 6 ) & 0x01, HEX );
int num = ( ( val >> 4 ) & 0x03 );
int nums [] = { 1, 5, 9, 16 };
Serial.print ( " Minimum reportable strikes/min ( 0 ): " ); Serial.print ( num );
Serial.print ( " => " ); Serial.println ( nums [ num ] );
Serial.print ( " Spike rejection ( 2 ): " ); Serial.println ( ( val >> 0 ) & 0x0f, HEX );
as3935.readRegister ( 3 , val );
Serial.print ( " Frequency division ratio for antenna tuning ( 0 ): " );
Serial.println ( ( val >> 6 ) & 0x02, HEX );
Serial.print ( " Mask Disturber ( 0 ): " ); Serial.println ( ( val >> 5 ) & 0x01, HEX );
Serial.print ( " Interrupt ( 0 ): " ); Serial.println ( ( val >> 0 ) & 0x0f, HEX );
if ( ! firstTimeP ) {
// avoid printing residual values during startup
unsigned long energy = 0;
as3935.readRegister ( 6 , val );
energy |= ( val & 0x0f );
energy <<= 4;
as3935.readRegister ( 5 , val );
energy |= ( val & 0xff );
energy <<= 8;
as3935.readRegister ( 4 , val );
energy |= ( val & 0xff );
if ( energy > 0 ) for ( int i = 0; i < tabColumn; i++ ) Serial.print ( " " );
Serial.print ( " Energy of the single lightning: " ); Serial.println ( energy );
if ( energy > 0 ) {
as3935.readRegister ( 7 , val );
val = ( val >> 0 ) & 0x3f;
if ( val < 0x3f ) for ( int i = 0; i < tabColumn; i++ ) Serial.print ( " " );
Serial.print ( " Distance estimate, km ( 63 ): " );
Serial.print ( val );
}
Serial.println ();
}
/*
// no referent!
Serial.print("EIFR: ");
Serial.print ( EIFR < 0x10 ? "0x0" : "0x" );
Serial.println(EIFR, HEX);
*/
Serial.flush();
firstTimeP = false;
}
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; };
I am trying to use pfc8583 . Board is STM32. It always hangs on setMode function..
Sample code:
uint16_t PCF8583::setMode(uint8_t address,uint8_t mode)
{
_address = address >> 1;
// _wire = theWire;
if(!Newwire.available())
{
Newwire.setTxBuffer(NewwireTxBuffer, sizeof(NewwireTxBuffer));
Newwire.setRxBuffer(NewwireRxBuffer, sizeof(NewwireRxBuffer));
Newwire.setTimeout(1000);
delay(100);
Newwire.begin();
delay(200);
}
// if(!Newwire.available())
// return 1;
// return 2;
delay(200);
// convert to 7 bit so Wire doesn't choke
uint8_t control = getRegister(LOCATION_CONTROL);
// uint8_t control = getRegister(LOCATION_CONTROL);
control = (control & ~MODE_TEST) | (mode & MODE_TEST);
setRegister(LOCATION_CONTROL, control);
}
It hangs when Calling setMode
Hello Sir, thank you for sharing such excellent work.
I tried to use ESP32 wroom dev board and use Adafruit_MLX90614 and MAX30102 sensor on I2C communication. As you might know both works on I2C communication. but It did not work. Any piece of advice will be highly appreciated.
There is a small bug in the example for DS1307 while getting the hour.
Here is the fix: tenHour = (registers[2] & 0x30) >> 4;
Hi Steve,
I am using this library to run on LoLin NODEMCU (ESP8266) which doesn't have hardware I2C.
When I try to compile example SoftWire_MLX90614 file, i get following compilation error.
Arduino: 1.8.5 (Windows 10), Board: "NodeMCU 0.9 (ESP-12 Module), 80 MHz, 115200, 4M (3M SPIFFS)"
Build options changed, rebuilding all
C:\Users\sumeetpatil\Documents\Arduino\libraries\SoftWire\src\SoftWire.cpp:1:25: fatal error: util/atomic.h: No such file or directory
#include <util/atomic.h>
^
compilation terminated.
exit status 1
Error compiling for board NodeMCU 0.9 (ESP-12 Module).
Question:
Can the clock frequency set to 400KHz in this Library?
Regards,
Sumeet
Hello! Love your library Steve,
I was having trouble finding how to set sda pins and scl pins during runtime, I'm requesting this block of code be mentioned in the README:
void SoftWire::setSda(uint8_t sda)
{
_sda = sda;
}
void SoftWire::setScl(uint8_t scl)
{
_scl = scl;
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.