Hi, I have a pH circuit, it has an ATtiny85 and communicates to a master using I2C.
I connected it to a Raspberry Pi but there were random parse errors, turns out to be caused from clock stretching and Pi's don't like that, here's an image from the analzyer.
If I slow the bus speed to 10kbit/s on the Pi the stretching stops and errors go away but I don't want to slow it down this much.
I've tried the Wire and multiple TinyWire libraries, all work but same issue.
Is there something I can change on the ATtiny85 side so the clock stretching doesn't happen.
This is the code.
#include <Wire.h>
#include <EEPROM.h>
#define PROBE_IN A3 //57 // anlaog a3 - green wire
#define PROBE_REF A2 //56 // anlaog a2 - white wire
byte ver; // eeprom 0
byte i2cAdd = 99; // eeprom 1
double pH;
float mVPerPH; // calibrated mV per pH without temperature compensation
byte in_char = 0;
char inData[30];
byte w = 0; //counter used for ph_data array.
char computerdata[31]; //we make a 20 byte character array to hold incoming data from a pc/mac/other.
void setup()
{
byte z = 255;
EEPROM.get(50, z);
if (z == 255) // Set Defaults
{
EEPROM.put(0, 1); // version
EEPROM.put(1, 99); // I2C address - 40, 41, 42, 43, 44, 45, 46, 47
EEPROM.put(28, 25.0); // calibration temperature
EEPROM.put(50, 1); // version
}
pinMode(1, OUTPUT);
digitalWrite(1, HIGH);
EEPROM.get(0, ver);
EEPROM.get(1, i2cAdd);
measuremV();
Wire.begin(i2cAdd);
// Wire.setClock(400000);
Wire.onReceive(receiveEvent); // register event
Wire.onRequest(requestEvent); // register event
}
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long timer = 1000;
void loop()
{
currentMillis = millis();
if ((currentMillis - previousMillis) >= 3000)
{
measuremV();
previousMillis = millis();
}
}
void measuremV()
{
double differentialmV;
float probeIn, probeRef, inputV, adcResolution;
analogReference(DEFAULT);
inputV = 3.36; // reference voltage
probeIn = ((readADC(PROBE_IN) * inputV) / 1024.0);
probeRef = ((readADC(PROBE_REF) * inputV) / 1024.0);
differentialmV = (probeIn - probeRef);
if (differentialmV <= -1.1)
{
analogReference(INTERNAL);
adcResolution = 2.56;
}
else if (differentialmV <= -0)
{
analogReference(INTERNAL); // set to INTERNAL for ATtiny
adcResolution = 1.1;
}
else if (differentialmV <= 1.1)
{
analogReference(INTERNAL);
adcResolution = 1.1;
}
else if (differentialmV <= 2.56)
{
analogReference(INTERNAL);
adcResolution = 2.56;
}
// take a reading
probeIn = ((readADC(PROBE_IN) * adcResolution) / 1024.0);
probeRef = ((readADC(PROBE_REF) * adcResolution) / 1024.0);
// turn V into mV
differentialmV = (probeIn - probeRef) * 1000;
mVPerPH = 59.16;
// convert to pH
pH = fabs(7.0 - (differentialmV / 59.16));
dtostrf(pH, 0, 3, computerdata); // convert float to char array so it can be sent over I2C
}
void receiveEvent(uint8_t howMany)
{
while (Wire.available()) { // are there bytes to receive.
in_char = Wire.read(); // receive a byte.
inData[w] = in_char; // load this byte into our array.
w += 1; // incur the counter for the array element.
if (in_char == 0) { // if we see that we have been sent a null command.
w = 0; // reset the counter w to 0.
digitalWrite(1, LOW); // LED on circuit board
break; // exit the while loop.
}
}
}
void requestEvent()
{
if ((inData[0] == 'R')) // request from reef-pi is pending
{
inData[0] = 0; // reset for next reading
Wire.write(1); // send byte 1
Wire.write(computerdata,30);
digitalWrite(1, HIGH); // LED on circuit board
}
}
double readADC(int channel)
{
uint32_t total = 0UL;
uint16_t sampleCount = 4096;
for (uint16_t i = 0; i < sampleCount; i++) {total += analogRead(channel);}
total = total >> 6;
double proportional = (total * 1.0) / (0b00000001 << 6);
return proportional;
}
Thanks
