C Attiny13a TSR-Programm AD-Abfrage und Ausgabe

Katastrophe ! Der Trennpunkt fehlt... Den müsste ich doch nur mit der Einerstelle verodern ? Oder ?

Du meinst das Komma?

Also wenn du den Wert als Ascii via UART überträgst, dann musst du doch nur nach der zweiten Stelle ein ',' senden.
Falls du das Komma (Dezimalpunkt) auf deinem Display mit den Shift-egistern darstellen willst, muss ich im Moment passen, da ich die Anschlussbelegung nicht weiß (kann sein, dass alles am Themenanfang irgendwo steht)
 
Du meinst das Komma?

Also wenn du den Wert als Ascii via UART überträgst, dann musst du doch nur nach der zweiten Stelle ein ',' senden.
Falls du das Komma (Dezimalpunkt) auf deinem Display mit den Shift-egistern darstellen willst, muss ich im Moment passen, da ich die Anschlussbelegung nicht weiß (kann sein, dass alles am Themenanfang irgendwo steht)

Ne ne ich meine 7-Segment-Anzeige...
Habs aber gefunden... einfach die Maske für die 7-Segment-Ansteuerung "verunden". Nun funtzts.
Mit der seriellen Übertragung hast Du jetzt bei mir einen tief schlafenden Hund geweckt.
Das lief bisher nur auf dem Atmega8, aber beim tiny13 habe ich mit der Zeit vor allem Schwierigkeiten, bzgl. der Baudrate.
Der tiny hat doch keine offizielle uart-Funktion, oder ? Zumindest habe ich keinen Hinweis auf rxd und txd im Manual gefunden.
 
Ach, es ist ja ein ATtiny13, dieser kat kein USART-Modul. Der ATtiny2313 hätte einen. Hier bleibt dir dann nur eine Software-UART-Loesung. Muss es denn der ATtiny13 sein?
 
Ach, es ist ja ein ATtiny13, dieser kat kein USART-Modul. Der ATtiny2313 hätte einen. Hier bleibt dir dann nur eine Software-UART-Loesung. Muss es denn der ATtiny13 sein?

Hier herrscht Planwirtschaft... hatte mir mal ein Haufen davon besorgt und dachte dass sie ausreichen für meine Bedürfnisse.
Und außerdem habe ich mir auf Lochraster 4 von den tiny13 aufgebaut.
Kennst Du eine gute Softwarelösung ? ( Die Frage musste doch jetzt kommen, oder ) :wink:
 
Hallo Ralf,

schau vielleicht mal bei Roboternetz Software-UART mit GCC.

Allerdings hast du ja sicher nicht mehr so viele Pins bei dem ATtiny13 frei.

Ich denke die nächst "größeren" ATtiny mit USART Modul haben 20 Pin (ATtiny2313, 4313, 1634, 167, 87).

Dirk :ciao:

Moin Dirk,
Pins frei ? Klar, hab' doch 4x Tiny13 auf der Platine. :yu:
Dann schaue ich mal dort nach.
Gruß
Ralf
 
Ein Quadcore System? :D
Erinnert mich irgendwie an:
[video=youtube;S_zfjmukIGM]http://www.youtube.com/watch?v=S_zfjmukIGM[/video]
 
Hallo Dirk und natürlich alle anderen,
nun habe ich mal versucht den Mittelwert durch ein Hintergrundprogramm durchzuführen.
Das Problem ist, dass ich nun eine Laufschrift habe.
Nehme ich die Abfrage
Code:
sensorValue=ADCsingleREAD();
aus dem Hintergrundprogramm raus und führe diese im Hauptprogramm durch, flackerts wie vom Teufel besessen.
Ich hab' den Code einfach mal übernommen und die Variablen an den attiny13 adaptiert.
Und ein Mittelwert wird auch nicht gebildet es springt die letzte Nachkommastelle trotz konstanter Spannung. (zudem Tiefpass vorgeschaltet).
Hups, ich glaub die Rechnung funktioniert eh nicht. Hätte ich 99 Messwert gemittelt und käme auf einen Wert wie z.B. 10 V. Nun wäre der nächste Wert 1 V.
Dann wäre die Rechnung (10 V + 1 V )/2 ---> 11/2--> 5,5 V. Das wäre ja arg daneben.
Wie liegt das Problem ?
Gruß
Ralf
Code:
//Interrupt Service Routine for INT0
ISR(INT0_vect)
{
	unsigned char i;
 	 
	for(i = 0; i<10; i++)
	{
	sensorValue=ADCsingleREAD();
	messwert= (26*sensorValue+messwert)/2;

	}
 
	
}	


