ADC Messung mit dem Attiny 841

Gast #6724935
Lesenswert?

Hallo
Beim Attiny 841 steht im Register ADCL und ADCH das Ergebnis der ADC 
Wandlung. In diesem Code erfolgt die Rückgabe des Ergenisses.
1
uint16_t ADC_Read()                  // ADC Einzelmessung
2
  {
3
  ADMUXA |=(1<<MUX1);          // Register ADMUXA
4
  // MUX - Auswahl welcher Eingang - 00011 - ADC3
5
  ADCSRA |= (1<<ADSC);                    // Register ADCSRA
6
  // ADSC - Start Konvertierung "single conversion"
7
  while (ADCSRA & (1<<ADSC) )
8
    {                        // auf Abschluss der Konvertierung warten
9
    }
10
  return ADCW;                            // ADC auslesen und zurückgeben
11
  }
Leider konnte ich verstehen was ADCW ist. Nach Angabe kann ich 10 Bit 
oder 8 Bit zurückgeben.
Wie kann ich das einstellen?
Gast #6724957
Lesenswert?

Heiner schrieb:
> Leider konnte ich verstehen was ADCW ist.

Ich nehme an du hast es nicht verstanden.

Aber ein Blick ins Datenblatt (16.13.3) lässt die Vermutung
aufkommen dass es sich um eine Kombination von ADCL und ADCH
handelt.

Das bestätigt dann auch ein Blick in die Datei iotn841.h
Gast #6724964
Lesenswert?

Wenn ich das in 16.13.5 richtig verstanden habe besteht ADCW bei 10 Bit 
aus ADCH und ADCL. Wenn ich nur 8 Bit brauche wird in Register ADCSRB 
das Bit ADLAR auf 1 gsetzt.
Habe ich das richtig verstanden?
Gast #6725017
Lesenswert?

Heiner schrieb:
> Kannst du mir ein paar Tips geben wenn ich 10 Bit per I2C übertragen
> will?

Man überträgt einfach zweimal 8 Bit (ein 10 Bit ADC Wert wird
in einer 16 Bit Variable gespeichert, siehe Return-Wert ADCW)
da du 10 bit über I2C nicht einfach übertragen kannst.
Gast #6725036
Lesenswert?

Habe bisher die übertragung der Tastenzustände am Attiny 841 vom Slave 
zum Master und zurück hinbekommen. Paralle habe ich den Komparator und 
ADC am ATI 841 geschafft. Da der Ati 841 beim Bus sehr anders ist, kann 
ich meine bisherigen Programm mit dem Atmega 128 nicht nutzen. Da werde 
ich wohl erst einiges machen müssen.
Gast #6725170
Lesenswert?

Heiner schrieb:

> Habe bisher die übertragung der Tastenzustände am Attiny 841 vom Slave
> zum Master und zurück hinbekommen. Paralle habe ich den Komparator und
> ADC am ATI 841 geschafft. Da der Ati 841 beim Bus sehr anders ist, kann
> ich meine bisherigen Programm mit dem Atmega 128 nicht nutzen.

Nicht der Bus ist anders, nur die Hardware. Und deren Funktionsprinzip 
ist sehr ähnlich, wenn man mal gedanklich auf Slave beschränkt und die 
Smart-Features des 441/841-TWI-Slave aussen vor läßt, also nicht 
aktiviert.

Unter diesen Randbedingungen kann man gut geschriebenen Slave-Code für 
die normale Mega-TWI-Einheit praktisch ohne jegliche strukturelle 
Änderungen für den TWI-Slave der 441/841 übernehmen. Man muß nur etliche 
symbolische Konstanten singemäß anpassen.

Setzt natürlich voraus, dass man den Sinn verstanden hat, was bei selbst 
geschriebenem Code vorausgesetzt werden kann. Nur bei C&P-Code muss man 
erst verstehen lernen, was der eigentlich tut...
Gast #6725303
Lesenswert?

Ich möchte euch auf keinen Fall verarschen. Um den Attiny 841 zu 
verstehen gehe ich jeden Anwendungsfall nach Datenblatt durch. Dazu 
übersetze ich mir den Inhalt, lese die Register genau und vergleiche es 
mit den Programmen die ich bisher habe. Hatte euch ja schon öfters um 
Rat gefragt und viele Infos dazu bekommen.
Mein Code für den Attiny841 als Slave zum I2C Bus:
1
void I2C_init(void)
2
  {
3
  TWSA = I2C_SLAVE_ADDRESS;          // TWI Adressregister
4
  TWSD = 0xFF;                // Datenregister
5
  TWSCRA = (1<<TWEN)|(1<<TWSHE)|(1<<TWASIE)|(1<<TWSIE)|(1<<TWDIE);      
6
  // Register A, TWEN-Schnittstelle Aktivieren, TWSHE-Haltezeit aktivieren, TWASIE-Adressenunterbrechung aktivieren, 
7
  // TWSIE-Stop Unterbrechung aktivieren, TWDIE-Datenunterbrechung aktivieren 
8
    TWSCRB = (1<<TWAA)|(1<<TWCMD1)|(0<<TWCMD0);  // Register B, TWI Bestätigungsaktion, TWI Befehl
9
  sei();      // Interrups einschalten
10
  }
