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
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();
}
Last edited: