ATtiny85: Alternative zu INT0 zur Flankenerkennung?

Hallo,

ich will mit einem ATtiny85 eine fallende Flanke erkennen, um Impulse einer Lichtschranke zu zählen.

Bei der Recherche, wie ich das umsetzen kann, bin ich im internationalen Arduino-Forum auf folgenden Code gestoßen:

Quelle: ATTINY85: Intercept FALLING on interrupt... is it possible? - Programming Questions - Arduino Forum (nickgammon - Post #25)

// ATMEL ATTINY 25/45/85 / ARDUINO
// Pin 1 is /RESET
//
//                  +-\/-+
// Ain0 (D 5) PB5  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0
//                  +----+

/*

  Pin 7  <-- switch to Gnd

  Pin 5 (PB0) <---- LED ---> 330 R <-----> Gnd
  
*/


#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>    // Power management

const byte LED = 0;          // pin 5 (D0)
const byte SW = 2;           // pin 7 (D2)
 
ISR (INT0_vect)
{
  GIMSK &= ~bit(INT0);     // disable INT0
}

void setup ()
  {
  pinMode (LED, OUTPUT);
  pinMode (SW, INPUT);
  digitalWrite (SW, HIGH);  // input pull-up
  ADCSRA = 0;            // turn off ADC
  MCUCR &= ~(bit(ISC01) | bit(ISC00));    // INT0 on low level
  }  // end of setup

void loop ()
  {

  power_timer0_enable ();
  delay (100);  // let timer reach a known point
  digitalWrite (LED, HIGH);
  delay (20);
  digitalWrite (LED, LOW);
  power_timer0_disable ();

  while (digitalRead (SW) == LOW)
    { }  // wait for switch to be released

  noInterrupts ();
  GIFR  = bit (INTF0);   // clear interrupt flag
  GIMSK = bit (INT0);    // enable INT0
    
  power_all_disable ();  // power off ADC, Timer 0 and 1, serial interface
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_enable ();       // ready to sleep
  interrupts ();
  sleep_cpu ();          // sleep                
  sleep_disable ();      // precaution

  }  // end of loop

Den Code habe ich probiert und er funktioniert auch gut.

Ich habe aber vor, einen Integer-Wert an den ATtiny85 zu senden, der dann als Soll-Wert für die Impulse dienen soll.

Also sende ich über i2c den Wert 100, dann soll der ATtiny 100 Impulse zählen und dann z.B. einen Digitalen Ausgang auf true setzen.

Das Problem, das ich dabei jetzt habe, ist, dass laut Datenblatt (https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf) nur der Pin 7 (PB2) / INT0 für die Erkennung einer bestimmten Flanke genutzt werden kann und dieser Pin aber gleichzeitig der SCL für den i2c Bus ist.

Es gibt zwar noch weitere Interrupt Pins "PCINT", aber die erkennen einfach eine Änderung am Pin und keine bestimmte Flanke.

Verstehe ich da jetzt was falsch, oder kann ich mein Vorhaben dann mit dem ATtiny85 wirklich nicht so umsetzen?

Du kannst auch mit einem PCINT eine Flanke erkennen, nur musst Du das dann selbst programmieren.
Pseudocode:

bool alterWert = LOW;
...

bool wert = digitalRead(Pin);
if (wert != alterWert) {
  alter Wert = wert;
  if (wert == HIGH) // das war eine LOW-> HIGH-Flanke
}

Gruß Tommy

Damit beim Einschalten keine nicht vorhandene Flanke erkannt wird:

bool alterWert = digitalRead(Pin);

Das würde ich (ohne bool) erst im Setup machen. Evtl. sind vorher die IO noch nicht initialisiert.

Gruß Tommy

Danke für Eure schnellen Antworten!

Hab ich genauso gemacht - im Setup, nachdem initialisiert wurde...

Funktioniert jetzt wunderbar so, aber was ich gerade nicht verstehe, ist, wieso in meinem Code teilweise verkehrte Welt herrscht!?

Der Ablauf ist jetzt so:

  1. Programm wird auf den ATtiny85 geschrieben
  2. Programm gestartet und LED aus
  3. Ich drehe den Motor und die Lichtschranke wird 10 mal unterbrochen. Bei jedem Mal unterbrechen, blinkt die LED kurz auf.
  4. Nach 10 Mal unterbrechen, bleibt die LED an (Natürlich nur bis ich weiter drehe, weil ich == und nicht >= verwende - Absicht)

Soweit alles gut, aber wieso muss ich die LED im Setup auf HIGH setzen, um sie beim Start auszuschalten, im Loop dann auf LOW setzen, um sie einzuschalten und im Interrupt passt es mit HIGH und LOW (An und Aus) ?

// ATMEL ATtiny85
//
//                  +-\/-+
//          Reset  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1 SCL
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0 SDA
//                  +----+
// Code für Attiny85
// Empfängt einen Integer-Wert und zählt dann die eigehenden Impulse, bis die Anzahl der Impulse diesem Integer-Wert entsprechen

#include <avr/io.h>
#include <avr/interrupt.h>

#define INTERRUPT_PIN PCINT3          // PB3
#define INT_PIN PB3                   // Interrupt pin: PB3
#define LED_PIN PB4                   // PB4
#define PCINT_VECTOR PCINT0_vect      // This step is not necessary - it's a naming thing for clarit

volatile unsigned long counter = 0;   // Zähler für die Impulse
bool oldValue = LOW;                  // Vergleichsvariable für die Flankenerkennung

void setup() {
  cli();                            // Disable interrupts during setup
  PCMSK |= (1 << INTERRUPT_PIN);    // Enable interrupt handler (ISR) for our chosen interrupt pin (PCINT1/PB1/pin 6)
  GIMSK |= (1 << PCIE);             // Enable PCINT interrupt in the general interrupt mask

  counter = 0;                      // Zähler zurücksetzen
  pinMode(LED_PIN, OUTPUT);         // Digitaler Ausgang (LED)
  digitalWrite(LED_PIN, HIGH);      // LED ausschalten - Wieso HIGH und nicht LOW?
  pinMode(INT_PIN, INPUT_PULLUP);   // Set our interrupt pin as input with a pullup to keep it stable
  oldValue = digitalRead(INT_PIN);  // Aktuellen Wert des Interrupt-Eingangs auslesen
  sei();                            // last line of setup - enable interrupts after setup
}

void loop() {
  if(counter == 10) {
    digitalWrite(LED_PIN, LOW);     // Wenn der Zählerstand X erreicht wurde, dann Ausgang auf HIGH setzen (Wieso auch hier LOW statt HIGH?)
  }
}

// Interrupt Handler
ISR(PCINT_VECTOR)
{
  bool currentValue = digitalRead(INT_PIN);
  if (currentValue != oldValue) {
    oldValue = currentValue;
    if (currentValue == HIGH) {
      digitalWrite(LED_PIN, HIGH);
      counter++;
    } else {
      digitalWrite(LED_PIN, LOW);
    }
  }
}

Tommy56:
Evtl. sind vorher die IO noch nicht initialisiert.

Vollkommen richtig. So wie in #4 hatte ich es gemeint.

somann88:
Soweit alles gut, aber wieso muss ich die LED im Setup auf HIGH setzen, um sie beim Start auszuschalten, im Loop dann auf LOW setzen, um sie einzuschalten und im Interrupt passt es mit HIGH und LOW (An und Aus) ?

Vermutlich hängt Deine LED an VCC und am Ausgang des Attiny. Deshalb ist die Logik invertiert. Oder nicht?

Gruß, Jürgen

Katsumi_S:
Vermutlich hängt Deine LED an VCC und am Ausgang des Attiny. Deshalb ist die Logik invertiert. Oder nicht?

Gruß, Jürgen

Ja, stimmt, das ist der Grund. Bin nur durcheinander gekommen, weil es in der Interrupt-Funktion scheinbar anders ist, aber da kommt es mit der Invertierung auch hin.
Also das Impulse zählen funktioniert schon sehr gut. Jetzt bin ich gerade dran, die i2c Kommunikation zu programmieren und da komme ich gerade nicht so richtig weiter. Vorerst programmiere ich mal nur die i2c Kommunikation, um es übersichtlicher zu halten. Später kombiniere ich dann beide Programme.
Ich wollte die Sache erstmal grundsätzlich verstehen und um zu sehen, ob der Wert, der gesendet wird auch gespeichert wird, gebe ich den empfangenen Wert bei einem Request wieder zurück. Das hat sporadisch mal funkioniert, aber jetzt geht irgendwie garnichts mehr.
Der Master ist übrigens ein Raspberry Pi 3b+
Wenn ich beim RPi den Befehl "i2cdetect -y 1" in der Konsole eingebe, wird der ATtiny85 auch unter der Adresse 0x20 erkannt. 0x60 ist ein Digital-Analog-Wandler.

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

Wenn ich dann den Befehl "i2cget -y 1 0x20" eingebe, kommt als Wert immer nur 0xff zurück.
Wenn ich z.B. "i2cset -y 1 0x20 0x64" eingebe und danach wieder "i2cget -y 1 0x20", kommt nach wie vor 0xff zurück.
Hier mal mein Code bis jetzt:

// ATMEL ATtiny45/85
//
//                  +-\/-+
//          Reset  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1 SCL
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0 SDA
//                  +----+

#include <TinyWireS.h>                           // Bezieht i2c Bibliothek ein
#define I2C_SLAVE_ADDRESS 0x20                   // i2c Slave Adresse
#define LED PB1

volatile uint8_t counter = 100;                  // Encoder Zähler

void setup() {
  TinyWireS.onRequest(requestEvent);             // Deklaration der Funktion für eine i2c Anfrage
  TinyWireS.onReceive(receiveEvent);             // Deklaration der Funktion für einen i2c Empfang
  TinyWireS.begin(I2C_SLAVE_ADDRESS);            // Verbindet mit dem i2c Bus
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);
}