Und ISR dazu:
1
ISR( TWI_SLAVE_vect )
2
  {
3
    uint8_t status = TWSSRA & 0xC0;      // Register A
4
  if (status & I2C_DATA_INTERRUPT)
5
  // Daten wurden vom Master empfangen oder werden angefordert
6
    {
7
      if (TWSSRA & (1 << TWDIR))          // Master fordert Daten vom Slave an
8
      {
9
      TWSD = tx_buff;
10
      TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
11
      }
12
    else       // Master sendet Daten zum Slave
13
      {
14
      TWSCRB |= (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
15
      command = TWSD;
16
      }
17
    }
18
  else if (status & I2C_ADDRESS_STOP_MATCH)
19
    {
20
    if (TWSSRA & I2C_BUS_COLLISION)
21
      {
22
      TWSCRB = (uint8_t) (1<<TWCMD1);
23
      }
24
    else
25
      {
26
      if (TWSSRA & (1<<TWAS))
27
        {
28
        // ACK
29
        TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
30
        }
31
      else
32
        {
33
        // Stop Condition
34
        TWSCRB = (uint8_t) (1<<TWCMD1);
35
        }
36
      }
37
    }
38
  }
Damit kann ich bereits Daten zum Master übertragen.
Sicher geht es besser.
Heiner
Gast #6725331
Lesenswert?

Noch mal zur ADC.

Heiner schrieb:
> Wenn ich das in 16.13.5 richtig verstanden habe besteht ADCW bei 10 Bit
> aus ADCH und ADCL. Wenn ich nur 8 Bit brauche wird in Register ADCSRB
> das Bit ADLAR auf 1 gsetzt.
> Habe ich das richtig verstanden?

Habe jetzt ADCSRB |=(1<<ADLAR) auf 1 gesetzt. Habe dann die Spannung 
zwischen 0 und 5V verändert. Klappt aber nicht damit nur 8 Bit zu 
nutzen.
Mit welchem Bit kann ich von 10 Bit auf 8 Bit umschalten?
Gast #6725834
Lesenswert?

Heiner schrieb:

> Habe jetzt ADCSRB |=(1<<ADLAR) auf 1 gesetzt. Habe dann die Spannung
> zwischen 0 und 5V verändert. Klappt aber nicht damit nur 8 Bit zu
> nutzen.

Doch das klappt schon. Wenn man verstanden hat, was da passiert.

> Mit welchem Bit kann ich von 10 Bit auf 8 Bit umschalten?

Garnicht. Wenn du nur 8 Bit des Ergebnisses haben willst, benutzt du 
auch einfach nur acht Bit davon.

ADLAR dient nur dazu, die relevanten 8Bit der Wandlungsergebnisses in 
einem 8Bit-Register bereitzustellen und erspart so, zwei Register 
auszulesen und das Ergebnis erst passend zu hinschieben zu müssen.

Sprich: statt ADCW (2x 8 Bit) liest du nur ADCH aus. Da stehen deine 8 
Bit schon vollkommen passend drinne. Die zwei wegzuwerfenden Bits stehen 
in ADCL. Da du sie sowieso wegwerfen willst, brauchst du es erst 
garnicht auslesen.
Gast #6725881
Lesenswert?

Heiner schrieb:
> Klappt aber nicht damit nur 8 Bit zu nutzen.
> Mit welchem Bit kann ich von 10 Bit auf 8 Bit umschalten?

Ich habe es dir doch beschrieben wie es funktioniert.
Was bitte ist an meinem Satz nicht zu verstehen?
Du schaffst es nicht deine Lesefunktion so abzuändern damit
es wie von mir beschrieben arbeitet?

weiter weg schrieb:
> Ja, und nur ADCH auslesen (8 bittig!)... da die unteren 2 Bit
> nicht zu auswerten sind.

Wenn du das nicht willst/kannst dann unterstelle ich dir Trollerei
oder vollständige Überforderung. Im zweiten Fall empfehle ich dir
ein anderes Hobby wie z.B. Wandern oder Stricken/Häkeln.
Gast #6725938
Lesenswert?

Warun wird hier einem sofort ein Troll zu sein untergeschoben?
Die Fragen die ich stelle sind von grossen Intresse für mich.
Ist das der Umgang von euch sogenannten Fachleuten mit Anfänger oder 
macht ihr nur Stimmung oder blöde Anmache.
Zurüchk zum Thema.
Habe es jetzt so hinbekommen.
1
ADCSRB |=(1<<ADLAR);        // bei 8 Bit links
2
  while (ADCSRA & (1<<ADSC))
3
    {                  // auf Abschluss der Konvertierung warten
4
    }
5
  //return ADCW;            // ADC auslesen und zurückgeben bei 16 Bit
6
  return ADCH;            // 8 Bit mit ADLAR=1
Damit läuft 8 Bit und ich kann mit den Auskommentierten Zeilen auf 16 
Bit umstellen.
Bleibt noch das Problem mit der übertragung von 16 Bit mit dem Bus.
Gast #6725946
Lesenswert?

Heiner schrieb:

> Bleibt noch das Problem mit der übertragung von 16 Bit mit dem Bus.

Du meinst, es bleibt das Problem, dass dir da noch niemand eine fertige 
Lösung geliefert hat, richtig?

Wie wäre es mal mit tatsächlich selber programmieren? Alles Nötige an 
Hinweisen hast du im Laufe dieses Threads bereits bekommen.

Mehr geht nicht, das wäre Auftragsarbeit, dafür musst du mit Kohle rüber 
kommen.
Gast #6726068
Lesenswert?

Nicht schon wieder das mit dem Troll. Versuche einfach es zu verstehen.
Hatte weiter oben bereits den Code für den Attiny 841 und den I2C bus 
angegeben. Da er anders ist z.B. als bei einem Slave (kein Prozessor) 
mit 16 Bit sieht die übertragung anders aus. Leider habe ich im Netz 
keine Info dazu gefunden.Vielleicht gehen ein paar Brocken zu meinem 
Verständnis.
Gast #6726105
Lesenswert?

Heiner schrieb:

> mit 16 Bit sieht die übertragung anders aus.

Nur ganz unwesentlich.

> Leider habe ich im Netz
> keine Info dazu gefunden.Vielleicht gehen ein paar Brocken zu meinem
> Verständnis.

Mein Gott. Verstehe einfach, wie I2C funktioniert und benutze es. Das 
hat doch rein garnix mit der AVR8-Architektur im Allgemeinen oder dem 
TWI-Slave der ATiny441/841 im Besonderen zu schaffen.

Man muss einfach nur verstehen, wie der Bus funktioniert und den 
vorhandenen Code entsprechend nutzen. Wenn man ein Byte korrekt senden 
kann, zwei aber nicht, beweist das genau eine Sache: Man benutzt Code, 
den man nicht verstanden hat. Und die einzige logische Erklärung dafür 
ist:

Weil man wohl einfach zu FAUL war, zu lernen, wie der Bus 
funktioniert...
Gast #6726144
Lesenswert?

Heiner schrieb:
> Hatte weiter oben bereits den Code für den Attiny 841 und den I2C bus
> angegeben.

Das hast du nicht!
Die Initialisierung, ja.
Die ISR auch.

Aber die (read/Write) API zur Software hast du geheim gehalten.

Also:
Nur ein untestbares Fragment gezeigt.
Exakt den Bereich, an dem es hakt, geheim gehalten.
Gast #6726250
Lesenswert?

Habe nichts geheim gehalten. Noch mal das komplette Programm. Mehr habe 
ich dazu nicht und es geht damit.
1
#include "main.h"            // CPU 16MHz
2
#include <avr/interrupt.h>        // dient zur Behandlung der Interrupts
3
#include <avr/io.h>            // Integer-Definitionen
4

5
#define I2C_SLAVE_ADDRESS       0x52  // Slave Adresse 0x52
6
#define I2C_DATA_INTERRUPT      0x80  // 0x80
7
#define I2C_BUS_COLLISION       0x08  // 0x08
8
#define I2C_ADDRESS_STOP_MATCH  0x40  // 0x40
9

10
volatile uint8_t command;
11
volatile uint8_t tx_buf[2];  // 4
12
volatile uint8_t tx_buff = 11;  // 4
13
volatile uint8_t tx_buf_index = 0;
14

15
// Funktionsprototypen
16
void I2C_init(void);
17

18
void I2C_init(void)
19
  {
20
  TWSA = I2C_SLAVE_ADDRESS;          // TWI Adressregister
21
  TWSD = 0xFF;                // Datenregister
22
  TWSCRA = (1<<TWEN)|(1<<TWSHE)|(1<<TWASIE)|(1<<TWSIE)|(1<<TWDIE);      
23
  // Register A, TWEN-Schnittstelle Aktivieren, TWSHE-Haltezeit aktivieren, TWASIE-Adressenunterbrechung aktivieren, 
24
  // TWSIE-Stop Unterbrechung aktivieren, TWDIE-Datenunterbrechung aktivieren 
25
    TWSCRB = (1<<TWAA)|(1<<TWCMD1)|(0<<TWCMD0);  // Register B, TWI Bestätigungsaktion, TWI Befehl
26
  sei();      // Interrups einschalten
27
  }
28

29
ISR( TWI_SLAVE_vect )
30
  {
31
    uint8_t status = TWSSRA & 0xC0;      // Register A
32
  if (status & I2C_DATA_INTERRUPT)
33
  // Daten wurden vom Master empfangen oder werden angefordert
34
    {
35
      if (TWSSRA & (1 << TWDIR))          // Master fordert Daten vom Slave an
36
      {
37
      TWSD = tx_buff;
38
      TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
39
      }
40
    else       // Master sendet Daten zum Slave
41
      {
42
      TWSCRB |= (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
43
      command = TWSD;
44
      }
45
    }
46
  else if (status & I2C_ADDRESS_STOP_MATCH)
47
    {
48
    if (TWSSRA & I2C_BUS_COLLISION)
49
      {
50
      TWSCRB = (uint8_t) (1<<TWCMD1);
51
      }
52
    else
53
      {
54
      if (TWSSRA & (1<<TWAS))
55
        {
56
        // ACK
57
        TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
58
        }
59
      else
60
        {
61
        // Stop Condition
62
        TWSCRB = (uint8_t) (1<<TWCMD1);
63
        }
64
      }
65
    }
66
  }
67

68
int main(void)
69
  {  
70
  DDRA=0b00000011;      // Port A auf Ausgang schalten
71
  PORTA=0b00000011;      // Port A auf aus 
72
  DDRB=0b00000011;      // Port A auf Ausgang schalten
73
  PORTB=0b00000011;      // Port A auf aus  
74
  I2C_init();
75
  while(1)
76
    {
77
    if (command != 42)       // Taster T2 PD0
78
     {              // Wenn T1 gedrückt...
79
       PORTA &=~(1<<PINA1);    // LED 2 ein  
80
     }
81
     else
82
    {              // wenn nicht
83
       PORTA |=(1<<PINA1);    // LED 2 ein ??
84
    }  
85
     if (command != 43)       // Taster T2 PD0
86
    {              // Wenn T1 gedrückt...
87
      PORTA &=~(1<<PINA0);    // LED 2 ein
88
    }
89
     else
90
    {              // wenn nicht  
91
      PORTA |=(1<<PINA0);    // LED 2 ein ??
92
    }   
93
    
94
    {
95
    
96
      {
97
            
98
    // ========>> TASTENEINGABEN T3
99
    if (!(PINA & (1<<PINA7)) )  // Taster T 3
100
      {              // Wenn T3 gedrückt...
101
      tx_buff = 5;  // 4
102
      }
103
    
104
    // ========>> TASTENEINGABEN T2
105
    if (!(PINB & (1<<PINB2)) )  // Taster T 3
106
      {              // Wenn T3 gedrückt...
107
      tx_buff = 3;  // 4
108
      }    
109
      }
110
    }
111
   
112
    }
113
  }
Das einzige was fehlt ist die main. Da steht nur drin das CPU 10MHz 
sind.
LG Heiner
Gast #6726317
Lesenswert?

Danke für die Info

Matthias S. schrieb:
> In deiner ADC Routine könnte zum füllen dann stehen
> tx_buff[0] = ADCH;
> tx_buff[1] = ADCL;

Bei 16 Bit verwende ich ADCW und das besteht aus ADCH und ADCL.
Wenn ich nur 8 Bit verwende, nutze ich ADCH und ADLAR=1.
Dann brauche ich im Master nur aus denn 2 x 8 Bit wieder 16 Bit machen.
Das gefällt mir.

Heiner schrieb:
> if (TWSSRA & (1 << TWDIR))          // Master fordert Daten vom Slave an
>       {
>       TWSD = tx_buff;
>       TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
>       }

Meinst du diese Stelle?
Gast #6726385
Lesenswert?

Das Programm des Slave beim I2C Bus bzw. ISR empfinde ich als relativ 
gross und kompliziert. Da ich noch nicht beim Bus angekommen bin, ergibt 
sich eine Frage für mich.
Gibt es ein weniger Aufwändiges Programm für den Slave beim Attiny 441?
#6726477
Lesenswert?

Hallo,

I2C erfordert mehr Aufwand. Derzeit schreibst du das zu sendende Byte 
direkt in das Senderegister. Du weißt es kann nur ein Daten Byte geben, 
deswegen ist alles andere "egal". Für mehr als 1 Daten Byte benötigt man 
ein Protokoll. Ansonsten weiß man nicht ob ein Byte das Erste oder das 
Zweite oder welches überhaupt ist, wenn man hintereinander senden würde. 
Schau dir einmal die App Note AVR311 und AVR315 von Atmel an. Die 
Register passt du auf deinen ATtiny an.
https://www.microchip.com//wwwAppNotes/AppNotes.aspx?appnote=en591794
https://www.microchip.com//wwwAppNotes/AppNotes.aspx?appnote=en591792

Am Ende hast du eine Sende- und Empfangsfunktion.
#6726944
Lesenswert?

Heiner schrieb:
> Habe mir die Stellen angesehen. Bin dazu geteilter Meinung. Habe z.B.
> Angaben wie asm und nop gefunden. Dachte eigentlich das sowas lange raus
> ist.

Hallo,

du meinst das?
1
asm("nop");

nop bedeutet eine einzige Taktverzögerung in der Arbeitung. asm bedeutet 
das nop inline gemacht wird, also wirklich real einen Takt Pause 
erzeugt. Im Kontext betrachtet mit den Kommentaren steht das in dem Code 
Bsp. nur als Platzhalter für irgendwelchen weiteren Code.

nop ist auch heute noch praktisch wenn man es sinnvoll einsetzt. Bspw. 
redet dein µC mit einem Device welches mittels meinetwegen SPI 
angesprochen wird. Jetzt ist dein Bus samt deiner Code Abarbeitung 
schneller wie das Device mit gewissen Wartezeiten zwischen seinen 
Kommandos/Daten. Allerdings sind die Wartezeiten auch nicht so lang, 
dass es sich lohnt kurz andere Dinge zu erledigen. Vorrausgesetzt Du 
möchtest das Device so schnell wie möglich fertig behandelt haben. Du 
benötigst bspw. 100ns Wartezeit wofür es sich nicht lohnt erst aus einer 
Funktion rauszuspringen und dann wieder reinzuspringen. Das benötigt 
deutlich mehr Takte als was es bringt. Hier kannste bspw. 2x nop 
einbauen. CPU Takt 20MHz -> 1x nop 50ns. Wenn das Device nicht 
zeitkritisch ist muss man es nicht machen und kann zwischendurch anderes 
erledigen.

Oft sieht man folgendes define.
1
#define NOP __asm__ __volatile__ ("nop\n\t")

Wofür \n\t hinter nop dienen soll kann ich nicht erklären.
new line und Tabulator? Wer kann den Grund dafür zusammen mit nop 
erklären?
Gast #6727000
Lesenswert?

Veit D. schrieb:
> Wofür \n\t hinter nop dienen soll kann ich nicht erklären.
> new line und Tabulator? Wer kann den Grund dafür zusammen mit nop
> erklären?

Wenn man sich den ASM Zwischencode anzeigen lässt, steht das schön 
untereinander, statt in einer Zeile gequetscht
Gast #6727003
Lesenswert?

Veit D. schrieb:
> Wofür \n\t hinter nop dienen soll kann ich nicht erklären.

Zeilenumbruch und Tabulator.
In Assembler muss hinter jedem Befehl ein Zeilenumbruch kommen und die 
Befehle sind üblicherweise mit Tabulator ein gerückt. Das spielt erst 
eine Rolle, wenn du mehrere asm befehle hintereinander schreibst und 
dann den Quelltext als Assembler-Listing ausgibt. Der sieht dann schöner 
aus.
#6727139
Lesenswert?

Hallo,

Danke euch. Also Syntaxvorschrift. Im disassamblierten Code kann ich das 
nicht herauslesen. Da finde ich nur
1
#define NOP __asm__ __volatile__ ("nop\n\t")
2
  NOP; 
3
 280:  00 00         nop
4
  asm("nop\n\t");
5
 282:  00 00         nop

Original:
1
void setup (void)
2
{
3
  #define NOP __asm__ __volatile__ ("nop\n\t")
4
  NOP; 
5
  asm("nop\n\t");
6
}
7

8
void loop (void)
9
{ }
Angehängte Dateien:
Gast #6727863
Lesenswert?

Du scheinst es nicht zu glauben. Ich will keinen ärgern, über den Tisch 
ziehen oder ähnliches damit machen. Mein Ziel ist es einfach den Attiny 
441 (841) zu verstehen und anzuwenden. Mir gefällt einfach die 
Baugrösse, klein relativ wenige Pins und viele Anwendungen. Leider 
scheint meine Freude an dem IC nur von wenigen geteilt zu werden. Man 
findet im Netz wenige Beispiel dazu. Ja es stimmt, verwende teilweise 
vorhandenen Code aus dem Netz. Das sind dann aber Sachen um die Funktion 
zu verstehen oder einfach mal anschauen wie es andere machen. Wenn ich 
dann das Datenblatt dazunehme komme ich mit den Funktione weit aus 
besser klar. Da die Anwendung aber auf mein Brett bezogen sind, muss ich 
alles umbauen oder halt neu machen.
Soweit ist das klar. Sehen wir mal was es so für den I2C Bus gibt. Ein 
Programm geht ja, ist aber wahrscheinlich einfacher möglich.
LG Heiner
Gast #6728090
Lesenswert?

@Stefan

Das wage ich zu bezweifeln. Auch wenn Arduino Libraries bietet, mit 
denen man Funktionen “zusammenklimpern” kann, muss man dennoch wissen, 
wie es geht 😉.

Außerdem hat Veit D. schon mit den links brauchbare Hinweise gegeben- 
wenn man aber nicht versteht sie anzuwenden…
Gast #6728166
Lesenswert?

Stefan ⛄ F. schrieb:
> Mit Arduino wärst du längst fertig.

Das ist schon möglich.
Kann ich den die ganzen Sachen verwenden wenn ich nicht mit einem 
Arduino arbeite?
Habe bisher alles in C gemacht ohne die ganzen Sachen von Arduino.
Alle notwendigen Sachen für den I2C Bus beim Attiny 841 sollen im 
Datenblatt stehen. Mag sein, leider schwer für mich zu verstehen. Habe 
angefangen die Register anzuschauen und wenn möglich zu verstehen. Ist 
leider für mich sehr schwer. Kann mir jemand dabei helfen es zu 
verstehen?
Gast #6728204
Lesenswert?

Die ADC mit 8 und 16 Bit geht ohne Probleme.
Möchte jetzt einfach weitermachen und den ADC Wert auf einem Display mit 
dem Bus darstellen. Dazu möchte ich einen Atmega 128 als Master 
verwenden und ein Display ansteuern. Die Ansteuerung mit dem Atmega 
funktioniert bereits korrekt.
Soll ich lieber etwas neues aufmachen?
Gast #6728217
Lesenswert?

Hannes schrieb:
> Ich dachte, Du hättest den I2C Bus vom Attiny 841 schon funktionsfähig
> bzw. schon Daten per I2C ausgetauscht?

Ja das stimmt, habe bereits Daten ausgetauscht. Leider ist das Programmm 
für den Slave etwas gross geraten. Deshalb mein Versuch es etwas kleiner 
und damit übersichtliches zu machen. Habe das Datenblatt dazu genommen, 
komme leider nur sehr schwer damit zurecht. Das funktionierende Beispiel 
für den slave kann ich kaum nachvollziehen.
Gast #6728225
Lesenswert?

Hallo Heiner

Habe ich das korrekt verstanden:
Du willst mit dem Attiny 841 per ADC Werte einlesen (8 Bit), diese per 
I2C an den Atmega 128 schicken und die Werte per Display (das direkt 
ohne I2C am Atmega 128 angeschlossen ist) anzeigen.
Stimmt meine Zusammenfassung?
Gast #6728562
Lesenswert?

Heiner schrieb:
> Kann ich den die ganzen Sachen verwenden wenn ich nicht mit einem
> Arduino arbeite?

Ja schon, weitgehend. Voraussetzung ist, dass Arduino diesen 
Mikrocontroller unterstützt. Offenbar gibt es für den ATtiny841 ein 
passendes Plugin (Core).

> Alle notwendigen Sachen für den I2C Bus beim Attiny 841 sollen im
> Datenblatt stehen. Mag sein, leider schwer für mich zu verstehen.

Ja das ist so. Die I²C Schnittstelle ist komplizierter als die meisten 
anderen, weil sie nicht nur einfach nur Daten rein/raus schiebt sondern 
ein komplettes Protokoll implementiert.

In Arduino ist der Teil bereits fertig. Diesen Anzuwenden ist fast so 
einfach, wie printf().

> Kann mir jemand dabei helfen es zu verstehen?

Fange mal mit eine Beschreibung des Protokolls an:
https://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/

Erstmal musst du verstehen, welche Signale der Bus in welcher 
Reihenfolge überträgt und welche Zustände es gibt. Denn diese spiegeln 
sich in den Registern wieder.

Lies auch die I²C Spezifikation, das Dokument ist uralt aber sehr gut:
https://www.nxp.com/docs/en/user-guide/UM10204.pdf
Gast #6728622
Lesenswert?

Hannes schrieb:
> Du willst mit dem Attiny 841 per ADC Werte einlesen (8 Bit), diese per
> I2C an den Atmega 128 schicken und die Werte per Display (das direkt
> ohne I2C am Atmega 128 angeschlossen ist) anzeigen.

Stimmt nicht ganz. Der Attiny 841 soll per I2C an den Atmega 128 
angeschlossen werden. Auch das Display wird per I2C angeschlossen z.B. 
mit PCF8574. Verwende teilweise verschiedene Displays. Das Display und 
Verbindung mit verschiedenen Slaves funktioniert korrekt.

Stefan ⛄ F. schrieb:
> Ja das ist so. Die I²C Schnittstelle ist komplizierter als die meisten
> anderen, weil sie nicht nur einfach nur Daten rein/raus schiebt sondern
> ein komplettes Protokoll implementiert.

Da gebe ich dir sofort Recht.
Mit diesem Protokoll gibt es den Attiny 441/841. Gibt es da noch andere 
Typen mit dem gleichen Protokoll.
LG Heiner
Gast #6728651
Lesenswert?

Heiner schrieb:
> Mit diesem Protokoll gibt es den Attiny 441/841. Gibt es da noch andere
> Typen mit dem gleichen Protokoll.
Die Frage verstehe ich nicht

I2C ist ein Protokoll!
Das Protokoll besteht aus einer Hardware Vereinbarung und einem 
logischen Regelwerk.

Ich sage mal: ALLE µC können I2C.
Ein paar Tinys bieten dafür den USI Block
Andere Mega, nutzen spezialisierte TWI Einheiten.
Und per Software geht auch immer, wenn sonst nix geht.

Also:
Protokolle hat man nicht, sondern man implementiert sie.

Ist klar geworden, wo der Fehler in der Frage liegt?
Gast #6728958
Lesenswert?

Vom Hersteller dieser Attiny werden noch andere Typen produziert. Gibt 
es andere Typen die die gleiche Hardware haben? Bei denen man auch mit 
der gleichen Software arbeiten kann?
Beispiel:
Es gibt Attiny die haben kein I2C. Da kann man per Software etwas 
machen.
Es gibt Attiny die haben I2C Bus ohne eigenes Protokoll.
Gibt es andere Attinys die das gleiche Protokoll verwenden?
Kurz gesagt, gibt es noch andere Typen deren Software auf dem Attiny 441 
anwenden oder vergleichen kann?
#6728971
Lesenswert?

Also ich habe den Tiny841 in einigen Projekten im Einsatz. Der tut was 
er soll, ohne große Überraschungen. Keine Ahnung warum jetzt 
ausgerechnet dieser Controller hier das Problem sein soll. Der TE ist 
das Problem. Mit dem Wissenstand wird JEDER Controller zum Problem. 
Daher kann ich leider auch nicht wirklich On-Topic antworten. Das wäre 
alles müßig und vergebens.
Gast #6728997
Lesenswert?

Verwende selber diesen Controller in einigen Anwendungen. Da ich ein 
Anfänger bin erarbeite ich mir die Anwendungen. Schaue dazu ins 
Datenblatt und gehe die verschiedenen Möglichkeiten durch. Weiter oben 
habe ich nach ADC gefragt. Das funktioniert jetzt ohne Probleme. Kann es 
Anwenden und Nutzen. Bin dan zur nächsten Stufe gegangen und das ist für 
mich I2C, die übertragung der Daten vom Slave zum Master und Anzeige auf 
einem Display. Bei anderen Controller habe ich das relativ einfach 
hinbekommen. Leider ist das Beispiel für einen funktionierenden Slave 
sehr gross und für mich in einigen Sachen nicht verständlich. Deshalb 
einfach die Frage nach Hilfe dabei.
Gast #6728999
Lesenswert?

Hannes schrieb:
> Hast Du hier schon mal geschaut
> Beitrag "ATtiny841 I2C Slave Beispiel"

Ja, diesen Beitrag kenne ich. Er ist auch Grundlage für meinen Slave. 
Mein Programm funktioniert damit, noch ein paar Anpassungen und es geht.
Was ich daran nicht verstehe ist die ISR. Die ist doch so gross.
Geht das nicht auch kleiner?
Gast #6729093
Lesenswert?

Hallo Hannes
Es geht haupsächlich darum es zu verstehen.
Habe jetzt im Netz gesucht und noch einiges gefunden.
Einfache Frage dazu:
Warum braucht der Attiny 441
- void Timer0_init(void)
- ISR(TIMER0_COMPA_vect)
- ISR(TWI_SLAVE_vect)

Da ich den Attiny 441(841) in verschiedenen Schaltungen verwenden 
möchte, kann es dazu führen 16 Bit oder 8 Bit oder mehrfache 8 Bit (z.B. 
2 oder 4 x ADC) oder (schnelle) Schalterstelleungen zu übertragen. Das 
nutze ich z.B. um eine Tasterentprellung zu machen. Dadurch kann man 
Tasten verschieden nutzen. Oder einen Enkoder als universeller Eingabe 
zu verwenden oder ein Joystick.
Teilweise sind Teile da von schon lauffähig, andere warten noch auf das 
Programm.
LG Heiner
Gast #6729121
Lesenswert?

Heiner schrieb:
> Mit diesem Protokoll gibt es den Attiny 441/841. Gibt es da noch andere
> Typen mit dem gleichen Protokoll.

Alle Mikrocontroller mit I²C (bzw. TWI), also eigentlich fast alle außer 
ein paar wenige Ausnahmen die nur USI haben. Die sind noch schwieriger 
zu programmieren.

Heiner schrieb:
> Vom Hersteller dieser Attiny werden noch andere Typen produziert. Gibt
> es andere Typen die die gleiche Hardware haben? Bei denen man auch mit
> der gleichen Software arbeiten kann?

Was soll denn diese Frage? Andere Typen mit gleicher hardware wirst du 
genau so wenig programmieren können. Bleibe mal lieber auf dem Weg zur 
Problemlösung.
#6729185
Lesenswert?

Hallo,

ehrlich gesagt verstehe ich dein Problem, Heiner, so langsam auch nicht 
mehr. Wenn du es bei anderen Controllern hinbekommen hast, woran 
scheitert es dann beim ATtiny? Das kam noch nie zur Sprache. Schau mal 
ob du damit was anfangen kannst.
http://www.peterfleury.epizy.com/avr-software.html#libs
Es ist auch keine Schande sich die Arduino Quellen anzuschauen oder gar 
zu nutzen. Im Grunde brauchst du dir nur die Quellen von Spencekonde 
anschauen. 
https://github.com/SpenceKonde/ATTinyCore/tree/master/avr/libraries/Wire
Jetzt bist du dran.
Gast #6729209
Lesenswert?

Es scheitert daran, daß manche AVR
- Kein I²C interface haben
- andere kein USI Interface besitzen
- wieder andere keins von Beiden und mittels Software selbst eines 
gebastelt werden muss

- Unverständliche Software mit unverständlichen Bibliotheken aus aller 
Herren Länder verwurstelt werden muß.

-> Schmeiß den Dreck aus dem Konntrolle und installiere Bascom. Damit 
geht es am Einfachsten und es gibt jeweils ein Beispielprogramm in der 
Hilfe.
Gast #6729226
Lesenswert?

Veit D. schrieb:
> Schau mal
> ob du damit was anfangen kannst.
> http://www.peterfleury.epizy.com/avr-software.html#libs

Die Datein und Programme von Peter verwende ich bereits. Besonders für 
I2C und das Display. Seine Programme sind auch Grundlage bei anderen 
Sachen von mir.
Leider ist der Attiny 441 mit seinem I2C Bus anders als die anderen. 
Nach Quellen im Netz haben die es total anders gemacht. Mit den anderen 
Programmen die auf den slaves laufen geht es nicht. Teilweise sind die 
Register anders.
Da muss ich mich weiter durchkämpfen.
LG Heiner
#6729264
Lesenswert?

Heiner schrieb:
> Stefan ⛄ F. schrieb:
>> Was soll denn diese Frage? Andere Typen mit gleicher hardware wirst du
>> genau so wenig programmieren können. Bleibe mal lieber auf dem Weg zur
>> Problemlösung.
>
> Habe gehofft einen anderen IC zu finden mit der gleichen Hardware, wo es
> vielleicht besser passende Software.

Naja, wenn's die gleiche Hardware ist, wird's wohl auch die gleiche 
Software sein ...
Denke, es wäre zielführend, wenn Du mal ALLE (!) Deine bislang für 
dieses Projekt erstellten Sourcen hier zur Verfügung stellen würdest; 
vielleicht könnte man dann besser Hilfe geben.

Und wenn Du GENAU erklärst, was Deine Zielsetzung ist - z.B "mit dem 
ATiny 841 ADC Werte (8Bit) einlesen, mittels I2C an den Master 
(ATMega128) übertragen und diese Werte mittels I2C an ein LCD schicken 
zwecks Anzeige der 8-Bit ADC Werte" - eine klar umrissene 
Aufgabenstellung...

mfg
Gast #6729270
Lesenswert?

Egonwalter M. schrieb:
> Und wenn Du GENAU erklärst, was Deine Zielsetzung ist - z.B "mit dem
> ATiny 841 ADC Werte (8Bit) einlesen, mittels I2C an den Master
> (ATMega128) übertragen und diese Werte mittels I2C an ein LCD schicken
> zwecks Anzeige der 8-Bit ADC Werte" - eine klar umrissene
> Aufgabenstellung...

Du hast es bereits gesagt. Genauso will ich es machen. Die gesamte 
vorhanden Software steht bereits oben drin. ADC funktioniert dank eurer 
Hilfe. Jetzt bleibt noch die Werte zum Master zuschicken und dann 
anzuzeigen
#6729350
Lesenswert?

Hallo Heiner

Ich versteh's nicht - Du hast doch Dein Programm von 
Beitrag "Re: ATtiny841 I2C Slave Beispiel"

- dieses Programm soll doch funktionieren, speziell nach den 
Zeit-Anpassungen beim Master

- Was funktioniert denn bei Deinem Programm nicht?

- Beim o.a. Programm sind ja DEBUG Ausgaben, damit man feststellen kann, 
was und wo's klemmt...

- eigentlich müsstest Du doch das o.a. Programm problemlos übernehmen 
können, da es für den Attiny 841 ist und einen Sendebuffer von 4 Bytes 
beim Slave (Attiny 841) hat ...

mfg
Gast #6729659
Lesenswert?

Ja das stimmt genau. Das Programm funktioniert korrekt. Was ich noch 
machen muss, die Anpassung an 8 oder 16 Bit und die passende übertragung 
dazu.
Was mich bei diesem Programm verunsicht ist die Grösse. Dadurch ist es 
für mich sehr unübersichtlich und kompliziert. Programme bei anderen 
slaves sind übersichtlicher und damit besser zu verstehen.
Deshalb auch die Frage dazu, geht es nicht kürzer bzw. einfacher.
#6729681
Lesenswert?

Hallo Heiner

Grundgütiger!

Wenn die Übertragung und die Anpassung an 8 bzw 16 Bit noch nicht 
gemacht ist, funktioniert Dein Programm noch NICHT - ganz klar!

Und das Programm kürzer machen - geht bestimmt, dann musst Du es aber 
auch mal zeigen, meine Glaskugel ist derzeit in Reparatur 🤷‍♂️.

Das Stück SW, das Du oben reingestellt hast ist gelinde gesagt …

Zeig was Du hast, sonst kann man Dir nicht helfen 🤷‍♂️

Eine schwammige Aussage wie “kann man das Programm nicht kleiner oder 
kürzer machen” ist Unsinn

Mit freundlichen Grüßen
#6729704
Lesenswert?

Hier fehlt es einfach an Programmiererfahrung und Wissen. Es gibt an 
sich gar kein Problem. Und per default ist das ADC Ergebnis sowieso 
schon am LSB ausgerichtet. Die Makros machen den Rest. D.h. man liest 
einfach ADCW und hat den 16 Bit Wert. Wer unbedingt den 8 Bit Wert will, 
setzt das entsprechende Bit für die Umschaltung der Ausrichtung und kann 
dann einfach ADCL lesen.
Das ist alles lächerlich einfach. Wer sich damit so überfordert fühlt 
der soll einfach mal einen Gang zurückschalten und nochmal zur 
blinkenden LED zurückgehen.

Und vor allem: I2C Slave an den AVRs, nein an allen Controller, würde 
ich vermeiden. Vor allem für so unsichere Anfänger. Einfach nicht 
machen.
Gast #6729996
Lesenswert?

Heiner schrieb:

> Was mich bei diesem Programm verunsicht ist die Grösse. Dadurch ist es
> für mich sehr unübersichtlich und kompliziert. Programme bei anderen
> slaves sind übersichtlicher und damit besser zu verstehen.

Wohl kaum. Das Programm ist (noch nicht einmal ganz) komplex genug, um 
das Protokoll abbilden zu können. Es gibt nunmal für einen I2C-slave so 
und so viele mögliche Stati und wenn man einen vollwertigen Slave 
implementieren will, muss man die halt auch alle unterstützen, also im 
Programm behandeln.

Einsparungen können sich nur dann ergeben, wenn man auf Teile der 
Möglichkeiten des Protokolls verzichtet, z.B. halt auf die Möglichkeit, 
mehr als ein Payload-Byte pro Transaktion zwischen Master und Slave zu 
bewegen. Und/oder gar auf die Möglichkeit, überhaupt Payload in eine der 
beiden Richtungen zu transferieren. Am allermeisten spart man 
allerdings, wenn man überhaupt keinen Transport von Payload vorsieht. 
Und du wirst lachen: selbst dafür gibt es denkbare Anwendungen.

Dein Problem ist offensichtlich: du kennst das I2C-Protokoll nicht und 
scheinst auch nicht gewillt zu sein, zu lernen, wie es funktioniert. 
Dann hat man NATÜRLICH erhebliche Probleme, zu verstehen, wie ein 
Programm funktioniert, welches dieses Protokoll implementiert. 
Insbesondere dann, wenn es das Protokoll vollständig implementiert, denn 
dann erreicht es naturgemäß den größten Umfang.
Gast #6730047
Lesenswert?

Könnte es seindas es hier Unterschiede im Protokoll gibt. Man kann ja 
Daten von einem Slave lesen, z.B. PCF8574 oder einem Attiny oder halt 
einen anderen Prozessor. Beim PCF8574 ist die Sache ja relativ einfach, 
ist Hardware mässig alles vorhanden. Die Software kommt in den Master. 
Der Master liest die Daten aus dem Slave aus oder schreibt neue rein. 
Weiter oben steht ein Hinweis auf das Protokoll. Das habe ich 
durchgelesen, ist unterteilt in verschiedene Bereiche, wie Adresse, 
Register und Daten.
Bei dem Attiny ist das was anderes für mich. Es gibt fertige 
Bibliotheken dazu, da wurde jtronic genannt. Die kenne ich, sind aber 
nur für bestimmte Typen brauchbar. Das passt alles nicht zum Attiny841. 
Vergessen wir mal den Umfang. Bin dabei zu lesen. Da werde ich nichts 
dran änder und alles so lassen wie es ist.
LG Heiner
Gast #6730080
Lesenswert?

Heiner schrieb:

> Könnte es seindas es hier Unterschiede im Protokoll gibt.

Nein, das I2C-Protokoll ist immer das gleiche. Aber man kann es auf 
unterschiedliche Art nutzen. Das ist dann ein übergeordnetes Protokoll. 
Es entsteht ein Protokollstack.

Ganz genau dieselbe Soße wie z.B. im Netzwerkbereich. Da gibt es MAC, 
darauf setzt z.B. IP auf, darauf wiederum z.B. TCP, darauf wiederum z.B. 
HTTP usw. usf.

In deinem Anwendungsfall ist es halt einfach so, dass du das 
übergeordnete Protokoll komplett frei definieren kannst, da du sowohl 
master als auch slave selber implementierst.
Es gibt keinen verpflichtenden Standard dafür. Das einzige, was es 
sicherstellen muss, ist die standardgerechte Nutzung des I2C-Protokolls, 
was es als Transport-Protokoll benutzt.
Im µC-Bereich verschmelzen aber diese beiden Layer aus Effizienzgründen 
oft, d.h.: man implementiert auf dem I2C-Layer nur das, was man für das 
übergeordnete Protokoll tatsächlich benötigt.

> PCF8574

Wenn du einen Slave bauen willst, der mit dem Anwendungsprotokoll dieses 
Teils kompatibel ist, dann musst du das halt einfach tun. Nur ist es 
wohl nicht sonderlich sinnvoll. 8Bit-digital-IO (konfigurierbar) vs. 
16bit-analog-out (nicht konfigurierbar)? Nur ein Idiot würde versuchen, 
das kompatibel zu machen. Passt einfach nicht.

Vergiß' die Wichsvorlagen, lerne Denken.
Beitrag #6731431 wurde von einem Moderator gelöscht.
Gast #6731837
Lesenswert?

Rainer V. schrieb:

> So weit waren wir am 12.06....und für mich ist der TO seitdem keinen
> Schritt weiter gekommen. Sorry...glaube kaum, dass das noch was wird.

Sehe ich auch so. Es sei denn, irgendwer erbarmt sich und liefert eine 
fertige Wichsvorlage.

So, wie's aussieht, ist genau das, was der TO erreichen will. Er selber 
ist offensichtlich unfähig, auch nur die Konzepte zu verstehen. Und 
lernen mag er wohl auch nicht.
Gast #6731872
Lesenswert?

Staube über deinen Pessimismus. Es kommt so richtig negativ rüber.
Zu deiner Info. Das Programm funktioniert ohne Probleme. Kann es als 8 
bit oder 10 Bit nutzen. Kann verschiedene Werte angeben. Habe 
verschiedne Stufen drin. Habe das Programm für mich vollkommen 
auskommentiert mit den Angaben im Datenblatt versehen. Die Einstellungen 
die DB angegeben werden sind soweit klar. Teste noch Einstellungen mit 
der Verstärkung, Differenzeingang und anderes. Da bin ich aber auch der 
Hardware dran. Ansonsten habe ich angefangen die Werte per I2C am Bus zu 
übertragen und Anzuzeigen.
Nach Anfang sieht das nicht mehr aus.
Beitrag #6731881 wurde von einem Moderator gelöscht.
Gast #6731882
Lesenswert?

Heiner schrieb:

> Staube über deinen Pessimismus. Es kommt so richtig negativ rüber.

Entspricht meinem Gefühl beim Schreiben. Das WAR sehr negativ.

> Zu deiner Info. Das Programm funktioniert ohne Probleme.

Wenn das so ist: Warum sind deine beiden Threads noch nicht mit "Lösung 
gefunden" und "Lösung sieht soundso aus" beendet?

Das wäre ja die logische Konsequenz, wenn stimmt, was du hier 
behauptest...
#6731903
Lesenswert?

Hallo Heiner

Wenn Dein Programm bezüglich ADC funktioniert-prima 👍.

Dann markiere DIESEN Thread als “erledigt”, damit keiner mehr meint, er 
müsste seinen “Senf” dazugeben - und Du ersparst Dir Beleidigungen wie 
von “c-hater” (schon sein Pseudonym ist Hinweis auf seine Einstellung 
und seine vulgäre Sprache 🤮)
#6731931
Lesenswert?

Egonwalter M. schrieb:
> und Du ersparst Dir Beleidigungen wie
> von “c-hater” (schon sein Pseudonym ist Hinweis auf seine Einstellung
> und seine vulgäre Sprache 🤮)

Bullshit...c-hater drückt oftmals genau das aus, was manchmal einfach 
ist! Nämlich unerträgliche Blödheit. Da schlägt man auch schon mal über 
die Strenge, besonders wenn sich Blödheit, Unkenntnis und Arroganz 
paaren. Geht mir oft auch so, auch wenn ich nicht immer einer Meinung 
mit anderen bin... auch wenn es so scheint. An den TO speziell: du 
scheinst zu den Leuten zu gehören, die extrem unflexibel und 
schwerfällig bei der Horizonterweiterung agieren. Zudem gehörst du auch 
offensichtlich zu den Leuten, die sich einfach umdrehen und weggehen, 
wenn sie nicht das hören, was sie hören wollen. Das ist auch im 
richtigen Leben richtig Sch...man macht keinen neuen Thread auf, nur 
weil man im alten zu hören bekommt, dass das Problem mangels 
Sachverstand nicht zu lösen sein wird. Aber was rede ich, ist ja alles 
nicht neu und wird auch nicht das letzte mal sein...also auf in den 
Biergarten :-)
Gruß Rainer
Gast #6731966
Lesenswert?

Zum ADC hatte ich gesagt es funktioniert und da der Titel nicht das 
aussagt was ich wissen möchte, kommt ein anderer Thread.
Warum müssen alle so agressiv sein. Ich Frage weil ich es nicht weis. Es 
kommen Hinweise, mal kleine oder mal grosse dazu. Ich will es nicht 
geschenkt haben, aber ein Hinweise oder Infos über was falsches sind 
sehr Hilfreich.
Leider bleibt mir der Inhalt der Datenblätter teilweise, auch mit 
übersetzung, sehr verschlossen.
Ein paar freundliche Worte oder ein kleiner Anstoss wirken Wunder und 
ist alle mal besser als seine Wut über das Wissen der anderen 
auszudrücken.
Geh ruhig Biertrinke und beruhige dich. Geniesse das schöne Wetter und 
lass uns gemeinsam anstossen.
#6731995
Lesenswert?

Ich akzeptiere dein Friede-Freude...aber es ist halt relativ sinnlos! 
Auch wenn du es nicht so empfinden wirst, ist hier zuallererst 
Sachlichkeit gefordert. Und die wird durch angekündigte Unwissenheit 
nicht einfach weggewischt. Hier meldet sich jeder zweite mit dem 
Hinweis, dass er erstens überhaupt keine Ahnung hat und zweitens auch 
gerade nicht weiß - also quasi ratlos ist - wie er überhaupt mehr Infos 
zu seinem "Wißbegehren" (genau das ist es und genau das ist in dieser 
Allgemeinheit in einem Fachforum eben fehl am Platz!) bekommen kann. Und 
genau diese Haltung provoziert oft nach wenigen Einträgen halt Unwillen. 
Wenn ich was zu Lebensfragen im allgemeinen Sinn wissen will, dann frage 
ich bei "Wer weiß was" und wenn ich mich berufen fühle, darauf zu 
Antworten, dann tu ich das dort. Aber hier ist kein "Wer weiß was" und 
das soll auch so bleiben!!
Gruß Rainer
Gast #6732004
Lesenswert?

Heiner schrieb:
> aber ein Hinweise oder Infos über was falsches sind
> sehr Hilfreich.

Hmm ....
Ich würde richtige Hinweise als hilfreicher erachten, als falsche, oder 
Hinweise auf falsches.

Heiner schrieb:
> Leider bleibt mir der Inhalt der Datenblätter teilweise, auch mit
> übersetzung, sehr verschlossen.
Das ist natürlich eine schwierige Situation.
Welche "wir" auch nicht ändern können.

Denn es gilt ja der Grundsatz:
> Selber lesen, macht selber schlau.
Beitrag #6732109 wurde von einem Moderator gelöscht.
Gast #6732313
Lesenswert?

Stefan ⛄ F. schrieb:

> Er will sich ja "nicht verzetteln" und lieber "bei C bleiben".

Das ist so ziemlich die einzige vernünftige Entscheidung, die er 
getroffen hat. Das muss man ihm zu Gute halten.

C ist schon schwierig genug, aber C++ ist ein absoluter Moloch, den 
selbst die Schöpfer und Entwickler der Sprache kaum noch im vollen 
Umfang überblicken.

Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße, 
kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen 
Umfang. Übrigens auch du nicht und auch der Fanboy nicht.
#6732336
Lesenswert?

Wenn es nicht so banal wäre, würde ich schon verzetteln beim TO für 
relativ unmöglich halten! Er kann sich gar nicht Verzetteln, weil er 
überhaupt nur einen einzigen großen Zettel hat! Ein eindeutiges Zeichen 
für vernünftiges Verhalten ist, seine Probleme verstehen zu können!!! 
Hat mal irgendwer gesagt (Monty Python war es sicher nicht)
Rainer
Gast #6732452
Lesenswert?

c-hater schrieb:
> C ist schon schwierig genug, aber C++ ist ein absoluter Moloch, den
> selbst die Schöpfer und Entwickler der Sprache kaum noch im vollen
> Umfang überblicken.
>
> Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße,
> kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen
> Umfang. Übrigens auch du nicht und auch der Fanboy nicht.

Da muss ich dir ausnahmsweise mal zustimmen.

Ergänzend: Es ist OK und praktikabel, eine Programmiersprache nur 
teilweise zu verwenden. Problematisch wird das erst, wenn man auf 
fremden Code stößt, den man deswegen nicht versteht.

Das vollständige Verstehen von beliebigem fremden Code ist allerdings 
eher etwas für die alten Hasen mit viel Berufserfahrung. C++ macht es da 
einem besonders schwer, dicht gefolgt von Java. Diese voll zu 
durchblicken sollte man nicht von Anfängern erwarten, das wäre gemein.

Es hat schon seinen guten Grund, warum immer wieder Programmiersprachen 
erdacht werden, die einfach und dennoch ausreichend seien sollen. Wir 
werden in 30 Jahren sehen, ob das jemandem mit Erfolg gelungen ist. 
Vielversprechende Ansätze sind zu sehen, z.B.: Python und Go. Die sind 
aber noch zu jung, um sie final zu bewerten, finde ich.

Assembler glänzt mit Einfachheit und der Gewissheit, dass man damit 
wirklich ohne Einschränkung alles machen kann - irgendwie. Doch der 
Sprache fehlt es am Mitteln zur übersichtlichen Gestaltung großer 
Programme, der Unterstützung von Teamarbeit und statische Code-Analysen 
zur Vermeidung von Fehlern.

Mit Assembler programmieren ist, als ob ich dich mit Spitzhacke, Schwert 
und Feuerzeug bewaffnet vor einen Berg stelle und dir sage: Baue mir ein 
Hotel - du hast 10 Monate Zeit.

Ist das machbar: Zweifellos! Will das jemand so machen? 
Unwahrscheinlich, es sei denn derjenige nennt sich c-hater.
#6732493
Lesenswert?

c-hater schrieb:
> Stefan ⛄ F. schrieb:
>
>> Er will sich ja "nicht verzetteln" und lieber "bei C bleiben".

> Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße,
> kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen
> Umfang. Übrigens auch du nicht und auch der Fanboy nicht.

Nur jemand mit übersteigertem Selbstbewusstsein wird für sich in 
Anspruch nehmen (wollen), dass er die selbst gewählte Sprache wirklich 
in vollem Umfang beherrscht.
Gast #6732523
Lesenswert?

Egonwalter M. schrieb:
> Nur jemand mit übersteigertem Selbstbewusstsein wird für sich in
> Anspruch nehmen (wollen), dass er die selbst gewählte Sprache wirklich
> in vollem Umfang beherrscht.

Oder jemand, der nur die primitivste Sprache akzeptiert, weil er sie 
tatsächlich vollständig beherrschen kann.

Meinen Pelikan Füller kann ich vollständig beherrschen, aber ich kann 
damit keine Enzyklopädie in angemessener Zeit und Qualität erstellen.
Gast #6732862
Lesenswert?

c-hater schrieb:
> Stefan ⛄ F. schrieb:
>
>> Er will sich ja "nicht verzetteln" und lieber "bei C bleiben".
>
> Das ist so ziemlich die einzige vernünftige Entscheidung, die er
> getroffen hat. Das muss man ihm zu Gute halten.
>
> C ist schon schwierig genug, aber C++ ist ein absoluter Moloch, den
> selbst die Schöpfer und Entwickler der Sprache kaum noch im vollen
> Umfang überblicken.
>
> Bezüglich der normalen Programmierer ist es aber ziemlich dieselbe Soße,
> kaum einer beherrscht die selbst gewählte Sprache wirklich im vollen
> Umfang. Übrigens auch du nicht und auch der Fanboy nicht.

Da ist er wieder der c-hater, und noch mehr C++ Hasser....

Meine Ansage lautet:
Wenn zur Wahl steht C oder C++ zu lernen, dann ist ganz klar C++ zu 
bevorzugen.


Von den Gründen möchte ich hier mal nur 2 aufführen.

- Pointer vs. Referenzen.
Man kann viel mehr Mist mit Pointern bauen, als mit Referenzen.

- Array Index Überschreitungen
Ein Tipp oder logischer Fehler, bei der Indexberechnung in for 
Schleifen, führt ganz fix ins Versagen.
Der RangeBasedForLoop vermeidet dieses.

Diesen Zugewinn in den Wind zu schlagen, nur weil an anderer Stelle 
evtl. eine Überforderung auftreten könnte ist dumm.

Damit ist die Entscheidung des TO dumm, weil ohne Fachkenntnis getroffen 
und die Zustimmung des c-hassers sicherlich aus dem gleichen Grund 
genauso dumm.

Dem TO, kann ich verzeihen da er es nicht besser weiß.
Aber der C-hater, der könnte es wissen, aber er hat wenn er C++ hört, 
sofort so viel Schaum vorm Mund, dass es ihn blind macht.
Gast #6732905
Lesenswert?

Arduino Fanboy D. schrieb:
> Diesen Zugewinn in den Wind zu schlagen, nur weil an anderer Stelle
> evtl. eine Überforderung auftreten könnte ist dumm.

Das ist nur dumm, wenn man davon ausgeht, irgendwann mal Fehler zu 
machen. Der c-hater weiß aber, dass er so etwas nicht nötig hat, weil er 
keine Fehler macht. Zumindest scheint er das zu glauben. Wir kennen ja 
seine entsprechenden Vorträge.
#6732933
Lesenswert?

Arduino Fanboy D. schrieb:


> Meine Ansage lautet:
> Wenn zur Wahl steht C oder C++ zu lernen, dann ist ganz klar C++ zu
> bevorzugen.
> >
> Von den Gründen möchte ich hier mal nur 2 aufführen.
>
> - Pointer vs. Referenzen.
> Man kann viel mehr Mist mit Pointern bauen, als mit Referenzen.
>
> - Array Index Überschreitungen
> Ein Tipp oder logischer Fehler, bei der Indexberechnung in for
> Schleifen, führt ganz fix ins Versagen.
> Der RangeBasedForLoop vermeidet dieses.
>
> Diesen Zugewinn in den Wind zu schlagen, nur weil an anderer Stelle
> evtl. eine Überforderung auftreten könnte ist dumm.
>
> Damit ist die Entscheidung des TO dumm, weil ohne Fachkenntnis getroffen
> und die Zustimmung des c-hassers sicherlich aus dem gleichen Grund
> genauso dumm.
>
> Dem TO, kann ich verzeihen da er es nicht besser weiß.
> Aber der C-hater, der könnte es wissen, aber er hat wenn er C++ hört,
> sofort so viel Schaum vorm Mund, dass es ihn blind macht.

Das ist eine etwas ... arrogante ... Sichtweise, jemandes Entscheidung 
als "dumm" zu bezeichnen, nur weil er sich für C und nicht C++ 
entschieden hat.
Ich kann auch kein C++, verwahre mich aber schärfstens dagegen, dass 
irgendjemand meine Entscheidung als "dumm" bezeichnet.

Noch herrscht das Recht auf freie Entscheidung, und die ist zu 
respektieren.
Gast #6732938
Lesenswert?

Egonwalter M. schrieb:


> Ich kann auch kein C++, verwahre mich aber schärfstens dagegen, dass
> irgendjemand meine Entscheidung als "dumm" bezeichnet.
>
> Noch herrscht das Recht auf freie Entscheidung, und die ist zu
> respektieren.

Aber doch nicht hier! Schreibe hier mal beiläufig, daß Du z.B. mit 
Bascom alle Deine Aufgaben erledigst. Binnen 5 Minuten liegst Du als 
blank genagtes Skelett da.

Der Mensch beginnt hier erst mit der Benutzung von C.
Gast #6733031
Lesenswert?

Punkt 1:
Egonwalter M. schrieb:
> Noch herrscht das Recht auf freie Entscheidung, und die ist zu
> respektieren.

Da hast du wahr!
Natürlich darfst du eigene Entscheidungen treffen!
Wie könnte ich dir das verwehren?

Allerdings darf ich auch eine Meinung dazu haben, wie "schlau" diese 
Entscheidung ist.

Und jetzt zu Punkt 2:
Natürlich darfst du dich auch so weit mit deinen Entscheidungen 
identifiziere, so dass eine Kritik an dieser Entscheidung, also eine 
Wertung dieser Entscheidung, dich beleidigt.
Das wäre allerdings schade, wenn du das konsequent so hältst....

Noch mal, ganz klar:
Es liegt nicht in meinem Interesse dich zu beleidigen.
Deine Entscheidung hatte ich eher für falsch, als richtig.
#6733131
Lesenswert?

Hallo Arduino Fanboy

Kritik an meinen Entscheidungen sind ok, solange sie konstruktiv ist und 
nicht destruktiv; dann ist sie willkommen, da sie einen Denkanstoß 
liefert

Und natürlich darf jeder eine Meinung darüber haben, ob meine 
Entscheidung klug war oder nicht

Ich denke, mit dieser Sichtweise sind wir beide gleicher Meinung 😉👍
Gast #6739103
Lesenswert?

Wie versprochen der ganze Code zur ADC Messung am Attiny 841. Habe die 
Variante drin mit 8 Bit und 10 Bit. Die Anzeige erfolgt durch 3 x LED. 
Beim drehen des Poti werden die LEDs nach einander eingeschaltet. Beim 
zurückdrehen gehen sie wieder aus.
1
#define F_CPU 16000000UL              // Angabe der Frequenz, wichtig für die Zeit
2
#include <util/delay.h>                // Einbindung Datei Pause
3
#include <avr/io.h>                  // Einbindung Datei Ausgänge
4
#include <avr/interrupt.h>
5

6
void init_ADC()
7
  {
8
  ADMUXB &=~((1<<REFS2)|(1<<REFS1)|(1<<REFS0));  // Register ADMUXB
9
  // REF-Auswahl Referenzspannung, auf Vcc(5V)
10
  ADCSRA |=((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));  // Register ADCSRA
11
  // ADPS - Teilungsfaktor 16MHz/128=125kHz
12
  ADCSRA |= (1<<ADEN);              // ADC aktivieren
13
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung "single conversion"
14
  while (ADCSRA & (1<<ADSC))
15
    {                        // auf Abschluss der Konvertierung warten
16
    }
17
  }
18

19
uint16_t ADC_Read()            // ADC Einzelmessung
20
  {
21
  ADMUXA |=(1<<MUX1);          // Register ADMUXA
22
  // MUX - Auswahl welcher Eingang - 000010 - ADC2
23
  ADCSRA |= (1<<ADSC);              // Register ADCSRA
24
  // ADSC - Start Konvertierung "single conversion"
25
  ADCSRB |=(1<<ADLAR);        // bei 8 Bit links
26
  while (ADCSRA & (1<<ADSC))
27
    {                  // auf Abschluss der Konvertierung warten
28
    }
29
  //return ADCW;            // ADC auslesen und zurückgeben bei 10 Bit ohne Adlar
30
  return ADCH;            // ADC auslesen und mit 8 Bit zurück mit ADLAR=1
31
  }
32

33
int main(void)
34
  {
35
  DDRA=0b00101001;          // Port A auf Ausgang schalten
36
  PORTA=0b00101001;          // Port A auf aus
37
  uint8_t adcval;            // 16 Bit mit ADCW
38
  init_ADC();
39
  while(1)
40
      {
41
    adcval = ADC_Read();
42
    if(adcval>=58)           // bei 8 Bit und 10 Bit
43
      {
44
      
45
      PORTA &=~(1<<PINA5);    // LED2 ein
46
      }
47
    else
48
      {
49
      PORTA |=(1<<PINA5);      // aus
50
      }
51
    if(adcval>128)           // bei 8 Bit, bei 10 Bit 600
52
      {
53
      PORTA &=~(1<<PINA0);    // LED3 ein
54
      }
55
    else
56
      {
57
      PORTA |=(1<<PINA0);      // aus
58
      }
59
    if(adcval>228)           // bei 8 Bit, bei 10 Bit 950
60
      {
61
      PORTA &=~(1<<PINA3);    // LED4 ein
62
      }
63
    else
64
      {
65
      PORTA |=(1<<PINA3);      // aus
66
      }  
67
    }    // while
68
  }      // main
Die 10 Bit habe ich auskommentieret. Programm läuft ohne Probleme bei 
mir.
Wünsche viel Spass damit. Danke an Alle und entschuldigung für die 
vielen blöden Fragen.
LG Heiner
Gast #6739126
Lesenswert?

Ja das stimmt. In dem DB steckt aber noch mehr. Das ist mein erstes 
Programm dazu. Erweiterungen jederzeit möglich. Besonders bei der 
eigentlichen Messung und übertragung. Da werde ich noch einiges machen 
dazu.
#6739131
Lesenswert?

Heiner schrieb:
> Ja das stimmt. In dem DB steckt aber noch mehr. Das ist mein
> erstes
> Programm dazu. Erweiterungen jederzeit möglich. Besonders bei der
> eigentlichen Messung und übertragung. Da werde ich noch einiges machen
> dazu.

Wenn Du es weißt, warum machst Du es dann nicht (mehrmals den ADC Wert 
einlesen und den ersten verwerfen) in Deinem hier vorgestellten 
Programm?

Und was hat das DB damit zu tun?
Gast #6739161
Lesenswert?

Im DB stehen die Register drin und die Anwendung dazu. Fange immer mit 
einem leichten Programm an und nehme dann in dem nächsten Programm 
weitere Sachen dazu. Lieber erst ein kleines und leichtes Programm zum 
laufen bekommen als gleich mit dem schwersten anfangen.

Egonwalter M. schrieb:
> Wenn Du es weißt, warum machst Du es dann nicht (mehrmals den ADC Wert
> einlesen und den ersten verwerfen) in Deinem hier vorgestellten
> Programm?

Das habe ich in einem Versuch bereits drin. Da in dem ersten Programm 
die Auswertung nur durch das ein- und ausschalten von LEDs erfolgt ist 
das noch nicht notwendig.
#6739174
Lesenswert?

Heiner schrieb:

> Egonwalter M. schrieb:
>> Wenn Du es weißt, warum machst Du es dann nicht (mehrmals den ADC Wert
>> einlesen und den ersten verwerfen) in Deinem hier vorgestellten
>> Programm?
>
> Das habe ich in einem Versuch bereits drin. Da in dem ersten Programm
> die Auswertung nur durch das ein- und ausschalten von LEDs erfolgt ist
> das noch nicht notwendig.

Wenn Dein Programm hier als Vorlage dienen soll, sollte es auch korrekt 
sein (mit mehrfachem Einlesen) damit eventuelle User nicht unliebsame 
Überraschungen erleben, wenn sie es denn nehmen und für ihre Zwecke 
verwenden.

Du möchtest ja auch nicht ein halb gares Programm nehmen, oder?

Wie auch immer - einmal einlesen ist Murks
Gast #6739609
Lesenswert?

Heiner schrieb:
> DDRA=0b00101001;          // Port A auf Ausgang schalten
> PORTA=0b00101001;         // Port A auf aus

> uint8_t adcval;           // 16 Bit mit ADCW

> if(adcval>=58)            // bei 8 Bit und 10 Bit

Die Kommentare stiften mehr Verwirrung als zu helfen.

Arbeite nochmal an der Positionierung der Klammern. Ich empfehle, Tabs 
durch 4 Leerzeichen zu ersetzen, das kannst du in deinem Editor bestimmt 
einstellen.

> PORTA &=~(1<<PINA5);    // LED2 ein

Dies würde ich in eine Funktion verschieben, die LED2_ein() heißt. 
Dadurch wird der Code besser lesbar. Und keine Sorge, er wird dadurch 
nicht größer oder langsamer.

Egonwalter M. schrieb:
> Sollte man eine ADC Messung nicht mehrmals nacheinander machen und die
> erste Messung verwerfen

Nur wenn die Quelle zu hochohmig ist und man mehr als 8 Bit nutzen will. 
Das macht man nicht für den ADC, sondern um Zeit für die äußere 
Schaltung zu gewinnen.
#6739628
Lesenswert?

Stefan ⛄ F. schrieb:

>
> Egonwalter M. schrieb:
>> Sollte man eine ADC Messung nicht mehrmals nacheinander machen und die
>> erste Messung verwerfen
>
> Nur wenn die Quelle zu hochohmig ist und man mehr als 8 Bit nutzen will.
> Das macht man nicht für den ADC, sondern um Zeit für die äußere
> Schaltung zu gewinnen.

Generell sollte man den ersten gelesenen Wert des ADC verwerfen, egal ob 
8 Bit oder 10 Bit, es sei denn, man will sich seltsame Effekte 
einhandeln - und wer will das?
Gast #6739633
Lesenswert?

Hatte es so verstanden:
Da die erste Wandlung nicht korrekt, sollte man sie verwerfen. Bei ( Bit 
streiten sich die Leute. Manche sagen: ist auf jeden Fall besser und die 
letzten Stellen wackeln nicht so stark. Andere sagen: Bei 8 Bit ist es 
nicht unbedingt notwendig.
In diesem Programm ist es relativ egal da das Auslesen mehrfach erfolgt 
und die Anzeige mit LEDs erfolgt. Dabei ist keine grosse Genauigkeit 
gefordert.

Stefan ⛄ F. schrieb:
> Die Kommentare stiften mehr Verwirrung als zu helfen.
>
> Arbeite nochmal an der Positionierung der Klammern. Ich empfehle, Tabs
> durch 4 Leerzeichen zu ersetzen, das kannst du in deinem Editor bestimmt
> einstellen.
>
>> PORTA &=~(1<<PINA5);    // LED2 ein

Danke für den Hinweis. Diese Kommentare sind eigentlich nur für mich, 
das ich nicht vergesse die richtigen Stellen zu ändern.
Verwende auch Funktionen, doch bei diesem Programm geht es erst mal um 
das Verständnis. Werde es aber auf jeden Fall machen.
LG Heiner
#6739638
Lesenswert?

Heiner schrieb:
> Hatte es so verstanden:
> Da die erste Wandlung nicht korrekt, sollte man sie verwerfen. Bei ( Bit
> streiten sich die Leute. Manche sagen: ist auf jeden Fall besser und die
> letzten Stellen wackeln nicht so stark. Andere sagen: Bei 8 Bit ist es
> nicht unbedingt notwendig.
> In diesem Programm ist es relativ egal da das Auslesen mehrfach erfolgt
> und die Anzeige mit LEDs erfolgt. Dabei ist keine grosse Genauigkeit
> gefordert.
>

Wenn ich weiß, dass es nicht korrekt ist und es trotzdem ignoriere …
Damit bin ich raus

Außerdem erfolgt das Auslesen nicht MEHRMALS, sondern EINMAL pro 
Durchlauf Deiner while-Schleife, Kollege
Gast #6739651
Lesenswert?

Heiner schrieb:
> Da die erste Wandlung nicht korrekt, sollte man sie verwerfen.

Im Datenblatt steht genau drin, wie viele Takte der ADC zur 
Initialisierung benötigt und wann sich das Umschalten des Multiplexers 
auswirkt. Wenn man diese Takte abwartet, dann misst der ADC von Anfang 
an korrekt.

Warten kann man auf unterschiedliche Art - auch indem man den ADC 
Messungen macht und verwirft. Aber das macht man, um Zeit zu schinden, 
nicht um irgend etwas einschwingen zu lassen. Der ADC muss sich nicht 
einschwingen.
Gast #6740249
Lesenswert?

Rainer V. schrieb:
> ..und das habe ich mir
> sicher so nicht ausgedacht.
Aber offensichtlich nicht verstanden!
Und darum falsch gemerkt und den Irrtum weiter verbreitet.

Die Umschaltung der Referenz, z.B. von Vcc zu Intern, benötigt Zeit.
Je größer der Kondensator an ARef, desto länger.

Auch ein (zu) hoher ADC Takt, klarer, zu kurze S&H Umladezeit, zu hohe 
Eingangsimpedanz können eine zweite Messung nötig machen.
Aber das ist nicht in Stein gemeißelt und hier sehe ich auch keine 
Anzeichen dafür.

Auch Multiplexerumschaltungen im FreeRunningMode erfordern das Verwerfen 
von Werten.
Aber das ist wieder ein anderes Thema....

Du siehst....
Verallgemeinern gilt nicht.
Gast #6740460
Lesenswert?

Arduino Fanboy D. schrieb:

> Die Umschaltung der Referenz, z.B. von Vcc zu Intern, benötigt Zeit.
> Je größer der Kondensator an ARef, desto länger.

Richtig.

> Auch ein (zu) hoher ADC Takt, klarer, zu kurze S&H Umladezeit, zu hohe
> Eingangsimpedanz können eine zweite Messung nötig machen.

Ebenfalls richtig.

> Auch Multiplexerumschaltungen im FreeRunningMode erfordern das Verwerfen
> von Werten.

Das ist falsch. Das ist höchstens dann zutreffend, wenn man das 
Zeitverhalten seines Codes nicht im Griff hat.
Gast #6740746
Lesenswert?

Das Umschalten des Multiplexers wirkt sich auf die nächste Messung aus, 
nicht auf die gerade laufende Messung. Das ist des Pudels Kern, so steht 
das auch im Datenblatt.

Für die Art, wie der TO hier den ADC nutzt, ist dieses Detail 
irrelevant.
Gast #6741104
Lesenswert?

Stefan ⛄ F. schrieb:

> Das Umschalten des Multiplexers wirkt sich auf die nächste Messung aus,
> nicht auf die gerade laufende Messung. Das ist des Pudels Kern, so steht
> das auch im Datenblatt.

So ist es, aber trotzdem nur die halbe Wahrheit.

Im FreeRunning-Mode gibt es nämlich die Möglichkeit für Quirks, wenn man 
den Multiplexer in der ADC-ISR umschaltet. Da kann es nämlich passieren, 
dass die neue Multiplexer-Konfiguration noch für den gerade laufenden 
(durch FreeRun automatisch gestarteten) ADC-Zyklus wirksam wird, nämlich 
dann, wenn die ISR wenig Overhead hat und auch gerade nicht durch eine 
konkurrierende ISR verzögert wurde.

OK: Bei in C geschriebenen ISRs ist es relativ unwahrscheinlich, dass 
das passiert, aber eben nicht unmöglich. In Asm hingegen ist das ein 
absolut relevantes Thema, welches man natürlich entsprechend 
berücksichtigen muss.

Und übrigens, ohne Quirks: Die Multiplexer-Konfiguration, wird im 
nächsten Zyklus gültig, d.h.: das daraus resultierende Ergebnis ist erst 
das ÜBERNÄCHSTE.
#6741823
Lesenswert?

c-hater schrieb:
> Im FreeRunning-Mode gibt es nämlich die Möglichkeit für Quirks, wenn man
> den Multiplexer in der ADC-ISR umschaltet.

Ja, der FreeRunning-Mode ist häßlich. Daher benutze ich ihn nur, wenn 
nur ein Eingang eingelesen werden muß.
Bei Prescaler 128 muß man sonst 128 CPU-Zyklen warten, bis der MUX 
umgeschaltet werden darf.
Gast #6741851
Lesenswert?

Peter D. schrieb:
> Daher benutze ich ihn nur, wenn
> nur ein Eingang eingelesen werden muß.

Naja...
Auch eine Möglichkeit des Ausblendens.

Peter D. schrieb:
> Bei Prescaler 128 muß man sonst 128 CPU-Zyklen warten, bis der MUX
> umgeschaltet werden darf.

Die Alternative ist, wenn man nicht weiß, in welchen ADC Takt man ihn 
erwischt hat, ist das verwerfen des ersten Ergebnisses nach der 
Umschaltung. Und wenn auch andere ISR im Spiel sind KANN man das nicht 
wissen.

Wozu der c-hater dann sagt:
c-hater schrieb:
> Das ist falsch.
Gast #6742061
Lesenswert?

Arduino Fanboy D. schrieb:

> Die Alternative ist, wenn man nicht weiß, in welchen ADC Takt man ihn
> erwischt hat, ist das verwerfen des ersten Ergebnisses nach der
> Umschaltung. Und wenn auch andere ISR im Spiel sind KANN man das nicht
> wissen.

Doch, natürlich kann man das wissen. Wenn man halt das Laufzeitverhalten 
seiner Anwendung vollständig im Griff hat. Dann kann man für JEDE 
einzelne ISR EXAKT vorhersehen, wie hoch die Latenz mindestens und 
höchstens ausfallen wird.

Und dann hat man noch die Wahl zwischen zwei Varianten. Wenn es nur 
wenige konkurrierende ISRs gibt und/oder man die Zeit ihrer exklusiven 
Ausführung kurz genug halten kann, dann kann man den ADC regulär und 
zuverlässig im "Quirks-Bereich" nutzen. Bis jetzt habe ich das noch in 
jeder Anwendung geschafft, in der sich FreeRunning anbot.

Und falls das mal nicht möglich sein sollte, hat man immer noch die 
Möglichkeit, die ADC-ISR so zu gestalten, dass die Wartezeit für den 
Fall der Minimal-Latenz keine verlorene Zeit ist, sondern sinnvoll 
genutzt werden kann.

> Wozu der c-hater dann sagt:
> c-hater schrieb:
>> Das ist falsch.

Ist es halt auch wirklich. In meiner Welt der berechenbaren 
Laufzeiten...
Gast #6743193
Lesenswert?

c-hater schrieb:
> Wenn man halt das Laufzeitverhalten
> seiner Anwendung vollständig im Griff hat.
Ah ja. Ein NOP hinzugefügt oder weggenommen und das Kartenhaus bricht 
zusammen...

> Dann kann man für JEDE
> einzelne ISR EXAKT vorhersehen, wie hoch die Latenz mindestens und
> höchstens ausfallen wird.
Schön. Und wenn Du eine Kleinigkeit am Code änderst, fängt die 
Rechnerei, ob alles noch passt von vorne an.
Kann man machen.

Oder man programmiert robust und defensiv...
Gast #6743202
Lesenswert?

Bernd schrieb:

> Ah ja. Ein NOP hinzugefügt oder weggenommen und das Kartenhaus bricht
> zusammen...

Nun, in gut geplante Kartenhauser braucht man halt nichts mehr 
hinzufügen oder wegnehmen. Die stehen ewig.

> Oder man programmiert robust und defensiv...

Das Vorgehen für diese Variante hatte ich doch ebenfalls beschrieben. Da 
geht es dann nur noch darum, in der ADC-ISR genug Rechenzeit sinnvoll zu 
benutzen, statt sinnlos zu verwarten. Das ist dann endgültig eine 
wirklich einfache Aufgabe, der vielleicht sogar Leute wie du gewachsen 
sein könnten...
Gast #6745787
Lesenswert?

Hallo
Habe zu der ADC Messung am Attiny 841 die Mittelwertbildund dazu 
genommen:
1
uint16_t ADC_lesen1()            // ADC Einzelmessung
2
  {
3
  ADMUXA |=(1<<MUX1);          // Register ADMUXA
4
  // MUX - Auswahl welcher Eingang - 000010 - ADC2
5
  ADCSRA |= (1<<ADSC);              // Register ADCSRA
6
  // ADSC - Start Konvertierung "single conversion"
7
  ADCSRB |=(1<<ADLAR);        // bei 8 Bit links
8
  while (ADCSRA & (1<<ADSC))
9
  {                  // auf Abschluss der Konvertierung warten
10
  }
11
  //return ADCW;            // ADC auslesen und zurückgeben bei 10 Bit ohne Adlar
12
  return ADCH;            // ADC auslesen und mit 8 Bit zurück mit ADLAR=1
13
  }
14
  
15
uint16_t ADC_lesen_avg(uint8_t anzahlmessung)
16
  {  
17
  uint16_t summemessung=0;
18
  for (uint8_t i = 0; i < anzahlmessung; ++i )  
19
    {
20
      summemessung += ADC_lesen1();  
21
    }
22
  return ( summemessung/anzahlmessung );    // Durchschnitt errechnen und zurück
23
  }
Den Aufruf und übertragung zum Master über den I2C Bus erfolgt damit:
1
int main(void)
2
  {
3
  init_I2C();  
4
  init_ADC();
5
  while(1)
6
    { 
7
    //wert1= ADC_lesen1();  
8
    wert1= ADC_lesen_avg(5);
9
    if(command != 0x00)
10
      {
11
      switch(command)
12
        {
13
        case 0x01:
14
        // Test Daten
15
        tx_buf[0] = wert1;
16
        tx_buf[1] = 2;
17
        tx_buf[2] = 3;
18
        tx_buf[3] = 14;
19
        tx_buf_index = 0;
20
        break;
21
        }
22
      command = 0x00;
23
      }
24
    }
25
  }
Bei einem Aufruf des Mittelwertes mit wert1= ADC_lesen_avg(5); werden 
für alle 4 tex_buf unterschiedliche Werte angezeigt. Bei jeder änderung 
des wert1 ändert sich auch tx_buf 1,2,3. Wenn ich nur mit wert1= 
ADC_lesen1(); den ADC Wert übertrage stimmen die Werte. Leider ist mir 
nicht klar warum das so ist.
LG Heiner
Gast #6745821
Lesenswert?

Kein Problem
1
#define F_CPU 16000000UL        // Angabe der Frequenz, wichtig für die Zeit
2
#include <util/delay.h>          // Einbindung Datei Pause
3
#include <avr/io.h>            // Einbindung Datei Ausgänge
4
#include <stdio.h>
5
#include <avr/interrupt.h>
6

7
#define I2C_SLAVE_ADDRESS       0x52
8
#define I2C_DATA_INTERRUPT      0x80
9
#define I2C_BUS_COLLISION       0x08
10
#define I2C_ADDRESS_STOP_MATCH  0x40
11

12
volatile uint8_t command;
13
volatile uint8_t tx_buf[4];
14
volatile uint8_t tx_buf_index = 0;
15
volatile uint8_t wert1;
16
//volatile uint16_t sum;
17

18
void init_I2C()
19
  {
20
  TWSA = I2C_SLAVE_ADDRESS;  // Slave Adresse
21
  TWSD = 0xFF;
22
  TWSCRA = (1 << TWEN)       // Zwei-Draht-Schnittstelle aktivieren
23
  | (1 << TWSHE)        // TWI SDA Haltezeit aktivieren
24
  | (1 << TWASIE)       // TWI-Adresse/Stop-Unterbrechung aktivieren
25
  | (1 << TWSIE)        // TWI Stop Interrupt Enable aktivieren
26
  | (1 << TWDIE);       // TWI Datenunterbrechung aktivieren
27
  sei();
28
  }
29

30
ISR( TWI_SLAVE_vect )
31
  {
32
  uint8_t status = TWSSRA & 0xC0;
33
  if (status & I2C_DATA_INTERRUPT)  // Daten wurden vom Master empfangen oder werden angefordert
34
    {
35
    if (TWSSRA & (1 << TWDIR))    // Master fordert Daten vom Slave an
36
      {
37
      if(tx_buf_index >= sizeof(tx_buf))
38
        {
39
        tx_buf_index=0;
40
        }
41
      TWSD = tx_buf[tx_buf_index];// Daten in Sendepuffer
42
      tx_buf_index++;
43
      TWSCRB = ((1<<TWCMD1)|(1<<TWCMD0));
44
      }
45
    else       // Master sendet Daten zum Slave
46
      {
47
      TWSCRB |= ((1<<TWCMD1)|(1<<TWCMD0));
48
      command = TWSD;
49
      }
50
    }
51
  else if (status & I2C_ADDRESS_STOP_MATCH)
52
    {
53
    if (TWSSRA & I2C_BUS_COLLISION)
54
      {
55
      TWSCRB = (1<<TWCMD1);
56
      }
57
    else
58
      {
59
      if (TWSSRA & (1<<TWAS))
60
        {      // ACK
61
        TWSCRB =  ((1<<TWCMD1)|(1<<TWCMD0));
62
        }
63
      else
64
        {      // Stop Condition
65
        TWSCRB = (1<<TWCMD1);
66
        }
67
      }
68
    }
69
  }
70

71
void init_ADC()
72
  {
73
  ADMUXB &=~((1<<REFS2)|(1<<REFS1)|(1<<REFS0));  // Register ADMUXB
74
  // REF-Auswahl Referenzspannung, auf Vcc(5V)
75
  ADCSRA |=((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));  // Register ADCSRA
76
  // ADPS - Teilungsfaktor 16MHz/128=125kHz
77
  ADCSRA |= (1<<ADEN);              // ADC aktivieren
78
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung "single conversion"
79
  while (ADCSRA & (1<<ADSC))
80
    {                        // auf Abschluss der Konvertierung warten
81
    }
82
  }
83

84
uint16_t ADC_lesen1()            // ADC Einzelmessung
85
  {
86
  ADMUXA |=(1<<MUX1);          // Register ADMUXA
87
  // MUX - Auswahl welcher Eingang - 000010 - ADC2
88
  ADCSRA |= (1<<ADSC);              // Register ADCSRA
89
  // ADSC - Start Konvertierung "single conversion"
90
  ADCSRB |=(1<<ADLAR);        // bei 8 Bit links
91
  while (ADCSRA & (1<<ADSC))
92
  {                  // auf Abschluss der Konvertierung warten
93
  }
94
  //return ADCW;            // ADC auslesen und zurückgeben bei 10 Bit ohne Adlar
95
  return ADCH;            // ADC auslesen und mit 8 Bit zurück mit ADLAR=1
96
  }
97
  
98
uint16_t ADC_lesen_avg(uint8_t anzahlmessung)
99
  {  
100
  uint16_t summemessung=0;
101
  for (uint8_t i = 0; i < anzahlmessung; ++i )  
102
    {
103
      summemessung += ADC_lesen1();  
104
    }
105
  return ( summemessung/anzahlmessung );    // Durchschnitt errechnen und zurück
106
  }
107
  
108
int main(void)
109
  {
110
  init_I2C();  
111
  init_ADC();
112
  while(1)
113
    { 
114
    //wert1= ADC_lesen1();  
115
    wert1= ADC_lesen_avg(5);
116
    if(command != 0x00)
117
      {
118
      switch(command)
119
        {
120
        case 0x01:
121
        // Test Daten
122
        tx_buf[0] = wert1;
123
        tx_buf[1] = 2;
124
        tx_buf[2] = 3;
125
        tx_buf[3] = 14;
126
        tx_buf_index = 0;
127
        break;
128
        }
129
      command = 0x00;
130
      }
131
    }
132
  }
Auf die tx_buf 1,2,3 wird nur an dieser Stelle zugegriffen. Wenn ich das 
gleiche mit wert1=ADC_lesen1(); mache ändern sich die Werte nicht.
Habe noch die ganzen Kommentare drin.
Gast #6745829
Lesenswert?

Ich sehe da auf Anhieb keinen Fehler.

Eine Frage um das Problem einzukreisen:
Bist du sicher dass sich tx_buf[1] bis [3] verändern oder schließt du 
das aus den Daten, die dein Mikrocontroller auf dem I²C Bus sendet?

Und noch eine: Wird der Stack-Pointer richtig initialisiert? 
Kontrolliere mal dessen Wert.
Gast #6745830
Lesenswert?

ist mit
volatile uint8_t tx_buf[4];
angegeben, da ich nur 8 Bit per Bus übertrage.
Mir ist noch was anderes aufgefallen. Wenn ich schreibe
1
wert1= ADC_lesen1();  
2
    //wert1= ADC_lesen_avg(5);
3
    if(command != 0x00)
4
      {
5
      switch(command)
6
        {
7
        case 0x01:
8
        // Test Daten
9
        tx_buf[0] = 12;
10
        tx_buf[1] = 2;
11
        tx_buf[2] = 3;
12
        tx_buf[3] = 14;
13
        tx_buf_index = 0;
14
        break;
15
        }
16
      command = 0x00;
17
      }
werden genau diese 4 Werte übertragen.
Schreibe ich aber
{c]
 {
    //wert1= ADC_lesen1();
    wert1= ADC_lesen_avg(5);
    if(command != 0x00)
      {
      switch(command)
        {
        case 0x01:
        // Test Daten
        tx_buf[0] = 12;
        tx_buf[1] = 2;
        tx_buf[2] = 3;
        tx_buf[3] = 14;
        tx_buf_index = 0;
        break;
        }
      command = 0x00;
      }
    }
[/c]
bekomme ich bei jeder Abfrage unterschiedliche Werte.
Wieso? Die Werte für tx_buf[..] sind doch immer gleich.
Gast #6745835
Lesenswert?

Ich glaube ich hab es:

Wenn der Master Daten anfordert, antwortest die ISR immer sofort mit den 
4 Bytes des Buffers, auf die tx_buf_index zeigt.

Während dessen läuft vielleicht gerade deine langsame 5-fache ADC 
Messung. Dann merkst du dass ein Kommando empfangen wurde und dann setzt 
du tx_buf_index index einfach auf 0 ohne zu berücksichtigen, in welchem 
Status sich die I²C Übertragung gerade befindet.

Es könnte sein, dass tx_buf_index gerade den Wert 1 oder 2 oder 3 hat 
und du setzt es dann einfach "unerlaubt" auf 0 zurück. Als nächstest 
sendet die ISR du dann erneut tx_buf[0] an den Master anstatt das 
richtige Byte das eigentlich an der Reihe gewesen wäre.

Das ist eine klassische Race Condition, Willkommen in der Welt der 
Nebenläufigkeit. Dir fehlt eine Synchronisation der beiden parallelen 
Vorgänge:

a) ADC auslesen (in main)
b) Messwerte senden (in der ISR)

Diese beiden Threads dürfen nur abwechselnd auf den Buffer zugreifen. 
Dir fehlt eine entsprechende Ablaufsteuerung. Wenn du diese einführst 
dann brauchst du wohl auch Clock-Stretching, denn du musst dem Master 
irgendwie mitteilen, dass er bitte warten soll weil du gerade die von 
ihm angeforderte Messung durchführst und eben deswegen jetzt nicht 
sofort antworten kannst.

Alternative: Du machst drei Kommandos:

1) Messung starten. Es gibt keine Antwort (außer natürlich das ACK).
2) Abfrage ob die Messung fertig ist. Antwort ist 0 oder 1.
3) Messergebnis abfragen. Antwort sind die 4 Bytes.

