Go Down

Topic: Problem mit TinyWireS (Read 2521 times) previous topic - next topic

Serenifly

Von der Kommunikation her geht es, aber da wird ein Array für die Daten genommen. Das hatte ich so gemacht wie es auf einem IC ist, wo man verschiedene Speicherzellen für verschiedene Daten hat. Erstens würde ich das heute nicht mehr so machen (siehe #9) und zweitens ist das nicht was du eigentlich willst. Du hast nicht zig Bytes an Daten die du senden willst.

Wenn man schnell genug abfragt sollte das eigentlich zeitlich gehen. Oder nimm die andere Variante mit der extra Statusleitung. Dann kannst du melden wenn etwas gedrückt wurde und sofort abfragen. Sollte aber nicht zwingend nötig sein

agmue

Von der Funktion: Auf dem ATtiny85 dekodiere ich eine IR-Fernbedienung. Bei einem neuen Tastendruck setze ich die Datenleitung, um dem Master dies mitzuteilen. Der Master setzt den Index dann auf Null und fordert ein Byte mit der Nummer der Taste an.

Das kommt, so dachte ich zumindest, Deiner Funktionalität recht nahe.

Serenifly meint aber, ich hätte eine exotische Variante der Programmbibliothek, was mir nicht mehr so in Erinnerung war und womit ich auch keine Verwirrung stiften wollte. Ich kann Dir die exotische Variante anbieten oder Du machst mit der normalen weiter.
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

Serenifly

Serenifly meint aber, ich hätte eine exotische Variante der Programmbibliothek,
Nicht exotisch. Halt eine andere. Die Version hatte ich wohl auch da verwendet. In der Version sind die Event Handler implementiert. In der anderen nicht. Das muss man beachten. Darüber ist er ja schon gestolpert und hat sich gewundert wieso ein anderes Beispiel nicht funktioniert.

magictrips

also mir is das ehrlich gesagt recht egal, was ich verwende, so lange es funktioniert.....

aber ich brauche ja nur das einfachste, was möglich ist....
nämlich nur ein byte senden, über zwei draht, da ich für drei drähte glaube ich keine pins mehr frei hab
aber selbst das läuft ja nicht ):

agmue

In #7 habe ich Dir die von mir verwendete TinyWireS mit Eventhandler angehängt. In requestEvent() müßtest Du buf[index]=0 setzen für "nichts los".

Ist nur ein Angebot, ich mache jetzt was anderes ...
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

magictrips

Vielen Dnak, ich habs jetzt mit der anderen TinyWireS hinbekommen, mal sehen ob ich auch den rest (im Loop) hinbekomme

magictrips

also ich habs jetzt sogar geschafft, ohne dieses void request()

hab einfach TinyWireS.send unter den Taster gepackt und der sendet mir beim Drücken des Tasters die bytes, die ich möchte.......
ansonst kommt immer 255 an.....aber kann man ja beim empfänger "wegprogrammieren"....

wenn ich das richtig verstanden hab, soll das ja falsch sein ? aber es funktioniert !

Serenifly

#22
Oct 29, 2015, 09:17 pm Last Edit: Oct 29, 2015, 09:19 pm by Serenifly
Na ja, normal haben Slaves die Schnauze zu halten wenn sie nicht gefragt werden. Du sagst du hast noch andere Geräte am Bus. Mit einem Slave mag das gehen. Aber was ist wenn du gerade mit der einer RTC oder einem LCD kommunizierst und du genau in dem Moment den Taster drückst?

magictrips

stimmt ! werd das mal ausprobieren, obwohl der slave ja einfach nur andauernd sendet und der master nur empfängt, wenn:

"
     byte num;
     Wire.requestFrom(I2C_SLAVE_ADDR, 1);
     while(Wire.available())
     {
     num = Wire.read();
     }     
"

Serenifly

Also ich habe es mal mit dem normalen Wire implementiert, auf einem UNO und einem Mega (als Slave). Das sollte sich aber leicht portieren lassen. Jedenfalls mit einer TinyWireS Version die die Event Handler implementiert hat.

Master:
Code: [Select]

#include <Wire.h>