void loop() {
  TinyWireS_stop_check();
}

void requestEvent() {
  TinyWireS.send(counter);                       // Sendet i2c Nachricht
}

void receiveEvent(uint8_t value) {
  while (TinyWireS.available())
    counter = TinyWireS.receive();               // Empfängt i2c Nachricht
}

Was mache ich hier falsch?

Übrigens habe ich auch noch einen sehr guten Code im Internet gefunden, der perfekt für meine Anforderung passen würde, aber auch hier kommt nur der Wert 0xff zurück...

/*
   I2C library used:
   https://github.com/rambo/TinyWire

   For ATtiny44a/84a running at 20 MHz.

   Available EEPROM: 256/512 bytes.
   Flash: 4/8 kB.
   RAM: 256/512 bytes.

   Prepare for ATTINY816: 128 bytes EEPROM, 512 bytes RAM, 8kB flash.
   ATTINY416: 128 bytes EEPROM, 256 bytes RAM, 4kB flash.

   All data is expected to be transmitted as highByte first.
   All data will be stored in EEPROM as highByte first.

*/

#include <TinyWireS.h>

#define I2C_DEFAULT 0x20                              // The default used if no address found in EEPROM.

// The available I2C commands.
#define READ_EC               0x11                    // Read the EC probe - produces 2 bytes of data (the cycle count).
#define CALIBRATE_EC          0x12                    // Set calibration of EC probe - comes with 2 bytes of data (value, pos).
#define GET_CALIBRATION       0x13                    // Get calibration of EC probe - comes with 1 byte of data (pos).
#define CLEAR_CALIBRATION     0x14                    // Remove a calibration point - comes with 1 byte of data (pos).
#define SET_EC_OVERSAMPLING   0x15                    // Set the oversampling factor (ranging from 0 = 1x to 10 = 1024x).