Dann muss der Master den Status wiederholt pollen und die Daten erst 
dann abholen, wenn dein Slave dazu bereit ist.
Gast #6745850
Lesenswert?

Muss ganz ehrlich sagen, habe deine Antwort erst mehrmals lesen müssen 
um es vielleicht zu verstehen. Es klingt recht plausibel. Was ich daran 
nicht verstehe, ohne Mittewertberechnung bzw. Aufruf geht es mit geht es 
nicht. Kann alles damit zusammenhängen.
Das andere Problem für mich ist die Lösung. Habe null Peilung wie ich 
das machen kann, da für mich so ein Problem noch nie aufgetreten ist. 
Die ADC Messung (einfach) habe ich ja in den Griff bekommen, tja der 
Rest ist noch unbekannt.
Gast #6745852
Lesenswert?

Stefan ⛄ F. schrieb:
> a) ADC auslesen (in main)
> b) Messwerte senden (in der ISR)

Wenn ich deine Worte richtig verstanden habe, muss das ADC auslesen 
fertig sein und dann darf erst Messwerte senden erfolgen. Damit sind 
korrekte Messwerte gegeben.
Dazu brauch ich doch die Info das das ADC auslesen fertig ist und dann 
über Freigabe 0 oder 1 die Werte zum Auslesen freigebe.
Sehe ich das richtig?
Gast #6745856
Lesenswert?