const int POLLING_INTERVAL = 1000;

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

void loop()
{
  static unsigned long previousMillis;

  if (millis() - previousMillis > POLLING_INTERVAL)
  {
    previousMillis = millis();
   
    Wire.requestFrom(0x30, 1);
    int data = Wire.read();

    if (data > 0)
      Serial.println((char)data);
  }
}


Hier wird nur alle Sekunde abgefragt. Aber das kannst du auch wesentlich schneller machen um direkt zu reagieren. Also z.B. alle 100ms

Slave:
Code: [Select]

#include <Keypad.h>
#include <Wire.h>

const byte ROWS = 4;
const byte COLS = 3;

const char keymap[ROWS][COLS] = {
  { '1','2','3' },
  { '4','5','6' },
  { '7','8','9' },
  { '*','0','#' }
};
byte rowPins[ROWS] = { A0, A1, A2, A3 };
byte colPins[COLS] = { A4, A5, A6 };

Keypad keypad = Keypad(makeKeymap(keymap), rowPins, colPins, ROWS, COLS);

char keyPressed;

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

  Wire.onRequest(requestEvent);
  Wire.begin(0x30);
}

void loop()
{
  char key = keypad.getKey();
  if (key)
  {
    Serial.println(key);
    keyPressed = key;
  }
}

void requestEvent()
{
  Wire.write(keyPressed);
  keyPressed = 0;
}


getKey() liefert 0 wenn nichts gedrückt wurde. Das wird dann gesendet wenn nichts gemacht wurde. Deshalb auf dem Master auf > 0 abfragen

magictrips

vielen Dank !

Ich habs etwas anders gemacht.......
erstmal wollte ich auf die lib verzichten, da ich die nicht brauche.....
dann wollte ich die taster beim master auswerten.......
und ich überklebe mein keypad auch später mit neuen beschriftungen und verwende das zur steuerung (hoch, runter, links, rechts) usw......