#define READ_NTC              0x20                    // Read the NTC probe - produces 2 bytes of data (the ADC reading).
#define SET_NTC_OVERSAMPLING  0x21                    // Set the oversampling factor (ranging from 0 = 1x to 10 = 1024x).

#define SET_ADDRESS           0x30                    // Set the I2C address of this device - comes with 1 byte of data (the address).

// Other I2C paramenters.
#define MAX_TRANSMISSION 16                           // No more than this many bytes in a single I2C transmission for this application, ever.

volatile uint8_t request[MAX_TRANSMISSION];           // Stores the incoming I2C data.
volatile uint8_t response[MAX_TRANSMISSION];          // Stores the outgoing I2C data.
volatile uint8_t availableBytes;                         // The number of valid data bytes available.

// Advance declaration of callback functions.
void wireRequest(void);
void wireReceive(void);

uint8_t address;

void setup() {

  // Set up I2C interface and callback functions.
  address = I2C_DEFAULT;
  TinyWireS.begin(address);
  TinyWireS.onRequest(wireRequest);
  TinyWireS.onReceive(wireReceive);

}

bool handleCommand = false;

void loop() {

  if (handleCommand) {
    handleCommand = false;
    availableBytes = 1;                               // Dealing with a new command: reset the response data.
    response[0] = 6;                                  // Set response status to "in progress".
    switch (request[0]) {
      case READ_EC:
        response[0] = 6;
        {
          uint32_t startMillis = millis();
          while (millis() - startMillis < 1000) {
            TinyWireS_stop_check();
          }
        }
        response[0] = 1;
        response[1] = 10;
        response[2] = 100;
        response[3] = 10;
        response[4] = 1;
        availableBytes = 5;
        break;

      case CALIBRATE_EC:
        response[0] = 12;
        break;

      case GET_CALIBRATION:
        for (uint8_t i = 0; i < 10; i++) {
          response[i] = i * 11 + 1;
        }
        availableBytes = 10;
        break;

      case CLEAR_CALIBRATION:
        response[0] = 14;
        availableBytes = 1;
        break;

      case SET_EC_OVERSAMPLING:
        response[0] = 15;
        availableBytes = 1;
        break;

      case READ_NTC:
        response[0] = 2;
        response[1] = 20;
        response[2] = 200;
        availableBytes = 3;
        break;

      case SET_NTC_OVERSAMPLING:
        response[0] = 5;
        if (request[1] > 0 && request[1] <= 10) {
          response[0] = 0;
        }
        availableBytes = 1;
        break;

      case SET_ADDRESS:
        response[0] = 99;
        availableBytes = 1;
    }
  }

  // This needs to be here for the TinyWireS lib
  TinyWireS_stop_check();
}