Heiner schrieb:
> Was ich daran
> nicht verstehe, ohne Mittewertberechnung bzw. Aufruf geht es

Weil dann die Messung immer schneller als die I²C Übertragung ist. Das 
Messergebnis steht immer rechtzeitig bereit.

> ...
> Sehe ich das richtig?

Ja

Das ist wirklich kein einfaches Thema. Aber da musst du durch - es sei 
denn du nutzt Clock-Stretching und machst die Messung innerhalb der ISR.

Dann hast du nämlich nur einen Thread, der auf die Messergebnisse 
zugreift. Zugriffskonflikte sind dann unmöglich.
Gast #6745876
Lesenswert?

Stefan ⛄ F. schrieb:
> Das ist wirklich kein einfaches Thema. Aber da musst du durch - es sei
> denn du nutzt Clock-Stretching und machst die Messung innerhalb der ISR.

Messung innerhalb der ISR ??? Dabei wird init_ADC gemacht wie bisher. 
Dann muss man innerhalb der ISR, Bereich Daten einlesen, auf die ADC 
Mittelwertbildung zugreifen. Die Mittelwertbildung greift dann ja wieder 
auf die eigentlich ADC Messung zu.
Habe ich das richtig verstanden?

Stefan ⛄ F. schrieb:
> Das ist wirklich kein einfaches Thema.