int i;

int main()
{
//uint16_t d1,d2,d3,d4,sensorValue,messwert;
messwert=0;

GIMSK = 1<<INT0;					// Enable INT0
MCUCR = 1<<ISC01 | 0<<ISC00;	// Trigger INT0 on rising edge
 
	sei();				//Enable Global Interrupt
   while(1)
   {
for(i=0;i<1;i++)
    {   
//sensorValue=ADCsingleREAD();
//messwert= (26*sensorValue+messwert)/2;
	}

d1=(messwert/10000);
d2=(messwert/1000) % 10;
d3=(messwert/100) % 10;
d4=(messwert/10) % 10;
 
Hallo Ralf,

so funktioniert es nicht. Dein Hauptprogramm weiß erst mal garnichts von der ISR, zudem ist sicher die ADC-Messung nicht so zeitkritisch (du machst ja sogar Mittelwertbildung), das dies in eine ISR verlegt werden muss.

Lass den Aufruf der Messung also im Hauptprogramm und ändere die Funktion ADCsingleREAD() folgendermaßen ab:

(1) ADC initialisieren (Referenz und Channel wählen)
(2) ADC Modul aktivieren (ADEN)
(3) Single Messung starten. Warten bis fertig und Ergebnis verwerfen. (Erste Messung nach Aktivierung des ADC Moduls ist schlecht)

(4) Hier eine Schleife (am besten 2x, 4x, 8x usw., Vorsicht, wenn zu viele Summierungen reicht uint16_t für die Summe eventuell nicht)
a) Single messung starten
b) warten bis Messung fertig ist
c) Ergebis summieren

(5) Mittelwert bilden (Ergebnis ist Summe durch Anzahl von Messungen)

fertig.
 
Hallo Ralf,

so funktioniert es nicht. Dein Hauptprogramm weiß erst mal garnichts von der ISR, zudem ist sicher die ADC-Messung nicht so zeitkritisch (du machst ja sogar Mittelwertbildung), das dies in eine ISR verlegt werden muss.

Lass den Aufruf der Messung also im Hauptprogramm und ändere die Funktion ADCsingleREAD() folgendermaßen ab:

(1) ADC initialisieren (Referenz und Channel wählen)
(2) ADC Modul aktivieren (ADEN)
(3) Single Messung starten. Warten bis fertig und Ergebnis verwerfen. (Erste Messung nach Aktivierung des ADC Moduls ist schlecht)

(4) Hier eine Schleife (am besten 2x, 4x, 8x usw., Vorsicht, wenn zu viele Summierungen reicht uint16_t für die Summe eventuell nicht)
a) Single messung starten
b) warten bis Messung fertig ist
c) Ergebis summieren

(5) Mittelwert bilden (Ergebnis ist Summe durch Anzahl von Messungen)

fertig.

Hallo Dirk,
Dank Deiner Hilfe und viel Einsatz läuft es jetzt. Auf der Platine fand noch ein atmega8 Platz. Daher wird die RS232 von diesem angesteuert.
Jetzt ist es ein HexCore-Rechner, obwohl.... ein attiny13 ist gerade wieder mal runter... :victory:
Gruß
Ralf
 
Hallo Dirk,
Dank Deiner Hilfe und viel Einsatz läuft es jetzt. Auf der Platine fand noch ein atmega8 Platz. Daher wird die RS232 von diesem angesteuert.
Jetzt ist es ein HexCore-Rechner, obwohl.... ein attiny13 ist gerade wieder mal runter... :victory:
Gruß
Ralf