void wireReceive(uint8_t n) {

  // Make sure we don't try to read more bytes than that fit in our data structure.
  if (n > MAX_TRANSMISSION) {
    n = MAX_TRANSMISSION;
  }
  for (uint8_t i = 0; i < n; i++) {
    if (TinyWireS.available()) {
      request[i] = TinyWireS.receive();
    }
    else {
      break;
    }
  }

  // Clear the buffer.
  // There should not be more data in the buffer than the already received bytes, unless the master
  // is misconfigured and sends more data than it should.
  while (TinyWireS.available())
    TinyWireS.receive();

  handleCommand = true;                               // Tell loop() that there's a command to be taken care of.
}

void wireRequest() {

  for (uint8_t i = 0; i < availableBytes; i++) {
    TinyWireS.send(response[i]);
  }
}

Ich habe den oberen Sketch auf einen ATtiny85 gespielt (8 MHz, interner Takt).
Also das:

// ATMEL ATtiny45/85
//
//                  +-\/-+
//          Reset  1|    |8  Vcc
// Ain3 (D 3) PB3  2|    |7  PB2 (D 2) Ain1 SCL
// Ain2 (D 4) PB4  3|    |6  PB1 (D 1) pwm1
//            GND  4|    |5  PB0 (D 0) pwm0 SDA
//                  +----+