Da gebe ich dir Recht. Konnte auch sehr wenig im Netz dazu finden was 
ich verstehe. Gerade beim Attiny 841 gibt es scheinbar garnichts dazu. 
Sicher sagen einige, ist kein Problem. Für mich leider schon. Vielleicht 
gibt es noch ein Paar Tips dazu. Vielleicht....
Gast #6746195
Lesenswert?

Heiner schrieb:
> Messung innerhalb der ISR ???
> Habe ich das richtig verstanden?

Nein, ich meinte dass dein Mikrocontroller nach Empfang des Kommandos 
die 5 Messungen innerhalb der ISR macht, den Mittelwert bildet und erst 
dann das Kommando mit ACK bestätigt. Danach sendest du die Antwort an 
den Master.

Die unschöne Konsequenz aus dieser simplen Umsetzung ist aber, dass das 
ACK erheblich verzöger wird, nämlich so lange wie die 5 ADC Messungen 
dauern. Um dies zu ermöglichen, musst du das Clock-Stretching Feature 
von I²C benutzen (welches der Raspberry Pi übrigens nicht unterstützt).

Die zweite unschöne Konsequenz ist, dass der Mikrocontroller während 
dieser Zeit vermutlich nicht anderes mehr tun kann, weil die ISR den 
Ablauf der main() eben so lange blockiert. Du kannst höchsten noch 
andere höher priorisierte ISR gleichzeitig ausführen, falls der µC das 
überhaupt unterstützt (die klassischen AVR tun es nicht).

