Hi all,
I'm trying to solve an i2c issue from some time now .. and I'm at a stall point where I really need some hint.
I'm using a teensy 3.2 with n.1 Adafruit SSD2306 oled display (i2c) and n.3 ATTiny85 attached to the i2c bus.
[OVERVIEW]
1) the purpose is to use the ATTiny85 as independent hifreq counters and display results by the teensy (plus other remote feature eventually ... this is why I love the Teensy!)
2) Initially for the display I was using the SSD1306_text (I just need text) with some bug fixes and I got what I needed...
3) problem is: after some random time everything is getting stuck, to a point that I need to power cycle
[DETAILS]
to interface the 5v peripherals I use a i2c adaptor from sparkfun, which already has pullups to 1Kohm (PCA9306) so I should be ok on levels.
the ATTiny85 is counting on one pin (uint64_t internal counter) with some sw debounce (see code below) and sends the value over i2c when requested.
Each of the n.3 ATTiny85 has a different address.
[DEBUG]
Initially I was under the impression that my fixes to the SSD1306_text library were the culprit, so I decided to load the Adafruit oled demo (the classical example).
the idea is that it should work even if I have the 3 attiny85 attached to the bus ... basically idle because they are never asked to send data by the master i2c (teensy)
Even the Adafruit demo is getting stuck "randomly", to a point that I need to power cycle.
The problem is the following:
1) I run the i2cScan on teensy (looping every 0.5s) and I can see all the 4 devices, no problems
2) I load the adafruit oled demo ... is getting stuck after few secs
3) without power cycle the diplay/attiny I load the i2cScan again .. and I get a bunch of errors, like the display bus is in a very weird state.
4) powercycle everything and the i2cScan works again .. no issues
So I decided to remove the ATTiny85 one by one:
1) with TWO attiny85 ... the problem is there, i2c display is getting stuck
2) if leave ONLY ONE attiny85: not a single problem, the display demo runs forever, but the attiny is running _the_same_code_ on the same i2c addr !!!
I tried to understand if this is a logic level issue, but voltage on the bus seems fine all the time,
and I don;t see the ATTiny85 to trigger a "false i2c request"
[HELP]
Anyone out there that has a display and a couple of attiny85 and wants to try?
It is certainly some issue on the tristate of the bus ... but I can't see why it should,
since the ATTiny85 are never asked to reply by the Adafruit demo...
anyone having multiple ATTiny85 runnig on the i2c bus of a Teensy??
:-)
Note: the bus length is very short... less than 40mm from the teensy to the display (1st) and the very last ATTiny85
Code:
#include <stdint.h>
#include "avr/interrupt.h"
#include "TinyWireS.h"
/* NOTE: make sure you change the slave addr on each ATTiny85 */
#define I2C_SLAVE_ADDR (0x0A)
#define COUNT32_PIN (1)
#define COUNT32_DEBOUNCE_MS (20) //~8ms
#define CONT32_RISING (HIGH)
#define CONT32_FALLING (LOW)
unsigned long isrCtrlTime = 0;
unsigned long debounceCtrlTime = 0;
volatile uint64_t count64 = 0;
volatile uint8_t count64_debounce_ms = COUNT32_DEBOUNCE_MS;
volatile uint8_t i2cReqCount = 0;
/* ************************************************************************* */
/* INPUT DEBOUCE CONFIG */
/* ************************************************************************* */
void debounceConfigInit()
{
pinMode(3, INPUT);
pinMode(4, INPUT);
uint8_t d1 = (HIGH==digitalRead(3))?1:0; //PB3 = bit1
uint8_t d0 = (HIGH==digitalRead(4))?1:0; //PB4 = bit0
uint8_t val = d0 + 2*d1;
switch(val)
{
case 0 : count64_debounce_ms = 0; break; //0ms
case 1 : count64_debounce_ms = 1; break; //8ms
case 2 : count64_debounce_ms = 3; break; //24ms
case 3 : count64_debounce_ms = 8; break; //64ms
default : count64_debounce_ms = 2; //16 ms
}
debounceCtrlTime = millis();
}
/* ************************************************************************* */
/* ISR */
/* ************************************************************************* */
//void countISR()
ISR(PCINT0_vect)
{
/* handle interrupt on rising only */
if(CONT32_FALLING == digitalRead(COUNT32_PIN))
{
return;
}
unsigned long deltaTimeMs = millis();
deltaTimeMs = (isrCtrlTime <= deltaTimeMs) ?
(deltaTimeMs-isrCtrlTime) : (0xFFFFFFFF + deltaTimeMs - isrCtrlTime);
/*
* SOFTWARE DEBOUNCE
*/
if(count64_debounce_ms < deltaTimeMs)
{
isrCtrlTime = millis();
count64++;
}
}
/* ************************************************************************* */
/* I2C */
/* ************************************************************************* */
void requestEvent()
{
//NOTE: count64 is 64bit, i.e. 8bytes
// the maste is aware of this and must call 8 times.
uint8_t shft = (i2cReqCount & 0x07) * 8;
TinyWireS.send( (byte) ((count64 >> shft)&0xFF) );
i2cReqCount++;
//digitalWrite(3,((i2cReqCount&0x01)?HIGH:LOW));
}
/* ************************************************************************* */
/* MAIN */
/* ************************************************************************* */
void setup() {
/* init I2C Slave mode */
TinyWireS.begin(I2C_SLAVE_ADDR);
TinyWireS.onRequest(requestEvent);
isrCtrlTime = millis();
/* SETUP INTERRUPTS, enable PB1 on change */
GIMSK = 0b00100000; // turns on pin change interrupts
PCMSK = 0b00000010; // turn on interrupts on pins PB1,
sei(); // enables interrupts
pinMode(COUNT32_PIN, INPUT);
debounceConfigInit();
}
void loop() {
TinyWireS_stop_check();
}