Hallo Zusammen,
Habe bisher wenig Arduino-Erfahrung und möchte somit vermeiden
mit dem falschen Werkzeug an die Aufgabe zu gehen.
Ich habe einen Digital-Code zu Decodieren der im 3,3V-Level mit
impulsbreiten zwischen 1 und 15 mikrosekunden arbeitet.
Ist der Arduino von Hause aus dafür schnell genug oder nicht?
Ich muß die Impuls-längen auswerten und den Code daraus extrahieren.
Ich hätte Arduino Uno oder Mega zur Verfügung.
Falls ungeeignet, hat jemand Vorschläge für geeignete
Lösungs-Alternativen?
Besten Dank im Voraus
Es ist möglich, einen digitalen Code mit 3,3V-Level mit einem Arduino zu decodieren, aber es ist nicht sehr einfach. Sie müssen einige Änderungen an der Hardware vornehmen, um den Arduino auf 3,3V laufen zu lassen und die USB-Stromversorgung durch den Spannungsregler zu leiten. Sie müssen auch eine geeignete Software schreiben, um die Impulslängen auszuwerten und den Code daraus zu extrahieren. Sie können einen Arduino Uno oder Mega verwenden, aber Sie müssen auf die Kompatibilität mit anderen 5V-Geräten achten
Ich hoffe, das beantwortet Ihre Frage!
Falls Ja, können Sie ja gerne ein Like da lassen!
Wie fein soll denn die Auflösung der "Impulsbreiten zwischen 1 und 15 µs" sein?
Das ist sicher die anspruchsvollere Aufgabe als solche Signale elektrisch von 3,3V auf 5V anzuheben.
Und was soll mit den decodierten Daten gemacht werden?
Hallo zusammen,
erstmal Danke für die schnellen Antworten.
Ich hatte Bedenken mit der Tauglichkeit, da ich bei euch im Forum was diesbezüglich gefunden hatte,
die von für mich zu langsameren Auswertezeiten gepostet hatten.
(bei 16 MHz-Prozessoren 4 µs Auflösung)
Daher war ich verunsichert.
Die Pegel-Anpassung auf 5V-Signal ist nicht das Problem.
Nun will ich genauer erklären worum es eigentlich geht:
Es ist ein Gerät, wo undokumentiert an einem Pin der Meßwert zur Verfügung steht.
Mittels Oszylloskop hab ich herausgefunden, das dort digitalcodiert der aktuelle Meßwert abgreifbar ist.
Ein genormtes Daten-Protokoll ist nicht erkennbar.
Es sind sieben Datenpakete von zusammen 930µs Länge, die alle 8,2ms wiederholt werden.
Interessant von den Datenpaketen sind aber nur das 5. und 6. Datenpaket(jeweils 8Bit).
Im 5.und 6. Packet wird der 16-BIT-Meßwert übergreifend Binär-Codiert ausgegeben.
Eben diesen möchte ich decodieren und Anzeigen.
Ich stelle mir folgende Programmstruktur vor:
Grundsätzlich das Zählen der l-h Flanken.
Abhängig vom Zählerstand die verschiedenen Aktionen:
bis 40: keine weitere Aktion
41-56: Auswertung der h-Impuls-länge
h-Länge <10 µs =0
h-Länge >10 µs =1
daraufhin Eintragen 0oder1 in 16-Bit Schieberegister Bit und 1 mal schieben
56: Warten auf h-Länge >100 µs und damit
SR-Wert(Ergebnis) wegspeichern und Reset Zähler und Schieberegister.
Das wars dann eigentlich.
Ich hoffe alles soweit verständlich erläutert zu haben.
Klingt für mich simpel, aber mangels Arduino-Programmier-Erfahrungen,
habe ich bisher keine Vorstellungen welche Programm-Instruktionen
dieses Programm umsetzen würden.
Insbesondere für die Auswertung der h-Impuls-länge
und für das Schieberegister-Handling fehlt mir der Ansatz.
Zwingt dich jemand micros() zu nutzen?
Ich sehe niemanden!
16MHz sind 16 Millionen Takte pro Sekunde.
Angenommen, ein ASM Statement benötigt im Durchschnitt 1,6 Takte...(weil es sich so schön rechnen lässt)
Macht 10 Millionen Instruktionen pro Sekunde
10 tausend in einer ms
10 Instruktionen pro µs
Bekommst du das hin?
Wie sollen wir die Frage beantworten können?
Hallo zusammen
Ich habe mich über Ostern mit Hardware-Vorbereitungen
zum Projekt beschäftigt.
Dabei habe ich den Datenwust auch von unnützen Vor-Impulsen bereinigt, zwecks Vereinfachung der Arduino-Aufgabe.
Es bleibt jetzt "nur noch" die Aufgabe der Interpretation/Umsetzung der Datenbits in einen Wert.
Anbei habe ich wie gewünscht ein paar Screenshots gemacht.
Was mir jetzt noch nicht klar ist, wie ich am besten die
l/h-Daten Erkennung realisieren könnte.
Und nach 7 Nutz-Daten-Bits kommt ein Schmutz-Bit.
Danach folgen 8 Nutz Daten-Bits, gefolgt noch von unnützen Impulsen.
Sorry ich bin eigentlich Hardware-Löte-Freak und noch keine
Arduino-Erfahrung.
Habe mir schon versucht viel anzulesen, aber das "Richtige"
habe ich da noch nicht gefunden.
Besten Dank im Voraus.
Eventuell wird noch das Ende der Übertragung mit unterschiedlichen Zeiten in den 2 letzten Low-Phasen kodiert, kann jetzt aber auch durch den Zoomlevel nur so aussehen.
Kannst du auch den Anfang eines Datentelegramms zeigen?
Anbei zwei Bilder.
Im 1. Bild ist jetzt die Impulsfolge vollständig zu sehen.
Im 2. Bild die mögliche Auswertung.
Also als HW-Freak könnte ich auch zusätzlich als Auswerte-Trigger einen 11ms Timer zur verfügung stellen.
Hab ich mal im 2.Bild rot eingemalt.
Dann hätte der Arduino zur Auswertung und Wegspeichern der Data-Bit-Werte theoretisch 13mys
(entsprechend 208 Clockcycles) Reaktionszeit zur Verfügung.
Das muß doch dann auf jeden Fall reichen oder?
Muß / sollte ich da mit Interrupt-Auswertung des Hardware-
Trigger Eingangs arbeiten?
Mir fehlt noch das Gefühl für die Programm-Ablauf-/Reaktions Geschwindigkeit, daher meine Frage.
Meine Meinung: Zusammen mit C++ eher nicht. Mit Assembler kann der UNO auch Schach spielen, aber da lasse ich die Finger von.
Wie immer kann ich mich irren, in Deinem Sinne hoffe ich das sogar
Da ich Dein Signal nicht habe, ist das Testen etwas schwierig. Daher habe ich die Zeiten mal mit 1000 skaliert, also ms anstelle µs. Dann gehen auch Debug-Ausgaben.
Dein letztes Bild hat mich auf die Idee gebracht, nur von fallender Flanke zur nächsten fallenden Flanke die Zeit zu messen. Als Schwelle 14,250 ms, bei kleiner 0, bei größer 1.
Ich würde das sizeof(daten) einmal berechnen und die Variable weiterverwenden.
Ist das Absicht, das sync nicht mehr false wird?
Und müsste daten nicht volatile sein? (Ich frag für'n Freund )
Wenn Du auf sync abgleichst könnte die Ausgabe dann nicht ins loop() und dort eine zweite Variable damit gefüttert um zu vermeiden, das während der Ausgabe der Inhalt geändert wird?
Als Optimist gehe ich davon aus, daß der optimierende Compiler das sowieso macht. Als Pessimist nutze ich eine Konstante, nicht Variable.
Ja, nur der erste Datenmüll wird entsorgt. Ob das auch mit den echten Daten so geht, ist zu prüfen.
Nach meinem Verständnis nicht. Ein funktionierendes Programm ist kein Beweis, aber es funktioniert.
Beim UNO kann ein Byte auch nicht gesplittet werden (wegen atomic, wäre die nächste mögliche Frage).
Beim Zurückskalieren muß natürlich Serial.print rausfliegen und es stellt sich die Frage der Weiterverarbeitung der gewonnenen Daten. Dafür bleibt kaum Zeit, daran könnte das Vorhaben scheitern. Dazu gibt es aber bislang keinerlei Infos. Die Verwendung von loop kann ich mir allenfalls dann vorstellen, wenn nur gelegentlich Datenpakete ausgewertet werden sollen.
Hab mal mit dem Capture Register gespielt. Der Timer läuft mit einem Prescaler von /8, d.h. 2MHz. Es werden die Zyklen zwischen den fallenden Flanken ausgegeben.
Ich hoffe, das nicht zuviel Zeit im ISR verloren geht.
// Connect data pin of sensor to D8 of the Arduino Uno/Nano/Mini
constexpr auto serial_baud = 230400;
/************************************************************/
constexpr uint16_t BUFFER_SIZE = 256;
volatile uint16_t buffer[BUFFER_SIZE];
volatile uint8_t buffer_write_pointer;
volatile uint8_t buffer_read_pointer;
volatile bool error = false;
ISR(TIMER1_CAPT_vect) {
uint16_t value = ICR1;
buffer[buffer_write_pointer] = value;
buffer_write_pointer++;
/*
if (buffer_write_pointer >= BUFFER_SIZE) {
buffer_write_pointer = 0;
}
*/
if (buffer_write_pointer == buffer_read_pointer) {
error = true;
}
}
bool buffer_available() {
return buffer_write_pointer != buffer_read_pointer;
}
uint16_t lastValue = 0;
uint16_t buffer_read() {
while (!buffer_available()) {
// wait for data
}
uint16_t tmp = buffer[buffer_read_pointer];
auto new_p = buffer_read_pointer + 1;
if (new_p >= BUFFER_SIZE) {
new_p = 0;
}
buffer_read_pointer = new_p;
uint16_t ret = tmp - lastValue;
lastValue = tmp;
return ret;
}
void setup() {
Serial.begin(serial_baud);
TCCR1A = 0;
TCCR1B = 2;
TCCR1C = 0;
TIMSK1 = (1 << ICIE1);
error = false;
}
void loop() {
auto dx = buffer_read();
Serial.println(dx);
if (error) {
Serial.println("Buffer overflow");
while (true) {
;
}
}
}
Wenn mir ein Gefühl für irgendwas fehlt, dann heißt das:
Mir fehlt Wissen und Erfahrung!
Abhilfe:
Lernen und üben!
Experimentieren!
Die ganze Prosa in Foren, auch der Innenwert Orbit (Denkfraktale), hindern eher, als sie nützen.
Was kann man tun? (wie würde ich anfangen)
Erstmal würde ich mir einen Datenspender bauen. einen der genau solche Signale erzeugt, wie ich auswerten will.
Hätte zudem den Vorteil, dass JEDER hier damit testen könnte.
Nebenbei, entwickelt sich "Gefühl".
Dann lesen, z.B. Nyquist-Shannon-Abtasttheorem
Und plötzlich wissen wir, welches Zeitraster für die Auswertung benötigt wird!
In Haushaltssprech: Mindestens 2 Abtastungen müssen in das kürzeste Signal passen, damit garantiert eine Abtastung Aussage treffend ist.
Das dann in C++ zu bauen ist ein Klacks!
Ob es dann funktioniert?
Das weiß ich auch erst, wenn es getan ist.
Ich sehe da jetzt noch kein Problem.
Aber: Wenn es ASM werden soll, dann ist das so....
Irgendwann gabs mal eine Diskussion zu Optimierung usw.
OK, da drehte es sich um Platz, nicht um einen Signal Parser.