Heiner schrieb:
> Gerade beim Attiny 841 gibt es scheinbar garnichts dazu.

Für den Anfang verwendest du besser einen Mikrocontroller, der unter 
Hobbyelektronikern beliebt und schon lange etabliert ist, denn dann 
findest du dazu die meisten leicht verständlichen Anleitungen. Vor ein 
paar Jahren war das noch der Atmega8, inzwischen wurde er (dank Arduino) 
durch den ATmega328 abgelöst. Bestelle dir einfach mal ein 5er Pack 
Arduino Nano Module, die kannst du immer mal gebrauchen. Zum 
Programmieren musst du ja nicht die Arduino IDE benutzen, es geht um die 
praktische Hardware.
Gast #6746772
Lesenswert?

Habe mir das Datenblatt vorgenommem. Unter 20.3.7 steht was dazu. Leider 
für mich sehr unklar.
Habe im Netz dazu gesucht. Auch leider alles relativ theoretisch 
gehalten.
Habe aber eine Frage dazu.
Was passiert wenn ich verschiedene ADC abfrage ohne Mittelwertbildung. 
Da ja 4 Werte übertragen kann, kann ich 2x ADC mit jewels 8 Bit nehmen.
Tritt dann das Problem auch auf? Sorry, meine Hardware ist noch nicht so 
weit um zu testen.
Gast #6746798
Lesenswert?