4 Digits funktionieren ja nun wunderbar... das Display hat aber 8. Und wenn man schon Spannung misst... könnte man ja auch den Strom messen :hmmmm:
Jetzt meine Frage: Wenn ich die adc-Abfrage für eine Messung an einem anderen adc-Eingang durchführen will, muß ich den zuerst genutzten adc-Eingang schliessen ?
Also Spannungsmessung an PB3 und eine indirekte Strommessung (also auch eine Spannungsmessung) an PB4. Ich führe dann das Unterporgramm ADCsingleREAD hintereinander aus. Das Problem ist dass die 2. Messung denselben Wert liefert wie der erste.
Es steht dann auf dem Display: 12.45 12.45, also 2x Spannung und nicht der Strom.
Gruß
Ralf
Code:
uint16_t ADCsingleREAD(uint8_t adc)
{
int ADCval;
int result;
uint16_t i;
/*
ACME = 1
ADEN = 1

ADMUX1	|	ADMUX0
---------------
0	|	0	ADC0 PB5 RESET !!!! ---->> 0
0	|	1	ADC1 PB2 Pin 7         ---->> 1
1	|	0	ADC2 PB4 Pin 3         ---->> 2
1	|	1	ADC3 PB3 Pin 2         ---->> 3

*/

//    ADMUX |= (1 << MUX0);         // use #1 ADC
//    ADMUX |= (1 << MUX1);         // use #1 ADC	PB3
        ADMUX |= adc;         // 

    
    ADMUX |= (0 << REFS0);    // use AVcc as the reference
    ADMUX &= ~(1 << ADLAR);   // clear for 10 bit resolution
    
    ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);    // 128 prescale for 8Mhz
    ADCSRA |= (1 << ADEN);    // Enable the ADC

    ADCSRA |= (1 << ADSC);    // Start the ADC conversion

    while(ADCSRA & (1 << ADSC));      // Thanks T, this line waits for the ADC to finish 

    ADCval = ADCL;
    ADCval = (ADCH << 8) + ADCval;    // ADCH is read so ADC can be updated again


result=0;

// Mittelwert
	for(i=0;i<=5;i++)
	{
	ADCSRA |= (1 << ADSC);    // Start the ADC conversion
    while(ADCSRA & (1 << ADSC));      // Thanks T, this line waits for the ADC to finish 
    ADCval = ADCL;
    ADCval = (ADCH << 8) + ADCval;    // ADCH is read so ADC can be updated again
	result=result+ADCval;
	}
	ADCval=result/6;


/* Folgende Zeilen habe ich mal probiert hat aber nix gebracht */

ADCSRA |= (0 << ADEN);    // Enable the ADC
ADCSRA |= (0 << ADSC);    // Start the ADC conversion
    return ADCval;
}
 
4 Digits funktionieren ja nun wunderbar... das Display hat aber 8. Und wenn man schon Spannung misst... könnte man ja auch den Strom messen :hmmmm:
Jetzt meine Frage: Wenn ich die adc-Abfrage für eine Messung an einem anderen adc-Eingang durchführen will, muß ich den zuerst genutzten adc-Eingang schliessen ?
Also Spannungsmessung an PB3 und eine indirekte Strommessung (also auch eine Spannungsmessung) an PB4. Ich führe dann das Unterporgramm ADCsingleREAD hintereinander aus. Das Problem ist dass die 2. Messung denselben Wert liefert wie der erste.
Es steht dann auf dem Display: 12.45 12.45, also 2x Spannung und nicht der Strom.
Gruß
Ralf
Code:
uint16_t ADCsingleREAD(uint8_t adc)
{
int ADCval;
int result;
uint16_t i;
/*
ACME = 1
ADEN = 1

ADMUX1	|	ADMUX0
---------------
0	|	0	ADC0 PB5 RESET !!!! ---->> 0
0	|	1	ADC1 PB2 Pin 7         ---->> 1
1	|	0	ADC2 PB4 Pin 3         ---->> 2
1	|	1	ADC3 PB3 Pin 2         ---->> 3

*/

//    ADMUX |= (1 << MUX0);         // use #1 ADC
//    ADMUX |= (1 << MUX1);         // use #1 ADC	PB3
        ADMUX |= adc;         // 

    
    ADMUX |= (0 << REFS0);    // use AVcc as the reference
    ADMUX &= ~(1 << ADLAR);   // clear for 10 bit resolution
    
    ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);    // 128 prescale for 8Mhz
    ADCSRA |= (1 << ADEN);    // Enable the ADC

    ADCSRA |= (1 << ADSC);    // Start the ADC conversion

    while(ADCSRA & (1 << ADSC));      // Thanks T, this line waits for the ADC to finish 

    ADCval = ADCL;
    ADCval = (ADCH << 8) + ADCval;    // ADCH is read so ADC can be updated again


result=0;

// Mittelwert
	for(i=0;i<=5;i++)
	{
	ADCSRA |= (1 << ADSC);    // Start the ADC conversion
    while(ADCSRA & (1 << ADSC));      // Thanks T, this line waits for the ADC to finish 
    ADCval = ADCL;
    ADCval = (ADCH << 8) + ADCval;    // ADCH is read so ADC can be updated again
	result=result+ADCval;
	}
	ADCval=result/6;


