Attiny I2c als Slave bekomme nur Wert 255

Servus zusammen,

Ich möchte mit einem Attiny85 einen Encoder auswerten und Deltawerte des Zählers zwischen den Abfragen über I2c übermitteln.

Leider bekomme ich nur den Wert 255 ausgelesen.

Die Verkabelung sollte passen werde Sie aber nochmals überprüfen.

Über I2c sollte ich doch auch mit dem befehl TinyWireS.send(Array,größe);
mehr als nur ein Byte gesendet bekommen?
Dann könnte ich die doofen Deltawerte sein lassen da mein counter schnell einen wert von mehreren tausend bekommt.

Hier mein Attiny code

// Code für Attiny85
// Sendet über I2c die Deltawerte des Encoders zwischen jeder Abfrage
// V 0.1

#include <TinyWireS.h>                           // Bezieht I2c Bibliothek ein
#include "avr/interrupt.h";                      // Bezieht AVR Interrupt Bibliothek ein  
#define I2C_SLAVE_ADDRESS 0x4                    // I2c Slave Adresse

volatile int counter=0;                          // Encoder Zähler
int calt=0;                                      // Zählerwert zum Zeitpunkt der letzten I2c Abfrage
byte d=0;                                        // Deltawert des Zählers



void setup() {                                    
  TinyWireS.begin(I2C_SLAVE_ADDRESS);             // Verbindet mit I2c Bus
  TinyWireS.onRequest(requestEvent);              // Bei I2c Anfrage springt in requestEvent Funktion
  GIMSK |= (1 << PCIE);                           // Aktiviert Interrupts
  PCMSK |= (1 << PCINT4);                         // Aktiviert PCINT4 als InerruptPin
  sei();                                          // Interrupts EIN
  pinMode(3, INPUT);                              // Setzt Pin 3 und 4 als Input und aktiviert pullup Widerstand
  pinMode(4, INPUT);

}

void loop() {                                      

}

ISR(PCINT0_vect){                                   // Funktion wird ausgeführt wenn Interrupt erkannt wird 
  if(digitalRead(4) != digitalRead(3))              // Encodereingange auswerten und couter entsprechend erhöhen oder veringern
    counter++;
  else
    counter--;
  
}

void requestEvent(){                                
  d = calt - counter;                               // Berechnung des Deltawertes
  TinyWireS.send(d);                                // Sendet I2c Nachricht
  calt = counter;                                   // Setzt calt gleich dem Zähler
}

Hier der Arduino code:

// I2c Master(DUE)

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);


}

void loop() {
   Wire.requestFrom(0x04,1);
  while(Wire.available()) {
    byte c = Wire.read();
    Serial.println(c);
  }

}

Danke für die Hilfe
Viele Grüße

Freddy

ATtiny85 als Slave:

// 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
//                  +----+
// Code für Attiny85
// Sendet über I2c die Deltawerte des Encoders zwischen jeder Abfrage
// V 0.1

// Get this from https://github.com/rambo/TinyWire
#include <util/atomic.h>
#define CriticalSection  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#include <TinyWireS.h>                           // Bezieht I2c Bibliothek ein
#include "avr/interrupt.h";                      // Bezieht AVR Interrupt Bibliothek ein 
#define I2C_SLAVE_ADDRESS 0x4                    // I2c Slave Adresse

volatile byte counter = 100;                        // Encoder Zähler
byte calt = 0;                                    // Zählerwert zum Zeitpunkt der letzten I2c Abfrage
byte d = 0;                                      // Deltawert des Zählers

void setup() {
  TinyWireS.onRequest(requestEvent);              // Bei I2c Anfrage springt in requestEvent Funktion
  TinyWireS.begin(I2C_SLAVE_ADDRESS);             // Verbindet mit I2c Bus
  pinMode(3, INPUT_PULLUP);                       // Setzt Pin 3 und 4 als Input und aktiviert pullup Widerstand
  pinMode(4, INPUT_PULLUP);
}

void loop() {
  CriticalSection
  {
    if (digitalRead(4) != digitalRead(3))             // Encodereingange auswerten und couter entsprechend erhöhen oder veringern
      counter++;
    else
      counter--;
  }
  analogWrite(1,counter);
  delay(100);
}

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

Mega2560 als Master:

// I2c Master(Mega2560)

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);
}

void loop() {
  Wire.requestFrom(0x04, 1);
  while (Wire.available()) {
    byte c = Wire.read();
    Serial.println(c);
  }
  delay(1000);
}

Wenn ich eine LED, mit analogWrite angesteuert, ansehe, sind die übertragenen Werte plausibel.

Ich bin gerade noch unterwegs und kann es erst später testen.

Aber funktioniert so noch das Encoder auswerten bzw. das Counter zählen ?
Kenne mich mit der CriticalSection Funktion nicht aus.

Weil mein Vergleich zwischen Kanal A und B wird ja erst aufgrund einer Änderung an Kanal A ausgeführt ?

Wenn etwas nicht wie erwartet funktioniert, gilt es, den oder gar die Fehler systematisch einzukreisen. Darum gebe ich Dir ein Programm, das bei mir funktioniert. Wenn es bei Dir nicht funktioniert, liegt der Fehler nicht im Programm, sondern beispielsweise an vergessenen PullUp-Widerständen.

Wenn es auch bei Dir funktioniert, kann man den nächsten Schritt versuchen. Und so weiter. Immer Schritt für Schritt.

CriticalSection ist der Bereich, wo kein Interrupt dazwischenfunken sollte. Ob das hier notwendig ist, wäre noch zu prüfen. Bei den ursprünglichen zwei Bytes eines int wohl schon.

Servus,

also jetzt bekomme ich mal Werte die ständig steigen bis es zum überlaufen kommt.

152
162
172
182
192
202
212
222
232
242
252
6
16
26
35
45
55
65
75
85
95
105
115
125
135

Noch interessanter ist, dass die Werte um fast genau 10 je Sekunde (?) steigen.

michael_x:
Noch interessanter ist, dass die Werte um fast genau 10 je Sekunde (?) steigen.

delay(100); für den Zähler und delay(1000); für das Lesen sind um den Faktor 10 auseinander. Paßt schon.