ich habs gaaaaaanz einfach gemacht (;

Code: [Select]

#include <TinyWireS.h>
#define I2C_SLAVE_ADDRESS 0x26

const int R1 = 0;
const int R2 = 1;
const int R3 = 2;
const int R4 = 3;
const int C1 = 4;
const int C2 = 5;
const int C3 = 6;
const int C4 = 7;

const int T51 = 8;
const int T52 = 9;
const int T53 = 10;
const int T54 = 11;

const int T6 = 12;

const int T7 = 13;
 
void setup()                   
{

TinyWireS.begin(I2C_SLAVE_ADDRESS);

pinMode(R1, OUTPUT);     
pinMode(R2, OUTPUT);     
pinMode(R3, OUTPUT);     
pinMode(R4, OUTPUT);   

pinMode(C1, INPUT);
digitalWrite(C1, HIGH);
pinMode(C2, INPUT);
digitalWrite(C2, HIGH);
pinMode(C3, INPUT);
digitalWrite(C3, HIGH);
pinMode(C4, INPUT);
digitalWrite(C4, HIGH);

pinMode(T51, INPUT);
digitalWrite(T51, HIGH);
pinMode(T52, INPUT);
digitalWrite(T52, HIGH);
pinMode(T53, INPUT);
digitalWrite(T53, HIGH);
pinMode(T54, INPUT);
digitalWrite(T54, HIGH);

pinMode(T6, INPUT);
digitalWrite(T6, HIGH);
pinMode(T7, INPUT);
digitalWrite(T7, HIGH);

}

 
void loop()                     
{
 
  digitalWrite(R1, LOW);
  digitalWrite(R2, HIGH);
  digitalWrite(R3, HIGH);
  digitalWrite(R4, HIGH);
   
  if (digitalRead(C1) == LOW)
  {
  TinyWireS.send(11);
  }
 
  if (digitalRead(C2) == LOW)
  {
  TinyWireS.send(12);
  }
 
  if (digitalRead(C3) == LOW)
  {
  TinyWireS.send(13);
  }

  if (digitalRead(C4) == LOW)
  {
  TinyWireS.send(14);
  }
 
 
  digitalWrite(R1, HIGH);
  digitalWrite(R2, LOW);
  digitalWrite(R3, HIGH);
  digitalWrite(R4, HIGH);
   
  if (digitalRead(C1) == LOW)
  {
  TinyWireS.send(21);
  }
 
  if (digitalRead(C2) == LOW)
  {
  TinyWireS.send(22);
  }
 
  if (digitalRead(C3) == LOW)
  {
  TinyWireS.send(23);
  }

  if (digitalRead(C4) == LOW)
  {
  TinyWireS.send(24);
  }
 
 
 
  digitalWrite(R1, HIGH);
  digitalWrite(R2, HIGH);
  digitalWrite(R3, LOW);
  digitalWrite(R4, HIGH);
   
  if (digitalRead(C1) == LOW)
  {
  TinyWireS.send(31);
  }
 
  if (digitalRead(C2) == LOW)
  {
  TinyWireS.send(32);
  }
 
  if (digitalRead(C3) == LOW)
  {
  TinyWireS.send(33);
  }

  if (digitalRead(C4) == LOW)
  {
  TinyWireS.send(34);
  }
 
 
 
  digitalWrite(R1, HIGH);
  digitalWrite(R2, HIGH);
  digitalWrite(R3, HIGH);
  digitalWrite(R4, LOW);
   
  if (digitalRead(C1) == LOW)
  {
  TinyWireS.send(41);
  }
 
  if (digitalRead(C2) == LOW)
  {
  TinyWireS.send(42);
  }
 
  if (digitalRead(C3) == LOW)
  {
  TinyWireS.send(43);
  }

  if (digitalRead(C4) == LOW)
  {
  TinyWireS.send(44);
  }


  if (digitalRead(T51) == LOW)
  {
  TinyWireS.send(51);
  }
 
  if (digitalRead(T52) == LOW)
  {
  TinyWireS.send(52);
  }
 
  if (digitalRead(T53) == LOW)
  {
  TinyWireS.send(53);
  }

  if (digitalRead(T54) == LOW)
  {
  TinyWireS.send(54);
  }

  if (digitalRead(T6) != LOW)
  {
  TinyWireS.send(6);
  }

  if (digitalRead(T7) != LOW)
  {
  TinyWireS.send(7);
  }
 
   
}



hab halt ein 4*4 Keypad
ein 1*4 keypad
und zwei einzelne taster (öffnern).

bisher funktionierts wunderbar !

jetzt nur noch schauen ob sich das mit der rtc verträgt, wenn nicht klau ich aus deinem sketch diese request-geschichte (;


Serenifly

Das mit dem Taster kann man ja anders machen. Es geht darum dass man erst mal nur speichert was gedrückt wurde und es später absendet.


Diese Version kann onRequest():
https://github.com/rambo/TinyWire/tree/master/TinyWireS

Aber den 4313 muss man in usiTwiSlave.c eintragen. Da aber der 2313 schon unterstützt wird sollte das kein Problem sein. Die haben die gleiche Pin-Belegung

magictrips

ja, hab den schon eingetragen ! da hatte mich zum glück schultewolters drauf hingewiesen.....

aber danke an alle !

klappt wunderbar !

ohne request....... mit dem sketch oben und beim empfänger:

byte read_button()
{
  byte button;
  Wire.requestFrom(I2C_SLAVE_ADDR, 1);
  while(Wire.available())
  {
  button = Wire.read();
  }   

  return button;
}


manchmal ist eine extrem minimale, aber spührbare verzögerung drin, aber der ließt auch vorher einige sensoren aus.......

agmue

Die Variante mit onRequest() geht ja eigentlich so, daß der Master die Initiative ergreift. In Hinsicht auf weitere angeschlossene Slaves halte ich diese Vorgehensweise auch für die erfolgversprechendere. Da ich Dich möglicherweise ungewollt irritiert habe, wollte ich dann doch wenigstens einen funktionierenden Sketch anbieten, verbunden mit der Hoffnung, Du kannst ihn für Dich adaptieren.

Viele Passagen sind nicht von mir, sondern bereits innerhalb dieses Themas aufgetaucht oder aus Beispielen.

Slave ATtiny4313:
Code: [Select]

// Funktioniert mit https://github.com/rambo/TinyWire/tree/master/TinyWireS und Ergänzung von ATtiny4313
#include <TinyWireS.h>
#define SLAVE_ADR 0x02 // the 7-bit address (remember to change this when adapting this example)

const int C1 = 4;
const int C2 = 5;
const int C3 = 6;
byte wert = 0;

void requestEvent()
{
  TinyWireS.send(wert); //aktuellen Index auf Bus schreiben
  wert = 0;
}

void setup()
{
  TinyWireS.onRequest(requestEvent);
  TinyWireS.begin(SLAVE_ADR);
  pinMode(C1, INPUT_PULLUP);
  pinMode(C2, INPUT_PULLUP);
  pinMode(C3, INPUT_PULLUP);
}

void loop() {
  if (digitalRead(C1) == LOW) wert = 11;
  if (digitalRead(C2) == LOW) wert = 12;
  if (digitalRead(C3) == LOW) wert = 13;
}



Master Arduino UNO:
Code: [Select]

#include <Wire.h>
#define DS3231_I2C_ADDRESS 0x68
const char wochentage[] = {"SonMonDieMitDonFreSam"};
const int VERZOEGERUNG = 1000;
unsigned long millisRTC = millis();

const int SLAVE_ADR = 2;
byte zAlt = 0;
byte zNeu = 0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Serial.println(F("Programmstart"));
}

void loop() {
  zNeu = readByte(SLAVE_ADR);
  if ((zNeu != 0) && (zNeu != zAlt)) {
    Serial.print("Taste: ");
    Serial.print(zNeu, HEX);
    Serial.println();
  }
  zAlt = zNeu;
  delay(1);
  if (millis() - millisRTC >= VERZOEGERUNG) {    // Verzoegerungszeit abgelaufen?
    millisRTC = millis();                        // neue Zeit merken
    displayTime(); // display the real-time clock data on the Serial Monitor
  }
}

//ein Byte anfordern und lesen
int readByte(int adr)
{
  Wire.requestFrom(adr, 1);
  return Wire.read();
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);  // retrieve data from DS3231

  Serial.print(hour, DEC);  // send it to the serial monitor
  Serial.print(":");
  if (minute < 10) {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second < 10) {
    Serial.print("0");
  }
  Serial.print(second, DEC);

  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch (dayOfWeek) {
    case 1:
      Serial.println("Sunday");
      break;
    case 2:
      Serial.println("Monday");
      break;
    case 3:
      Serial.println("Tuesday");
      break;
    case 4:
      Serial.println("Wednesday");
      break;
    case 5:
      Serial.println("Thursday");
      break;
    case 6:
      Serial.println("Friday");
      break;
    case 7:
      Serial.println("Saturday");
      break;
  }
}