/* Folgende Zeilen habe ich mal probiert hat aber nix gebracht */

ADCSRA |= (0 << ADEN);    // Enable the ADC
ADCSRA |= (0 << ADSC);    // Start the ADC conversion
    return ADCval;
}
:goodnight:

Jetzt läufts !
Code:
ADCSRA &= ~(1<<ADEN);           // ADC deaktivieren (2)
ADMUX = 0x00;              // ADMUX löschen
 
:goodnight:

Jetzt läufts !
Code:
ADCSRA &= ~(1<<ADEN);           // ADC deaktivieren (2)
ADMUX = 0x00;              // ADMUX löschen

Hallo Ralf,

das hat aber nichts mit aktivieren/deaktivieren vom ADC-Modul zu tun.

ADMUX ist ein IO-Register und das ist global statisch verfügbar. Wenn dort eine Funktion Bits setzt, bleiben diese Zustände erhalten.

Am Anfang deiner ADC-Wandel-Funktion stellst du den Eingangsmultiplexer so ein ...

ADMUX |= adc;

Die ODER Verknüpfung bewirkt, dass du hier nur Bits setzen kannst. Das ist der Grund, warum du nach ADC3 keinen andere Eingang wählen konntest. MUX1 und MUX0 waren immer gesetzt.

Da du VCC als Referenz verwendest (REFS0=0) und LeftAdjust ebenfalls deaktiviert ist (ADLAR=0) kannst du den Multiplexer zum Beispeil so einstellen.

ADMUX = adc & ((1<<MUX1) | (1<<MUX0));

Da du anscheinend auch permanent den ADC nutzt, kannst du das ADC-Modul einmalig am Anfang von main() aktivieren.

---

Vorteilhaft ist es, für die Mittelwertbildung immer 2^n Summierungen zu machen, da man dann schnell eine Division durch rechtsshift der Summe hinbekommt.

Beispiel: geteilt durch 8 entspricht Summe>>3

---

Dies
ADMUX |= (0 << REFS0);
hat übrigens keine Wirkung.

Dirk :ciao:
 
Hallo Ralf,

das hat aber nichts mit aktivieren/deaktivieren vom ADC-Modul zu tun.

ADMUX ist ein IO-Register und das ist global statisch verfügbar. Wenn dort eine Funktion Bits setzt, bleiben diese Zustände erhalten.

Am Anfang deiner ADC-Wandel-Funktion stellst du den Eingangsmultiplexer so ein ...

ADMUX |= adc;

Die ODER Verknüpfung bewirkt, dass du hier nur Bits setzen kannst. Das ist der Grund, warum du nach ADC3 keinen andere Eingang wählen konntest. MUX1 und MUX0 waren immer gesetzt.

Da du VCC als Referenz verwendest (REFS0=0) und LeftAdjust ebenfalls deaktiviert ist (ADLAR=0) kannst du den Multiplexer zum Beispeil so einstellen.

ADMUX = adc & ((1<<MUX1) | (1<<MUX0));

Da du anscheinend auch permanent den ADC nutzt, kannst du das ADC-Modul einmalig am Anfang von main() aktivieren.

---

Vorteilhaft ist es, für die Mittelwertbildung immer 2^n Summierungen zu machen, da man dann schnell eine Division durch rechtsshift der Summe hinbekommt.

Beispiel: geteilt durch 8 entspricht Summe>>3

---

Dies
ADMUX |= (0 << REFS0);
hat übrigens keine Wirkung.

Dirk :ciao:

Hallo Dirk,
jetzt läufts soweit. Allerdings ist der Code knapp über 1000 bytes. Da geht nix mehr.
Aus alten Dos-Zeiten weiß ich noch dass ein Assembler-Code deutlich kleiner sein kann als der einer Hochsprache.
Vielleicht probiere ich es damit nochmal. Aber Assembler.... da war doch was... :pcguru:
Derzeit überwache ich den Ladevorgang eines Akkus. Also DC-Spannungsquelle und Akku über 10 R auf Masse.
Den Strom messe ich indirekt über den R-> Problem: Die gemessene Spannung (nicht die über den Shunt) beinhaltet auch den Abfall über den Shunt.
D.h. ich muß den Wert welcher über dem Shunt abfällt subtrahieren. Und, da steigt der Compiler in Ermanglung an Speicherplatz aus.
Gruß
Ralf
 
Hallo Ralf,

du benötigst doch nur noch ein paar Byte. Da lässt sich bestimmt noch etwas an deinem Programm optimieren.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)