#include <TinyWireS.h>                           // Bezieht i2c Bibliothek ein
#define I2C_SLAVE_ADDRESS 0x20                   // i2c Slave Adresse
#define LED PB1

volatile uint8_t counter = 100;                  // Encoder Zähler

void setup() {
  TinyWireS.onRequest(requestEvent);             // Deklaration der Funktion für eine i2c Anfrage
  TinyWireS.onReceive(receiveEvent);             // Deklaration der Funktion für einen i2c Empfang
  TinyWireS.begin(I2C_SLAVE_ADDRESS);            // Verbindet mit dem i2c Bus
  pinMode(LED, OUTPUT);
  digitalWrite(LED, HIGH);
}

void loop() {
  TinyWireS_stop_check();
}

void requestEvent() {
  TinyWireS.send(counter);                       // Sendet i2c Nachricht
}

void receiveEvent(uint8_t value) {
  while (TinyWireS.available())
    counter = TinyWireS.receive();               // Empfängt i2c Nachricht
}

Die TinyWireS (Slave) stammt von hier: GitHub - rambo/TinyWire: My modifications to TinyWire Arduino libs.

Weil ich gerade keinen Raspberry Pi greifbar habe, habe ich als I2C-Master einen Arduino UNO genommen. Mit diesem Sketch (da wird einfach 1 Byte geschrieben, danach 1 Byte gelesen):

// ARDUINO  MASTER
// Wiring:
//     Master (Uno)       Slave (ATTINY85)
//       SDA(A4) ---------- SDA(PB0)
//       SCL(A5) ---------- SCL(PB2)
//       GND -------------- GND
//       5V  -------------- Vcc

#include<Wire.h>
const byte SLAVE_ADDRESS = 0x20;
byte buf [32];    // receive buffer
byte myCounter = 100;

void setup() {
  Serial.begin(9600);
  Wire.begin();    //   // Start the I2C Bus as Master
}

void loop() {
  // Master: send data to slave
  Wire.beginTransmission(SLAVE_ADDRESS);
  Wire.write (myCounter);
  if (Wire.endTransmission () == 0) {
    Serial.println("write success");
  }
  else {
    Serial.println("write failure");
  }

  delay(1000);

  // Master: request information from slave
  if (Wire.requestFrom (SLAVE_ADDRESS, 1)) {   // Address, Bytes to read  // if request succeeded
    byte gotBack = Wire.read ();
    Serial.print("read success \t");
    Serial.println(gotBack);
  }
  else {
    Serial.println("read failure!"); 
  }

  delay(1000);
  myCounter++;
}

Funktioniert ausgezeichnet.
Ausgabe im seriellen Monitor:

write success
read success    100
write success
read success    101
write success
read success    102
write success
read success    103
...

Also dein Sketch am ATtiny funktioniert prinzipiell.
Dann wird es wohl ein anderes Problem geben, zum Beispiel:

  • falscher Takt am ATtiny
  • Verkabelung
  • Programm am Raspberry
    ...

Danke, dass du meinen Code mal getestet hast!

Ich hab deinen Master Code auch mal auf meinen Arduino Uno geschrieben, aber auch da kommt immer der selbe Wert zurück.

write success: 	100
read success 	255
write success: 	101
read success 	255
write success: 	102
read success 	255
write success: 	103
read success 	255
write success: 	104
read success 	255
write success: 	105
read success 	255
write success: 	106
read success 	255
write success: 	107
read success 	255

An der Verkabelung kann es auch nicht liegen. Ich hab lediglich VCC, GND, SCL und SDA angeschlossen und mehrfach geprüft, dass alles korrekt ist.

Also liegt das Problem auch offenbar nicht am RPi, sondern kann eigentlich nur noch der ATtiny selbst sein.

Was genau meinst du mit "Falscher Takt am ATtiny"? Kann ich den Takt überhaupt irgendwie verändern?