Die RTC habe ich nur ergänzt, um die funktionierende Kommunikation mit einem weiteren I2C-Slave zu demonstrieren.

Ausgabe (Sommerzeit)
20:16:46 31/10/15 Day of week: Saturday
20:16:47 31/10/15 Day of week: Saturday
20:16:48 31/10/15 Day of week: Saturday
20:16:49 31/10/15 Day of week: Saturday
Taste: B
20:16:50 31/10/15 Day of week: Saturday
20:16:51 31/10/15 Day of week: Saturday
Taste: D
20:16:52 31/10/15 Day of week: Saturday
Taste: C
20:16:53 31/10/15 Day of week: Saturday
20:16:54 31/10/15 Day of week: Saturday
20:16:55 31/10/15 Day of week: Saturday
20:16:56 31/10/15 Day of week: Saturday
20:16:57 31/10/15 Day of week: Saturday


Innerhalb von loop() mußte ich delay(1); einfügen, weil sonst die Veränderung des Tastendrucks nicht erkannt wird und "Taste: x" ständig ausgegeben wird. Wieso das so ist, konnte ich bisher nicht herausfinden. Es passiert auch, wenn ich die RTC-Abfrage rauslasse. Das müssen Dir schlauere Menschen erklären.  :)
Wahnsinn und Verstand trennt nur eine dünne Wand. (Daniel Düsentrieb)

Go Up