Heiner schrieb:
> Tritt dann das Problem auch auf?

Ja, denn es ist ein Timing Problem. DU kannst froh sein, dass du 
wenigstens eine ADC Abfrage auf diese Art machen kannst. Takte den mal 
langsamer, dann geht nicht einmal das mehr.

Heiner schrieb:
> Kann man einfach die übertragung der Werte stoppen bevor die ADC Messung
> und Mittelwertbildung fertig ist?

Dazu dient das von mir genannte Clock Stretching. Lies doch mal, was 
dieser Begriff beim I²C Bus bedeutet. Ich hoffe du hast die 
Spezifikation vorliegen: 
https://www.nxp.com/docs/en/user-guide/UM10204.pdf Das ist für dich 
Pflichtlektüre!
#6747126
Lesenswert?

Peter D. schrieb:

> Der ATtiny841 ist eine Spätgeburt. D.h. viele haben schon mit früheren
> AVRs angefangen und benutzen diese weiterhin.
> Auch benutzen viele Bastler gerne MCs, die noch als DIP verfügbar sind.
> Die kann man schnell mal auf ein Steckbrett friemeln.

Aber auch da kommt man nicht umhin, sich mit Clockstretching 
auseinanderzusetzen 😉 (dürfte da aber einfacher zu haendeln sein)
Gast #6747194
Lesenswert?

Genug der Vorrede. Habt mir genug Angst gemacht. Es wird Zeit etwas zu 
machen. Habe angefangen das von NXP zu lesen. Habe mir schon einiges im 
Netz gesucht. Im Netz gibt es aber das Problem, das viele Sachen auf den 
Atmega 8 oder die älteren Attiny laufen. Da ja der Atiiny 841 etwas 
anders ist liegt dabei das Problem.
#6747199
Lesenswert?

Heiner schrieb:
> Im Netz gibt es aber das Problem, das viele Sachen auf den
> Atmega 8 oder die älteren Attiny laufen. Da ja der Atiiny 841 etwas
> anders ist liegt dabei das Problem.

Das Problem ist, dass du ohne Code aus dem Netz anscheinend gar nichts 
machen kannst. Mir ist es doch völlig egal ob es Code für diesen oder 
jenen Controller nicht gibt. Ich nehme das Datenblatt und programmiere 
für MEINEN Controller. Lerne programmieren. Dieses Defizit springt hier 
aus jedem deiner Posts geradezu heraus.
#6747241
Lesenswert?

Cyblord -. schrieb:

> Das Problem ist, dass du ohne Code aus dem Netz anscheinend gar nichts
> machen kannst. Mir ist es doch völlig egal ob es Code für diesen oder
> jenen Controller nicht gibt. Ich nehme das Datenblatt und programmiere
> für MEINEN Controller. Lerne programmieren. Dieses Defizit springt hier
> aus jedem deiner Posts geradezu heraus.

Kann man nichts gegen sagen, allerdings hat der TO wohl das Problem, 
dass er das Datenblatt (da in Englisch) nicht ohne Übersetzer lesen (und 
umsetzen) kann ... und die Übersetzung ist wohl manchmal nicht so 
zielführend...

Außerdem möchte der TO wohl ganz gerne den Code "mundgerecht" ;-)
#6747242
Lesenswert?

Egonwalter M. schrieb:

> Kann man nichts gegen sagen, allerdings hat der TO wohl das Problem,
> dass er das Datenblatt (da in Englisch) nicht ohne Übersetzer lesen (und
> umsetzen) kann ... und die Übersetzung ist wohl manchmal nicht so
> zielführend...

Ein englisches Datenblatt ist grundlegendes Handwerkszeug im Umgang mit 
Digitaltechnik. Da kommt man nicht drum rum. Aber technisches Englisch 
ist nicht besonders schwierig.
Gast #6747267
Lesenswert?

Matthias S. schrieb:
> Ein Problem, was noch auffällt: deine 'ADC_lesen_avg()' returniert ein
> uint16_t, aber du schickst das ohne Typecast auf ein uint8_t Array. Das
> kann klappen, muss aber nicht.

Das habe ich auch gesehen und bereits korregiert.

Egonwalter M. schrieb:
> Außerdem möchte der TO wohl ganz gerne den Code "mundgerecht" ;-)

Möchte den Code nicht "mundgerecht" haben. Man kann das Datenblat 
auswendig lernen oder die englische Version als Grundlage nehmen, alles 
geht. Es gibt verschiedene Wege etwas zu machen. Ein Lehrling lernt aus 
Erfahrung und Erkenntnis was zu machen ist. Wenn ich ein Stück Code 
nehme und es zerlege und schaue wie es andere machen, lerne ich daran 
mehr als ein DB auswendig zu lernen. Für mich ist es zielführend wenn 
man nicht ständig auf ein Lehrbuch verwiesen wird und ständig als "Nicht 
Wissender" in der Edelforn genannt wird. Ein Anfänger hat den Vorteil 
oder auch Nachteil nicht alles zu wissen. Hat aber die Aufgabe den 
Lehrer zu fragen. Und der Lehrer kann es als Hinweis für eine LKösung 
machen.
#6747273
Lesenswert?

Heiner schrieb:
> Möchte den Code nicht "mundgerecht" haben. Man kann das Datenblat
> auswendig lernen oder die englische Version als Grundlage nehmen, alles
> geht. Es gibt verschiedene Wege etwas zu machen.

Kranke und nicht zielführende Einstellung. Man muss das Datenblatt nicht 
auswendig lernen, man hat es ja jederzeit zur Hand.
Man muss es nur verstehen und danach programmieren können. Daran 
scheitert es. Alles andere ist nur Rechtfertigung für diesen einfachen 
Umstand.

Und NATÜRLICH ist das englische Datenblatt die Grundlage. Nichts 
anderes.
Gast #6747281
Lesenswert?

Da das DB die Grundlage ist, habe ich darin zwei Sachen gefunden, TWDIF 
und TWASIF. Da gibs den Hinweis im Register TWSSRA das SCL so lange auf 
GND liegen soll bis der Slave ihn wieder frei gibt bzw. verzögert. Ist 
leider bisher das einzige was gefunden habe.
#6747286
Lesenswert?

Heiner schrieb:
> Da das DB die Grundlage ist, habe ich darin zwei Sachen gefunden, TWDIF
> und TWASIF. Da gibs den Hinweis im Register TWSSRA das SCL so lange auf
> GND liegen soll bis der Slave ihn wieder frei gibt bzw. verzögert. Ist
> leider bisher das einzige was gefunden habe.

Das Datenblatt ist ja auch nicht dazu da dir den I2C Bus zu erklären, 
sondern wie du mit diesem Controller am Bus teilnimmst. Um den I2C Bus 
mit all seinen Spielarten zu verstehen gibt es andere Dokumente. Sobald 
du dann weißt WAS du eigentlich auf dem Bus tun willst, kann dir das 
Datenblatt sagen WIE du den Controller dazu bringst das zu tun.
Gast #6747410
Lesenswert?

Heiner schrieb:
> Da ja der Atiiny 841 etwas
> anders ist liegt dabei das Problem.

Ich bin absolut sicher, dass ein älterer AVR bei dem aktuellen Problem 
technisch gesehen kein bisschen einfacher ist.

Cyblord -. schrieb:
> Das Datenblatt ist ja auch nicht dazu da dir den I2C Bus zu erklären

