Hallo,
mangels Kenntnissen wie man den Atmega "richtig" programmiert bzw. auch
kene Toolchain dafür vorhanden vergewaltige ich einen Arduino Pro Mini
etwas, bzw. nutze die IDE nur zum Uploaden. Er soll IR Daten einlesen
was er auch tut, inzwischen zumindest.
Die TSOP Low Flanken werden auf INT0 erkannt und dort vermessen.
Erkenntnis 1: micros() funktioniert in einer ISR nur, wenn man
Interrupts wieder zulässt. Sonst kommt da Murks bei raus. Im Netz wird
oft was anderes behauptet aber es ist so.
Erkenntnis 2: Oh weh! Damit erlaube ich ja auch Störsignalen auf dem
TSOP sich rekursiv einzhuhaken, denn die ISR Sperre für den Durchlauf
der INT0 ISR wird ja durch das globale INT Flag ausgelöst.
Das GICR Register ist über die Arduino IDE nicht erreichbar, da wollte
ich zunächst nut INT0 blockieren aber die INTs für micros() zulassen.
Und jetzt wird es tricky:
1
void int0vect()
2
{
3
(Varibalendeklarationen)
4
5
if (f_ISR_Blocker) return;
6
interrupts(); // Erlaube micros()
7
f_ISR_Blocker = true; // Routine gegen Fehlsignale blocken
8
period = micros()-10; // Aktuellen Timerwert speichern und Offset abziehen
9
while (!digitalRead(TSOP)); // Warte bis Pin wieder HIGH geht
10
period = micros()-period; // Dauer in us berechnen
11
noInterrupts();
12
f_ISR_Blocker = false;
13
--> Auswertung
14
15
}
durch f_ISR_Blocker versuche ich das "aufzuhalten", dass unmittelbar
nach Einspruung Störsignale einen Stacküberlauf erzeugen.
Gibt es da noch einen eleganteren Weg? Wenn GICR verfügbar wäre würde
ich da direkt abschalten aber leider meckert er dass er das register
nicht kennt.
MCUCR aber ist vorhanden.
Gruss
Christian
Deine Arduino-IDE installiert einen normalen AVR-GCC mit.
Also "Toolchain vorhanden", wenn auch etwas versteckt.
Dann: vergiss das ausmessen mit "micros()".
Der AVR hat extra Hardware zum vermessen von solchen Signalen: Timer mit
Capture.
> Gibt es da noch einen eleganteren Weg?
Ja. Warten in einer ISR ist per se pöse [0].
> Wenn GICR verfügbar wäre würde ich da direkt abschalten aber leider> meckert er dass er das register nicht kennt.
Zurecht. Heisst ja auch EIMSK. Kuckst Du Datenplatt.
HTH
[0] extrem gute Gründe ausgenommen, die liegen hier aber nicht vor
Linksammler schrieb:> Dann: vergiss das ausmessen mit "micros()".> Der AVR hat extra Hardware zum vermessen von solchen Signalen: Timer mit> Capture.
Aber über die Jehova IDE sind die nicht erreichbar. Dafür muss man auf
die registerebene runter. Und es fehlen eben Registerdeklarationen.
Linksammler schrieb:> dann ändere den Prescaler in "initTimer".
Ist aufwendiger als das hier zudem der Stein nichts anderes zu tun hat
als zu warten und zu decodieren.
EIMSK = EIMSK & ~(1 << 0); // INT0 abschalten
interrupts(); // Globale Ints für micros() zulassen
period = micros()-10; // Aktuellen Timerwert speichern
while (!digitalRead(TSOP)); // Warte bis Pin wieder HIGH geht
period = micros()-period; // Dauer in us berechnen
noInterrupts(); // Global wieder sperren
EIMSK = EIMSK | (1 << 0);// INT0 reaktivieren
Kurze Frage bevor alles klar:Ist es richtig, dass die AVR bei Ausführung
einer ISR das Global Int Flag sperren im SREG und es nach Ende wieder
freigeben?
ps: ok, passt! Sieht schoa besser aus als dieser Arduino Kram. Läuft
einwandfrei während im Zimmer hier die Daten durch die Luft sausen.
EIMSK = EIMSK & ~(1 << 0); // INT0 abschalten
SREG = SREG | (1 << 7); // Globale Ints für micros() zulassen
period = micros()-10; // Aktuellen Timerwert speichern und Offset
abziehen
while (!digitalRead(TSOP)); // Warte bis Pin wieder HIGH geht
period = micros()-period; // Dauer in us berechnen
SREG = SREG & ~(1<<7); // Globale Ints wieder sperren
EIMSK = EIMSK | (1 << 0); // INT0 reaktivieren
Christian J. schrieb:> Ist aufwendiger als das hier zudem der Stein nichts anderes zu tun hat> als zu warten und zu decodieren.
Dumme Frage: Warum tust du dir dann überhaupt das INT0-Gehampel an?
Dann kannst du auch beide Flanken per Polling abfragen, Abwechselnd mit
> while (!digitalRead(TSOP));
und
> while (digitalRead(TSOP));
Schön ist das aber auch nicht.
Linksammler schrieb:> Dumme Frage: Warum tust du dir dann überhaupt das INT0-Gehampel an?> Dann kannst du auch beide Flanken per Polling abfragen, Abwechselnd mit>> while (!digitalRead(TSOP));> und>> while (digitalRead(TSOP));
Kann man... aber INTs sind "eleganter" und hat mich mehr gereizt als das
altbacken zu machen. Die Polling Lösung mit pulseIn habe ich vorher
gemacht. Außerdem läuft der Empfang weiter während er schon den letzten
Datensatz Richtung PC raushaut.
Christian J. schrieb:> Kann man... aber INTs sind "eleganter"
Aber eine Warteschleife innerhalb eines INTs ist so ziemlich das
"uneleganteste" was man darin veranstalten kann.
Wenn du schon die extra-Capture-Hardware nicht nutzen magst, aber
zwingend den externen INT-Pin, warum nicht in der ISR nur timestamps
ziehen, und jedes mal die Trigger-Flanke für den Interrupt
umkonfigurieren?
die Profis (IRMP) machen das übrigens mit Polling aus dem
Timer-Interrupt.
Du scheinst da was grundsätzlich mißverstanden zu haben. Das Ziel beim
Programmieren ist nicht, maximalen Schaden in der Programmstruktur
anzurichten.
Sondern im Gegenteil, die Ressourcen mit Bedacht zu verwenden, damit
auch noch viele andere Tasks implementiert werden können.
Es gibt meines Wissens auch (noch) keinen Award für die schlechteste
CPU-Auslastung.
Linksammler schrieb:> warum nicht in der ISR nur timestamps> ziehen, und jedes mal die Trigger-Flanke für den Interrupt> umkonfigurieren?
Jo, bei einem PIC auch schon so gemacht.... mal schauen, heute abend
wenn ich Lust zu habe. Das ist echt eleganter. Aber es ist nicht alles
aus der Arduino IDE erreichbar, was man mit klassischer programmierung
macht.
Christian J. schrieb:> Aber es ist nicht alles> aus der Arduino IDE erreichbar, was man mit klassischer programmierung> macht.
Was soll denn da nicht gehen?
Arduino ist erstmal plain C, d.h. Du kannst alles machen, was in C auch
geht.
Arduino hat nur noch eine zusätzliche Lib mit Funktionen, die natürlich
Ressourcen belegen, wenn man sie benutzt. Aber niemand zwingt Dich, sie
zu benutzen.
In der Doku müßten auch alle Einschränkungen und Seiteneffekte drin
stehen.
Christian J. schrieb:> Aber es ist nicht alles> aus der Arduino IDE erreichbar, was man mit klassischer programmierung> macht.
was denn?
ist mir nie aufgefallen, ich kann die Arduino nehmen oder klassisch wie
vor meiner Arduinozeit, ich kann beide mixen und bin so von vor Arduino
zum Ardunio pö a pö umgezogen.
Zuerst pur AVR im Studio, dann Arduino mit IDE, einige Codes von vor
Arduino eingebaut und freunde mich so nach und nach mit der Arduino IDE
an,
ob ich nun I2C per Register anspreche oder per wire.h ist doch egal,
kommt fast immer auf selbe raus wenn man hinter die Arduinokulissen
schaut.
Peter Dannegger schrieb:> Arduino ist erstmal plain C, d.h. Du kannst alles machen, was in C auch> geht.> Arduino hat nur noch eine zusätzliche Lib mit Funktionen, die natürlich> Ressourcen belegen, wenn man sie benutzt. Aber niemand zwingt Dich, sie> zu benutzen.> In der Doku müßten auch alle Einschränkungen und Seiteneffekte drin> stehen.
Wenn man die Arduino-HAL (Hardware Abstraction Layer; Ich nenn es jetzt
mal HAL und nicht Lib) nicht verwenden möchte, sollte man auch nicht die
Arduino-IDE verwenden.
Die main() wird bereits in der Arduino-HAL definiert, daher muss man die
vorgesehenen Funktionen setup() und loop() verwenden.
Theoretisch aber nicht empfohlen, kannst du die setup() wie eine main
benutzen und auf jeden weiteren Arduino-HAL Funktionsaufruf verzichten.
Jetzt kommt die krucks.
Man sollte loop() verwenden, da nach jedem Loop ein paar Arduino-HAL
Tasks (zumindest für UART) gepollt werden.
Die Arduino-HAL führt eine Initialisierung der Hardware durch, und
belegt einen Timer. Es werden für einige Hardwarekomponenten ISRs
definiert, die du in deinem eigenen Code dann nicht selbst
ausprogrammieren kannst.
Ich verwende Eclipse mit CDT und "AVR-Eclipse"-Plugin. Man kann aus
Eclipse heraus mittels AVRDude die Arduinos per USB programmieren.
avr-gcc und avrdude werden zwar bei der Arduino-IDE mitgeliefert. Aber
es fehlt eine make.exe.
Daher WinAVR installieren, da ist avr-gcc, avrdude und make enthalten.
Joachim B. schrieb:> ob ich nun I2C per Register anspreche oder per wire.h ist doch egal,> kommt fast immer auf selbe raus wenn man hinter die Arduinokulissen> schaut.
Arduino belegt von Haus aus einige Ressourcen und das ist nicht
dokumentiert. Fummelt man unter der HAL herum kann es sein dass einiges
nicht mehr funktioniert. Stoppt man die Interrupts läuft auch I2C nicht
mehr, die Uart nicht, millies, micros usw.
Ich nutze die Libs gerne und die Vereinfachungen, sowie die einfache
Upload Möglichkeit mit 1-Click und Terminalfenster aber ansonsten will
ich davon weg, hatte ich bei PICS auch nicht und kam damit gut klar. Nur
solange ich AVR noch nicht so gut kenne nutze ich das.
Christian J. schrieb:> Stoppt man die Interrupts läuft auch I2C nicht> mehr, die Uart nicht, millies, micros usw.
millies, micros nutze ich nicht, zu abstrakt, bei meinen eigenen
Timerroutinen weiss ich was läuft.
Bei der Uart schwanke ich noch zwischen geht so und ist grausam.
Christian J. schrieb:> Ich nutze die Libs gerne und die Vereinfachungen, sowie die einfache> Upload Möglichkeit mit 1-Click und Terminalfenster aber ansonsten will> ich davon weg,
so gehts mir ja auch, die farb TFT mit Touch Ansteuerung selber fummeln,
nee danke,
dito mit Nokia 5110 oder OLED.
Die RTC hatte ich mir mal selber geschrieben, nutze aber jetzt den
Komfort der DS1307 Lib auch am DS3231 mit eigenen Erweiterungen,
feststellen welcher drin ist, 1307 oder 3231 und dann entweder RAM oder
Tempfühler nutzen.
Die WS2812b LIB musste ich patchen weil die buggy ist mit m1284p und die
Autoren unwillig waren, alles kein Ding, machen es nicht andere muss ich
halt selbst ran.
Peter Dannegger schrieb:> Es gibt meines Wissens auch (noch) keinen Award für die schlechteste> CPU-Auslastung.
[troll]
Der würde dauerhaft an Windows gehen ;)
[/troll]
Eric B. schrieb:> [troll]> Der würde dauerhaft an Windows gehen ;)> [/troll]
[fish for troll]
Deshalb gibt es bald Windows 10 für Arduino
[/fish for troll]
Christian K. schrieb:> Die Arduino-HAL führt eine Initialisierung der Hardware durch, und> belegt einen Timer. Es werden für einige Hardwarekomponenten ISRs> definiert, die du in deinem eigenen Code dann nicht selbst> ausprogrammieren kannst.
Das erklärt allerdings nicht solche Merkwürden wie dass eine lokale
static Variable in einer Routine gar nicht static ist, sondern bei jedem
Aufruf wieder auf 0 gesetzt wird. Ich habe mich neulich gewundert, dass
ein einfaches
static int c = 0;
if(c++ > 3) {
c=0;
...
nie ausgeführt wird bis ich c mal ausgeben liess, was immer 1 wurde und
dann wieder 0. Auch kein volatile half da. Woanders klappte das prima
aber in der Routine die keine ISR war nicht. Leider kommt man an den Asm
schwer ran, nur per Hand, was ich ärgerlich finde.
Christian J. schrieb:> Das erklärt allerdings nicht solche Merkwürden wie dass eine lokale> static Variable in einer Routine gar nicht static ist,
zeig doch Mal den ganzen Code, das klingt zu merkwürdig um wahr zu sein