Ich hab zur Sicherheit auch mal das selbe Programm auf einen neuen ATtiny geschrieben. Auch hier immer die 255 als Antwort.

Eigentlich kann der Fehler ja jetzt nur noch am Programmer, also meinem Arduino Uno liegen...

Ich verwende den Sketch: Datei -> Beispiele -> 11.ArduinoISP -> ArduinoISP
Die Einstellungen sind folgendermaßen:
Board: ATtiny25/45/85
Prozessor: ATtiny85
Clock: Internal 1 MHz
Programmer: Arduino as ISP

Die Clock-Einstellung soll laut einem Tutorial auf 1 MHz eingestellt sein und nicht 8 MHz, da sonst folgendes passiert: Bootloader kaputt

Ich hab auch schon mehrfach was von PullUp-Widerständen für SCL und SDA gelesen. Kann es sein, dass ich das noch brauch?

somann88:
Ich hab auch schon mehrfach was von PullUp-Widerständen für SCL und SDA gelesen. Kann es sein, dass ich das noch brauch?

Ja, unbedingt!

Irgend ein Wert aus der Bastelkiste 1 bis 10 kOhm.

somann88:
Die Clock-Einstellung soll laut einem Tutorial auf 1 MHz eingestellt sein und nicht 8 MHz, da sonst folgendes passiert: Bootloader kaputt

Im Link wurde 8 MHz extern ohne vorhandenen Resonator verwendet, was nicht funktionieren kann. Die Einstellung 8 MHz intern funktioniert bestens.

Die Clock-Einstellung soll laut einem Tutorial auf 1 MHz eingestellt sein und nicht 8 MHz, da sonst folgendes passiert: Bootloader kaputt

Unfug!

Ein ATTiny85 läuft prächtig mit 8MHz internem Takt!
Selbst mit 16 oder 16,5MHz intern.

Ich hab auch schon mehrfach was von PullUp-Widerständen für SCL und SDA gelesen. Kann es sein, dass ich das noch brauch?

Lesestoff

Ja, unbedingt!

Irgend ein Wert aus der Bastelkiste 1 bis 10 kOhm.

Ich hab jetzt 10kOhm, 4,7 kOhm und 1 kOhm probiert. Der ATtiny wird zwar immer mit "i2cdetect -y 1" erkannt, aber es kommt nach wie vor 255 zurück.

Unfug!

Ein ATTiny85 läuft prächtig mit 8MHz internem Takt!
Selbst mit 16 oder 16,5MHz intern.

Auch das hab ich jetzt geändert und auf 8MHz internen Takt eingestellt. Das beschreiben des ATtiny funktioniert bestens. Keine Fehler, keine Warnungen, ich hab sogar die Debug LEDs an den Arduino Uno angeschlossen:

// ArduinoISP
// ...
// Put an LED (with resistor) on the following pins:
// 9: Heartbeat - shows the programmer is running
// 8: Error - Lights up if something goes wrong (use red if that makes sense)
// 7: Programming - In communication with the slave
// ...

Alle LEDs funktionieren, aber ein Fehler wird auch hier nicht angezeigt.

Ich weiß nicht mehr weiter... woran könnte es denn noch liegen? Die Verbindung zum ATtiny scheint ja zu funktionieren. Ist der Arduino Uno eventuell als Programmer die Fehlerquelle?

Nachdem ich jetzt noch meinen USBASP als Programmer probiert hab und auch das selbe Ergebnis rausgekommen ist, bin ich endlich auf die Lösung gekommen!

Es ist ein Fehler in der TinyWireS Library:

Ich hab jetzt diese Version hier verwendet und schon funktioniert alles wie gedacht:

Danke für die Rückmeldung!

Super, dass es jetzt funktioniert.
Habe jetzt nochmal probiert mit verschiedenen (internen) Takttraten des ATtiny85: 1 MHz und 8 MHz.
Es funktioniert bei mir ohne Probleme, sowohl mit der TiniWireS-Library aus #8 als auch mit der aus #14.

Hier "Beweisfotos": :slight_smile:

attinySlaveI2Cuno.png
(Sorry, es war gerade kein Original-UNO zur Hand)

attinySlaveI2Cuno.png

agmue:
Danke für die Rückmeldung!

Kein Problem, hoffe es kann jemandem einen Tag Fehlersuche ersparen!

Super, dass es jetzt funktioniert.
Habe jetzt nochmal probiert mit verschiedenen (internen) Takttraten des ATtiny85: 1 MHz und 8 MHz.
Es funktioniert bei mir ohne Probleme, sowohl mit der TiniWireS-Library aus #8 als auch mit der aus #14.

Ich hab jetzt auch nochmal die verschiedenen Bibliotheken probiert. Welchen Branch hast du genau verwendet?

Also wenn ich den Master-Branch aus dem Repository GitHub - rambo/TinyWire: My modifications to TinyWire Arduino libs verwende, wird den ATtiny zwar erkannt, aber es kommt immer der Wert 0xff zurück - was höchstwahrscheinlich bedeutet, dass der ATtiny einfach gar nicht antwortet, weil die Funktion "requestEvent" nicht aufgerufen wird.

Wenn ich aber den Rollback-Branch des selben Repository verwende, dann funktioniert alles.

Wenn es bei dir wirklich mit der Bibliothek aus dem Master-Branch funktioniert, dann kann ich es mir nur noch so erklären, dass wir wohl verschiedene Versionen des ATtiny85 haben.
Folgendes steht auf meinem ATtiny85:

Amtel 20U
TINY85
20337VH

Vielleicht kannst du die Bezeichnung von deinem ATtiny auch mal nennen. Interessiert mich jetzt schon, woher der Unterschied kommt.

somann88:
Welchen Branch hast du genau verwendet?

Also wenn ich den Master-Branch aus dem Repository GitHub - rambo/TinyWire: My modifications to TinyWire Arduino libs verwende, wird den ATtiny zwar erkannt, aber es kommt immer der Wert 0xff zurück - was höchstwahrscheinlich bedeutet, dass der ATtiny einfach gar nicht antwortet, weil die Funktion "requestEvent" nicht aufgerufen wird.

Wenn ich aber den Rollback-Branch des selben Repository verwende, dann funktioniert alles.

Wenn es bei dir wirklich mit der Bibliothek aus dem Master-Branch funktioniert, dann kann ich es mir nur noch so erklären, dass wir wohl verschiedene Versionen des ATtiny85 haben.

Ich muss gestehen, dass ich nicht auf den "Branch" geachtet habe, als ich die Library heruntergeladen habe.
Um ehrlich zu sein, wusste ich bis vor ein paar Minuten gar nicht, was das überhaupt bedeutet. :slight_smile:

Ich bin einfach auf die Website gegangen, habe auf "Code" und dann auf "Download ZIP" geklickt, und habe das Heruntergeladene dann in meine Arduino-IDE eingebunden.
Dass der Ordnername "TinyWire-rollback" und nicht (wie sonst üblich) "TinyWire-master" lautet, ist mir zwar aufgefallen, ich habe dem aber keine besondere Bedeutung beigemessen - es hat ja alles funktioniert. :slight_smile:

Ich habe also offensichtlich den "Rollback-Branch" verwendet. Weil das anscheinend der "Default-Branch" ist (siehe Bild). Ich habe keinen Branch aktiv ausgewählt und so habe ich den Default-Branch heruntergeladen.

Somit erklärt sich auch, warum es bei mir funktioniert hat.

Wieder was gelernt - weiß aber noch nicht genau, was :slight_smile: (nämlich wieso Default auf "rollback" steht und nicht auf "master" und was das genau bedeutet).

Danke jedenfalls für die Nachfrage!

branch_default.png

branch_default.png

Da der master-Branch anscheinend Fehler hat, hat der Autor wohl einige Änderungen zurück genommen (rollback) und diesen Stand als Default ausgewählt.

Gruß Tommy