So ist es. Das Datenblatt setzt voraus, dass du mit der Funktionsweise 
des I²C vertraut bist, bevor du eigene Programme dafür schreibst. Das 
gilt für alle Schnittstellen die irgendein Protokoll fahren.

In der Bedienungsanleitung deines Autos werden auch nicht die 
Verkehrsregeln erklärt, z.B. wann man links blinken soll und wie man 
korrekt überholt. Die Anleitung erklärt nur, worauf du dazu drücken 
musst.

Ich persönlich habe den I²C Bus lange Zeit mit der sogenannten 
"bit-banging" Methode genutzt. Das bedeutet: Ich habe dafür zwei simple 
I/O generische Pins verwendet, anstatt die spezielle I²C Hardware. 
Angefangen hatte ich mit dem Parallel-Port meines PC, von dem ich 
einfach die Leitungen D0 und D1 zweckentfremdete*. Auf der Gegenseite 
habe ich fertige Slaves benutzt bei denen ich sicher sein konnte, dass 
sie sich an die Regeln halten.

*) Ich hatte eine I/O Karte mit bidirektionalem parallel-Port, nicht den 
einfachen unidirektionalen Standard von IBM. Mit DOS Programmen konnte 
man darauf damals noch "einfach so" zugreifen, genau wie der 
Mikrocontroller auf seine I/O Pins zugreift.

Wenn ich als Anfänger Master und Slave gleichzeitig programmiere, habe 
ich zwei Baustellen gleichzeitig. So will ich nicht lernen, ist mir viel 
zu unsicher. Wer so arbeitet kann auch einfach behaupten, dass der 
Himmel grün sei. Solange sich alle Komponenten darüber einig sind (und 
das sind sie, weil ich sie gemacht habe) fällt der Fehler nicht auf. Das 
ist nicht gut.

Heiner schrieb:
> Da gibs den Hinweis im Register TWSSRA das SCL so lange auf
> GND liegen soll bis der Slave ihn wieder frei gibt bzw. verzögert. Ist
> leider bisher das einzige was gefunden habe.

Das ist Clock-Stretching. Wenn der Slave nicht sofort antworten kann, 
zieht er SCL so lange auf Low, bis er antworten kann. Achtung: Damit 
blockiert man den Bus, andere Übertragungen müssen dann ebenfalls 
warten.
Gast #6749663
Lesenswert?

Habe die letzten Tage damit zugebracht im Netz Beschreibungen und 
Angaben zu Clock Stretching zu suchen und zu lesen. Dazu zählen auch die 
Angaben von Atmel und Nachfolger. Leider ist sehr viel Rede von den 
allgemeinen Angaben, wie z.B. kurze Beschreibungen und allgemeine 
technische Angaben.

Stefan ⛄ F. schrieb:
> Das ist Clock-Stretching. Wenn der Slave nicht sofort antworten kann,
> zieht er SCL so lange auf Low, bis er antworten kann. Achtung: Damit
> blockiert man den Bus, andere Übertragungen müssen dann ebenfalls
> warten.

Diese Aussage ist schon fast das wichtigste was drin steht.

Warum gibt es dazu so gut wie keine Angaben? Weder in den Datenblättern 
noch in den Schriften der Hersteller steht was konkretes. Alle möglichen 
Leute beziehen sich darauf oder suchen was dazu, doch keiner nennt was 
konkretes.
Gibt es dieses Problem nur wenn man einen Attiny oder anderes kleines 
als Slave nutzt?
Gast #6749691
Lesenswert?

Heiner schrieb:

> Warum gibt es dazu so gut wie keine Angaben?

Weil Clock-Stretching einfach fester Bestandteil der I²C-Spezifikation 
ist. Alles, was was taugt und I²C-kompatibel sein will, hat es zu 
unterstützen.

Das betrifft natürlich nur Master. Ein Client, der kein Clockstretching 
benötigt, um seine Aufgabe erledigen zu können, braucht über 
Clock-Stretching auch nichts zu wissen.

In deinem konkreten Fall (TWI-Client der Tiny 441/841) weiß allerdings 
die Client-Hardware bereits alles nötige über Clock-Stretching und 
wendet das ganz automatisch an, wenn der Programmierer ihr keine andere 
Wahl läßt. Das ist auch überhaupt kein Problem, jeder standardgerecht 
Master hat damit lt. Standard problemlos klarzukommen.

D.h.: normalerweise ist bereits der Drops gelutscht, egal wie Scheiße du 
als Programmierer bist. Nur dann, wenn der Master standardwidrig unfähig 
ist, mit Clock-Stretching umzugehen, dann ist es nicht mehr egal. Dann 
ist dein Job, dafür zu sorgen, dass der Client kein Clock-Stretching 
mehr anwenden muss. D.h. im Kern, dass dein Code schlicht in jeder 
denkbaren Situation schnell genug sinnvoll auf den Interrupt der 
TWI-Slave-Hardware reagieren muss.

> Leute beziehen sich darauf oder suchen was dazu, doch keiner nennt was
> konkretes.

Diese Leute haben wohl alle den Standard gelesen und verstanden. Das ist 
alles.

> Gibt es dieses Problem nur wenn man einen Attiny oder anderes kleines
> als Slave nutzt?

Nein. Das Problem gibt es vielmehr nur, wenn man nicht 
Clock-Stretching-fähige (d.h.: nicht standardgerechte) Master benutzt.
#6749694
Lesenswert?

Heiner schrieb:
> Warum gibt es dazu so gut wie keine Angaben?

na weil das doch quasi trivial ist! Stefan und andere haben das doch 
schon beschrieben. Man muß sich eher Gedanken machen, wie man die 
Blockade in seinem Programm sinnvoll bearbeitet. Ich weiß nicht, ob das 
bei den diversen Programmpaketen drin ist, aber ich (als ASM) würde da 
auf jeden Fall sowas wie ein "timeout" einbauen, damit das System nicht 
auf ewig festhängt. Am Besten wäre doch für den TO einfach mal Spielen 
:-)
Gruß Rainer
Gast #6749767
Lesenswert?

Rainer V. schrieb:
> Stefan ⛄ F. schrieb:
>> Das ist Clock-Stretching. Wenn der Slave nicht sofort antworten kann,
>> zieht er SCL so lange auf Low, bis er antworten kann. Achtung: Damit
>> blockiert man den Bus, andere Übertragungen müssen dann ebenfalls
>> warten.
>
> ...was bitte verstehst du daran nicht???

Das verstehe ich sehr wohl und bin daran was zu machen.
Darüber steht aber auch die Aussage:

c-hater schrieb:
> Nein. Das Problem gibt es vielmehr nur, wenn man nicht
> Clock-Stretching-fähige (d.h.: nicht standardgerechte) Master benutzt.
Gast #6749774
Lesenswert?

Wie gesagt kannst du einfach innerhalb der ISR deine 5 ADC abfragen 
machen, bevor du damit beginnst, die Antwort (das ACK) zurück zu 
liefern.

Zur Erinnerung: Das ist die Zeile wo du das ACK sendest:
> TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));

Mehr ist da gar nicht zu tun, der Rest (das Clock Stretching) ergibt 
sich dann von ganz alleine.
Angehängte Dateien:
Gast #6751492
Lesenswert?

In diesem Bereich erfolgt das lesen der ADC Wert im Slave:
1
if (TWSSRA & (1 << TWDIR))    // Master fordert Daten vom Slave an
2
      {
3
      if(tx_buf_index >= sizeof(tx_buf))
4
        {
5
        tx_buf_index=0;
6
        }
7
      TWSD = tx_buf[tx_buf_index];// Daten in Sendepuffer
8
      tx_buf_index++;
9
      TWSCRB = ((1<<TWCMD1)|(1<<TWCMD0)); //Das ist die Zeile wo das ACK sendet
10
      }
Wenn ich die Funktion richtig verstanden habe
- fordert der Master vom Slave Daten ab mit if (TWSSRA & (1 << TWDIR))
- diese Daten stehen dann im TWSD (Datenpuffer)
- tx_buf_index steht auf 0 und wird so oft hochgezählt wie es angegeben 
ist
- es werden die Daten in TWSD geladen mit tx_buf und dem tx_buf_index
- tx_buf_index wird hochgezählt
- mit TWSCRB = ((1<<TWCMD1)|(1<<TWCMD0)) erfolgt die übertragung der 
Daten zum Master

Dann müsste in der Zeile da vor die Abfrage ob ADC fertig ist bzw. die 
Verzögerung von SCL.

Noch eins zur Hardware. Möchte das ganze auch auf einen Joystick mit 2 x 
ADC, Encoder und vielleicht auf entprellte Taster (nach Peter) 
verwenden.

Habe das im DB gefunden:
Das Datenregister wird beim Senden und Empfangen von Daten verwendet. 
Während der Übertragung werden die Daten vom/zum TWSD-Register und 
zum/vom Bus geschoben. Daher kann während der Byte-Übertragung nicht auf 
das Datenregister zugegriffen werden. Dies ist in der Hardware 
geschützt. Auf das Datenregister kann nur zugegriffen werden, wenn die 
SCL-Leitung vom Slave auf Low gehalten wird, d. h. wenn TWCH gesetzt 
ist.
... und das wird im TWSSRA gemacht.
LG Heiner
Gast #6752190
Lesenswert?

Stefan ⛄ F. schrieb:
> Zur Erinnerung: Das ist die Zeile wo du das ACK sendest:
>> TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
>
> Mehr ist da gar nicht zu tun, der Rest (das Clock Stretching) ergibt
> sich dann von ganz alleine.

Habe dazu die Tabelle 20-2 gefunden. Dort steht

TWCMD[1:0]   TWDIR     Betrieb/Operation

00   X     Keine Aktion
01   X     Reserviert

10   Wird verwendet, um die Transaktion abzuschließen
0   Acknowledge-Aktion ausführen, dann auf eine START (S/Sr)-Bedingung 
warten
1  Warten auf eine beliebige START (S/Sr)-Bedingung

11   Wird als Antwort auf ein Adressbyte verwendet (TWASIF ist gesetzt)
0     Acknowledge-Aktion ausführen, dann nächstes Byte empfangen
1   Acknowledge-Aktion ausführen, dann TWDIF setzenVerwendet als Antwort 
auf ein Datenbyte (TWDIF ist gesetzt)
0     Acknowledge-Aktion ausführen, dann auf nächstes Byte warten
1     Keine Aktion

Hoffe das die Formatierung auch so rüber kommt wie im ori.
In der Tabelle werden TWCMD 1 und 0 und TWDIR angegeben und ACK bzw. 
Einstellungen dazu.
Habe ich das richtig verstanden das TWCMD1=1 und TWCMD0=1 und TWDIR=0 
sein muss und damit Clock Stretching eingeschaltet wird?
Sorry, ist mir ganz unklar.
Gast #6752284
Lesenswert?

Ich habe gerade die Augen verdreht. Ist das denn wirklich so schwer?

Du sollst an dem Code für die Bits gar nichts ändern, sondern einfach 
nach dem Empfang des Kommandos erst den ADC 5x abfragen und danach das 
ACK senden. In der Zeitspanne zwischen ISR und dem Beschreiben des 
TWSCRB Registers passiert das Clock-Stretching von ganz alleine.
1
ISR( TWI_SLAVE_vect )
2
{
3
  uint8_t status = TWSSRA & 0xC0;
4
  if (status & I2C_DATA_INTERRUPT)
5
  {
6
    if (TWSSRA & (1 << TWDIR)) // Master fordert Daten vom Slave an
7
    {
8
      TWSD = ... // ein Byte antworten
9
      TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0)); // Ack senden
10
    }
11
    else  // Master hat ein Byte (=Kommando) zum Slave gesendet
12
    {
13
      command = TWSD;
14

15
      // Wenn das Start-Kommando empfangen wurde
16
      // hier den ADC 5x abfragen
17
      // erst dann mit ACK antworten
18

19
      TWSCRB |= (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0)); // Ack senden
20
    }
21
  }
22
  else if (status & I2C_ADDRESS_STOP_MATCH) 
23
  ...

TWDIR ist gar nicht zum Beschreiben vorgesehen. Dieses Bit kannst du nur 
lesen. Es zeigt an, ob der Master dir gerade ein Kommando-Byte 
gesendet hat, oder ob du ihm mit einem Daten-Byte antworten sollst.
1
Bit 1 – TWDIR: TWI Read/Write Direction
2

3
This bit indicates the direction bit from the last address packet received from a master. When this bit is one, a master read operation is in progress. When the bit is zero a master write operation is in progress.
Angehängte Dateien:
Gast #6752309
Lesenswert?

Stefan ⛄ F. schrieb:

> Ich habe gerade die Augen verdreht. Ist das denn wirklich so schwer?

Also manchmal bewundere ich wirklich deine Ausdauer und Geduld. Auch 
wenn selbst du hier scheinbar langsam an deine Grenzen stößt.

Aber vielleicht musst du dich am Ende doch mit dem Schluß abfinden, dass 
dieser Typ einfach mal vollständig lernresistent ist.

Das muss seinerseits kein böser Wille sein, aber wenn's das nicht ist, 
bleibt nur: IQ-Defizit. Bitter (für ihn), aber nicht zu ändern (für 
uns).
Gast #6752890
Lesenswert?

c-hater schrieb:
> Aber vielleicht musst du dich am Ende doch mit dem Schluß abfinden, dass
> dieser Typ einfach mal vollständig lernresistent ist.
>
> Das muss seinerseits kein böser Wille sein, aber wenn's das nicht ist,
> bleibt nur: IQ-Defizit. Bitter (für ihn), aber nicht zu ändern (für
> uns).

Es ist auf keinen Fall ein böser Wille von mir. Leider ist bei diesen 
Sachen auch das Ende meines Verständnisses (IQ) erreicht.
Eine Sache habt ihr damit wunderbar geschafft, das ich das Datenblatt 
lese. Muss ganz offen sagen, so gründlich und oft wie in diesem Fall 
habe ich noch nie ein Datenblatt gelesen. Habe auch versucht (so weit 
möglich für mich) die Zusammenhänge zwischen den einzelnen Registern und 
Einstellungen nach zu vollziehen. Einige Sachen fehlen noch beim lesen.
Werde auf jeden Fall weiter machen mit dem Attiny 841 und dran arbeiten 
es zu verstehen. Manches geht leichter für mich andere Sachen sind sehr 
schwer zu verstehen.
Hatte einen anderen Rat befolgt und mit den Einstellungen probiert, 
leider ohne Erfolg. Wie ich jetzt sehe war ich auf dem richtigen Weg 
aber sehr halbherzig. Hatte nur die hälfte gemacht und den zweiten Teil 
total vergessen.
Werde alles testen und berichten. Sicher helfen wir und besonders ihr 
auch vielen anderen Lesern (Anfängern) beim programmieren und lernen. 
Allein dafür gebürt euch mein grosser Dank.
LG Heiner

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren